@phuetz/code-buddy 2.0.0 → 2.1.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 (403) hide show
  1. package/README.fr.md +56 -0
  2. package/README.md +73 -16
  3. package/codebuddy-runtime.json +5 -5
  4. package/dist/agent/codebuddy-agent.d.ts +18 -0
  5. package/dist/agent/codebuddy-agent.js +45 -8
  6. package/dist/agent/execution/agent-executor.d.ts +0 -9
  7. package/dist/agent/execution/agent-executor.js +165 -12
  8. package/dist/agent/execution/context-pipeline.d.ts +9 -0
  9. package/dist/agent/execution/context-pipeline.js +64 -2
  10. package/dist/agent/execution/tool-loop-guard.d.ts +76 -0
  11. package/dist/agent/execution/tool-loop-guard.js +165 -0
  12. package/dist/agent/execution/tool-selection-strategy.js +19 -2
  13. package/dist/agent/facades/session-facade.d.ts +0 -6
  14. package/dist/agent/facades/session-facade.js +0 -45
  15. package/dist/agent/hermes-claw-migrate.d.ts +0 -21
  16. package/dist/agent/hermes-claw-migrate.js +9 -4
  17. package/dist/agent/hermes-protocol-gateways.js +8 -1
  18. package/dist/agent/repo-profiler.js +17 -4
  19. package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
  20. package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
  21. package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
  22. package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
  23. package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
  24. package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
  25. package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
  26. package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
  27. package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
  28. package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
  29. package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
  30. package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
  31. package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
  32. package/dist/agent/self-improvement/proposal-store.js +79 -17
  33. package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
  34. package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
  35. package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
  36. package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
  37. package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
  38. package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
  39. package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
  40. package/dist/agent/self-improvement/skill-engine.js +385 -13
  41. package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
  42. package/dist/agent/self-improvement/skill-gate.js +17 -2
  43. package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
  44. package/dist/agent/self-improvement/skill-mutator.js +51 -15
  45. package/dist/agent/self-improvement/skill-types.d.ts +2 -1
  46. package/dist/agent/self-improvement/types.d.ts +11 -0
  47. package/dist/agent/tool-handler.d.ts +1 -1
  48. package/dist/agent/tool-handler.js +28 -9
  49. package/dist/auth/profile-manager.js +1 -1
  50. package/dist/channels/companion-channel-turn.d.ts +53 -4
  51. package/dist/channels/companion-channel-turn.js +218 -16
  52. package/dist/channels/slash-parity.d.ts +4 -6
  53. package/dist/channels/slash-parity.js +9 -44
  54. package/dist/cli/session-commands.d.ts +9 -0
  55. package/dist/cli/session-commands.js +45 -5
  56. package/dist/cli/session-picker.d.ts +43 -0
  57. package/dist/cli/session-picker.js +128 -0
  58. package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
  59. package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
  60. package/dist/codebuddy/fleet-tool-defs.d.ts +1 -0
  61. package/dist/codebuddy/fleet-tool-defs.js +24 -0
  62. package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
  63. package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
  64. package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
  65. package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
  66. package/dist/codebuddy/providers/provider-openai-compat.js +1 -1
  67. package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
  68. package/dist/codebuddy/ragchat-tool-defs.js +19 -0
  69. package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
  70. package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
  71. package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
  72. package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
  73. package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
  74. package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
  75. package/dist/codebuddy/tools.d.ts +0 -6
  76. package/dist/codebuddy/tools.js +25 -3
  77. package/dist/commands/cli/daemon-commands.js +3 -1
  78. package/dist/commands/cli/evolve-command.js +21 -5
  79. package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
  80. package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
  81. package/dist/commands/cli/fleet-commands.js +29 -0
  82. package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
  83. package/dist/commands/cli/fleet-mission-commands.js +72 -0
  84. package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
  85. package/dist/commands/cli/fleet-rooms-commands.js +289 -0
  86. package/dist/commands/cli/tools-commands.js +2 -1
  87. package/dist/commands/cli/triage-command.d.ts +8 -0
  88. package/dist/commands/cli/triage-command.js +72 -0
  89. package/dist/commands/cli/utility-commands.js +25 -1
  90. package/dist/commands/client-dispatcher.d.ts +7 -0
  91. package/dist/commands/client-dispatcher.js +73 -21
  92. package/dist/commands/cron-cli/index.d.ts +3 -1
  93. package/dist/commands/cron-cli/index.js +25 -0
  94. package/dist/commands/device-auth.d.ts +10 -0
  95. package/dist/commands/device-auth.js +91 -0
  96. package/dist/commands/enhanced-command-handler.d.ts +9 -0
  97. package/dist/commands/enhanced-command-handler.js +28 -6
  98. package/dist/commands/handlers/agent-handlers.d.ts +1 -1
  99. package/dist/commands/handlers/agent-handlers.js +4 -4
  100. package/dist/commands/handlers/channel-handlers.js +53 -2
  101. package/dist/commands/handlers/export-handlers.d.ts +3 -2
  102. package/dist/commands/handlers/export-handlers.js +55 -28
  103. package/dist/commands/handlers/extra-handlers.js +5 -1
  104. package/dist/commands/handlers/grill-me-handler.js +26 -18
  105. package/dist/commands/handlers/memory-handlers.d.ts +6 -2
  106. package/dist/commands/handlers/memory-handlers.js +35 -15
  107. package/dist/commands/handlers/missing-handlers.d.ts +2 -2
  108. package/dist/commands/handlers/missing-handlers.js +4 -4
  109. package/dist/commands/handlers/resources-handler.d.ts +12 -0
  110. package/dist/commands/handlers/resources-handler.js +52 -0
  111. package/dist/commands/handlers/starter-handlers.d.ts +1 -1
  112. package/dist/commands/handlers/starter-handlers.js +32 -2
  113. package/dist/commands/handlers/switch-handler.d.ts +1 -1
  114. package/dist/commands/handlers/switch-handler.js +15 -0
  115. package/dist/commands/handlers/test-handlers.js +4 -86
  116. package/dist/commands/handlers/ui-handlers.js +11 -5
  117. package/dist/commands/login-chatgpt.d.ts +8 -0
  118. package/dist/commands/login-chatgpt.js +17 -0
  119. package/dist/commands/mcp-import.d.ts +11 -0
  120. package/dist/commands/mcp-import.js +67 -0
  121. package/dist/commands/mcp-invoke.d.ts +2 -0
  122. package/dist/commands/mcp-invoke.js +68 -0
  123. package/dist/commands/mcp.js +4 -0
  124. package/dist/commands/pipeline.d.ts +7 -1
  125. package/dist/commands/pipeline.js +104 -7
  126. package/dist/commands/resources.d.ts +2 -0
  127. package/dist/commands/resources.js +64 -0
  128. package/dist/commands/skills-cli/index.js +35 -12
  129. package/dist/commands/slash/builtin-commands.js +16 -3
  130. package/dist/commands/slash/index.d.ts +3 -1
  131. package/dist/commands/slash/index.js +2 -0
  132. package/dist/commands/slash/surfaces.d.ts +53 -0
  133. package/dist/commands/slash/surfaces.js +177 -0
  134. package/dist/commands/slash/types.d.ts +17 -0
  135. package/dist/commands/try.d.ts +1 -1
  136. package/dist/commands/try.js +1 -1
  137. package/dist/companion/companion-identity.d.ts +43 -0
  138. package/dist/companion/companion-identity.js +136 -0
  139. package/dist/companion/companion-toolset.d.ts +66 -0
  140. package/dist/companion/companion-toolset.js +368 -0
  141. package/dist/companion/companion-turn.d.ts +10 -2
  142. package/dist/companion/companion-turn.js +38 -1
  143. package/dist/config/code-exec-policy.d.ts +25 -0
  144. package/dist/config/code-exec-policy.js +39 -0
  145. package/dist/config/model-tools.d.ts +9 -0
  146. package/dist/config/model-tools.js +4 -0
  147. package/dist/context/context-manager-v2.js +2 -2
  148. package/dist/context/lm-resizer-compressor.js +3 -2
  149. package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
  150. package/dist/context/lm-resizer-diagnostics.js +30 -0
  151. package/dist/context/tool-output-masking.js +3 -4
  152. package/dist/curator/curator.d.ts +6 -0
  153. package/dist/curator/curator.js +53 -3
  154. package/dist/daemon/cron-agent-bridge.d.ts +6 -0
  155. package/dist/daemon/cron-agent-bridge.js +31 -4
  156. package/dist/doctor/index.d.ts +11 -2
  157. package/dist/doctor/index.js +84 -21
  158. package/dist/doctor/integrations.d.ts +179 -0
  159. package/dist/doctor/integrations.js +227 -0
  160. package/dist/doctor/triage.d.ts +108 -0
  161. package/dist/doctor/triage.js +304 -0
  162. package/dist/fleet/collaboration.d.ts +44 -0
  163. package/dist/fleet/collaboration.js +170 -0
  164. package/dist/fleet/fleet-listener.d.ts +1 -0
  165. package/dist/fleet/fleet-listener.js +87 -46
  166. package/dist/fleet/fleet-registry.d.ts +2 -0
  167. package/dist/fleet/resource-catalog.d.ts +245 -0
  168. package/dist/fleet/resource-catalog.js +211 -0
  169. package/dist/fleet/rooms/room-access.d.ts +138 -0
  170. package/dist/fleet/rooms/room-access.js +196 -0
  171. package/dist/fleet/rooms/room-client.d.ts +158 -0
  172. package/dist/fleet/rooms/room-client.js +685 -0
  173. package/dist/fleet/rooms/room-event.d.ts +139 -0
  174. package/dist/fleet/rooms/room-event.js +330 -0
  175. package/dist/fleet/rooms/room-filter.d.ts +48 -0
  176. package/dist/fleet/rooms/room-filter.js +152 -0
  177. package/dist/fleet/rooms/room-hub.d.ts +154 -0
  178. package/dist/fleet/rooms/room-hub.js +363 -0
  179. package/dist/fleet/rooms/room-identity.d.ts +26 -0
  180. package/dist/fleet/rooms/room-identity.js +82 -0
  181. package/dist/fleet/rooms/room-lock.d.ts +34 -0
  182. package/dist/fleet/rooms/room-lock.js +180 -0
  183. package/dist/fleet/rooms/room-observations.d.ts +7 -0
  184. package/dist/fleet/rooms/room-observations.js +61 -0
  185. package/dist/fleet/rooms/room-server.d.ts +28 -0
  186. package/dist/fleet/rooms/room-server.js +75 -0
  187. package/dist/fleet/rooms/room-store.d.ts +119 -0
  188. package/dist/fleet/rooms/room-store.js +448 -0
  189. package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
  190. package/dist/fleet/rooms/room-ws-bridge.js +137 -0
  191. package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
  192. package/dist/fleet/sensory-mission-bridge.js +136 -0
  193. package/dist/git/worktree-sessions.js +1 -0
  194. package/dist/harness/contract.d.ts +4 -4
  195. package/dist/harness/fleet-supervisor.d.ts +16 -0
  196. package/dist/harness/fleet-supervisor.js +64 -0
  197. package/dist/harness/index.d.ts +4 -0
  198. package/dist/harness/index.js +4 -0
  199. package/dist/harness/mission-runner.d.ts +3 -0
  200. package/dist/harness/mission-runner.js +53 -0
  201. package/dist/harness/mission-store.d.ts +93 -0
  202. package/dist/harness/mission-store.js +297 -0
  203. package/dist/harness/tool-harness.d.ts +56 -0
  204. package/dist/harness/tool-harness.js +153 -0
  205. package/dist/hooks/use-enhanced-input.js +48 -4
  206. package/dist/hooks/use-input-handler.d.ts +1 -0
  207. package/dist/hooks/use-input-handler.js +82 -22
  208. package/dist/hooks/use-input-history.js +1 -0
  209. package/dist/identity/lisa-introspection.js +5 -2
  210. package/dist/identity/operational-self-model.d.ts +2 -0
  211. package/dist/identity/operational-self-model.js +4 -0
  212. package/dist/index.js +52 -6
  213. package/dist/mcp/client.js +6 -0
  214. package/dist/mcp/config.d.ts +20 -0
  215. package/dist/mcp/config.js +121 -8
  216. package/dist/mcp/import-normalize.d.ts +12 -0
  217. package/dist/mcp/import-normalize.js +114 -0
  218. package/dist/mcp/transports.d.ts +10 -5
  219. package/dist/mcp/transports.js +61 -99
  220. package/dist/mcp/types.d.ts +5 -0
  221. package/dist/media/comfyui-recipe-contract.d.ts +7 -7
  222. package/dist/memory/facts-memory.d.ts +11 -1
  223. package/dist/memory/facts-memory.js +47 -8
  224. package/dist/memory/memory-candidate-queue.d.ts +2 -2
  225. package/dist/memory/memory-candidate-queue.js +6 -6
  226. package/dist/memory/persistent-memory.d.ts +13 -8
  227. package/dist/memory/persistent-memory.js +77 -30
  228. package/dist/nodes/device-node.js +5 -9
  229. package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
  230. package/dist/observability/run-event-writer.d.ts +21 -0
  231. package/dist/observability/run-event-writer.js +81 -0
  232. package/dist/observability/run-store.d.ts +5 -0
  233. package/dist/observability/run-store.js +18 -13
  234. package/dist/observability/run-trajectory.js +1 -1
  235. package/dist/optimization/prompt-cache.d.ts +19 -2
  236. package/dist/optimization/prompt-cache.js +41 -6
  237. package/dist/orchestration/orchestrator.d.ts +21 -0
  238. package/dist/orchestration/orchestrator.js +122 -15
  239. package/dist/persistence/session-content.d.ts +8 -0
  240. package/dist/persistence/session-content.js +76 -0
  241. package/dist/persistence/session-handoff.d.ts +64 -0
  242. package/dist/persistence/session-handoff.js +80 -0
  243. package/dist/persistence/session-history.d.ts +4 -0
  244. package/dist/persistence/session-history.js +38 -0
  245. package/dist/persistence/session-store.d.ts +9 -0
  246. package/dist/persistence/session-store.js +48 -20
  247. package/dist/personas/persona-manager.js +17 -1
  248. package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
  249. package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
  250. package/dist/plugins/plugin-manager.js +10 -1
  251. package/dist/prompts/prompt-manager.js +11 -4
  252. package/dist/prompts/system-base.js +6 -2
  253. package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
  254. package/dist/protocols/a2a/codebuddy-executor.js +9 -8
  255. package/dist/protocols/a2a/index.d.ts +1 -1
  256. package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
  257. package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
  258. package/dist/protocols/a2a/peer-config.d.ts +20 -0
  259. package/dist/protocols/a2a/peer-config.js +55 -0
  260. package/dist/providers/codex-oauth.js +30 -6
  261. package/dist/providers/model-provider-compat.js +2 -1
  262. package/dist/sandbox/os-sandbox.d.ts +1 -1
  263. package/dist/scheduler/cron-scheduler.d.ts +15 -2
  264. package/dist/scheduler/cron-scheduler.js +35 -4
  265. package/dist/scheduler/job-notepad.d.ts +69 -0
  266. package/dist/scheduler/job-notepad.js +339 -0
  267. package/dist/security/audit-logger.d.ts +1 -1
  268. package/dist/security/compute-confinement.d.ts +4 -0
  269. package/dist/security/compute-confinement.js +89 -0
  270. package/dist/security/session-encryption.d.ts +4 -0
  271. package/dist/security/session-encryption.js +31 -0
  272. package/dist/sensory/voice-loop.d.ts +17 -0
  273. package/dist/sensory/voice-loop.js +72 -15
  274. package/dist/server/auth/device-session-context.d.ts +9 -0
  275. package/dist/server/auth/device-session-context.js +13 -0
  276. package/dist/server/auth/device-store.d.ts +89 -0
  277. package/dist/server/auth/device-store.js +261 -0
  278. package/dist/server/auth/device-token.d.ts +3 -0
  279. package/dist/server/auth/device-token.js +6 -0
  280. package/dist/server/auth/jwt.js +4 -0
  281. package/dist/server/index.d.ts +0 -10
  282. package/dist/server/index.js +28 -0
  283. package/dist/server/middleware/auth.js +3 -2
  284. package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
  285. package/dist/server/routes/a2a-jsonrpc.js +66 -0
  286. package/dist/server/routes/a2a-protocol.d.ts +12 -0
  287. package/dist/server/routes/a2a-protocol.js +1 -1
  288. package/dist/server/routes/device-auth.d.ts +4 -0
  289. package/dist/server/routes/device-auth.js +40 -0
  290. package/dist/server/types.d.ts +4 -0
  291. package/dist/server/websocket/handler.d.ts +13 -0
  292. package/dist/server/websocket/handler.js +102 -17
  293. package/dist/services/prompt-builder.d.ts +2 -0
  294. package/dist/services/prompt-builder.js +13 -5
  295. package/dist/services/runtime-settings-context.d.ts +73 -0
  296. package/dist/services/runtime-settings-context.js +69 -0
  297. package/dist/skills/executor.js +2 -0
  298. package/dist/skills/hub.js +16 -14
  299. package/dist/skills/local-inventory.d.ts +21 -0
  300. package/dist/skills/local-inventory.js +72 -0
  301. package/dist/skills/skill-loader.js +2 -2
  302. package/dist/skills/skill-usage-store.d.ts +49 -0
  303. package/dist/skills/skill-usage-store.js +121 -0
  304. package/dist/testing/ai-integration-tests.js +8 -5
  305. package/dist/themes/theme-manager.d.ts +12 -0
  306. package/dist/themes/theme-manager.js +29 -0
  307. package/dist/themes/theme-schema.d.ts +24 -24
  308. package/dist/tools/a2a-call-tool.d.ts +34 -0
  309. package/dist/tools/a2a-call-tool.js +75 -0
  310. package/dist/tools/bash/streaming-executor.d.ts +1 -0
  311. package/dist/tools/bash/streaming-executor.js +78 -90
  312. package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
  313. package/dist/tools/code-exec-preflight-runner.js +254 -0
  314. package/dist/tools/code-exec-preflight.d.ts +44 -0
  315. package/dist/tools/code-exec-preflight.js +501 -0
  316. package/dist/tools/code-exec-tool.d.ts +48 -1
  317. package/dist/tools/code-exec-tool.js +191 -47
  318. package/dist/tools/comment-watcher.js +29 -12
  319. package/dist/tools/core-code-inspection.d.ts +56 -0
  320. package/dist/tools/core-code-inspection.js +86 -0
  321. package/dist/tools/create-skill-tool.d.ts +2 -3
  322. package/dist/tools/create-skill-tool.js +16 -75
  323. package/dist/tools/cronjob-tool.d.ts +1 -0
  324. package/dist/tools/cronjob-tool.js +1 -0
  325. package/dist/tools/env-doctor-tool.d.ts +2 -0
  326. package/dist/tools/env-doctor-tool.js +4 -3
  327. package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
  328. package/dist/tools/execute-code-rpc-invoker.js +35 -19
  329. package/dist/tools/execute-code-runner.d.ts +2 -0
  330. package/dist/tools/execute-code-runner.js +52 -17
  331. package/dist/tools/fleet-room-tool.d.ts +104 -0
  332. package/dist/tools/fleet-room-tool.js +124 -0
  333. package/dist/tools/integration-tool-hints.d.ts +4 -0
  334. package/dist/tools/integration-tool-hints.js +19 -0
  335. package/dist/tools/list-peers-tool.d.ts +3 -0
  336. package/dist/tools/list-peers-tool.js +11 -4
  337. package/dist/tools/media-generation-tool.d.ts +16 -1
  338. package/dist/tools/media-generation-tool.js +341 -9
  339. package/dist/tools/merge-conflict-tool.js +53 -25
  340. package/dist/tools/metadata.d.ts +1 -5
  341. package/dist/tools/metadata.js +21 -28
  342. package/dist/tools/ragchat-tool.d.ts +39 -0
  343. package/dist/tools/ragchat-tool.js +105 -0
  344. package/dist/tools/registry/fleet-tools.d.ts +9 -0
  345. package/dist/tools/registry/fleet-tools.js +22 -1
  346. package/dist/tools/registry/knowledge-tools.d.ts +2 -2
  347. package/dist/tools/registry/knowledge-tools.js +2 -2
  348. package/dist/tools/registry/lessons-tools.d.ts +7 -0
  349. package/dist/tools/registry/lessons-tools.js +43 -3
  350. package/dist/tools/registry/memory-tools.d.ts +1 -1
  351. package/dist/tools/registry/memory-tools.js +8 -8
  352. package/dist/tools/registry/research-tools.d.ts +1 -0
  353. package/dist/tools/registry/research-tools.js +4 -13
  354. package/dist/tools/registry/self-describe-tools.d.ts +1 -1
  355. package/dist/tools/registry/self-describe-tools.js +43 -30
  356. package/dist/tools/resource-catalog-tool.d.ts +38 -0
  357. package/dist/tools/resource-catalog-tool.js +46 -0
  358. package/dist/tools/skills-inspection-tool.js +30 -1
  359. package/dist/tools/stream-tool-output.d.ts +3 -0
  360. package/dist/tools/stream-tool-output.js +33 -0
  361. package/dist/tools/tool-call-scheduler.d.ts +10 -0
  362. package/dist/tools/tool-call-scheduler.js +58 -0
  363. package/dist/tools/tool-effect.d.ts +5 -0
  364. package/dist/tools/tool-effect.js +26 -0
  365. package/dist/tools/tool-search.d.ts +12 -11
  366. package/dist/tools/tool-search.js +67 -26
  367. package/dist/tools/types.d.ts +6 -0
  368. package/dist/ui/components/ChatHistory.d.ts +1 -1
  369. package/dist/ui/components/ChatHistory.js +2 -2
  370. package/dist/ui/components/ChatInput.d.ts +2 -1
  371. package/dist/ui/components/ChatInput.js +42 -88
  372. package/dist/ui/components/ChatInterface.d.ts +4 -2
  373. package/dist/ui/components/ChatInterface.js +27 -63
  374. package/dist/ui/components/CommandSuggestions.d.ts +0 -1
  375. package/dist/ui/components/CommandSuggestions.js +4 -6
  376. package/dist/ui/components/FileAutocomplete.js +1 -1
  377. package/dist/ui/components/KeyboardHelp.js +8 -6
  378. package/dist/ui/components/ModelSelection.js +6 -5
  379. package/dist/ui/components/StatusBar.d.ts +2 -1
  380. package/dist/ui/components/StatusBar.js +8 -7
  381. package/dist/ui/context/theme-context.js +3 -2
  382. package/dist/ui/index.d.ts +1 -1
  383. package/dist/ui/index.js +1 -1
  384. package/dist/ui/utils/markdown-renderer.js +4 -13
  385. package/dist/utils/atomic-write.d.ts +22 -0
  386. package/dist/utils/atomic-write.js +29 -0
  387. package/dist/utils/bounded-output.d.ts +16 -0
  388. package/dist/utils/bounded-output.js +63 -0
  389. package/dist/utils/device-store-file.d.ts +4 -0
  390. package/dist/utils/device-store-file.js +40 -0
  391. package/dist/utils/export-manager.d.ts +9 -0
  392. package/dist/utils/export-manager.js +19 -0
  393. package/dist/utils/first-use-hints.d.ts +25 -0
  394. package/dist/utils/first-use-hints.js +58 -0
  395. package/dist/utils/history-manager.js +1 -1
  396. package/dist/utils/update-notifier.js +16 -18
  397. package/dist/wizard/environment-detection.d.ts +5 -1
  398. package/dist/wizard/environment-detection.js +49 -7
  399. package/dist/wizard/onboarding.d.ts +5 -1
  400. package/dist/wizard/onboarding.js +90 -30
  401. package/dist/wizard/provider-onboarding.d.ts +2 -0
  402. package/dist/wizard/provider-onboarding.js +55 -17
  403. package/package.json +7 -3
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Fleet rooms — exclusive single-writer lock for one ledger directory.
3
+ *
4
+ * Two `buddy server` processes commonly share one HOME. Without a lock both
5
+ * would hand out the same `seq` and one compaction would erase the other's
6
+ * appends. The lock is a `writer.lock` file created with `O_CREAT|O_EXCL`
7
+ * holding `{ pid, hostname, token }`.
8
+ *
9
+ * Recovery is deliberately narrow: a lock is reclaimed only when it names THIS
10
+ * host and a pid that no longer exists (`ESRCH`). A live pid (even a reused
11
+ * one), another host, `EPERM` or an unreadable/corrupt lock file all fail
12
+ * closed with {@link RoomLockError}; the operator removes the file by hand.
13
+ *
14
+ * @module fleet/rooms/room-lock
15
+ */
16
+ import { randomBytes } from 'crypto';
17
+ import fs from 'fs';
18
+ import os from 'os';
19
+ import path from 'path';
20
+ const LOCK_FILE = 'writer.lock';
21
+ const RECOVERY_LOCK_FILE = 'writer.lock.recovery';
22
+ export class RoomLockError extends Error {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = 'RoomLockError';
26
+ }
27
+ }
28
+ function readLock(lockPath) {
29
+ try {
30
+ const parsed = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
31
+ if (parsed.version === 1 && Number.isSafeInteger(parsed.pid) && parsed.pid > 0 &&
32
+ typeof parsed.hostname === 'string' && typeof parsed.token === 'string') {
33
+ return parsed;
34
+ }
35
+ }
36
+ catch {
37
+ // unreadable or corrupt: caller fails closed
38
+ }
39
+ return undefined;
40
+ }
41
+ function pidIsGone(pid) {
42
+ try {
43
+ process.kill(pid, 0);
44
+ return false;
45
+ }
46
+ catch (error) {
47
+ return error.code === 'ESRCH';
48
+ }
49
+ }
50
+ export class RoomDirectoryLock {
51
+ lockPath;
52
+ recoveryLockPath;
53
+ token = randomBytes(16).toString('hex');
54
+ released = false;
55
+ constructor(directory) {
56
+ this.lockPath = path.join(directory, LOCK_FILE);
57
+ this.recoveryLockPath = path.join(directory, RECOVERY_LOCK_FILE);
58
+ }
59
+ /** Acquire the lock or throw {@link RoomLockError}. */
60
+ static acquire(directory) {
61
+ const lock = new RoomDirectoryLock(directory);
62
+ if (fs.existsSync(lock.recoveryLockPath)) {
63
+ throw new RoomLockError(`room ledger recovery lock ${lock.recoveryLockPath} remains; refusing automatic recovery (remove it manually only if no server uses this directory)`);
64
+ }
65
+ if (lock.tryCreate())
66
+ return lock;
67
+ if (!lock.tryCreateRecoveryMutex()) {
68
+ throw new RoomLockError(`room ledger recovery lock ${lock.recoveryLockPath} is already held; refusing concurrent recovery`);
69
+ }
70
+ try {
71
+ // Re-read only after winning the recovery mutex. Another contender may
72
+ // have replaced the stale writer between our first O_EXCL failure and
73
+ // this point; that replacement must never be renamed.
74
+ const holder = readLock(lock.lockPath);
75
+ if (!holder) {
76
+ throw new RoomLockError(`room ledger lock ${lock.lockPath} is unreadable; refusing to share the ledger (remove it only if no server uses this directory)`);
77
+ }
78
+ if (holder.hostname !== os.hostname() || holder.pid === process.pid || !pidIsGone(holder.pid)) {
79
+ throw new RoomLockError(`room ledger ${directory} is already owned by pid ${holder.pid} on ${holder.hostname}`);
80
+ }
81
+ const stale = `${lock.lockPath}.stale-${holder.pid}-${Date.now()}`;
82
+ try {
83
+ fs.renameSync(lock.lockPath, stale);
84
+ }
85
+ catch (error) {
86
+ throw new RoomLockError(`could not reclaim stale room ledger lock: ${error.message}`);
87
+ }
88
+ if (!lock.tryCreate()) {
89
+ throw new RoomLockError(`room ledger ${directory} was claimed by another process during recovery`);
90
+ }
91
+ return lock;
92
+ }
93
+ finally {
94
+ lock.releaseRecoveryMutex();
95
+ }
96
+ }
97
+ tryCreateRecoveryMutex() {
98
+ let fd;
99
+ try {
100
+ fd = fs.openSync(this.recoveryLockPath, 'wx', 0o600);
101
+ }
102
+ catch (error) {
103
+ if (error.code === 'EEXIST')
104
+ return false;
105
+ throw new RoomLockError(`could not create room ledger recovery lock: ${error.message}`);
106
+ }
107
+ try {
108
+ fs.writeSync(fd, JSON.stringify({
109
+ version: 1,
110
+ pid: process.pid,
111
+ hostname: os.hostname(),
112
+ token: this.token,
113
+ acquiredAt: new Date().toISOString(),
114
+ }));
115
+ fs.fsyncSync(fd);
116
+ }
117
+ finally {
118
+ fs.closeSync(fd);
119
+ }
120
+ return true;
121
+ }
122
+ releaseRecoveryMutex() {
123
+ if (readLock(this.recoveryLockPath)?.token !== this.token)
124
+ return;
125
+ try {
126
+ fs.unlinkSync(this.recoveryLockPath);
127
+ }
128
+ catch {
129
+ // A residue deliberately fails future recovery closed and requires an
130
+ // operator to confirm that no server is active before removing it.
131
+ }
132
+ }
133
+ tryCreate() {
134
+ let fd;
135
+ try {
136
+ fd = fs.openSync(this.lockPath, 'wx', 0o600);
137
+ }
138
+ catch (error) {
139
+ if (error.code === 'EEXIST')
140
+ return false;
141
+ throw new RoomLockError(`could not create room ledger lock: ${error.message}`);
142
+ }
143
+ try {
144
+ const content = {
145
+ version: 1,
146
+ pid: process.pid,
147
+ hostname: os.hostname(),
148
+ token: this.token,
149
+ acquiredAt: new Date().toISOString(),
150
+ };
151
+ fs.writeSync(fd, JSON.stringify(content));
152
+ fs.fsyncSync(fd);
153
+ }
154
+ finally {
155
+ fs.closeSync(fd);
156
+ }
157
+ return true;
158
+ }
159
+ /** True while the lock file on disk still carries this holder's token. */
160
+ isHeld() {
161
+ if (this.released)
162
+ return false;
163
+ return readLock(this.lockPath)?.token === this.token;
164
+ }
165
+ /** Release once; never removes a lock that another holder now owns. */
166
+ release() {
167
+ if (this.released)
168
+ return;
169
+ this.released = true;
170
+ if (readLock(this.lockPath)?.token === this.token) {
171
+ try {
172
+ fs.unlinkSync(this.lockPath);
173
+ }
174
+ catch {
175
+ // already gone
176
+ }
177
+ }
178
+ }
179
+ }
180
+ //# sourceMappingURL=room-lock.js.map
@@ -0,0 +1,7 @@
1
+ import { type SensoryMissionBus } from '../sensory-mission-bridge.js';
2
+ import type { RoomHub } from './room-hub.js';
3
+ export declare const ROOM_OBSERVATION_PRINCIPAL = "local:fleet-room-observations";
4
+ export declare function startRoomObservations(hub: RoomHub, options?: {
5
+ env?: NodeJS.ProcessEnv;
6
+ bus?: SensoryMissionBus;
7
+ }): () => void;
@@ -0,0 +1,61 @@
1
+ /** Publishes local status snapshots through the same membership checks as peers. */
2
+ import { getGlobalEventBus } from '../../events/event-bus.js';
3
+ import { createMissionObservationRoomPublisher, wireSensoryMissionBridge, } from '../sensory-mission-bridge.js';
4
+ import { buildRoomAuth, buildRoomMessage, isValidRoomId, signRoomEvent } from './room-event.js';
5
+ import { loadRoomIdentity } from './room-identity.js';
6
+ export const ROOM_OBSERVATION_PRINCIPAL = 'local:fleet-room-observations';
7
+ export function startRoomObservations(hub, options = {}) {
8
+ const env = options.env ?? process.env;
9
+ if (env.CODEBUDDY_FLEET_ROOMS_OBSERVATIONS !== 'true')
10
+ return () => { };
11
+ const room = env.CODEBUDDY_FLEET_ROOMS_ROOM;
12
+ const missionId = env.CODEBUDDY_FLEET_ROOMS_MISSION;
13
+ if (typeof room !== 'string' || !isValidRoomId(room) || !missionId || !/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/.test(missionId)) {
14
+ throw new Error('Room observations require a valid CODEBUDDY_FLEET_ROOMS_ROOM and CODEBUDDY_FLEET_ROOMS_MISSION');
15
+ }
16
+ const identity = loadRoomIdentity(env.CODEBUDDY_FLEET_ROOMS_IDENTITY);
17
+ const audience = hub.audiences[0];
18
+ if (!audience)
19
+ throw new Error('Room observations require a configured hub audience');
20
+ const session = hub.open({
21
+ connectionId: ROOM_OBSERVATION_PRINCIPAL,
22
+ principalId: ROOM_OBSERVATION_PRINCIPAL,
23
+ send: () => false,
24
+ isBackpressured: () => false,
25
+ });
26
+ try {
27
+ const challenge = session.hello();
28
+ const auth = session.authenticate(signRoomEvent(buildRoomAuth(challenge.challenge, audience, Math.floor(hub.now() / 1000)), identity.secretKey));
29
+ if (!auth.ok || !hub.access.canWrite(identity.publicKey, room)) {
30
+ throw new Error('Room observation identity is not allowed to publish to the configured room');
31
+ }
32
+ const stop = wireSensoryMissionBridge({
33
+ enabled: true,
34
+ missionId,
35
+ bus: options.bus ?? getGlobalEventBus(),
36
+ now: hub.now,
37
+ ...(env.CODEBUDDY_FLEET_ROOMS_OBSERVATION_INTERVAL_MS !== undefined
38
+ ? { intervalMs: Number(env.CODEBUDDY_FLEET_ROOMS_OBSERVATION_INTERVAL_MS) }
39
+ : {}),
40
+ publish: createMissionObservationRoomPublisher(room, async (target, content, createdAt, signal) => {
41
+ signal.throwIfAborted();
42
+ const result = session.publish(signRoomEvent(buildRoomMessage({ room: target, content, createdAt }, identity.publicKey), identity.secretKey));
43
+ if (!result.accepted)
44
+ throw new Error(result.message);
45
+ }),
46
+ });
47
+ let stopped = false;
48
+ return () => {
49
+ if (stopped)
50
+ return;
51
+ stopped = true;
52
+ stop();
53
+ session.dispose();
54
+ };
55
+ }
56
+ catch (error) {
57
+ session.dispose();
58
+ throw error;
59
+ }
60
+ }
61
+ //# sourceMappingURL=room-observations.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Fleet rooms — opt-in startup for `buddy server`.
3
+ *
4
+ * `CODEBUDDY_FLEET_ROOMS=true` opens the ledger (exclusive lock), loads the room
5
+ * policy and registers the `fleet.rooms.*` WebSocket messages. Unset, nothing is
6
+ * opened or registered: `/ws` answers `UNKNOWN_TYPE` exactly as before.
7
+ *
8
+ * Accepted auth audiences: the loopback URLs of the listening port, plus the
9
+ * canonical URLs listed in `CODEBUDDY_FLEET_ROOMS_AUDIENCE` (csv) — the address
10
+ * remote members dial (e.g. `ws://codebuddy-hub.example:3000/ws`). A hub never accepts
11
+ * a proof addressed to a URL it was not told is its own.
12
+ *
13
+ * @module fleet/rooms/room-server
14
+ */
15
+ import { RoomHub } from './room-hub.js';
16
+ import { RoomStore } from './room-store.js';
17
+ export interface FleetRoomsHandle {
18
+ readonly hub: RoomHub;
19
+ readonly store: RoomStore;
20
+ readonly audiences: readonly string[];
21
+ stop(): void;
22
+ }
23
+ export declare function fleetRoomsEnabled(env?: NodeJS.ProcessEnv): boolean;
24
+ export declare function resolveFleetRoomsAudiences(port: number, env?: NodeJS.ProcessEnv): string[];
25
+ export declare function startFleetRooms(options: {
26
+ port: number;
27
+ env?: NodeJS.ProcessEnv;
28
+ }): FleetRoomsHandle;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Fleet rooms — opt-in startup for `buddy server`.
3
+ *
4
+ * `CODEBUDDY_FLEET_ROOMS=true` opens the ledger (exclusive lock), loads the room
5
+ * policy and registers the `fleet.rooms.*` WebSocket messages. Unset, nothing is
6
+ * opened or registered: `/ws` answers `UNKNOWN_TYPE` exactly as before.
7
+ *
8
+ * Accepted auth audiences: the loopback URLs of the listening port, plus the
9
+ * canonical URLs listed in `CODEBUDDY_FLEET_ROOMS_AUDIENCE` (csv) — the address
10
+ * remote members dial (e.g. `ws://codebuddy-hub.example:3000/ws`). A hub never accepts
11
+ * a proof addressed to a URL it was not told is its own.
12
+ *
13
+ * @module fleet/rooms/room-server
14
+ */
15
+ import { logger } from '../../utils/logger.js';
16
+ import { RoomAccessPolicy } from './room-access.js';
17
+ import { canonicalRoomAudience } from './room-event.js';
18
+ import { RoomHub } from './room-hub.js';
19
+ import { startRoomObservations } from './room-observations.js';
20
+ import { RoomStore } from './room-store.js';
21
+ import { wireFleetRoomsBridge } from './room-ws-bridge.js';
22
+ export function fleetRoomsEnabled(env = process.env) {
23
+ return env.CODEBUDDY_FLEET_ROOMS === 'true';
24
+ }
25
+ export function resolveFleetRoomsAudiences(port, env = process.env) {
26
+ if (!Number.isSafeInteger(port) || port <= 0 || port > 65_535) {
27
+ throw new RangeError('port must be an integer between 1 and 65535');
28
+ }
29
+ const audiences = [`ws://127.0.0.1:${port}/ws`, `ws://localhost:${port}/ws`, `ws://[::1]:${port}/ws`];
30
+ for (const entry of (env.CODEBUDDY_FLEET_ROOMS_AUDIENCE ?? '').split(',')) {
31
+ const trimmed = entry.trim();
32
+ if (trimmed)
33
+ audiences.push(canonicalRoomAudience(trimmed));
34
+ }
35
+ return [...new Set(audiences.map((audience) => canonicalRoomAudience(audience)))];
36
+ }
37
+ export function startFleetRooms(options) {
38
+ const env = options.env ?? process.env;
39
+ const audiences = resolveFleetRoomsAudiences(options.port, env);
40
+ const store = new RoomStore({ directory: env.CODEBUDDY_FLEET_ROOMS_DIR });
41
+ let unwire;
42
+ let stopObservations;
43
+ let hub;
44
+ try {
45
+ hub = new RoomHub({ store, access: new RoomAccessPolicy({ path: env.CODEBUDDY_FLEET_ROOMS_CONFIG }), audiences });
46
+ unwire = wireFleetRoomsBridge(hub);
47
+ }
48
+ catch (error) {
49
+ store.close();
50
+ throw error;
51
+ }
52
+ try {
53
+ stopObservations = startRoomObservations(hub, { env });
54
+ }
55
+ catch {
56
+ logger.warn('[fleet-rooms] observations disabled: check the configured mission, identity and room permissions');
57
+ }
58
+ logger.info('[fleet-rooms] enabled on /ws', { storeId: store.storeId, audiences: audiences.length });
59
+ let stopped = false;
60
+ return {
61
+ hub,
62
+ store,
63
+ audiences,
64
+ stop: () => {
65
+ if (stopped)
66
+ return;
67
+ stopped = true;
68
+ stopObservations?.();
69
+ unwire?.();
70
+ hub.close();
71
+ store.close();
72
+ },
73
+ };
74
+ }
75
+ //# sourceMappingURL=room-server.js.map
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Fleet rooms — durable append-only message ledger.
3
+ *
4
+ * Buzz stores events in Postgres and replays by `created_at` (`since`), which
5
+ * trusts every author's clock (`crates/buzz-acp/src/relay.rs::channel_since`).
6
+ * A fleet mixes machines whose clocks drift, so the hub also stamps each
7
+ * accepted event with a strictly increasing `seq`: reconnection resumes from
8
+ * the last `seq` a member saw, and a message signed with a late clock cannot
9
+ * fall behind the cursor. `storeId` names the ledger generation so a cursor
10
+ * from a wiped ledger is never trusted (same role as the cognition bus epoch).
11
+ *
12
+ * Guarantees, each covered by tests:
13
+ * - single writer: an exclusive directory lock ({@link RoomDirectoryLock}),
14
+ * re-checked with the ledger inode and size before every write or compaction;
15
+ * - durability: an append is `fsync`ed before `append()` returns, so the hub
16
+ * only acknowledges what survives a crash;
17
+ * - crash tail: bytes after the last newline (torn OR complete-but-unterminated)
18
+ * are copied to `ledger.jsonl.tail-*` and truncated BEFORE `seq` is reused;
19
+ * - strict order and integrity: every complete record must be valid, authentic
20
+ * and strictly increasing or the store fails closed;
21
+ * - compaction: eviction watermarks are persisted before the ledger rewrite,
22
+ * so a crash in between can only over-report a gap, never hide one;
23
+ * - duplicate detection: ids are remembered for the retained window only;
24
+ * - immutability: stored records are deep-frozen copies of the input.
25
+ *
26
+ * @module fleet/rooms/room-store
27
+ */
28
+ import { type ReadonlyRoomEvent } from './room-event.js';
29
+ import { type RoomFilter } from './room-filter.js';
30
+ export declare const DEFAULT_MAX_EVENTS_PER_ROOM = 2000;
31
+ export declare const DEFAULT_MAX_ROOMS = 1024;
32
+ export declare const DEFAULT_MAX_LEDGER_BYTES: number;
33
+ export interface RoomRecord {
34
+ readonly seq: number;
35
+ readonly receivedAt: number;
36
+ readonly event: ReadonlyRoomEvent;
37
+ }
38
+ export interface RoomStoreOptions {
39
+ /** Defaults to `$CODEBUDDY_FLEET_ROOMS_DIR` or `<CODEBUDDY_HOME>/fleet/rooms`. */
40
+ directory?: string;
41
+ maxEventsPerRoom?: number;
42
+ maxRooms?: number;
43
+ /** Refuse to load, and to grow, a ledger beyond this size. */
44
+ maxLedgerBytes?: number;
45
+ compactAfterEvictions?: number;
46
+ }
47
+ export type RoomAppendResult = {
48
+ status: 'stored';
49
+ record: RoomRecord;
50
+ } | {
51
+ status: 'duplicate';
52
+ record: RoomRecord;
53
+ };
54
+ export interface RoomQueryResult {
55
+ records: RoomRecord[];
56
+ /** Replay only: more matching records exist after the last one returned. */
57
+ truncated: boolean;
58
+ }
59
+ export declare class RoomStoreError extends Error {
60
+ readonly code: 'FULL' | 'CONFLICT' | 'CLOSED' | 'INVALID' | 'CORRUPT';
61
+ constructor(message: string, code: 'FULL' | 'CONFLICT' | 'CLOSED' | 'INVALID' | 'CORRUPT');
62
+ }
63
+ export declare function defaultRoomStoreDirectory(): string;
64
+ export declare class RoomStore {
65
+ readonly directory: string;
66
+ readonly storeId: string;
67
+ private readonly ledgerPath;
68
+ private readonly metaPath;
69
+ private readonly maxEventsPerRoom;
70
+ private readonly maxRooms;
71
+ private readonly maxLedgerBytes;
72
+ private readonly compactAfterEvictions;
73
+ private readonly lock;
74
+ private readonly byRoom;
75
+ private readonly byId;
76
+ private readonly evicted;
77
+ private fd;
78
+ private expectedSize;
79
+ private lastSeq;
80
+ private evictionsSinceCompaction;
81
+ private closed;
82
+ private failure;
83
+ constructor(options?: RoomStoreOptions);
84
+ get latestSeq(): number;
85
+ private readMeta;
86
+ private load;
87
+ /** Move the bytes after the last newline aside and cut them from the ledger. */
88
+ private quarantineTail;
89
+ private parseRecord;
90
+ private insert;
91
+ private assertWritable;
92
+ /** Stop at the first sign that another process touched the ledger. */
93
+ private assertExclusive;
94
+ get(id: string): RoomRecord | undefined;
95
+ /**
96
+ * Durably persist an authentic room message. Idempotency is guaranteed for
97
+ * ids still in the retained window; an evicted id may be stored again. The
98
+ * input is copied and the returned record is deep-frozen.
99
+ */
100
+ append(input: unknown, receivedAt?: number): RoomAppendResult;
101
+ /** Rewrite the ledger with retained records; watermarks are persisted first. */
102
+ compact(): void;
103
+ /**
104
+ * True when records of these rooms with `seq > afterSeq` were evicted, i.e.
105
+ * a replay from `afterSeq` cannot be complete.
106
+ */
107
+ hasGapAfter(rooms: readonly string[], afterSeq: number): boolean;
108
+ /**
109
+ * Replay (`afterSeq` set): every match after the cursor, oldest first, capped.
110
+ * History (no cursor): the newest `limit` matches of each filter, NIP-01
111
+ * style, returned oldest first.
112
+ */
113
+ query(filters: readonly RoomFilter[], options?: {
114
+ afterSeq?: number;
115
+ maxRecords?: number;
116
+ }): RoomQueryResult;
117
+ /** Close the append descriptor and release the directory lock. Idempotent. */
118
+ close(): void;
119
+ }