@tt-a1i/hive 1.7.0 → 2.0.2

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 (251) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.en.md +73 -11
  3. package/README.md +41 -8
  4. package/dist/src/cli/hive-remote.d.ts +46 -0
  5. package/dist/src/cli/hive-remote.js +257 -0
  6. package/dist/src/cli/hive-update.js +7 -2
  7. package/dist/src/cli/hive.d.ts +6 -0
  8. package/dist/src/cli/hive.js +64 -0
  9. package/dist/src/cli/team.d.ts +22 -0
  10. package/dist/src/cli/team.js +255 -5
  11. package/dist/src/server/agent-command-resolver.js +10 -3
  12. package/dist/src/server/agent-exit-classification.d.ts +6 -0
  13. package/dist/src/server/agent-exit-classification.js +6 -0
  14. package/dist/src/server/agent-manager-support.d.ts +2 -1
  15. package/dist/src/server/agent-manager-support.js +59 -15
  16. package/dist/src/server/agent-manager.d.ts +3 -0
  17. package/dist/src/server/agent-manager.js +22 -7
  18. package/dist/src/server/agent-run-bootstrap.d.ts +14 -0
  19. package/dist/src/server/agent-run-bootstrap.js +11 -4
  20. package/dist/src/server/agent-run-exit-handler.js +14 -8
  21. package/dist/src/server/agent-run-starter.d.ts +3 -1
  22. package/dist/src/server/agent-run-starter.js +22 -5
  23. package/dist/src/server/agent-run-sync.js +13 -5
  24. package/dist/src/server/agent-runtime-types.d.ts +1 -0
  25. package/dist/src/server/agent-runtime.d.ts +2 -1
  26. package/dist/src/server/agent-runtime.js +9 -2
  27. package/dist/src/server/agent-startup-instructions.d.ts +2 -1
  28. package/dist/src/server/agent-startup-instructions.js +8 -4
  29. package/dist/src/server/agent-stdin-dispatcher.d.ts +4 -2
  30. package/dist/src/server/agent-stdin-dispatcher.js +35 -3
  31. package/dist/src/server/command-preset-defaults.d.ts +6 -1
  32. package/dist/src/server/command-preset-defaults.js +56 -0
  33. package/dist/src/server/fs-browse.d.ts +2 -0
  34. package/dist/src/server/fs-browse.js +165 -31
  35. package/dist/src/server/fs-pick-folder.js +6 -69
  36. package/dist/src/server/fs-sandbox.d.ts +5 -3
  37. package/dist/src/server/fs-sandbox.js +5 -3
  38. package/dist/src/server/hive-team-guidance.js +18 -6
  39. package/dist/src/server/machine-name.d.ts +2 -0
  40. package/dist/src/server/machine-name.js +13 -0
  41. package/dist/src/server/open-target-commands.d.ts +1 -0
  42. package/dist/src/server/open-target-commands.js +4 -1
  43. package/dist/src/server/orchestrator-autostart.js +1 -1
  44. package/dist/src/server/platform-path.d.ts +1 -0
  45. package/dist/src/server/platform-path.js +14 -1
  46. package/dist/src/server/post-start-input-writer.js +50 -13
  47. package/dist/src/server/preset-launch-support.js +1 -0
  48. package/dist/src/server/recovery-summary.d.ts +2 -1
  49. package/dist/src/server/recovery-summary.js +2 -1
  50. package/dist/src/server/remote-audit-store.d.ts +51 -0
  51. package/dist/src/server/remote-audit-store.js +108 -0
  52. package/dist/src/server/remote-config-keys.d.ts +17 -0
  53. package/dist/src/server/remote-config-keys.js +27 -0
  54. package/dist/src/server/remote-control-constants.d.ts +30 -0
  55. package/dist/src/server/remote-control-constants.js +29 -0
  56. package/dist/src/server/remote-device-session.d.ts +40 -0
  57. package/dist/src/server/remote-device-session.js +22 -0
  58. package/dist/src/server/remote-device-store.d.ts +36 -0
  59. package/dist/src/server/remote-device-store.js +67 -0
  60. package/dist/src/server/remote-frame-bridge.d.ts +102 -0
  61. package/dist/src/server/remote-frame-bridge.js +791 -0
  62. package/dist/src/server/remote-gateway-client.d.ts +14 -0
  63. package/dist/src/server/remote-gateway-client.js +36 -0
  64. package/dist/src/server/remote-loopback-auth.d.ts +6 -0
  65. package/dist/src/server/remote-loopback-auth.js +112 -0
  66. package/dist/src/server/remote-pairing-tunnel.d.ts +59 -0
  67. package/dist/src/server/remote-pairing-tunnel.js +146 -0
  68. package/dist/src/server/remote-pairing.d.ts +58 -0
  69. package/dist/src/server/remote-pairing.js +237 -0
  70. package/dist/src/server/remote-tunnel.d.ts +113 -0
  71. package/dist/src/server/remote-tunnel.js +514 -0
  72. package/dist/src/server/restart-policy-support.d.ts +4 -1
  73. package/dist/src/server/restart-policy-support.js +3 -1
  74. package/dist/src/server/restart-policy.d.ts +1 -1
  75. package/dist/src/server/restart-policy.js +19 -3
  76. package/dist/src/server/route-types.d.ts +1 -1
  77. package/dist/src/server/routes-dispatches.js +1 -1
  78. package/dist/src/server/routes-fs.js +3 -3
  79. package/dist/src/server/routes-marketplace.js +2 -2
  80. package/dist/src/server/routes-open-workspace.js +1 -1
  81. package/dist/src/server/routes-remote.d.ts +2 -0
  82. package/dist/src/server/routes-remote.js +166 -0
  83. package/dist/src/server/routes-runtime.js +6 -6
  84. package/dist/src/server/routes-settings.js +16 -16
  85. package/dist/src/server/routes-tasks.js +2 -2
  86. package/dist/src/server/routes-team-memory.d.ts +2 -0
  87. package/dist/src/server/routes-team-memory.js +154 -0
  88. package/dist/src/server/routes-team-recall.d.ts +2 -0
  89. package/dist/src/server/routes-team-recall.js +119 -0
  90. package/dist/src/server/routes-team.js +31 -9
  91. package/dist/src/server/routes-ui.js +11 -1
  92. package/dist/src/server/routes-workflow-schedules.js +3 -3
  93. package/dist/src/server/routes-workflows.js +5 -5
  94. package/dist/src/server/routes-workspace-memory-dreams.d.ts +2 -0
  95. package/dist/src/server/routes-workspace-memory-dreams.js +105 -0
  96. package/dist/src/server/routes-workspace-memory.d.ts +2 -0
  97. package/dist/src/server/routes-workspace-memory.js +215 -0
  98. package/dist/src/server/routes-workspaces.js +9 -9
  99. package/dist/src/server/routes.js +10 -0
  100. package/dist/src/server/runtime-database.d.ts +1 -0
  101. package/dist/src/server/runtime-database.js +27 -2
  102. package/dist/src/server/runtime-restart-policy.d.ts +3 -1
  103. package/dist/src/server/runtime-restart-policy.js +2 -1
  104. package/dist/src/server/runtime-store-contract.d.ts +37 -0
  105. package/dist/src/server/runtime-store-dream.d.ts +23 -0
  106. package/dist/src/server/runtime-store-dream.js +16 -0
  107. package/dist/src/server/runtime-store-helpers.d.ts +20 -0
  108. package/dist/src/server/runtime-store-helpers.js +81 -7
  109. package/dist/src/server/runtime-store-memory.d.ts +33 -0
  110. package/dist/src/server/runtime-store-memory.js +37 -0
  111. package/dist/src/server/runtime-store-remote.d.ts +5 -0
  112. package/dist/src/server/runtime-store-remote.js +45 -0
  113. package/dist/src/server/runtime-store-workflows.js +2 -0
  114. package/dist/src/server/runtime-store.js +14 -3
  115. package/dist/src/server/session-capture-claude.d.ts +1 -1
  116. package/dist/src/server/session-capture-claude.js +7 -4
  117. package/dist/src/server/session-capture-codex.js +4 -5
  118. package/dist/src/server/session-capture-gemini.js +4 -5
  119. package/dist/src/server/session-capture-opencode.d.ts +4 -4
  120. package/dist/src/server/session-capture-opencode.js +20 -12
  121. package/dist/src/server/session-capture-qwen.d.ts +5 -0
  122. package/dist/src/server/session-capture-qwen.js +104 -0
  123. package/dist/src/server/session-capture.d.ts +17 -0
  124. package/dist/src/server/session-capture.js +16 -0
  125. package/dist/src/server/sqlite-schema-v23.d.ts +2 -0
  126. package/dist/src/server/sqlite-schema-v23.js +43 -0
  127. package/dist/src/server/sqlite-schema-v24.d.ts +2 -0
  128. package/dist/src/server/sqlite-schema-v24.js +34 -0
  129. package/dist/src/server/sqlite-schema-v25.d.ts +2 -0
  130. package/dist/src/server/sqlite-schema-v25.js +127 -0
  131. package/dist/src/server/sqlite-schema-v26.d.ts +2 -0
  132. package/dist/src/server/sqlite-schema-v26.js +56 -0
  133. package/dist/src/server/sqlite-schema-v27.d.ts +6 -0
  134. package/dist/src/server/sqlite-schema-v27.js +92 -0
  135. package/dist/src/server/sqlite-schema-v28.d.ts +2 -0
  136. package/dist/src/server/sqlite-schema-v28.js +19 -0
  137. package/dist/src/server/sqlite-schema-v29.d.ts +2 -0
  138. package/dist/src/server/sqlite-schema-v29.js +27 -0
  139. package/dist/src/server/sqlite-schema-v30.d.ts +2 -0
  140. package/dist/src/server/sqlite-schema-v30.js +27 -0
  141. package/dist/src/server/sqlite-schema-v31.d.ts +2 -0
  142. package/dist/src/server/sqlite-schema-v31.js +30 -0
  143. package/dist/src/server/sqlite-schema.d.ts +1 -1
  144. package/dist/src/server/sqlite-schema.js +49 -1
  145. package/dist/src/server/startup-command-parser.js +5 -1
  146. package/dist/src/server/tasks-file-watcher.d.ts +2 -0
  147. package/dist/src/server/tasks-file-watcher.js +15 -6
  148. package/dist/src/server/tasks-file.js +30 -5
  149. package/dist/src/server/tasks-websocket-server.js +4 -0
  150. package/dist/src/server/team-authz.d.ts +1 -1
  151. package/dist/src/server/team-authz.js +13 -1
  152. package/dist/src/server/team-list-enrichment.js +3 -1
  153. package/dist/src/server/team-memory-digest.d.ts +52 -0
  154. package/dist/src/server/team-memory-digest.js +200 -0
  155. package/dist/src/server/team-memory-dream-applier.d.ts +5 -0
  156. package/dist/src/server/team-memory-dream-applier.js +234 -0
  157. package/dist/src/server/team-memory-dream-http-serializers.d.ts +13 -0
  158. package/dist/src/server/team-memory-dream-http-serializers.js +12 -0
  159. package/dist/src/server/team-memory-dream-ops.d.ts +40 -0
  160. package/dist/src/server/team-memory-dream-ops.js +153 -0
  161. package/dist/src/server/team-memory-dream-reverter.d.ts +22 -0
  162. package/dist/src/server/team-memory-dream-reverter.js +221 -0
  163. package/dist/src/server/team-memory-dream-run-store.d.ts +23 -0
  164. package/dist/src/server/team-memory-dream-run-store.js +211 -0
  165. package/dist/src/server/team-memory-dream-runner.d.ts +37 -0
  166. package/dist/src/server/team-memory-dream-runner.js +178 -0
  167. package/dist/src/server/team-memory-dream-scheduler.d.ts +32 -0
  168. package/dist/src/server/team-memory-dream-scheduler.js +115 -0
  169. package/dist/src/server/team-memory-dream-store.d.ts +19 -0
  170. package/dist/src/server/team-memory-dream-store.js +16 -0
  171. package/dist/src/server/team-memory-dream-types.d.ts +104 -0
  172. package/dist/src/server/team-memory-dream-types.js +23 -0
  173. package/dist/src/server/team-memory-export.d.ts +22 -0
  174. package/dist/src/server/team-memory-export.js +220 -0
  175. package/dist/src/server/team-memory-feature.d.ts +12 -0
  176. package/dist/src/server/team-memory-feature.js +12 -0
  177. package/dist/src/server/team-memory-http-serializers.d.ts +102 -0
  178. package/dist/src/server/team-memory-http-serializers.js +46 -0
  179. package/dist/src/server/team-memory-injection.d.ts +31 -0
  180. package/dist/src/server/team-memory-injection.js +49 -0
  181. package/dist/src/server/team-memory-store.d.ts +116 -0
  182. package/dist/src/server/team-memory-store.js +513 -0
  183. package/dist/src/server/team-operations.d.ts +5 -1
  184. package/dist/src/server/team-operations.js +46 -16
  185. package/dist/src/server/team-recall-store.d.ts +38 -0
  186. package/dist/src/server/team-recall-store.js +205 -0
  187. package/dist/src/server/terminal-input-profile.d.ts +1 -1
  188. package/dist/src/server/terminal-input-profile.js +18 -0
  189. package/dist/src/server/terminal-ws-server.js +6 -0
  190. package/dist/src/server/ui-auth-helpers.d.ts +1 -1
  191. package/dist/src/server/ui-auth-helpers.js +7 -1
  192. package/dist/src/server/ui-auth.d.ts +3 -0
  193. package/dist/src/server/ui-auth.js +21 -1
  194. package/dist/src/server/workflow-cli-policy.d.ts +2 -3
  195. package/dist/src/server/workflow-cli-policy.js +3 -3
  196. package/dist/src/server/workflow-runner.d.ts +1 -0
  197. package/dist/src/server/workflow-runner.js +9 -4
  198. package/dist/src/server/workspace-path-validation.js +6 -2
  199. package/dist/src/server/workspace-store.d.ts +1 -1
  200. package/dist/src/server/workspace-store.js +35 -9
  201. package/dist/src/shared/fs-browse.d.ts +1 -0
  202. package/dist/src/shared/fs-browse.js +1 -0
  203. package/dist/src/shared/path-input.d.ts +12 -0
  204. package/dist/src/shared/path-input.js +22 -0
  205. package/dist/src/shared/remote-bridge-routing.d.ts +19 -0
  206. package/dist/src/shared/remote-bridge-routing.js +141 -0
  207. package/dist/src/shared/remote-crypto.d.ts +138 -0
  208. package/dist/src/shared/remote-crypto.js +427 -0
  209. package/dist/src/shared/remote-pairing-code.d.ts +7 -0
  210. package/dist/src/shared/remote-pairing-code.js +47 -0
  211. package/dist/src/shared/remote-protocol.d.ts +160 -0
  212. package/dist/src/shared/remote-protocol.js +526 -0
  213. package/dist/src/shared/team-memory.d.ts +11 -0
  214. package/dist/src/shared/team-memory.js +10 -0
  215. package/dist/src/shared/team-recall.d.ts +1 -0
  216. package/dist/src/shared/team-recall.js +1 -0
  217. package/dist/src/shared/types.d.ts +4 -5
  218. package/package.json +12 -5
  219. package/scripts/postinstall-native-artifacts.mjs +113 -0
  220. package/web/dist/assets/AddWorkerDialog-CbV75qUX.js +2 -0
  221. package/web/dist/assets/AddWorkspaceFlow-CwV-7wPx.js +1 -0
  222. package/web/dist/assets/FirstRunWizard-a6PWIK3x.js +1 -0
  223. package/web/dist/assets/MarketplaceDrawer-Dd8WIA8T.js +67 -0
  224. package/web/dist/assets/TaskGraphDrawer-Bk5WFIk_.js +1 -0
  225. package/web/dist/assets/{WhatsNewDialog-CHkZeINH.js → WhatsNewDialog-C2VZaip0.js} +1 -1
  226. package/web/dist/assets/WorkerModal-DucW-9YT.js +1 -0
  227. package/web/dist/assets/WorkflowsDrawer-Bjf4olbR.js +1 -0
  228. package/web/dist/assets/WorkspaceMemoryDrawer-DglCy_5f.js +1 -0
  229. package/web/dist/assets/WorkspaceTaskDrawer-BIWwISvA.js +1 -0
  230. package/web/dist/assets/index-BAiLYajK.css +1 -0
  231. package/web/dist/assets/index-BV2k9Dts.js +73 -0
  232. package/web/dist/assets/search-Bk2HQvO7.js +1 -0
  233. package/web/dist/assets/square-terminal-D93m9hfY.js +1 -0
  234. package/web/dist/cli-icons/agy.png +0 -0
  235. package/web/dist/cli-icons/cursor.ico +0 -0
  236. package/web/dist/cli-icons/grok.ico +0 -0
  237. package/web/dist/cli-icons/qwen.png +0 -0
  238. package/web/dist/index.html +8 -3
  239. package/web/dist/sw.js +1 -1
  240. package/scripts/fix-runtime-artifacts.mjs +0 -33
  241. package/web/dist/assets/AddWorkerDialog-BRUxpa3f.js +0 -2
  242. package/web/dist/assets/AddWorkspaceDialog-D56x5JCb.js +0 -1
  243. package/web/dist/assets/FirstRunWizard-BFVaMIsE.js +0 -1
  244. package/web/dist/assets/MarketplaceDrawer-DeEZ35dN.js +0 -76
  245. package/web/dist/assets/WorkerModal-BBCuMLIa.js +0 -1
  246. package/web/dist/assets/WorkspaceTaskDrawer-CpZHAcj1.js +0 -1
  247. package/web/dist/assets/WorkspaceTerminalPanels-7If2mDyp.js +0 -1
  248. package/web/dist/assets/WorkspaceTerminalPanels-DDGTF8rc.css +0 -1
  249. package/web/dist/assets/index-5zh61jMg.css +0 -1
  250. package/web/dist/assets/index-CxNL0O-C.js +0 -73
  251. package/web/dist/assets/path-join-7MR1s7b1.js +0 -1
@@ -21,11 +21,11 @@ const getSerializedWorker = (workspaceId, workerId, store) => {
21
21
  const getRuntimePort = (request) => String(request.socket.localPort ?? '');
22
22
  export const workspaceRoutes = [
23
23
  route('GET', '/api/workspaces', ({ request, response, store }) => {
24
- requireUiTokenFromRequest(request, store.validateUiToken);
24
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
25
25
  sendJson(response, 200, store.listWorkspaces());
26
26
  }),
27
27
  route('POST', '/api/workspaces', async ({ request, response, store }) => {
28
- requireUiTokenFromRequest(request, store.validateUiToken);
28
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
29
29
  const body = await readJsonBody(request);
30
30
  const startupCommand = typeof body.startup_command === 'string' ? body.startup_command : null;
31
31
  const workspacePath = validateWorkspacePath(body.path);
@@ -50,7 +50,7 @@ export const workspaceRoutes = [
50
50
  if (!workspaceId) {
51
51
  return;
52
52
  }
53
- requireUiTokenFromRequest(request, store.validateUiToken);
53
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
54
54
  await store.deleteWorkspace(workspaceId);
55
55
  response.statusCode = 204;
56
56
  response.end();
@@ -60,7 +60,7 @@ export const workspaceRoutes = [
60
60
  if (!workspaceId) {
61
61
  return;
62
62
  }
63
- requireUiTokenFromRequest(request, store.validateUiToken);
63
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
64
64
  sendJson(response, 200, enrichTeamList(workspaceId, store, store.listWorkers(workspaceId)).map(serializeTeamListItem));
65
65
  }),
66
66
  route('GET', '/api/workspaces/:workspaceId/team', ({ params, request, response, store }) => {
@@ -90,7 +90,7 @@ export const workspaceRoutes = [
90
90
  if (!workspaceId) {
91
91
  return;
92
92
  }
93
- requireUiTokenFromRequest(request, store.validateUiToken);
93
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
94
94
  const body = await readJsonBody(request);
95
95
  const presetId = body.command_preset_id ?? null;
96
96
  const startupCommand = typeof body.startup_command === 'string' ? body.startup_command : null;
@@ -128,7 +128,7 @@ export const workspaceRoutes = [
128
128
  if (!workspaceId || !workerId) {
129
129
  return;
130
130
  }
131
- requireUiTokenFromRequest(request, store.validateUiToken);
131
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
132
132
  store.deleteWorker(workspaceId, workerId);
133
133
  response.statusCode = 204;
134
134
  response.end();
@@ -139,7 +139,7 @@ export const workspaceRoutes = [
139
139
  if (!workspaceId || !workerId) {
140
140
  return;
141
141
  }
142
- requireUiTokenFromRequest(request, store.validateUiToken);
142
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
143
143
  const body = await readJsonBody(request);
144
144
  if (typeof body.name !== 'string') {
145
145
  sendJson(response, 400, { error: 'name is required' });
@@ -153,7 +153,7 @@ export const workspaceRoutes = [
153
153
  if (!workspaceId) {
154
154
  return;
155
155
  }
156
- requireUiTokenFromRequest(request, store.validateUiToken);
156
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
157
157
  const body = await readJsonBody(request);
158
158
  store.recordUserInput(workspaceId, `${workspaceId}:orchestrator`, body.text);
159
159
  sendJson(response, 202, { ok: true });
@@ -164,7 +164,7 @@ export const workspaceRoutes = [
164
164
  if (!workspaceId || !agentId) {
165
165
  return;
166
166
  }
167
- requireUiTokenFromRequest(request, store.validateUiToken);
167
+ requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
168
168
  if (agentId === getOrchestratorId(workspaceId) &&
169
169
  !store.peekAgentLaunchConfig(workspaceId, agentId)) {
170
170
  seedOrchestratorLaunchConfig(store, store.settings, workspaceId);
@@ -3,14 +3,19 @@ import { dispatchRoutes } from './routes-dispatches.js';
3
3
  import { fsRoutes } from './routes-fs.js';
4
4
  import { marketplaceRoutes } from './routes-marketplace.js';
5
5
  import { openWorkspaceRoutes } from './routes-open-workspace.js';
6
+ import { remoteRoutes } from './routes-remote.js';
6
7
  import { runtimeRoutes } from './routes-runtime.js';
7
8
  import { settingsRoutes } from './routes-settings.js';
8
9
  import { taskRoutes } from './routes-tasks.js';
9
10
  import { teamRoutes } from './routes-team.js';
11
+ import { teamMemoryRoutes } from './routes-team-memory.js';
12
+ import { teamRecallRoutes } from './routes-team-recall.js';
10
13
  import { uiRoutes } from './routes-ui.js';
11
14
  import { versionRoutes } from './routes-version.js';
12
15
  import { workflowScheduleRoutes } from './routes-workflow-schedules.js';
13
16
  import { workflowRoutes } from './routes-workflows.js';
17
+ import { workspaceMemoryRoutes } from './routes-workspace-memory.js';
18
+ import { workspaceMemoryDreamRoutes } from './routes-workspace-memory-dreams.js';
14
19
  import { workspaceRoutes } from './routes-workspaces.js';
15
20
  const routes = [
16
21
  ...workspaceRoutes,
@@ -20,12 +25,17 @@ const routes = [
20
25
  ...uiRoutes,
21
26
  ...settingsRoutes,
22
27
  ...taskRoutes,
28
+ ...workspaceMemoryDreamRoutes,
29
+ ...workspaceMemoryRoutes,
23
30
  ...runtimeRoutes,
31
+ ...teamRecallRoutes,
32
+ ...teamMemoryRoutes,
24
33
  ...teamRoutes,
25
34
  ...fsRoutes,
26
35
  ...marketplaceRoutes,
27
36
  ...workflowRoutes,
28
37
  ...workflowScheduleRoutes,
38
+ ...remoteRoutes,
29
39
  ];
30
40
  export const matchRoute = (method, pathname) => {
31
41
  for (const routeDefinition of routes) {
@@ -1,2 +1,3 @@
1
1
  import type { Database } from 'better-sqlite3';
2
+ export declare const formatRuntimeDataDirOpenMessage: (dataDir: string, error: unknown) => string;
2
3
  export declare const openRuntimeDatabase: (dataDir?: string) => Database;
@@ -2,15 +2,40 @@ import { mkdirSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import BetterSqlite3 from 'better-sqlite3';
4
4
  import { initializeRuntimeDatabase } from './sqlite-schema.js';
5
+ export const formatRuntimeDataDirOpenMessage = (dataDir, error) => {
6
+ const detail = error instanceof Error ? error.message : String(error);
7
+ return [
8
+ `Hive could not open its local data directory: ${dataDir}`,
9
+ detail,
10
+ '',
11
+ 'Choose a writable local folder and start Hive with HIVE_DATA_DIR set, for example:',
12
+ ' PowerShell: $env:HIVE_DATA_DIR="C:\\HiveData"; hive',
13
+ ' cmd.exe: set HIVE_DATA_DIR=C:\\HiveData && hive',
14
+ ].join('\n');
15
+ };
16
+ const createRuntimeDataDirOpenError = (dataDir, error) => new Error(formatRuntimeDataDirOpenMessage(dataDir, error), { cause: error });
17
+ const configureRuntimeDatabase = (database, input) => {
18
+ database.pragma('busy_timeout = 5000');
19
+ if (!input.persistent)
20
+ return;
21
+ database.pragma('journal_mode = WAL');
22
+ database.pragma('synchronous = NORMAL');
23
+ };
5
24
  export const openRuntimeDatabase = (dataDir) => {
6
25
  let database;
7
26
  if (dataDir) {
8
- mkdirSync(dataDir, { recursive: true });
9
- database = new BetterSqlite3(join(dataDir, 'runtime.sqlite'));
27
+ try {
28
+ mkdirSync(dataDir, { recursive: true });
29
+ database = new BetterSqlite3(join(dataDir, 'runtime.sqlite'));
30
+ }
31
+ catch (error) {
32
+ throw createRuntimeDataDirOpenError(dataDir, error);
33
+ }
10
34
  }
11
35
  else {
12
36
  database = new BetterSqlite3(':memory:');
13
37
  }
38
+ configureRuntimeDatabase(database, { persistent: Boolean(dataDir) });
14
39
  initializeRuntimeDatabase(database);
15
40
  return database;
16
41
  };
@@ -2,14 +2,16 @@ import type { AgentRunStorePort } from './agent-runtime-ports.js';
2
2
  import type { FeatureFlags } from './feature-flags.js';
3
3
  import type { MessageLogHandle, MessageLogRecord, RecoveryMessage } from './message-log-store.js';
4
4
  import type { TasksFileService } from './tasks-file.js';
5
+ import type { TeamMemoryInjectionService } from './team-memory-injection.js';
5
6
  import type { WorkspaceStore } from './workspace-store.js';
6
- export declare const buildRuntimeRestartPolicy: ({ agentRunStore, messageLogStore, tasksFileService, workspaceStore, getFlags, }: {
7
+ export declare const buildRuntimeRestartPolicy: ({ agentRunStore, messageLogStore, memoryInjection, tasksFileService, workspaceStore, getFlags, }: {
7
8
  agentRunStore: Pick<AgentRunStorePort, "listAgentRuns">;
8
9
  messageLogStore: {
9
10
  deleteMessage: (handle: MessageLogHandle) => void;
10
11
  insertMessage: (record: MessageLogRecord) => MessageLogHandle;
11
12
  listMessagesForRecovery: (workspaceId: string, sinceMs: number) => RecoveryMessage[];
12
13
  };
14
+ memoryInjection?: TeamMemoryInjectionService;
13
15
  tasksFileService: Pick<TasksFileService, "readTasks">;
14
16
  workspaceStore: Pick<WorkspaceStore, "getWorkspaceSnapshot">;
15
17
  getFlags?: () => FeatureFlags;
@@ -1,6 +1,6 @@
1
1
  import { createRestartPolicy } from './restart-policy.js';
2
2
  // Narrow helper keeps runtime-store under the hard line cap.
3
- export const buildRuntimeRestartPolicy = ({ agentRunStore, messageLogStore, tasksFileService, workspaceStore, getFlags, }) => createRestartPolicy({
3
+ export const buildRuntimeRestartPolicy = ({ agentRunStore, messageLogStore, memoryInjection, tasksFileService, workspaceStore, getFlags, }) => createRestartPolicy({
4
4
  deleteMessage: messageLogStore.deleteMessage,
5
5
  getWorkspaceSnapshot: workspaceStore.getWorkspaceSnapshot,
6
6
  insertMessage: messageLogStore.insertMessage,
@@ -8,4 +8,5 @@ export const buildRuntimeRestartPolicy = ({ agentRunStore, messageLogStore, task
8
8
  listMessagesForRecovery: messageLogStore.listMessagesForRecovery,
9
9
  readTasks: tasksFileService.readTasks,
10
10
  ...(getFlags ? { getFlags } : {}),
11
+ ...(memoryInjection ? { memoryInjection } : {}),
11
12
  });
@@ -1,3 +1,4 @@
1
+ import type { IncomingMessage } from 'node:http';
1
2
  import type { AgentSummary, TeamListItem, WorkspaceSummary } from '../shared/types.js';
2
3
  import type { AgentManager } from './agent-manager.js';
3
4
  import type { AgentLaunchConfigInput, PersistedAgentRun } from './agent-run-store.js';
@@ -5,8 +6,16 @@ import type { LiveAgentRun } from './agent-runtime-types.js';
5
6
  import type { DispatchRecord, ListDispatchesOptions } from './dispatch-ledger-store.js';
6
7
  import type { RecoveryMessage } from './message-log-store.js';
7
8
  import type { PtyOutputBus } from './pty-output-bus.js';
9
+ import type { RemoteAuditStore } from './remote-audit-store.js';
10
+ import type { DeviceSessionProvider } from './remote-device-session.js';
11
+ import type { RemoteDeviceRecord, RemoteDeviceStore } from './remote-device-store.js';
12
+ import type { RemotePairing } from './remote-pairing.js';
13
+ import type { RemoteTunnel, TunnelStatus } from './remote-tunnel.js';
8
14
  import type { SettingsStore } from './settings-store.js';
15
+ import type { DreamRunRecord } from './team-memory-dream-store.js';
16
+ import type { AddMemoryEntryInput, LogMemoryInjectionsInput, MemoryEntryWithSources, MemoryInjectionWithMemory, MemoryListOptions, MemorySearchOptions, MemorySearchResult } from './team-memory-store.js';
9
17
  import type { CancelTaskInput, DispatchTaskInput, ReportTaskInput, ReportTaskResult, StatusTaskInput } from './team-operations.js';
18
+ import type { RecallOptions, RecallResult } from './team-recall-store.js';
10
19
  import type { TerminalRunSummary } from './terminal-input-profile.js';
11
20
  import type { WorkflowDispatchAwaiter } from './workflow-dispatch-awaiter.js';
12
21
  import type { WorkflowRunRecord } from './workflow-run-store.js';
@@ -59,6 +68,22 @@ export interface RuntimeStore {
59
68
  registerTasksListener: (listener: (workspaceId: string, content: string) => void) => () => void;
60
69
  listAgentRuns: (agentId: string) => PersistedAgentRun[];
61
70
  listMessagesForRecovery: (workspaceId: string, sinceMs: number) => RecoveryMessage[];
71
+ recallMessages: (workspaceId: string, query: string, options?: RecallOptions) => RecallResult[];
72
+ addMemoryEntry: (input: AddMemoryEntryInput) => MemoryEntryWithSources;
73
+ approveMemoryCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
74
+ archiveMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
75
+ getMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
76
+ listMemoryEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
77
+ listMemoryInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
78
+ logMemoryInjections: (input: LogMemoryInjectionsInput) => string[];
79
+ rejectMemoryCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
80
+ searchMemoryEntries: (workspaceId: string, query: string, options?: MemorySearchOptions) => MemorySearchResult[];
81
+ setMemoryDisabled: (workspaceId: string, memoryId: string, disabled: boolean) => MemoryEntryWithSources;
82
+ setMemoryPinned: (workspaceId: string, memoryId: string, pinned: boolean) => MemoryEntryWithSources;
83
+ listMemoryDreamRuns: (workspaceId: string, limit?: number) => DreamRunRecord[];
84
+ revertMemoryDream: (workspaceId: string, runId: string) => DreamRunRecord;
85
+ runMemoryDream: (workspaceId: string) => Promise<DreamRunRecord>;
86
+ tickMemoryDreamScheduler: (now?: number) => Promise<void>;
62
87
  peekAgentToken: (agentId: string) => string | undefined;
63
88
  pauseTerminalRun: (runId: string) => void;
64
89
  resizeAgentRun: (runId: string, cols: number, rows: number) => void;
@@ -69,6 +94,18 @@ export interface RuntimeStore {
69
94
  stopAgentRun: (runId: string) => void;
70
95
  validateAgentToken: (agentId: string, token: string | undefined) => boolean;
71
96
  validateUiToken: (token: string | undefined) => boolean;
97
+ authorizeRemoteTunnelRequest: (request: IncomingMessage) => boolean;
98
+ getRemoteTunnelSecret: () => string;
99
+ getRemoteAuditStore: () => RemoteAuditStore;
100
+ getRemoteDeviceSessions: () => DeviceSessionProvider;
101
+ getRemotePairing: () => RemotePairing;
102
+ confirmRemotePairing: (pairingId: string, name?: string) => Promise<RemoteDeviceRecord | null>;
103
+ getRemoteDeviceStore: () => RemoteDeviceStore;
104
+ getRemoteTunnelStatus: () => TunnelStatus;
105
+ setRemoteTunnelStatus: (status: TunnelStatus) => void;
106
+ bindRemoteTunnel: (tunnel: RemoteTunnel) => void;
107
+ setRemoteEnabled: (enabled: boolean) => void;
108
+ revokeRemoteDevice: (deviceId: string) => boolean;
72
109
  getWorkflowDispatchAwaiter: () => WorkflowDispatchAwaiter;
73
110
  runWorkflow: (input: RunWorkflowInput) => Promise<WorkflowRunRecord>;
74
111
  startWorkflow: (input: RunWorkflowInput) => Promise<WorkflowRunRecord>;
@@ -0,0 +1,23 @@
1
+ import type { DreamRunRecord } from './team-memory-dream-store.js';
2
+ interface RuntimeStoreDreamServices {
3
+ teamMemoryDreamRunner: {
4
+ runManual: (workspaceId: string) => Promise<DreamRunRecord>;
5
+ };
6
+ teamMemoryDreamScheduler: {
7
+ tick: (now?: number) => Promise<void>;
8
+ };
9
+ teamMemoryDreamStore: {
10
+ listRuns: (workspaceId: string, limit?: number) => DreamRunRecord[];
11
+ revertRun: (workspaceId: string, runId: string) => DreamRunRecord;
12
+ };
13
+ teamMemoryExport: {
14
+ schedule: (workspaceId: string) => void;
15
+ };
16
+ }
17
+ export declare const createRuntimeStoreDreamMethods: (services: RuntimeStoreDreamServices) => {
18
+ listMemoryDreamRuns(workspaceId: string, limit?: number): DreamRunRecord[];
19
+ revertMemoryDream(workspaceId: string, runId: string): DreamRunRecord;
20
+ runMemoryDream(workspaceId: string): Promise<DreamRunRecord>;
21
+ tickMemoryDreamScheduler(now?: number): Promise<void>;
22
+ };
23
+ export {};
@@ -0,0 +1,16 @@
1
+ export const createRuntimeStoreDreamMethods = (services) => ({
2
+ listMemoryDreamRuns(workspaceId, limit) {
3
+ return services.teamMemoryDreamStore.listRuns(workspaceId, limit);
4
+ },
5
+ revertMemoryDream(workspaceId, runId) {
6
+ const run = services.teamMemoryDreamStore.revertRun(workspaceId, runId);
7
+ services.teamMemoryExport.schedule(workspaceId);
8
+ return run;
9
+ },
10
+ runMemoryDream(workspaceId) {
11
+ return services.teamMemoryDreamRunner.runManual(workspaceId);
12
+ },
13
+ tickMemoryDreamScheduler(now) {
14
+ return services.teamMemoryDreamScheduler.tick(now);
15
+ },
16
+ });
@@ -5,11 +5,21 @@ import type { LiveAgentRun } from './agent-runtime-types.js';
5
5
  import { createDispatchLedgerStore } from './dispatch-ledger-store.js';
6
6
  import { createMessageLogStore } from './message-log-store.js';
7
7
  import type { PtyOutputBus } from './pty-output-bus.js';
8
+ import { type RemoteAuditStore } from './remote-audit-store.js';
9
+ import type { DeviceSessionProvider } from './remote-device-session.js';
10
+ import { type RemoteDeviceStore } from './remote-device-store.js';
11
+ import { type RemotePairing } from './remote-pairing.js';
8
12
  import { openRuntimeDatabase } from './runtime-database.js';
9
13
  import { createSettingsStore } from './settings-store.js';
10
14
  import { createTasksFileService } from './tasks-file.js';
11
15
  import { createTasksFileWatcher } from './tasks-file-watcher.js';
16
+ import { createTeamMemoryDreamRunner } from './team-memory-dream-runner.js';
17
+ import { createTeamMemoryDreamScheduler } from './team-memory-dream-scheduler.js';
18
+ import { createTeamMemoryDreamStore } from './team-memory-dream-store.js';
19
+ import { createTeamMemoryExportService } from './team-memory-export.js';
20
+ import { createTeamMemoryStore } from './team-memory-store.js';
12
21
  import { createTeamOperations } from './team-operations.js';
22
+ import { createTeamRecallStore } from './team-recall-store.js';
13
23
  import { createUiAuth } from './ui-auth.js';
14
24
  import { createWebhookNotifier } from './webhook-notifier.js';
15
25
  import { type WorkerOutputTracker } from './worker-output-tracker.js';
@@ -25,11 +35,21 @@ export interface RuntimeStoreServices {
25
35
  db: ReturnType<typeof openRuntimeDatabase>;
26
36
  dispatchLedgerStore: ReturnType<typeof createDispatchLedgerStore>;
27
37
  messageLogStore: ReturnType<typeof createMessageLogStore>;
38
+ remoteAuditStore: RemoteAuditStore;
39
+ remoteDeviceSessions: DeviceSessionProvider;
40
+ remoteDeviceStore: RemoteDeviceStore;
41
+ remotePairing: RemotePairing;
28
42
  settings: ReturnType<typeof createSettingsStore>;
29
43
  shellRuntime: ReturnType<typeof createWorkspaceShellRuntime>;
30
44
  tasksFileWatcher: ReturnType<typeof createTasksFileWatcher>;
31
45
  tasksFileWatchCallbacks: Set<(workspaceId: string, content: string) => void>;
32
46
  tasksFileService: ReturnType<typeof createTasksFileService>;
47
+ teamMemoryDreamRunner: ReturnType<typeof createTeamMemoryDreamRunner>;
48
+ teamMemoryDreamScheduler: ReturnType<typeof createTeamMemoryDreamScheduler>;
49
+ teamMemoryDreamStore: ReturnType<typeof createTeamMemoryDreamStore>;
50
+ teamMemoryStore: ReturnType<typeof createTeamMemoryStore>;
51
+ teamMemoryExport: ReturnType<typeof createTeamMemoryExportService>;
52
+ teamRecallStore: ReturnType<typeof createTeamRecallStore>;
33
53
  teamOps: ReturnType<typeof createTeamOperations>;
34
54
  uiAuth: ReturnType<typeof createUiAuth>;
35
55
  webhookNotifier: ReturnType<typeof createWebhookNotifier>;
@@ -5,13 +5,24 @@ import { createDispatchLedgerStore } from './dispatch-ledger-store.js';
5
5
  import { readFeatureFlags } from './feature-flags.js';
6
6
  import { createMessageLogStore } from './message-log-store.js';
7
7
  import { seedOrchestratorLaunchConfig } from './orchestrator-launch.js';
8
+ import { createRemoteAuditStore } from './remote-audit-store.js';
9
+ import { REMOTE_DAEMON_ID_KEY, REMOTE_GATEWAY_URL_KEY } from './remote-config-keys.js';
10
+ import { createPersistentDeviceSessionProvider, createRemoteDeviceStore, } from './remote-device-store.js';
11
+ import { createRemotePairing } from './remote-pairing.js';
8
12
  import { createReportOutboxStore } from './report-outbox-store.js';
9
13
  import { openRuntimeDatabase } from './runtime-database.js';
10
14
  import { buildRuntimeRestartPolicy } from './runtime-restart-policy.js';
11
15
  import { createSettingsStore } from './settings-store.js';
12
16
  import { createTasksFileService } from './tasks-file.js';
13
17
  import { createTasksFileWatcher } from './tasks-file-watcher.js';
18
+ import { createWorkspaceMemoryDigestProvider } from './team-memory-digest.js';
19
+ import { createTeamMemoryDreamRunner, defaultDreamCliCommand, dreamCliCommandForLaunchCommand, } from './team-memory-dream-runner.js';
20
+ import { createTeamMemoryDreamScheduler } from './team-memory-dream-scheduler.js';
21
+ import { createTeamMemoryDreamStore } from './team-memory-dream-store.js';
22
+ import { createTeamMemoryExportService, MEMORY_EXPORT_DREAM_CHANGELOG_LIMIT, } from './team-memory-export.js';
23
+ import { createTeamMemoryStore } from './team-memory-store.js';
14
24
  import { createTeamOperations } from './team-operations.js';
25
+ import { createTeamRecallStore } from './team-recall-store.js';
15
26
  import { resolveTerminalInputProfile } from './terminal-input-profile.js';
16
27
  import { createUiAuth } from './ui-auth.js';
17
28
  import { createWebhookNotifier, WEBHOOK_URL_KEY } from './webhook-notifier.js';
@@ -36,6 +47,9 @@ export const createRuntimeStoreServices = (options = {}) => {
36
47
  const db = openRuntimeDatabase(options.dataDir);
37
48
  const messageLogStore = createMessageLogStore(db);
38
49
  const dispatchLedgerStore = createDispatchLedgerStore(db);
50
+ const teamMemoryStore = createTeamMemoryStore(db);
51
+ const teamMemoryDreamStore = createTeamMemoryDreamStore(db);
52
+ const teamRecallStore = createTeamRecallStore(db);
39
53
  const reportOutbox = createReportOutboxStore(db);
40
54
  const workflowDispatchAwaiter = createWorkflowDispatchAwaiter();
41
55
  const workflowRunStore = createWorkflowRunStore(db);
@@ -45,6 +59,16 @@ export const createRuntimeStoreServices = (options = {}) => {
45
59
  const agentSessionStore = createAgentSessionStore(db);
46
60
  const settings = createSettingsStore(db);
47
61
  const getFlags = () => readFeatureFlags(settings);
62
+ const memoryDigestProvider = createWorkspaceMemoryDigestProvider({
63
+ memoryStore: teamMemoryStore,
64
+ settings,
65
+ });
66
+ const memoryInjection = {
67
+ buildDigest: memoryDigestProvider.buildDigest,
68
+ buildDispatchDigest: memoryDigestProvider.buildDispatchDigest,
69
+ deleteInjections: teamMemoryStore.deleteInjections,
70
+ logInjections: teamMemoryStore.logInjections,
71
+ };
48
72
  const webhookNotifier = createWebhookNotifier({
49
73
  getUrl: () => settings.getAppState(WEBHOOK_URL_KEY)?.value ?? null,
50
74
  });
@@ -58,10 +82,27 @@ export const createRuntimeStoreServices = (options = {}) => {
58
82
  getFlags,
59
83
  });
60
84
  const uiAuth = createUiAuth();
85
+ const remoteAuditStore = createRemoteAuditStore(db);
86
+ // M4: the live runtime uses the PERSISTENT provider backed by the device store (M3's
87
+ // InMemoryDeviceSessionProvider stays test-only). A device row exists only after a desktop confirm,
88
+ // so this provider serves nothing until then; a revoke drops it from get()/candidates() at once.
89
+ const remoteDeviceStore = createRemoteDeviceStore(db);
90
+ const remoteDeviceSessions = createPersistentDeviceSessionProvider(remoteDeviceStore);
91
+ const remotePairing = createRemotePairing({
92
+ deviceStore: remoteDeviceStore,
93
+ audit: remoteAuditStore,
94
+ getGatewayUrl: () => settings.getAppState(REMOTE_GATEWAY_URL_KEY)?.value ?? null,
95
+ getDaemonId: () => settings.getAppState(REMOTE_DAEMON_ID_KEY)?.value ?? null,
96
+ });
61
97
  const shellRuntime = createWorkspaceShellRuntime(options.agentManager);
62
98
  agentRunStore.markUnfinishedRunsStale();
63
99
  workflowRunStore.markUnfinishedRunsInterrupted();
64
- const workspaceStore = createWorkspaceStore(db, dispatchLedgerStore.listOpenDispatchKinds());
100
+ const workspaceStore = createWorkspaceStore(db, dispatchLedgerStore.listOpenDispatchKinds);
101
+ const teamMemoryExport = createTeamMemoryExportService({
102
+ getWorkspacePath: (workspaceId) => workspaceStore.getWorkspaceSnapshot(workspaceId).summary.path,
103
+ listDreamRuns: (workspaceId) => teamMemoryDreamStore.listRuns(workspaceId, MEMORY_EXPORT_DREAM_CHANGELOG_LIMIT),
104
+ listEntries: teamMemoryStore.listExportEntries,
105
+ });
65
106
  const startExistingWorkspaceWatches = () => {
66
107
  for (const workspace of workspaceStore.listWorkspaces()) {
67
108
  void tasksFileWatcher
@@ -72,6 +113,7 @@ export const createRuntimeStoreServices = (options = {}) => {
72
113
  const restartPolicy = buildRuntimeRestartPolicy({
73
114
  agentRunStore,
74
115
  messageLogStore,
116
+ memoryInjection,
75
117
  tasksFileService,
76
118
  workspaceStore,
77
119
  getFlags,
@@ -121,20 +163,41 @@ export const createRuntimeStoreServices = (options = {}) => {
121
163
  for (const child of children)
122
164
  removeWorkerCompletely(workspaceId, child.id);
123
165
  }
124
- }, restartPolicy, (workspaceId, agentId) => workspaceStore.getAgent(workspaceId, agentId), getFlags);
125
- // Mirrors runtime-store.deleteWorker (stop run → drop launch config → drop
126
- // dispatches → drop worker row, transactionally). Hoisted `function` so the
166
+ }, restartPolicy, (workspaceId, agentId) => workspaceStore.getAgent(workspaceId, agentId), getFlags, memoryInjection);
167
+ const teamMemoryDreamRunner = createTeamMemoryDreamRunner({
168
+ dreamStore: teamMemoryDreamStore,
169
+ getDreamCliCommand: (workspaceId) => {
170
+ seedOrchestratorLaunchConfig(agentRuntime, settings, workspaceId);
171
+ const config = agentRuntime.peekAgentLaunchConfig(workspaceId, getOrchestratorId(workspaceId));
172
+ return config?.command
173
+ ? dreamCliCommandForLaunchCommand(config.command)
174
+ : defaultDreamCliCommand();
175
+ },
176
+ getWorkspacePath: (workspaceId) => workspaceStore.getWorkspaceSnapshot(workspaceId).summary.path,
177
+ memoryStore: teamMemoryStore,
178
+ scheduleExport: teamMemoryExport.schedule,
179
+ });
180
+ const teamMemoryDreamScheduler = createTeamMemoryDreamScheduler({
181
+ getScheduleState: teamMemoryDreamStore.getScheduleState,
182
+ getWorkspaceSnapshot: (workspaceId) => workspaceStore.getWorkspaceSnapshot(workspaceId),
183
+ listWorkspaces: workspaceStore.listWorkspaces,
184
+ runScheduled: teamMemoryDreamRunner.runScheduled,
185
+ settings,
186
+ });
187
+ teamMemoryDreamScheduler.start();
188
+ // Mirrors runtime-store.deleteWorker (drop dispatches + worker row
189
+ // transactionally → drop launch config → stop run). Hoisted `function` so the
127
190
  // onAgentExit closure above can reference it; only invoked at runtime, after
128
191
  // agentRuntime is assigned.
129
192
  function removeWorkerCompletely(workspaceId, workerId) {
130
193
  const activeRun = agentRuntime.getActiveRunByAgentId(workspaceId, workerId);
131
- if (activeRun)
132
- agentRuntime.stopAgentRun(activeRun.runId);
133
- agentRuntime.deleteAgentLaunchConfig(workspaceId, workerId);
134
194
  db.transaction(() => {
135
195
  dispatchLedgerStore.deleteWorkerDispatches(workspaceId, workerId);
136
196
  workspaceStore.deleteWorker(workspaceId, workerId);
137
197
  })();
198
+ agentRuntime.deleteAgentLaunchConfig(workspaceId, workerId);
199
+ if (activeRun)
200
+ agentRuntime.stopAgentRun(activeRun.runId);
138
201
  }
139
202
  // Boot cleanup: after a runtime restart every ephemeral worker is an orphan
140
203
  // (its spawner — a workflow run or an orchestrator PTY — is gone). Remove
@@ -173,11 +236,21 @@ export const createRuntimeStoreServices = (options = {}) => {
173
236
  db,
174
237
  dispatchLedgerStore,
175
238
  messageLogStore,
239
+ remoteAuditStore,
240
+ remoteDeviceSessions,
241
+ remoteDeviceStore,
242
+ remotePairing,
176
243
  settings,
177
244
  shellRuntime,
178
245
  tasksFileWatcher,
179
246
  tasksFileWatchCallbacks,
180
247
  tasksFileService,
248
+ teamMemoryDreamRunner,
249
+ teamMemoryDreamScheduler,
250
+ teamMemoryDreamStore,
251
+ teamMemoryExport,
252
+ teamMemoryStore,
253
+ teamRecallStore,
181
254
  teamOps,
182
255
  uiAuth,
183
256
  webhookNotifier,
@@ -248,6 +321,7 @@ export const createRuntimeStoreLifecycle = ({ agentManager, services, }) => {
248
321
  // instead of hanging on a Promise that can never resolve.
249
322
  services.workflowDispatchAwaiter.cancelAll('runtime closing');
250
323
  services.shellRuntime.close();
324
+ await services.teamMemoryExport.close();
251
325
  await services.agentRuntime.close();
252
326
  await services.tasksFileWatcher.close();
253
327
  services.workerOutputTracker?.closeAll();
@@ -0,0 +1,33 @@
1
+ import type { AddMemoryEntryInput, LogMemoryInjectionsInput, MemoryEntryWithSources, MemoryInjectionWithMemory, MemoryListOptions, MemorySearchOptions, MemorySearchResult } from './team-memory-store.js';
2
+ interface RuntimeStoreMemoryServices {
3
+ teamMemoryExport: {
4
+ schedule: (workspaceId: string) => void;
5
+ };
6
+ teamMemoryStore: {
7
+ addEntry: (input: AddMemoryEntryInput) => MemoryEntryWithSources;
8
+ approveCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
9
+ archiveEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
10
+ getEntryWithSources: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
11
+ listEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
12
+ listInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
13
+ logInjections: (input: LogMemoryInjectionsInput) => string[];
14
+ rejectCandidate: (workspaceId: string, memoryId: string) => MemoryEntryWithSources;
15
+ searchEntries: (workspaceId: string, query: string, options?: MemorySearchOptions) => MemorySearchResult[];
16
+ setDisabled: (workspaceId: string, memoryId: string, disabled: boolean) => MemoryEntryWithSources;
17
+ setPinned: (workspaceId: string, memoryId: string, pinned: boolean) => MemoryEntryWithSources;
18
+ };
19
+ }
20
+ export declare const createRuntimeStoreMemoryMethods: (services: RuntimeStoreMemoryServices) => {
21
+ addMemoryEntry(input: AddMemoryEntryInput): MemoryEntryWithSources;
22
+ approveMemoryCandidate(workspaceId: string, memoryId: string): MemoryEntryWithSources;
23
+ archiveMemoryEntry(workspaceId: string, memoryId: string): MemoryEntryWithSources;
24
+ getMemoryEntry: (workspaceId: string, memoryId: string) => MemoryEntryWithSources | undefined;
25
+ listMemoryEntries: (workspaceId: string, options?: MemoryListOptions) => MemoryEntryWithSources[];
26
+ listMemoryInjectionsForDispatch: (workspaceId: string, dispatchId: string) => MemoryInjectionWithMemory[];
27
+ logMemoryInjections: (input: LogMemoryInjectionsInput) => string[];
28
+ rejectMemoryCandidate(workspaceId: string, memoryId: string): MemoryEntryWithSources;
29
+ searchMemoryEntries: (workspaceId: string, query: string, options?: MemorySearchOptions) => MemorySearchResult[];
30
+ setMemoryDisabled(workspaceId: string, memoryId: string, disabled: boolean): MemoryEntryWithSources;
31
+ setMemoryPinned(workspaceId: string, memoryId: string, pinned: boolean): MemoryEntryWithSources;
32
+ };
33
+ export {};
@@ -0,0 +1,37 @@
1
+ export const createRuntimeStoreMemoryMethods = (services) => ({
2
+ addMemoryEntry(input) {
3
+ const memory = services.teamMemoryStore.addEntry(input);
4
+ services.teamMemoryExport.schedule(input.workspaceId);
5
+ return memory;
6
+ },
7
+ approveMemoryCandidate(workspaceId, memoryId) {
8
+ const memory = services.teamMemoryStore.approveCandidate(workspaceId, memoryId);
9
+ services.teamMemoryExport.schedule(workspaceId);
10
+ return memory;
11
+ },
12
+ archiveMemoryEntry(workspaceId, memoryId) {
13
+ const memory = services.teamMemoryStore.archiveEntry(workspaceId, memoryId);
14
+ services.teamMemoryExport.schedule(workspaceId);
15
+ return memory;
16
+ },
17
+ getMemoryEntry: (workspaceId, memoryId) => services.teamMemoryStore.getEntryWithSources(workspaceId, memoryId),
18
+ listMemoryEntries: (workspaceId, options) => services.teamMemoryStore.listEntries(workspaceId, options),
19
+ listMemoryInjectionsForDispatch: (workspaceId, dispatchId) => services.teamMemoryStore.listInjectionsForDispatch(workspaceId, dispatchId),
20
+ logMemoryInjections: (input) => services.teamMemoryStore.logInjections(input),
21
+ rejectMemoryCandidate(workspaceId, memoryId) {
22
+ const memory = services.teamMemoryStore.rejectCandidate(workspaceId, memoryId);
23
+ services.teamMemoryExport.schedule(workspaceId);
24
+ return memory;
25
+ },
26
+ searchMemoryEntries: (workspaceId, query, options) => services.teamMemoryStore.searchEntries(workspaceId, query, options),
27
+ setMemoryDisabled(workspaceId, memoryId, disabled) {
28
+ const memory = services.teamMemoryStore.setDisabled(workspaceId, memoryId, disabled);
29
+ services.teamMemoryExport.schedule(workspaceId);
30
+ return memory;
31
+ },
32
+ setMemoryPinned(workspaceId, memoryId, pinned) {
33
+ const memory = services.teamMemoryStore.setPinned(workspaceId, memoryId, pinned);
34
+ services.teamMemoryExport.schedule(workspaceId);
35
+ return memory;
36
+ },
37
+ });
@@ -0,0 +1,5 @@
1
+ import type { RuntimeStore } from './runtime-store-contract.js';
2
+ import type { RuntimeStoreServices } from './runtime-store-helpers.js';
3
+ type RuntimeStoreRemoteMethods = Pick<RuntimeStore, 'authorizeRemoteTunnelRequest' | 'bindRemoteTunnel' | 'confirmRemotePairing' | 'getRemoteAuditStore' | 'getRemoteDeviceSessions' | 'getRemoteDeviceStore' | 'getRemotePairing' | 'getRemoteTunnelSecret' | 'getRemoteTunnelStatus' | 'revokeRemoteDevice' | 'setRemoteEnabled' | 'setRemoteTunnelStatus'>;
4
+ export declare const createRuntimeStoreRemoteMethods: (services: RuntimeStoreServices) => RuntimeStoreRemoteMethods;
5
+ export {};
@@ -0,0 +1,45 @@
1
+ import { REMOTE_ENABLED_KEY } from './remote-config-keys.js';
2
+ export const createRuntimeStoreRemoteMethods = (services) => {
3
+ // Remote tunnel handle (M4). bindRemoteTunnel sets it in hive.ts after the tunnel is constructed;
4
+ // a runtime that never builds a tunnel leaves it null and the revoke closed loop still rejects new
5
+ // streams via the persistent provider.
6
+ let remoteTunnel = null;
7
+ let remoteTunnelStatus = 'disabled';
8
+ return {
9
+ authorizeRemoteTunnelRequest: (request) => services.uiAuth.isTunnelRequest(request),
10
+ getRemoteTunnelSecret: () => services.uiAuth.getTunnelSecret(),
11
+ getRemoteAuditStore: () => services.remoteAuditStore,
12
+ getRemoteDeviceSessions: () => services.remoteDeviceSessions,
13
+ getRemotePairing: () => services.remotePairing,
14
+ confirmRemotePairing: async (pairingId, name) => {
15
+ // D3: the tunnel driver owns the full confirm sequence (local row -> gateway /pair/confirm ->
16
+ // `confirmed` to the phone). If no tunnel is bound, fall back to local-only confirm.
17
+ if (remoteTunnel)
18
+ return remoteTunnel.confirmPairing(pairingId, name);
19
+ return services.remotePairing.confirmPairing(pairingId, name === undefined ? undefined : { name });
20
+ },
21
+ getRemoteDeviceStore: () => services.remoteDeviceStore,
22
+ getRemoteTunnelStatus: () => remoteTunnelStatus,
23
+ setRemoteTunnelStatus: (status) => {
24
+ remoteTunnelStatus = status;
25
+ },
26
+ bindRemoteTunnel: (tunnel) => {
27
+ remoteTunnel = tunnel;
28
+ },
29
+ setRemoteEnabled: (enabled) => {
30
+ services.settings.setAppState(REMOTE_ENABLED_KEY, enabled ? 'true' : 'false');
31
+ // Reconcile the outbound socket against the new flag. No-op when no tunnel is bound.
32
+ remoteTunnel?.refresh();
33
+ },
34
+ revokeRemoteDevice: (deviceId) => {
35
+ // (1) Persistent provider drops the session at once; (2) live streams are closed best-effort;
36
+ // (3) audit one revoke row for actual state changes.
37
+ const revoked = services.remoteDeviceStore.revoke(deviceId);
38
+ remoteTunnel?.closeDevice(deviceId, 'revoked');
39
+ if (revoked) {
40
+ services.remoteAuditStore.enqueue({ action: 'revoke', deviceId, result: 'ok' });
41
+ }
42
+ return revoked;
43
+ },
44
+ };
45
+ };