hyperbrane 0.1.1 → 0.2.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 (287) hide show
  1. package/README.md +81 -11
  2. package/dist/agent/agentClient.d.ts +5 -0
  3. package/dist/agent/agentClient.js +4 -0
  4. package/dist/agent/agentService.d.ts +9 -30
  5. package/dist/agent/agentService.js +62 -293
  6. package/dist/agent/agentStorage.d.ts +1 -20
  7. package/dist/agent/agentStorage.js +0 -30
  8. package/dist/agent/api.d.ts +89 -133
  9. package/dist/agent/api.js +4 -4
  10. package/dist/agent/client.d.ts +3 -1
  11. package/dist/agent/client.js +2 -3
  12. package/dist/agent/control.d.ts +23 -0
  13. package/dist/agent/control.js +479 -0
  14. package/dist/agent/hostTranscript.d.ts +0 -6
  15. package/dist/agent/hostTranscript.js +3 -14
  16. package/dist/agent/session/backend.d.ts +17 -30
  17. package/dist/agent/session/claude/home.d.ts +0 -1
  18. package/dist/agent/session/claude/home.js +0 -1
  19. package/dist/agent/session/claude/provision.d.ts +10 -0
  20. package/dist/agent/session/claude/provision.js +17 -0
  21. package/dist/agent/session/claude/transcript.d.ts +2 -7
  22. package/dist/agent/session/claude/transcript.js +68 -14
  23. package/dist/agent/session/client.d.ts +1 -10
  24. package/dist/agent/session/client.js +0 -3
  25. package/dist/agent/session/codex/provision.d.ts +14 -0
  26. package/dist/agent/session/codex/provision.js +25 -0
  27. package/dist/agent/session/fileTranscript.d.ts +6 -49
  28. package/dist/agent/session/fileTranscript.js +26 -82
  29. package/dist/agent/session/install.d.ts +5 -0
  30. package/dist/agent/session/install.js +35 -0
  31. package/dist/agent/session/sessionStorage.d.ts +4 -35
  32. package/dist/agent/session/sessionStorage.js +10 -16
  33. package/dist/agent/session/sharedConnection.d.ts +0 -8
  34. package/dist/agent/session/sharedConnection.js +0 -7
  35. package/dist/agent/session/storedTranscripts.d.ts +1 -6
  36. package/dist/agent/session/storedTranscripts.js +0 -3
  37. package/dist/agent/session/worker/jsonRpc.d.ts +2 -13
  38. package/dist/agent/session/worker/jsonRpc.js +2 -11
  39. package/dist/agent/session/worker/protocol.d.ts +27 -18
  40. package/dist/agent/session/worker/protocol.js +32 -16
  41. package/dist/agent/session/worker/workerParams.d.ts +0 -5
  42. package/dist/agent/session/worker/workerParams.js +15 -14
  43. package/dist/agent/session/workerConnection.d.ts +2 -13
  44. package/dist/agent/session/workerConnection.js +7 -12
  45. package/dist/agent/session/workerGatewayConnection.d.ts +18 -0
  46. package/dist/agent/session/workerGatewayConnection.js +86 -0
  47. package/dist/agent/vendor-types/manifest.json +87 -0
  48. package/dist/agent/workerBundle.d.ts +4 -19
  49. package/dist/agent/workerBundle.generated.js +1 -1
  50. package/dist/agent/workerBundle.js +3 -30
  51. package/dist/agent/workerReplacement.d.ts +3 -0
  52. package/dist/agent/workerReplacement.js +49 -0
  53. package/dist/cli/agent.js +44 -16
  54. package/dist/cli/command.d.ts +10 -11
  55. package/dist/cli/command.js +0 -4
  56. package/dist/cli/dimension.js +6 -6
  57. package/dist/cli/gateway.js +3 -6
  58. package/dist/cli/main.js +14 -31
  59. package/dist/cli/streamPrinter.d.ts +2 -10
  60. package/dist/cli/streamPrinter.js +16 -46
  61. package/dist/cli/table.d.ts +0 -3
  62. package/dist/cli/table.js +0 -4
  63. package/dist/dimension/api.d.ts +39 -27
  64. package/dist/dimension/api.js +28 -47
  65. package/dist/dimension/client.d.ts +5 -0
  66. package/dist/dimension/client.js +4 -0
  67. package/dist/dimension/control.d.ts +21 -0
  68. package/dist/dimension/control.js +328 -0
  69. package/dist/dimension/image.d.ts +0 -5
  70. package/dist/dimension/image.js +0 -8
  71. package/dist/dimension/imageFiles.generated.js +1 -1
  72. package/dist/dimension/paths.d.ts +5 -4
  73. package/dist/dimension/paths.js +15 -6
  74. package/dist/dimension/service.d.ts +8 -21
  75. package/dist/dimension/service.js +60 -224
  76. package/dist/dimension/transport-worker.d.ts +1 -0
  77. package/dist/dimension/transport-worker.js +151 -0
  78. package/dist/dimension/transportBundle.d.ts +2 -0
  79. package/dist/dimension/transportBundle.generated.d.ts +1 -0
  80. package/dist/dimension/transportBundle.generated.js +2 -0
  81. package/dist/dimension/transportBundle.js +4 -0
  82. package/dist/dimension/transportClient.d.ts +10 -0
  83. package/dist/dimension/transportClient.js +115 -0
  84. package/dist/dimension/transportProtocol.d.ts +53 -0
  85. package/dist/dimension/transportProtocol.js +8 -0
  86. package/dist/index.d.ts +5 -8
  87. package/dist/index.js +5 -16
  88. package/dist/lib/control.d.ts +8 -0
  89. package/dist/lib/control.js +62 -0
  90. package/dist/lib/docker.d.ts +0 -22
  91. package/dist/lib/docker.js +0 -10
  92. package/dist/lib/image.d.ts +0 -3
  93. package/dist/lib/image.js +0 -2
  94. package/dist/lib/jsonDirectory.d.ts +0 -13
  95. package/dist/lib/jsonDirectory.js +10 -15
  96. package/dist/lib/scriptBundle.d.ts +6 -0
  97. package/dist/lib/scriptBundle.js +28 -0
  98. package/dist/lib/sh.d.ts +2 -0
  99. package/dist/lib/sh.js +8 -0
  100. package/dist/lib/sleep.d.ts +0 -1
  101. package/dist/lib/sleep.js +0 -1
  102. package/dist/lib/streamFetch.d.ts +15 -0
  103. package/dist/lib/streamFetch.js +150 -0
  104. package/dist/lib/tar.d.ts +0 -1
  105. package/dist/lib/tar.js +5 -11
  106. package/dist/portal-gateway/api.d.ts +13 -44
  107. package/dist/portal-gateway/api.js +1 -3
  108. package/dist/portal-gateway/control.d.ts +42 -0
  109. package/dist/portal-gateway/control.js +657 -0
  110. package/dist/portal-gateway/gatewayClient.d.ts +5 -0
  111. package/dist/portal-gateway/gatewayClient.js +4 -0
  112. package/dist/portal-gateway/gatewayService.d.ts +8 -35
  113. package/dist/portal-gateway/gatewayService.js +79 -253
  114. package/dist/portal-gateway/image.d.ts +1 -2
  115. package/dist/portal-gateway/image.js +1 -3
  116. package/dist/portal-gateway/imageFiles.generated.js +3 -3
  117. package/dist/portal-gateway/portalClient.d.ts +5 -0
  118. package/dist/portal-gateway/portalClient.js +4 -0
  119. package/dist/portal-gateway/portalService.d.ts +5 -47
  120. package/dist/portal-gateway/portalService.js +19 -317
  121. package/dist/portal-gateway/transport-worker.d.ts +1 -0
  122. package/dist/portal-gateway/transport-worker.js +205 -0
  123. package/dist/portal-gateway/transportBundle.d.ts +2 -0
  124. package/dist/portal-gateway/transportBundle.generated.d.ts +1 -0
  125. package/dist/portal-gateway/transportBundle.generated.js +2 -0
  126. package/dist/portal-gateway/transportBundle.js +4 -0
  127. package/dist/portal-gateway/upstream.d.ts +12 -82
  128. package/dist/portal-gateway/upstream.js +0 -1
  129. package/dist/sandbox/api.d.ts +121 -178
  130. package/dist/sandbox/api.js +5 -7
  131. package/dist/sandbox/client.d.ts +2 -0
  132. package/dist/sandbox/client.js +4 -0
  133. package/dist/sandbox/data-endpoints/dataEndpoints.d.ts +13 -0
  134. package/dist/sandbox/data-endpoints/dataEndpoints.js +100 -0
  135. package/dist/sandbox/data-endpoints/firewalledPorts.d.ts +4 -0
  136. package/dist/sandbox/data-endpoints/firewalledPorts.js +28 -0
  137. package/dist/sandbox/lib/httpOverStream.d.ts +3 -0
  138. package/dist/sandbox/lib/httpOverStream.js +21 -0
  139. package/dist/sandbox/lib/remoteFileOperations.d.ts +10 -0
  140. package/dist/sandbox/lib/remoteFileOperations.js +70 -0
  141. package/dist/sandbox/lib/shellCommand.d.ts +3 -0
  142. package/dist/sandbox/lib/shellCommand.js +7 -0
  143. package/dist/sandbox/providers/boat/boatService.d.ts +2 -0
  144. package/dist/sandbox/providers/boat/boatService.js +321 -0
  145. package/dist/sandbox/providers/exedev/exeDevService.d.ts +2 -0
  146. package/dist/sandbox/providers/exedev/exeDevService.js +127 -0
  147. package/dist/sandbox/providers/exedev/exeDevToken.d.ts +1 -0
  148. package/dist/sandbox/providers/exedev/exeDevToken.js +54 -0
  149. package/dist/sandbox/providers/local/localService.d.ts +2 -0
  150. package/dist/sandbox/providers/local/localService.js +219 -0
  151. package/dist/sandbox/providers/ssh/sshService.d.ts +2 -0
  152. package/dist/sandbox/providers/ssh/sshService.js +82 -0
  153. package/dist/sandbox/providers/ssh/sshTransport.d.ts +12 -0
  154. package/dist/sandbox/providers/ssh/sshTransport.js +216 -0
  155. package/dist/sandbox/service.d.ts +2 -0
  156. package/dist/sandbox/service.js +18 -0
  157. package/dist/sandbox/storage/descriptors.d.ts +6 -0
  158. package/dist/sandbox/storage/descriptors.js +25 -0
  159. package/dist/sandbox/storage/sandboxStorage.d.ts +11 -0
  160. package/dist/sandbox/storage/sandboxStorage.js +42 -0
  161. package/dist/upstreams/anthropic.d.ts +0 -5
  162. package/dist/upstreams/anthropic.js +1 -8
  163. package/dist/upstreams/index.d.ts +2 -6
  164. package/dist/upstreams/index.js +0 -4
  165. package/dist/upstreams/openai.d.ts +0 -5
  166. package/dist/upstreams/openai.js +1 -13
  167. package/package.json +12 -4
  168. package/dist/agent/gatewaySignIns.d.ts +0 -5
  169. package/dist/agent/gatewaySignIns.js +0 -11
  170. package/dist/agent/session/codex/home.d.ts +0 -2
  171. package/dist/agent/session/codex/home.js +0 -4
  172. package/dist/agent/session/codex/messages.d.ts +0 -30
  173. package/dist/agent/session/codex/messages.js +0 -135
  174. package/dist/agent/session/codex/transcript.d.ts +0 -12
  175. package/dist/agent/session/codex/transcript.js +0 -22
  176. package/dist/agent/session/sdkMessages.d.ts +0 -15
  177. package/dist/agent/session/sdkMessages.js +0 -28
  178. package/dist/agent/session/workerSseConnection.d.ts +0 -15
  179. package/dist/agent/session/workerSseConnection.js +0 -26
  180. package/dist/agent/vendor-types/codex/app-server/AbsolutePathBuf.d.ts +0 -10
  181. package/dist/agent/vendor-types/codex/app-server/AbsolutePathBuf.js +0 -2
  182. package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputBody.d.ts +0 -2
  183. package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputBody.js +0 -2
  184. package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputContentItem.d.ts +0 -22
  185. package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputContentItem.js +0 -2
  186. package/dist/agent/vendor-types/codex/app-server/ImageDetail.d.ts +0 -1
  187. package/dist/agent/vendor-types/codex/app-server/ImageDetail.js +0 -2
  188. package/dist/agent/vendor-types/codex/app-server/ImageGenerationFailure.d.ts +0 -5
  189. package/dist/agent/vendor-types/codex/app-server/ImageGenerationFailure.js +0 -2
  190. package/dist/agent/vendor-types/codex/app-server/ImageGenerationItem.d.ts +0 -11
  191. package/dist/agent/vendor-types/codex/app-server/ImageGenerationItem.js +0 -2
  192. package/dist/agent/vendor-types/codex/app-server/LegacyAppPathString.d.ts +0 -23
  193. package/dist/agent/vendor-types/codex/app-server/LegacyAppPathString.js +0 -2
  194. package/dist/agent/vendor-types/codex/app-server/MessagePhase.d.ts +0 -7
  195. package/dist/agent/vendor-types/codex/app-server/MessagePhase.js +0 -2
  196. package/dist/agent/vendor-types/codex/app-server/ReasoningEffort.d.ts +0 -4
  197. package/dist/agent/vendor-types/codex/app-server/ReasoningEffort.js +0 -2
  198. package/dist/agent/vendor-types/codex/app-server/SleepItem.d.ts +0 -7
  199. package/dist/agent/vendor-types/codex/app-server/SleepItem.js +0 -2
  200. package/dist/agent/vendor-types/codex/app-server/WebSearchItem.d.ts +0 -14
  201. package/dist/agent/vendor-types/codex/app-server/WebSearchItem.js +0 -2
  202. package/dist/agent/vendor-types/codex/app-server/serde_json/JsonValue.d.ts +0 -3
  203. package/dist/agent/vendor-types/codex/app-server/serde_json/JsonValue.js +0 -2
  204. package/dist/agent/vendor-types/codex/app-server/v2/AgentMessageDelivery.d.ts +0 -1
  205. package/dist/agent/vendor-types/codex/app-server/v2/AgentMessageDelivery.js +0 -2
  206. package/dist/agent/vendor-types/codex/app-server/v2/AsyncUserInputQuestion.d.ts +0 -4
  207. package/dist/agent/vendor-types/codex/app-server/v2/AsyncUserInputQuestion.js +0 -2
  208. package/dist/agent/vendor-types/codex/app-server/v2/ByteRange.d.ts +0 -4
  209. package/dist/agent/vendor-types/codex/app-server/v2/ByteRange.js +0 -2
  210. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentState.d.ts +0 -5
  211. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentState.js +0 -2
  212. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentStatus.d.ts +0 -1
  213. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentStatus.js +0 -2
  214. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentTool.d.ts +0 -1
  215. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentTool.js +0 -2
  216. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentToolCallStatus.d.ts +0 -1
  217. package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentToolCallStatus.js +0 -2
  218. package/dist/agent/vendor-types/codex/app-server/v2/CommandAction.d.ts +0 -19
  219. package/dist/agent/vendor-types/codex/app-server/v2/CommandAction.js +0 -2
  220. package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionSource.d.ts +0 -1
  221. package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionSource.js +0 -2
  222. package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionStatus.d.ts +0 -1
  223. package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionStatus.js +0 -2
  224. package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallOutputContentItem.d.ts +0 -10
  225. package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallOutputContentItem.js +0 -2
  226. package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallStatus.d.ts +0 -1
  227. package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallStatus.js +0 -2
  228. package/dist/agent/vendor-types/codex/app-server/v2/FileUpdateChange.d.ts +0 -6
  229. package/dist/agent/vendor-types/codex/app-server/v2/FileUpdateChange.js +0 -2
  230. package/dist/agent/vendor-types/codex/app-server/v2/HookPromptFragment.d.ts +0 -4
  231. package/dist/agent/vendor-types/codex/app-server/v2/HookPromptFragment.js +0 -2
  232. package/dist/agent/vendor-types/codex/app-server/v2/McpAppDisplayMode.d.ts +0 -1
  233. package/dist/agent/vendor-types/codex/app-server/v2/McpAppDisplayMode.js +0 -2
  234. package/dist/agent/vendor-types/codex/app-server/v2/McpAppUi.d.ts +0 -8
  235. package/dist/agent/vendor-types/codex/app-server/v2/McpAppUi.js +0 -2
  236. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallAppContext.d.ts +0 -7
  237. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallAppContext.js +0 -2
  238. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallError.d.ts +0 -3
  239. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallError.js +0 -2
  240. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallResult.d.ts +0 -6
  241. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallResult.js +0 -2
  242. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallStatus.d.ts +0 -1
  243. package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallStatus.js +0 -2
  244. package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitation.d.ts +0 -5
  245. package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitation.js +0 -2
  246. package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitationEntry.d.ts +0 -6
  247. package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitationEntry.js +0 -2
  248. package/dist/agent/vendor-types/codex/app-server/v2/PatchApplyStatus.d.ts +0 -1
  249. package/dist/agent/vendor-types/codex/app-server/v2/PatchApplyStatus.js +0 -2
  250. package/dist/agent/vendor-types/codex/app-server/v2/PatchChangeKind.d.ts +0 -8
  251. package/dist/agent/vendor-types/codex/app-server/v2/PatchChangeKind.js +0 -2
  252. package/dist/agent/vendor-types/codex/app-server/v2/SubAgentActivityKind.d.ts +0 -1
  253. package/dist/agent/vendor-types/codex/app-server/v2/SubAgentActivityKind.js +0 -2
  254. package/dist/agent/vendor-types/codex/app-server/v2/TextElement.d.ts +0 -11
  255. package/dist/agent/vendor-types/codex/app-server/v2/TextElement.js +0 -2
  256. package/dist/agent/vendor-types/codex/app-server/v2/ThreadItem.d.ts +0 -215
  257. package/dist/agent/vendor-types/codex/app-server/v2/ThreadItem.js +0 -2
  258. package/dist/agent/vendor-types/codex/app-server/v2/UserInput.d.ts +0 -35
  259. package/dist/agent/vendor-types/codex/app-server/v2/UserInput.js +0 -2
  260. package/dist/agent/vendor-types/codex/app-server/v2/WebSearchAction.d.ts +0 -14
  261. package/dist/agent/vendor-types/codex/app-server/v2/WebSearchAction.js +0 -2
  262. package/dist/cli/services.d.ts +0 -19
  263. package/dist/cli/services.js +0 -33
  264. package/dist/dimension/http.d.ts +0 -7
  265. package/dist/dimension/http.js +0 -77
  266. package/dist/dimension/storage.d.ts +0 -39
  267. package/dist/dimension/storage.js +0 -79
  268. package/dist/portal-gateway/fakes.d.ts +0 -3
  269. package/dist/portal-gateway/fakes.js +0 -11
  270. package/dist/portal-gateway/gatewayStorage.d.ts +0 -66
  271. package/dist/portal-gateway/gatewayStorage.js +0 -125
  272. package/dist/portal-gateway/portalStorage.d.ts +0 -34
  273. package/dist/portal-gateway/portalStorage.js +0 -44
  274. package/dist/sandbox/boatService.d.ts +0 -52
  275. package/dist/sandbox/boatService.js +0 -343
  276. package/dist/sandbox/containerService.d.ts +0 -15
  277. package/dist/sandbox/containerService.js +0 -184
  278. package/dist/sandbox/endpointProxy.d.ts +0 -90
  279. package/dist/sandbox/endpointProxy.js +0 -701
  280. package/dist/sandbox/exeDevAuth.d.ts +0 -16
  281. package/dist/sandbox/exeDevAuth.js +0 -49
  282. package/dist/sandbox/localService.d.ts +0 -19
  283. package/dist/sandbox/localService.js +0 -200
  284. package/dist/sandbox/sseConnection.d.ts +0 -41
  285. package/dist/sandbox/sseConnection.js +0 -166
  286. package/dist/sandbox/sshService.d.ts +0 -30
  287. package/dist/sandbox/sshService.js +0 -680
@@ -1,31 +1,4 @@
1
- import { createHash } from "node:crypto";
2
- import { existsSync } from "node:fs";
3
1
  import { join } from "node:path";
4
- let bundled;
5
- /**
6
- * The worker, once per process. Under Bun with the sources at hand (a checkout) it is bundled from
7
- * them; otherwise (Node, or the built package, which ships no sources) it comes from
8
- * agent/workerBundle.generated.ts (scripts/bundle-worker.ts).
9
- */
10
- export function workerBundle() {
11
- bundled ??= load().catch((error) => {
12
- bundled = undefined;
13
- throw error;
14
- });
15
- return bundled;
16
- }
17
- async function load() {
18
- const fromSources = "Bun" in globalThis && existsSync(join(import.meta.dirname, "session", "main.ts"));
19
- const source = fromSources ? await buildWorkerSource() : (await import("./workerBundle.generated.js")).WORKER_SOURCE;
20
- return { source, build: createHash("sha256").update(source).digest("hex").slice(0, 16) };
21
- }
22
- /** Bundles the worker with Bun.build. */
23
- export async function buildWorkerSource() {
24
- const result = await Bun.build({
25
- entrypoints: [join(import.meta.dirname, "session", "main.ts")],
26
- target: "bun",
27
- });
28
- if (!result.success)
29
- throw new Error(`bundling the session worker failed:\n${result.logs.join("\n")}`);
30
- return result.outputs[0].text();
31
- }
2
+ import { scriptBundle } from "../lib/scriptBundle.js";
3
+ export const workerEntry = () => join(import.meta.dirname, "session", "main.ts");
4
+ export const workerBundle = scriptBundle(workerEntry, async () => (await import("./workerBundle.generated.js")).WORKER_SOURCE);
@@ -0,0 +1,3 @@
1
+ import { type WorkerClient } from "./session/client.ts";
2
+ import type { ConnectWorker } from "./session/workerConnection.ts";
3
+ export declare function replacingWorkerClient(connect: ConnectWorker, replace: (replaceBuild: boolean) => Promise<void>): WorkerClient;
@@ -0,0 +1,49 @@
1
+ import { SandboxConnectionRefusedError } from "../sandbox/api.js";
2
+ import { createWorkerClient } from "./session/client.js";
3
+ import { WorkerMethodNotFoundError, WorkerProtocolMismatchError } from "./session/worker/protocol.js";
4
+ export function replacingWorkerClient(connect, replace) {
5
+ const reconnecting = async (onNotification) => {
6
+ try {
7
+ return await connect(onNotification);
8
+ }
9
+ catch (error) {
10
+ if (!(error instanceof SandboxConnectionRefusedError))
11
+ throw error;
12
+ await replace(false);
13
+ return connect(onNotification);
14
+ }
15
+ };
16
+ const client = createWorkerClient(reconnecting);
17
+ const outdated = async (error) => {
18
+ if (!(error instanceof WorkerProtocolMismatchError || error instanceof WorkerMethodNotFoundError))
19
+ throw error;
20
+ await replace(error instanceof WorkerMethodNotFoundError);
21
+ };
22
+ return {
23
+ async call(method, params) {
24
+ try {
25
+ return await client.call(method, params);
26
+ }
27
+ catch (error) {
28
+ await outdated(error);
29
+ return client.call(method, params);
30
+ }
31
+ },
32
+ async *stream(session, afterId) {
33
+ let streamed = false;
34
+ try {
35
+ for await (const message of client.stream(session, afterId)) {
36
+ streamed = true;
37
+ yield message;
38
+ }
39
+ return;
40
+ }
41
+ catch (error) {
42
+ if (streamed)
43
+ throw error;
44
+ await outdated(error);
45
+ }
46
+ yield* client.stream(session, afterId);
47
+ },
48
+ };
49
+ }
package/dist/cli/agent.js CHANGED
@@ -1,9 +1,8 @@
1
- import { AGENT_BACKENDS } from "../agent/api.js";
1
+ import { AGENT_BACKENDS, AGENT_PERMISSION_MODES, } from "../agent/api.js";
2
2
  import { CPULimit, MemoryLimit } from "../dimension/api.js";
3
3
  import { QUIET_FLAG, UsageError, forEach, printList, requireFlag } from "./command.js";
4
4
  import { createTerminalPrinter, preview } from "./streamPrinter.js";
5
5
  import { formatTable } from "./table.js";
6
- /** How often `session attach` looks for permission requests and questions to point out. */
7
6
  const PENDING_POLL_MS = 1_000;
8
7
  function backendArg(name) {
9
8
  const backend = AGENT_BACKENDS.find((known) => known === name);
@@ -11,7 +10,6 @@ function backendArg(name) {
11
10
  throw new UsageError(`unknown backend ${name}: use one of ${AGENT_BACKENDS.join(", ")}`);
12
11
  return backend;
13
12
  }
14
- /** "AGENT/SESSION" -> the session's ref. */
15
13
  function sessionRef(arg) {
16
14
  const slash = arg.indexOf("/");
17
15
  if (slash <= 0 || slash === arg.length - 1)
@@ -21,7 +19,6 @@ function sessionRef(arg) {
21
19
  function refName({ agentName, sessionName }) {
22
20
  return `${agentName}/${sessionName}`;
23
21
  }
24
- /** --env KEY=VALUE flags -> an environment. */
25
22
  function envFlag(flags) {
26
23
  const entries = flags.env;
27
24
  if (!Array.isArray(entries) || entries.length === 0)
@@ -35,10 +32,6 @@ function envFlag(flags) {
35
32
  }
36
33
  return env;
37
34
  }
38
- /**
39
- * Points out, once each, the permission requests and questions the session is waiting on, with the
40
- * command that answers them. Returns the function that stops looking.
41
- */
42
35
  function watchPending(agents, ref) {
43
36
  const seen = new Set();
44
37
  const name = refName(ref);
@@ -97,10 +90,23 @@ export const agentCommands = {
97
90
  summary: `Install or update backends in an agent's dimension (${AGENT_BACKENDS.join(", ")})`,
98
91
  args: ["AGENT", "BACKEND..."],
99
92
  async run([agent, ...backends], _flags, { agents }) {
100
- backends.forEach(backendArg); // all known, before installing any
93
+ backends.forEach(backendArg);
101
94
  await forEach(backends, (backend) => agents.install(agent, backendArg(backend)));
102
95
  },
103
96
  },
97
+ backends: {
98
+ summary: "Show the backends installed in an agent's dimension",
99
+ args: ["AGENT"],
100
+ flags: QUIET_FLAG,
101
+ async run([agent], flags, { agents }) {
102
+ const rows = (await agents.listBackends(agent)).map(({ backend, version, ready }) => [
103
+ backend,
104
+ version ?? "-",
105
+ ready ? "ready" : version ? "incomplete or outdated: install it" : "not installed",
106
+ ]);
107
+ printList(flags, ["BACKEND", "VERSION", "STATUS"], rows);
108
+ },
109
+ },
104
110
  rm: {
105
111
  summary: "Stop one or more agents' workers (their sessions stay in the dimension)",
106
112
  args: ["NAME..."],
@@ -137,7 +143,15 @@ const modelCommands = {
137
143
  },
138
144
  },
139
145
  };
140
- /** A sign-in status as lines for the terminal: what to do next when it's waiting for the user. */
146
+ function describeStatus(status) {
147
+ if (status.state === "tool")
148
+ return `tool: ${status.tools.join(", ")}`;
149
+ if (status.state !== "exited")
150
+ return status.state;
151
+ if (status.signal)
152
+ return `exited (${status.signal})`;
153
+ return status.code === null ? "exited" : `exited (code ${status.code})`;
154
+ }
141
155
  function describeAuth(name, status) {
142
156
  if (status.state === "signedIn")
143
157
  return "signed in";
@@ -201,6 +215,22 @@ const taskCommands = {
201
215
  const permissionCommands = {
202
216
  summary: "List and answer a session's permission requests: tool calls waiting to run",
203
217
  commands: {
218
+ mode: {
219
+ summary: `Show the session's permission mode, or switch it: "ask" before each tool call, or "auto" to allow them all (the waiting ones too)`,
220
+ args: ["AGENT/SESSION", "[MODE]"],
221
+ async run([name, mode], _flags, { agents }) {
222
+ const ref = sessionRef(name);
223
+ if (mode === undefined) {
224
+ const session = (await agents.listSessions()).find((candidate) => candidate.agentName === ref.agentName && candidate.name === ref.sessionName);
225
+ return console.log(session?.permissionMode ?? "ask");
226
+ }
227
+ const known = AGENT_PERMISSION_MODES.find((candidate) => candidate === mode);
228
+ if (!known)
229
+ throw new UsageError(`unknown permission mode ${mode}: use one of ${AGENT_PERMISSION_MODES.join(", ")}`);
230
+ await agents.setPermissionMode(ref, known);
231
+ console.log(known);
232
+ },
233
+ },
204
234
  ls: {
205
235
  summary: "List a session's tool calls waiting for permission",
206
236
  args: ["AGENT/SESSION"],
@@ -280,7 +310,7 @@ export const sessionCommands = {
280
310
  .map((session) => [
281
311
  `${session.agentName}/${session.name}`,
282
312
  session.backend,
283
- session.status,
313
+ describeStatus(session.status),
284
314
  session.model ?? "(default)",
285
315
  session.nativeId ?? "",
286
316
  ])
@@ -354,7 +384,6 @@ export const sessionCommands = {
354
384
  const ref = sessionRef(name);
355
385
  const stopWatching = watchPending(agents, ref);
356
386
  const printer = createTerminalPrinter({ paced: true });
357
- // Ctrl-C: out with what's still being typed, and the terminal back to normal text.
358
387
  process.once("SIGINT", () => {
359
388
  printer.close();
360
389
  process.exit(130);
@@ -390,8 +419,8 @@ export const sessionCommands = {
390
419
  before: typeof flags.before === "string" ? timeFlag(flags.before) : undefined,
391
420
  });
392
421
  const printer = createTerminalPrinter({ paced: false });
393
- for (const { type, message } of page.messages)
394
- printer.printTranscript(type, message.content);
422
+ for (const message of page.messages)
423
+ printer.printTranscript(message);
395
424
  printer.close();
396
425
  if (page.nextBefore)
397
426
  process.stderr.write(`(older: hyperbrane session logs ${name} --before ${page.nextBefore})\n`);
@@ -403,7 +432,7 @@ export const sessionCommands = {
403
432
  async run([name], _flags, { agents }) {
404
433
  const ref = sessionRef(name);
405
434
  const [state, messages] = await Promise.all([agents.getSessionStatus(ref), agents.getLastUserMessages(ref)]);
406
- console.log(state);
435
+ console.log(describeStatus(state));
407
436
  for (const { message, queued } of messages) {
408
437
  const content = message.message.content;
409
438
  const text = typeof content === "string" ? content : content.map((block) => (block.type === "text" ? block.text : "")).join("");
@@ -426,7 +455,6 @@ export const sessionCommands = {
426
455
  },
427
456
  };
428
457
  const AGO_UNITS = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 };
429
- /** --before's TIME as an ISO 8601 time: a date or time, or how long ago ("30m"). */
430
458
  function timeFlag(value) {
431
459
  const ago = /^(\d+)([smhd])$/.exec(value);
432
460
  const time = ago ? Date.now() - Number(ago[1]) * AGO_UNITS[ago[2]] : Date.parse(value);
@@ -1,34 +1,35 @@
1
- import type { Services } from "./services.ts";
1
+ import type { AgentClient, AgentProvision, AgentSessionCapabilities } from "../agent/api.ts";
2
+ import type { DimensionClient } from "../dimension/api.ts";
3
+ import type { GatewayClient, PortalClient } from "../portal-gateway/api.ts";
2
4
  export type Flag = {
3
5
  type: "string" | "boolean";
4
6
  short?: string;
5
- /** Shown in help, e.g. "BYTES". */
6
7
  value?: string;
7
8
  description: string;
8
- /** May be given more than once; its value is then a string[]. */
9
9
  multiple?: boolean;
10
10
  };
11
11
  export type Flags = Record<string, string | boolean | string[] | undefined>;
12
+ export type Clients = {
13
+ readonly dimensions: DimensionClient;
14
+ readonly gateways: GatewayClient;
15
+ readonly portals: PortalClient;
16
+ readonly agents: AgentClient & AgentProvision & AgentSessionCapabilities;
17
+ };
12
18
  export type Command = {
13
19
  summary: string;
14
- /** Positional arguments: "NAME" is required, "[NAME]" optional, a trailing "NAME..." takes one or more. */
15
20
  args?: string[];
16
21
  flags?: Record<string, Flag>;
17
- run(args: string[], flags: Flags, services: Services): Promise<void>;
22
+ run(args: string[], flags: Flags, clients: Clients): Promise<void>;
18
23
  };
19
24
  export type CommandGroup = {
20
25
  summary: string;
21
- /** A group may hold groups of its own: `hyperbrane session permission allow`. */
22
26
  commands: Record<string, Command | CommandGroup>;
23
- /** Runs when the next word isn't one of `commands`: `hyperbrane session model A/S` next to `... model set`. */
24
27
  default?: Command;
25
28
  };
26
29
  export declare function isGroup(entry: Command | CommandGroup): entry is CommandGroup;
27
- /** Bad invocation: printed with a pointer to --help. */
28
30
  export declare class UsageError extends Error {
29
31
  name: string;
30
32
  }
31
- /** Some items of a multi-item command failed; each error was already printed. */
32
33
  export declare class PartialFailure extends Error {
33
34
  name: string;
34
35
  }
@@ -37,9 +38,7 @@ export declare function parseCommand(command: Command, argv: string[]): {
37
38
  flags: Flags;
38
39
  };
39
40
  export declare function requireFlag(flags: Flags, name: string): string;
40
- /** docker rm style: every item is attempted, each success prints its name, failures print and fail the command. */
41
41
  export declare function forEach(names: string[], action: (name: string) => Promise<void>): Promise<void>;
42
- /** `ls` output: the table, or with -q only the first column. */
43
42
  export declare function printList(flags: Flags, headers: string[], rows: string[][]): void;
44
43
  export declare const QUIET_FLAG: Record<string, Flag>;
45
44
  export declare function commandUsage(path: string, command: Command): string;
@@ -3,11 +3,9 @@ import { formatTable } from "./table.js";
3
3
  export function isGroup(entry) {
4
4
  return "commands" in entry;
5
5
  }
6
- /** Bad invocation: printed with a pointer to --help. */
7
6
  export class UsageError extends Error {
8
7
  name = "UsageError";
9
8
  }
10
- /** Some items of a multi-item command failed; each error was already printed. */
11
9
  export class PartialFailure extends Error {
12
10
  name = "PartialFailure";
13
11
  }
@@ -39,7 +37,6 @@ export function requireFlag(flags, name) {
39
37
  throw new UsageError(`--${name} is required`);
40
38
  return value;
41
39
  }
42
- /** docker rm style: every item is attempted, each success prints its name, failures print and fail the command. */
43
40
  export async function forEach(names, action) {
44
41
  let failed = false;
45
42
  for (const name of names) {
@@ -55,7 +52,6 @@ export async function forEach(names, action) {
55
52
  if (failed)
56
53
  throw new PartialFailure();
57
54
  }
58
- /** `ls` output: the table, or with -q only the first column. */
59
55
  export function printList(flags, headers, rows) {
60
56
  if (flags.quiet) {
61
57
  for (const row of rows)
@@ -8,13 +8,12 @@ function statusColumn(dimension) {
8
8
  }
9
9
  return dimension.status[0].toUpperCase() + dimension.status.slice(1);
10
10
  }
11
- function dimensionRow(dimension) {
12
- const usage = dimension.memoryUsage === null ? "--" : formatBytes(dimension.memoryUsage);
11
+ function dimensionRow(dimension, usage) {
13
12
  return [
14
13
  dimension.name,
15
14
  statusColumn(dimension),
16
- dimension.cpuUsage === null ? "--" : formatCpuPercent(dimension.cpuUsage),
17
- `${usage} / ${formatBytes(dimension.memoryLimit)}`,
15
+ usage ? formatCpuPercent(usage.cpuUsage) : "--",
16
+ `${usage ? formatBytes(usage.memoryUsage) : "--"} / ${formatBytes(dimension.memoryLimit)}`,
18
17
  String(dimension.cpuLimit),
19
18
  dimension.directory,
20
19
  ];
@@ -26,9 +25,10 @@ export const dimensionCommands = {
26
25
  summary: "List dimensions",
27
26
  flags: QUIET_FLAG,
28
27
  async run(_args, flags, { dimensions }) {
29
- const rows = (await dimensions.getDimensions())
28
+ const [list, usage] = await Promise.all([dimensions.listDimensions(), dimensions.getDimensionUsage()]);
29
+ const rows = list
30
30
  .sort((a, b) => a.name.localeCompare(b.name))
31
- .map(dimensionRow);
31
+ .map((dimension) => dimensionRow(dimension, usage.find((used) => used.name === dimension.name)));
32
32
  printList(flags, ["NAME", "STATUS", "CPU %", "MEM USAGE / LIMIT", "CPUS", "DIRECTORY"], rows);
33
33
  },
34
34
  },
@@ -7,10 +7,9 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import { resolve } from "node:path";
10
- import anthropic from "../upstreams/anthropic.js";
11
- import openai from "../upstreams/openai.js";
10
+ import { BUILTIN_UPSTREAMS as BUILTINS } from "../upstreams/index.js";
12
11
  import { QUIET_FLAG, UsageError, forEach, printList, requireFlag } from "./command.js";
13
- const BUILTIN_UPSTREAMS = { anthropic, openai };
12
+ const BUILTIN_UPSTREAMS = Object.fromEntries(BUILTINS.map((upstream) => [upstream.name, upstream]));
14
13
  const TRAFFIC_ACTIONS = ["BLOCK", "DELAY", "ASK", "INTERCEPT"];
15
14
  export const gatewayCommands = {
16
15
  summary: "Manage portal gateways: proxies that hold credentials for the dimensions behind them",
@@ -37,10 +36,8 @@ export const gatewayCommands = {
37
36
  create: {
38
37
  summary: "Create a gateway, finish creating one that was interrupted, or upgrade one to the current image",
39
38
  args: ["NAME"],
40
- async run([name], _flags, { gateways, portals }) {
39
+ async run([name], _flags, { gateways }) {
41
40
  await gateways.createGateway({ name: name });
42
- // An upgrade replaces the container, and its portals' links with it.
43
- await portals.restorePortals({ gatewayName: name });
44
41
  console.log(name);
45
42
  },
46
43
  },
package/dist/cli/main.js CHANGED
@@ -1,24 +1,14 @@
1
1
  #!/usr/bin/env bun
2
- import { createPortalWatcher } from "../portal-gateway/portalService.js";
3
2
  import { PartialFailure, UsageError, commandUsage, groupUsage, parseCommand, isGroup, } from "./command.js";
4
3
  import { agentCommands, sessionCommands } from "./agent.js";
5
4
  import { dimensionCommands } from "./dimension.js";
6
5
  import { credentialCommands, gatewayCommands, keyCommands, ruleCommands, upstreamCommands } from "./gateway.js";
7
6
  import { portalCommands } from "./portal.js";
8
- import { createServices } from "./services.js";
9
- const daemon = {
10
- summary: "Run the background work until stopped: restoring portals after container restarts",
11
- async run(_args, _flags, { portals, docker }) {
12
- const watcher = createPortalWatcher(portals, docker);
13
- watcher.start();
14
- console.error("hyperbrane daemon running; Ctrl-C to stop");
15
- await new Promise((done) => {
16
- process.once("SIGINT", done);
17
- process.once("SIGTERM", done);
18
- });
19
- await watcher.stop();
20
- },
21
- };
7
+ import { createAgentClient } from "../agent/agentClient.js";
8
+ import { createDimensionClient } from "../dimension/client.js";
9
+ import { createGatewayClient } from "../portal-gateway/gatewayClient.js";
10
+ import { createPortalClient } from "../portal-gateway/portalClient.js";
11
+ import { createSandboxClient } from "../sandbox/client.js";
22
12
  const GROUPS = {
23
13
  dimension: dimensionCommands,
24
14
  gateway: gatewayCommands,
@@ -30,9 +20,8 @@ const GROUPS = {
30
20
  agent: agentCommands,
31
21
  session: sessionCommands,
32
22
  };
33
- const COMMANDS = { daemon };
34
23
  function usage() {
35
- const names = [...Object.keys(GROUPS), ...Object.keys(COMMANDS)];
24
+ const names = Object.keys(GROUPS);
36
25
  const width = Math.max(...names.map((name) => name.length)) + 3;
37
26
  return [
38
27
  "Usage: hyperbrane COMMAND",
@@ -42,21 +31,14 @@ function usage() {
42
31
  "Management Commands:",
43
32
  ...Object.entries(GROUPS).map(([name, group]) => ` ${name.padEnd(width)}${group.summary}`),
44
33
  "",
45
- "Commands:",
46
- ...Object.entries(COMMANDS).map(([name, command]) => ` ${name.padEnd(width)}${command.summary}`),
47
- "",
48
34
  "Run 'hyperbrane COMMAND --help' for more information on a command.",
49
35
  ].join("\n");
50
36
  }
51
37
  const isHelp = (arg) => arg === "--help" || arg === "-h";
52
- /** Resolves the command to run, or returns help text to print. Groups nest: each word picks an entry. */
53
38
  function resolveCommand(argv) {
54
39
  const [first] = argv;
55
40
  if (first === undefined || isHelp(first) || first === "help")
56
41
  return { help: usage() };
57
- const standalone = COMMANDS[first];
58
- if (standalone)
59
- return { path: first, command: standalone, rest: argv.slice(1) };
60
42
  let group = GROUPS[first];
61
43
  if (!group)
62
44
  return new UsageError(`unknown command ${first}`);
@@ -99,14 +81,15 @@ async function main(argv) {
99
81
  console.error(`Error: ${error.message}\nRun 'hyperbrane ${path} --help' for usage.`);
100
82
  return 2;
101
83
  }
102
- const services = createServices();
103
- // A container restart takes its portals with it, and nothing else may be running to notice: every
104
- // command re-wires what's gone first (a quick look at each gateway when nothing is).
105
- await services.portals.restorePortals().catch((error) => {
106
- console.error(`Warning: restoring portals failed: ${error.message}`);
107
- });
84
+ const machine = createSandboxClient({ kind: "local" });
85
+ const clients = {
86
+ dimensions: createDimensionClient(machine),
87
+ gateways: createGatewayClient(machine),
88
+ portals: createPortalClient(machine),
89
+ agents: createAgentClient(machine),
90
+ };
108
91
  try {
109
- await command.run(parsed.args, parsed.flags, services);
92
+ await command.run(parsed.args, parsed.flags, clients);
110
93
  return 0;
111
94
  }
112
95
  catch (error) {
@@ -1,22 +1,14 @@
1
- import type { AgentStreamingMessage } from "../agent/api.ts";
1
+ import type { AgentStreamingMessage, AgentTranscriptMessage } from "../agent/api.ts";
2
2
  export declare function preview(value: unknown): string;
3
- /** The part of stdout the printer uses. */
4
3
  export type TerminalStream = {
5
4
  isTTY?: boolean;
6
5
  write(chunk: string): unknown;
7
6
  };
8
7
  export interface TerminalPrinter {
9
- /** A stream message: partial text and thinking as they arrive, tool calls and results, and how each turn ended. */
10
8
  print(message: AgentStreamingMessage): void;
11
- /** A complete message of a transcript. */
12
- printTranscript(role: "user" | "assistant", content: unknown): void;
9
+ printTranscript(message: AgentTranscriptMessage): void;
13
10
  close(): void;
14
11
  }
15
- /**
16
- * Prints to `stream` (stdout); `paced` text is typed out steadily (see createPacedOutput) when it's
17
- * a terminal. A complete assistant message's text is printed only if none of it streamed: claude
18
- * reports failures it hits before reaching the API (a TLS error, say) as a synthetic message.
19
- */
20
12
  export declare function createTerminalPrinter({ paced, stream }: {
21
13
  paced: boolean;
22
14
  stream?: TerminalStream;
@@ -1,18 +1,10 @@
1
- /** Longest a tool input or result is shown, in characters. */
2
1
  const PREVIEW_LENGTH = 400;
3
- /** The pacer's clock: about a frame. */
4
2
  const TICK_MS = 16;
5
- /** Deltas arriving this close together are one burst. */
6
3
  const BURST_GAP_MS = 20;
7
- /** How far back the arrival rate is measured. */
8
4
  const RATE_WINDOW_MS = 2_000;
9
- /** The time a lone first burst is spread over, before there's a rate to go by. */
10
5
  const FIRST_BURST_MS = 300;
11
- /** Typing runs this much faster than text arrives, so the buffer drains rather than grows. */
12
6
  const CATCH_UP = 1.1;
13
- /** The slowest the pacer types, in characters per ms. */
14
7
  const MIN_RATE = 0.06;
15
- /** No character waits longer than this to be typed, whatever the pace. */
16
8
  const MAX_LAG_MS = 1_000;
17
9
  const DIM = "\x1b[2m";
18
10
  const NORMAL = "\x1b[22m";
@@ -20,10 +12,6 @@ export function preview(value) {
20
12
  const text = typeof value === "string" ? value : JSON.stringify(value);
21
13
  return text.length > PREVIEW_LENGTH ? `${text.slice(0, PREVIEW_LENGTH)}…` : text;
22
14
  }
23
- /**
24
- * Writes to `stream`, switching styles as text changes between answer and thinking: dimmed on a
25
- * terminal, marked with [thinking] otherwise. Thinking always ends on a line of its own.
26
- */
27
15
  function createStyledWriter(stream) {
28
16
  const tty = stream.isTTY === true;
29
17
  let style = "text";
@@ -47,25 +35,15 @@ function createStyledWriter(stream) {
47
35
  },
48
36
  };
49
37
  }
50
- /** Writes everything at once, as it comes. */
51
38
  function createDirectOutput(stream) {
52
39
  const writer = createStyledWriter(stream);
53
40
  return { text: writer.text, line: writer.line, close: () => writer.line("") };
54
41
  }
55
- /**
56
- * Types text out at a steady pace instead of in the bursts it arrives in (model APIs send several
57
- * words at once, then pause for a while): at the rate text has been arriving, a little faster, so
58
- * each burst lasts until about when the next one comes, and never more than MAX_LAG_MS behind. A
59
- * pause shows only when the model pauses for longer than that. Lines wait for the text before
60
- * them, then go out whole.
61
- */
62
42
  function createPacedOutput(stream) {
63
43
  const writer = createStyledWriter(stream);
64
44
  const queue = [];
65
- /** Recent bursts: when each came, and how many characters. */
66
45
  const bursts = [];
67
46
  let waitingChars = 0;
68
- /** Characters the pace has allowed but not yet typed (fractions carry over between ticks). */
69
47
  let credit = 0;
70
48
  let lastTick = 0;
71
49
  let timer;
@@ -79,22 +57,12 @@ function createPacedOutput(stream) {
79
57
  while (bursts.length > 1 && now - bursts[0].at > RATE_WINDOW_MS)
80
58
  bursts.shift();
81
59
  }
82
- /**
83
- * Characters per ms the text has been arriving at: the bursts before the newest over the time they
84
- * span up to it, since the newest is what covers the time ahead. A lone burst is spread over
85
- * FIRST_BURST_MS.
86
- */
87
60
  function arrivalRate() {
88
61
  if (bursts.length < 2)
89
62
  return (bursts[0]?.chars ?? 0) / FIRST_BURST_MS;
90
63
  const earlier = bursts.slice(0, -1).reduce((sum, burst) => sum + burst.chars, 0);
91
64
  return earlier / (bursts.at(-1).at - bursts[0].at);
92
65
  }
93
- /**
94
- * The least that keeps every waiting chunk within MAX_LAG_MS, spread evenly over the ticks left
95
- * rather than all at once when it's due: for each chunk, the characters up to its end over the
96
- * ticks until its deadline. Only matters when text arrives faster than the rate predicted.
97
- */
98
66
  function deadlinePace() {
99
67
  const now = performance.now();
100
68
  let before = 0;
@@ -110,7 +78,6 @@ function createPacedOutput(stream) {
110
78
  }
111
79
  function tick() {
112
80
  const now = performance.now();
113
- // A late tick (a busy event loop) catches up, but not by more than a few frames at once.
114
81
  credit += Math.max(MIN_RATE, arrivalRate() * CATCH_UP) * Math.min(now - lastTick, TICK_MS * 4);
115
82
  lastTick = now;
116
83
  let budget = Math.max(Math.floor(credit), deadlinePace());
@@ -141,14 +108,12 @@ function createPacedOutput(stream) {
141
108
  lastTick = performance.now();
142
109
  timer = setInterval(tick, TICK_MS);
143
110
  }
144
- // Nothing is banked while idle: the next burst paces from zero instead of coming out at once.
145
111
  function stop() {
146
112
  clearInterval(timer);
147
113
  timer = undefined;
148
114
  credit = 0;
149
115
  }
150
116
  function text(chunk, style) {
151
- // Code points, so a character outside the BMP is never split across ticks.
152
117
  const chars = [...chunk];
153
118
  queue.push({ kind: "text", style, chars, arrivedAt: performance.now() });
154
119
  waitingChars += chars.length;
@@ -173,11 +138,19 @@ function createPacedOutput(stream) {
173
138
  }
174
139
  return { text, line, close };
175
140
  }
176
- /**
177
- * A message's content as a terminal transcript: the user's words as "> ...", tool calls and their
178
- * results on lines of their own, and the assistant's text and thinking when `withText` (a stream has
179
- * already printed them as partial output).
180
- */
141
+ function printSystem(output, message) {
142
+ output.line(`\n[${describeSystem(message)}]\n`);
143
+ }
144
+ function describeSystem(message) {
145
+ if (message.subtype === "compact_boundary") {
146
+ const meta = message.compact_metadata;
147
+ return meta ? `compacted, ${meta.trigger}, from ${meta.pre_tokens} tokens` : "compacted";
148
+ }
149
+ const { event } = message;
150
+ if (event.kind === "review")
151
+ return `review ${event.state}: ${event.review}`;
152
+ return `subagent ${event.agent} (${event.path}) ${event.activity}`;
153
+ }
181
154
  function printContent(output, role, content, withText) {
182
155
  if (typeof content === "string") {
183
156
  if (role === "user")
@@ -201,11 +174,6 @@ function printContent(output, role, content, withText) {
201
174
  output.line(`[result${block.is_error ? ", error" : ""}] ${preview(block.content ?? "")}\n`);
202
175
  }
203
176
  }
204
- /**
205
- * Prints to `stream` (stdout); `paced` text is typed out steadily (see createPacedOutput) when it's
206
- * a terminal. A complete assistant message's text is printed only if none of it streamed: claude
207
- * reports failures it hits before reaching the API (a TLS error, say) as a synthetic message.
208
- */
209
177
  export function createTerminalPrinter({ paced, stream = process.stdout }) {
210
178
  const output = paced && stream.isTTY ? createPacedOutput(stream) : createDirectOutput(stream);
211
179
  let streamed = false;
@@ -239,13 +207,15 @@ export function createTerminalPrinter({ paced, stream = process.stdout }) {
239
207
  output.line("\n[done]\n");
240
208
  return;
241
209
  case "system":
210
+ if (message.subtype === "compact_boundary" || message.subtype === "session_event")
211
+ return printSystem(output, message);
242
212
  output.line(`[session ${message.session_id}, model ${message.model}]\n`);
243
213
  return;
244
214
  }
245
215
  }
246
216
  return {
247
217
  print,
248
- printTranscript: (role, content) => printContent(output, role, content, true),
218
+ printTranscript: (message) => (message.type === "system" ? printSystem(output, message) : printContent(output, message.type, message.message.content, true)),
249
219
  close: output.close,
250
220
  };
251
221
  }
@@ -1,7 +1,4 @@
1
1
  export declare function formatTable(headers: string[], rows: string[][]): string;
2
- /** 268435456 -> "256MiB", 1597440 -> "1.523MiB" (docker's units.BytesSize). */
3
2
  export declare function formatBytes(bytes: number): string;
4
- /** 0.0512 cores -> "5.12%" (docker stats' CPU %: 100% is one full core). */
5
3
  export declare function formatCpuPercent(cores: number): string;
6
- /** Seconds -> "3 minutes", "About an hour", ... (docker's units.HumanDuration). */
7
4
  export declare function formatDuration(seconds: number): string;