@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
@@ -1,11 +1,47 @@
1
1
  import { execFile, execFileSync } from 'node:child_process';
2
+ import { createRequire } from 'node:module';
3
+ import { classifyCompletedRunStatus } from './agent-exit-classification.js';
2
4
  export const MAX_RUN_OUTPUT_LENGTH = 1_000_000;
3
5
  const FORCE_KILL_DELAY_MS = 750;
4
6
  const TASKKILL_TIMEOUT_MS = 3000;
5
7
  const PTY_READ_EOF_EXIT_GRACE_MS = 1000;
6
- const isPtyReadEofError = (error) => {
8
+ const require = createRequire(import.meta.url);
9
+ const childProcess = require('node:child_process');
10
+ const isConptyConsoleListAgentPath = (modulePath) => {
11
+ const normalized = String(modulePath).replaceAll('\\', '/');
12
+ return (normalized.endsWith('/conpty_console_list_agent') ||
13
+ normalized.endsWith('/conpty_console_list_agent.js'));
14
+ };
15
+ export const withSilencedConptyConsoleListAgent = (platform, action) => {
16
+ if (platform !== 'win32')
17
+ return action();
18
+ const originalFork = childProcess.fork;
19
+ const patchedFork = (modulePath, argsOrOptions, options) => {
20
+ if (!isConptyConsoleListAgentPath(modulePath)) {
21
+ return Array.isArray(argsOrOptions)
22
+ ? originalFork.call(childProcess, modulePath, argsOrOptions, options)
23
+ : originalFork.call(childProcess, modulePath, argsOrOptions);
24
+ }
25
+ const forkOptions = Array.isArray(argsOrOptions) ? options : argsOrOptions;
26
+ const silentOptions = { ...(forkOptions ?? {}), silent: true };
27
+ const child = Array.isArray(argsOrOptions)
28
+ ? originalFork.call(childProcess, modulePath, argsOrOptions, silentOptions)
29
+ : originalFork.call(childProcess, modulePath, silentOptions);
30
+ child.stderr?.resume();
31
+ child.stdout?.resume();
32
+ return child;
33
+ };
34
+ childProcess.fork = patchedFork;
35
+ try {
36
+ return action();
37
+ }
38
+ finally {
39
+ childProcess.fork = originalFork;
40
+ }
41
+ };
42
+ const isPtyReadEofError = (error, platform = process.platform) => {
7
43
  const candidate = error;
8
- return process.platform !== 'win32' && candidate?.code === 'EIO' && candidate.syscall === 'read';
44
+ return platform !== 'win32' && candidate?.code === 'EIO' && candidate.syscall === 'read';
9
45
  };
10
46
  const serializePtyInput = (input) => Buffer.isBuffer(input) ? input.toString('latin1') : input;
11
47
  const defaultExecRunner = (cmd, args, done) => {
@@ -71,17 +107,21 @@ export const toAgentRunSnapshot = (run) => ({
71
107
  export const finishAgentRun = (run, exitCode, ptyOutputBus) => {
72
108
  if (run.status === 'exited' || run.status === 'error')
73
109
  return;
74
- run.status = exitCode === 0 ? 'exited' : 'error';
110
+ run.status = classifyCompletedRunStatus(exitCode);
75
111
  run.exitCode = exitCode;
76
- run.onExit?.({ runId: run.runId, exitCode });
77
- ptyOutputBus.clear(run.runId);
112
+ try {
113
+ run.onExit?.({ runId: run.runId, exitCode });
114
+ }
115
+ finally {
116
+ ptyOutputBus.clear(run.runId);
117
+ }
78
118
  };
79
- export const attachAgentPty = (run, pty, ptyOutputBus) => {
119
+ export const attachAgentPty = (run, pty, ptyOutputBus, platform = process.platform, execRunner = defaultExecRunner) => {
80
120
  let stdinClosed = false;
81
121
  let forceKillTimer;
82
122
  let ptyReadEofTimer;
83
123
  const resolveProcessGroupId = () => {
84
- if (process.platform === 'win32' || pty.pid <= 0)
124
+ if (platform === 'win32' || pty.pid <= 0)
85
125
  return null;
86
126
  try {
87
127
  const value = execFileSync('ps', ['-o', 'pgid=', '-p', String(pty.pid)], {
@@ -109,7 +149,7 @@ export const attachAgentPty = (run, pty, ptyOutputBus) => {
109
149
  throw error;
110
150
  };
111
151
  const killProcessGroup = (signal) => {
112
- if (process.platform === 'win32' || processGroupId === null)
152
+ if (platform === 'win32' || processGroupId === null)
113
153
  return;
114
154
  try {
115
155
  process.kill(-processGroupId, signal);
@@ -120,14 +160,17 @@ export const attachAgentPty = (run, pty, ptyOutputBus) => {
120
160
  };
121
161
  const killPtyDirect = (signal) => {
122
162
  try {
123
- pty.kill(signal);
163
+ if (platform === 'win32')
164
+ withSilencedConptyConsoleListAgent(platform, () => pty.kill());
165
+ else
166
+ pty.kill(signal);
124
167
  }
125
168
  catch (error) {
126
169
  ignoreMissingProcess(error);
127
170
  }
128
171
  };
129
172
  const killPty = (signal) => {
130
- if (process.platform === 'win32') {
173
+ if (platform === 'win32') {
131
174
  // taskkill /pid <pid> /t /f walks the parent's process tree
132
175
  // BEFORE terminating it — so we have to run it while the parent
133
176
  // is still alive. Calling pty.kill() first (the previous
@@ -136,7 +179,7 @@ export const attachAgentPty = (run, pty, ptyOutputBus) => {
136
179
  // become orphans. taskkill /f also terminates the parent, so
137
180
  // pty.kill() is the fallback for the rare case where taskkill
138
181
  // is missing from PATH or refused (e.g. restricted PowerShell).
139
- if (!taskkillProcessTree(pty.pid, process.platform, defaultExecRunner, () => killPtyDirect()))
182
+ if (!taskkillProcessTree(pty.pid, platform, execRunner, () => killPtyDirect()))
140
183
  killPtyDirect();
141
184
  }
142
185
  else
@@ -185,11 +228,12 @@ export const attachAgentPty = (run, pty, ptyOutputBus) => {
185
228
  forceKillTimer = setTimeout(() => {
186
229
  forceKillTimer = undefined;
187
230
  try {
188
- if (process.platform === 'win32') {
231
+ if (platform === 'win32') {
189
232
  // Same ordering as killPty(): tree-kill before terminating the
190
233
  // parent, so taskkill /T can still enumerate the process tree.
191
- // pty.kill() is the fallback for taskkill-missing hosts.
192
- if (!taskkillProcessTree(pty.pid, process.platform, defaultExecRunner, () => killPtyDirect()))
234
+ // pty.kill() is the cleanup fallback for taskkill-missing hosts;
235
+ // its noisy dependency helper is silenced in killPtyDirect().
236
+ if (!taskkillProcessTree(pty.pid, platform, execRunner, () => killPtyDirect()))
193
237
  killPtyDirect();
194
238
  }
195
239
  else
@@ -247,7 +291,7 @@ export const attachAgentPty = (run, pty, ptyOutputBus) => {
247
291
  pty.on?.('error', (error) => {
248
292
  if (stopped())
249
293
  return;
250
- if (isPtyReadEofError(error)) {
294
+ if (isPtyReadEofError(error, platform)) {
251
295
  // Unix PTYs can surface a closed slave as read/EIO just before
252
296
  // node-pty delivers the real onExit event. Treat it as EOF, not
253
297
  // as the run's terminal status.
@@ -1,3 +1,4 @@
1
+ import { type IWindowsPtyForkOptions } from 'node-pty';
1
2
  import { type PtyOutputBus } from './pty-output-bus.js';
2
3
  type RunStatus = 'starting' | 'running' | 'exited' | 'error';
3
4
  interface StartAgentInput {
@@ -45,6 +46,8 @@ interface AgentManager {
45
46
  removeRun: (runId: string) => void;
46
47
  stopRun: (runId: string) => void;
47
48
  }
49
+ export declare const createSpawnEnv: (inputEnv?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, parentEnv?: NodeJS.ProcessEnv) => NodeJS.ProcessEnv;
50
+ export declare const buildAgentPtySpawnOptions: (cwd: string, env: NodeJS.ProcessEnv, platform?: NodeJS.Platform) => IWindowsPtyForkOptions;
48
51
  export declare const createAgentManager: ({ ptyOutputBus, }?: {
49
52
  ptyOutputBus?: PtyOutputBus;
50
53
  }) => AgentManager;
@@ -4,14 +4,33 @@ import { resolveSpawnCommand } from './agent-command-resolver.js';
4
4
  import { attachAgentPty, toAgentRunSnapshot } from './agent-manager-support.js';
5
5
  import { createPtyOutputBus } from './pty-output-bus.js';
6
6
  const createRunId = () => randomUUID();
7
- const createSpawnEnv = (inputEnv) => {
8
- const env = { ...process.env, ...inputEnv };
7
+ const getWindowsEnvKey = (env, key) => {
8
+ if (Object.hasOwn(env, key))
9
+ return key;
10
+ return Object.keys(env)
11
+ .filter((item) => item.toLowerCase() === key.toLowerCase())
12
+ .at(-1);
13
+ };
14
+ export const createSpawnEnv = (inputEnv, platform = process.platform, parentEnv = process.env) => {
15
+ const env = { ...parentEnv };
16
+ for (const [key, value] of Object.entries(inputEnv ?? {})) {
17
+ const targetKey = platform === 'win32' ? (getWindowsEnvKey(env, key) ?? key) : key;
18
+ env[targetKey] = value;
19
+ }
9
20
  for (const key of Object.keys(env)) {
10
21
  if (env[key] === undefined)
11
22
  delete env[key];
12
23
  }
13
24
  return env;
14
25
  };
26
+ export const buildAgentPtySpawnOptions = (cwd, env, platform = process.platform) => ({
27
+ cols: 80,
28
+ cwd,
29
+ env,
30
+ name: 'xterm-256color',
31
+ rows: 24,
32
+ ...(platform === 'win32' ? { useConpty: true } : {}),
33
+ });
15
34
  export const createAgentManager = ({ ptyOutputBus = createPtyOutputBus(), } = {}) => {
16
35
  const runs = new Map();
17
36
  const getRunRecord = (runId) => {
@@ -54,11 +73,7 @@ export const createAgentManager = ({ ptyOutputBus = createPtyOutputBus(), } = {}
54
73
  run.onExit = input.onExit;
55
74
  runs.set(runId, run);
56
75
  try {
57
- attachAgentPty(run, spawn(spawnCommand.command, spawnCommand.args, {
58
- cwd: input.cwd,
59
- env,
60
- name: 'xterm-256color',
61
- }), ptyOutputBus);
76
+ attachAgentPty(run, spawn(spawnCommand.command, spawnCommand.args, buildAgentPtySpawnOptions(input.cwd, env)), ptyOutputBus);
62
77
  }
63
78
  catch (error) {
64
79
  runs.delete(runId);
@@ -30,6 +30,7 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
30
30
  CODEX_HOME?: never;
31
31
  HIVE_GEMINI_HOME?: never;
32
32
  HIVE_OPENCODE_DB_PATH?: never;
33
+ HIVE_QWEN_HOME?: never;
33
34
  };
34
35
  knownSessionIds: Set<string>;
35
36
  root: string;
@@ -39,6 +40,7 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
39
40
  HIVE_CLAUDE_PROJECTS_DIR?: never;
40
41
  HIVE_GEMINI_HOME?: never;
41
42
  HIVE_OPENCODE_DB_PATH?: never;
43
+ HIVE_QWEN_HOME?: never;
42
44
  };
43
45
  knownSessionIds: Set<string>;
44
46
  root: string;
@@ -48,6 +50,7 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
48
50
  HIVE_CLAUDE_PROJECTS_DIR?: never;
49
51
  CODEX_HOME?: never;
50
52
  HIVE_OPENCODE_DB_PATH?: never;
53
+ HIVE_QWEN_HOME?: never;
51
54
  };
52
55
  knownSessionIds: Set<string>;
53
56
  root: string;
@@ -57,6 +60,17 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
57
60
  HIVE_CLAUDE_PROJECTS_DIR?: never;
58
61
  CODEX_HOME?: never;
59
62
  HIVE_GEMINI_HOME?: never;
63
+ HIVE_QWEN_HOME?: never;
64
+ };
65
+ knownSessionIds: Set<string>;
66
+ root: string;
67
+ } | {
68
+ env: {
69
+ HIVE_QWEN_HOME: string;
70
+ HIVE_CLAUDE_PROJECTS_DIR?: never;
71
+ CODEX_HOME?: never;
72
+ HIVE_GEMINI_HOME?: never;
73
+ HIVE_OPENCODE_DB_PATH?: never;
60
74
  };
61
75
  knownSessionIds: Set<string>;
62
76
  root: string;
@@ -1,6 +1,7 @@
1
1
  import { dirname, posix, resolve, sep, win32 } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { buildAgentLegacyIdentityMarker, buildAgentSessionBindingMarker, } from './agent-startup-instructions.js';
4
+ import { getBuiltinCommandPresetByCommand } from './command-preset-defaults.js';
4
5
  import { withPresetResumeArgs } from './preset-launch-support.js';
5
6
  import { captureSessionIdForCapture, getSessionCaptureEnvironment, snapshotSessionIdsForCapture, } from './session-capture.js';
6
7
  const resolveHiveBinDir = () => {
@@ -12,6 +13,13 @@ const resolveHiveBinDir = () => {
12
13
  };
13
14
  const HIVE_BIN_DIR = resolveHiveBinDir();
14
15
  const SESSION_CAPTURE_TIMEOUT_MS = 30_000;
16
+ const getWindowsEnvKey = (env, key) => {
17
+ if (Object.hasOwn(env, key))
18
+ return key;
19
+ return Object.keys(env)
20
+ .filter((item) => item.toLowerCase() === key.toLowerCase())
21
+ .at(-1);
22
+ };
15
23
  /**
16
24
  * Builds a `{ <PATH-key>: <new-value> }` object for the spawn env override.
17
25
  * Critical on Windows: the OS env block reports PATH under its native casing
@@ -29,9 +37,7 @@ const SESSION_CAPTURE_TIMEOUT_MS = 30_000;
29
37
  * caller.
30
38
  */
31
39
  export const buildSpawnPathEnvEntry = (parentEnv, hiveBinDir, platform) => {
32
- const existingKey = platform === 'win32'
33
- ? Object.keys(parentEnv).find((key) => key.toLowerCase() === 'path')
34
- : undefined;
40
+ const existingKey = platform === 'win32' ? getWindowsEnvKey(parentEnv, 'PATH') : undefined;
35
41
  const key = existingKey ?? 'PATH';
36
42
  const existingValue = existingKey ? parentEnv[existingKey] : parentEnv.PATH;
37
43
  // Target platform's delimiter — Windows uses `;`, POSIX `:` — independent
@@ -45,7 +51,8 @@ const resolveLaunchPreset = (config, getCommandPreset) => {
45
51
  return undefined;
46
52
  if (config.commandPresetId)
47
53
  return getCommandPreset(config.commandPresetId);
48
- const implicitPreset = getCommandPreset(config.command);
54
+ const implicitBuiltin = getBuiltinCommandPresetByCommand(config.command);
55
+ const implicitPreset = getCommandPreset(implicitBuiltin?.id ?? config.command);
49
56
  if (!implicitPreset || implicitPreset.command !== config.command)
50
57
  return undefined;
51
58
  return {
@@ -1,6 +1,7 @@
1
+ import { shouldClearResumedSessionOnExit } from './agent-exit-classification.js';
1
2
  import { completeLiveRun } from './agent-run-sync.js';
2
3
  const clearResumedSessionOnFailure = (context, exitCode) => {
3
- if (exitCode !== 0 && context.startConfig.resumedSessionId) {
4
+ if (shouldClearResumedSessionOnExit(exitCode) && context.startConfig.resumedSessionId) {
4
5
  context.sessionStore.clearLastSessionId(context.workspace.id, context.agentId);
5
6
  }
6
7
  };
@@ -15,12 +16,17 @@ export const handleAgentRunExit = (context, { exitCode, endedAt, runId }) => {
15
16
  context.registry.clearPendingExitCode(runId);
16
17
  return false;
17
18
  }
18
- completeLiveRun(liveRun, exitCode, endedAt, context.store);
19
- clearResumedSessionOnFailure(context, exitCode);
20
19
  context.handledRunExits.add(runId);
21
- context.tokenRegistry.revokeIfMatches(context.agentId, context.token);
22
- context.onAgentExit(context.workspace.id, context.agentId);
23
- context.registry.resolveExit(runId);
24
- context.registry.clearPendingExitCode(runId);
25
- return true;
20
+ try {
21
+ completeLiveRun(liveRun, exitCode, endedAt, context.store);
22
+ if (!liveRun.userStopped)
23
+ clearResumedSessionOnFailure(context, exitCode);
24
+ context.onAgentExit(context.workspace.id, context.agentId);
25
+ return true;
26
+ }
27
+ finally {
28
+ context.tokenRegistry.revokeIfMatches(context.agentId, context.token);
29
+ context.registry.resolveExit(runId);
30
+ context.registry.clearPendingExitCode(runId);
31
+ }
26
32
  };
@@ -9,6 +9,7 @@ import type { CommandPresetRecord } from './command-preset-store.js';
9
9
  import { type FeatureFlags } from './feature-flags.js';
10
10
  import type { LiveRunRegistry } from './live-run-registry.js';
11
11
  import type { RestartPolicy } from './restart-policy.js';
12
+ import { type TeamMemoryInjectionService } from './team-memory-injection.js';
12
13
  interface AgentRunStarterInput {
13
14
  agentManager: AgentManager | undefined;
14
15
  registry: LiveRunRegistry;
@@ -23,6 +24,7 @@ interface AgentRunStarterInput {
23
24
  * prompt (`workflowsEnabled` gates the `team workflow` line + authoring
24
25
  * rule; `autostaffEnabled` gates the team-sizing rule). */
25
26
  getFlags?: () => FeatureFlags;
27
+ memoryInjection?: TeamMemoryInjectionService;
26
28
  }
27
- export declare const createAgentRunStarter: ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, }: AgentRunStarterInput) => (workspace: WorkspaceSummary, agentId: string, config: AgentLaunchConfigInput, hivePort: string) => Promise<LiveAgentRun>;
29
+ export declare const createAgentRunStarter: ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, memoryInjection, }: AgentRunStarterInput) => (workspace: WorkspaceSummary, agentId: string, config: AgentLaunchConfigInput, hivePort: string) => Promise<LiveAgentRun>;
28
30
  export {};
@@ -1,9 +1,11 @@
1
+ import { classifyCompletedRunStatus, shouldClearResumedSessionOnExit, } from './agent-exit-classification.js';
1
2
  import { buildAgentRunBootstrap, startAgentRunCapture } from './agent-run-bootstrap.js';
2
3
  import { handleAgentRunExit } from './agent-run-exit-handler.js';
3
4
  import { buildAgentStartupInstructions } from './agent-startup-instructions.js';
4
5
  import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
5
6
  import { createPostStartInputWriter, isInteractiveAgentCommand } from './post-start-input-writer.js';
6
- export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, }) => async (workspace, agentId, config, hivePort) => {
7
+ import { buildMemoryDigestSafely, logMemoryDigestInjection, rollbackMemoryDigestInjection, } from './team-memory-injection.js';
8
+ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, memoryInjection, }) => async (workspace, agentId, config, hivePort) => {
7
9
  if (!agentManager)
8
10
  throw new Error('Agent manager is required to start agents');
9
11
  const agent = getAgent?.(workspace.id, agentId);
@@ -74,8 +76,9 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
74
76
  registry.createExitEntry(run.runId);
75
77
  registry.add(liveRun);
76
78
  if (run.status === 'error') {
77
- store.updatePersistedRun(run.runId, 'error', run.exitCode, Date.now());
78
- if (startConfig.resumedSessionId) {
79
+ liveRun.status = classifyCompletedRunStatus(run.exitCode);
80
+ store.updatePersistedRun(run.runId, liveRun.status, run.exitCode, Date.now());
81
+ if (startConfig.resumedSessionId && shouldClearResumedSessionOnExit(run.exitCode)) {
79
82
  sessionStore.clearLastSessionId(workspace.id, agentId);
80
83
  }
81
84
  tokenRegistry.revokeIfMatches(agentId, token);
@@ -110,15 +113,29 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
110
113
  workspace,
111
114
  writeToRun: postStartWriter,
112
115
  });
113
- if (!startConfig.resumedSessionId &&
114
- !injectedRestartMessage &&
116
+ if (!injectedRestartMessage &&
115
117
  agent &&
116
118
  isInteractiveAgentCommand(startConfig.interactiveCommand ?? startConfig.command)) {
119
+ const memoryDigest = buildMemoryDigestSafely({
120
+ contextType: 'startup',
121
+ memoryInjection,
122
+ workspaceId: workspace.id,
123
+ });
124
+ const injectionIds = logMemoryDigestInjection({
125
+ agentId,
126
+ contextType: 'startup',
127
+ memoryDigest,
128
+ memoryInjection,
129
+ workspaceId: workspace.id,
130
+ });
131
+ const auditedMemoryDigest = injectionIds ? memoryDigest : null;
117
132
  void postStartWriter(run.runId, buildAgentStartupInstructions({
118
133
  agent,
134
+ memoryDigest: auditedMemoryDigest?.text,
119
135
  workspace,
120
136
  flags: getFlags?.() ?? FEATURE_FLAGS_ALL_OFF,
121
137
  })).catch(() => {
138
+ rollbackMemoryDigestInjection({ injectionIds, memoryInjection });
122
139
  // The agent may have exited before post-start guidance could be written.
123
140
  });
124
141
  }
@@ -1,24 +1,32 @@
1
+ import { classifyCompletedRunStatus } from './agent-exit-classification.js';
1
2
  const MAX_RUN_OUTPUT_LENGTH = 1_000_000;
2
3
  const toPersistedStatus = (run) => {
4
+ if ('userStopped' in run &&
5
+ run.userStopped === true &&
6
+ (run.status === 'error' || run.status === 'exited')) {
7
+ return 'exited';
8
+ }
3
9
  if (run.status === 'error' || run.status === 'exited' || run.status === 'starting') {
4
10
  return run.status;
5
11
  }
6
- return run.exitCode === null ? 'running' : run.exitCode === 0 ? 'exited' : 'error';
12
+ return run.exitCode === null ? 'running' : classifyCompletedRunStatus(run.exitCode);
7
13
  };
8
14
  export const syncPersistedRun = (run, snapshot, store) => {
9
- const nextStatus = toPersistedStatus(snapshot);
15
+ const nextStatus = toPersistedStatus(run.userStopped ? { ...snapshot, userStopped: true } : snapshot);
10
16
  const output = snapshot.output.slice(-MAX_RUN_OUTPUT_LENGTH);
11
17
  if (run.status === nextStatus && run.exitCode === snapshot.exitCode && run.output === output) {
12
18
  return run;
13
19
  }
20
+ const endedAt = nextStatus === 'exited' || nextStatus === 'error' ? Date.now() : null;
21
+ store.updatePersistedRun(run.runId, nextStatus, snapshot.exitCode, endedAt);
14
22
  run.status = nextStatus;
15
23
  run.output = output;
16
24
  run.exitCode = snapshot.exitCode;
17
- store.updatePersistedRun(run.runId, nextStatus, snapshot.exitCode, nextStatus === 'exited' || nextStatus === 'error' ? Date.now() : null);
18
25
  return run;
19
26
  };
20
27
  export const completeLiveRun = (run, exitCode, endedAt, store) => {
21
- run.status = exitCode === 0 ? 'exited' : 'error';
28
+ const nextStatus = run.userStopped ? 'exited' : classifyCompletedRunStatus(exitCode);
29
+ store.updatePersistedRun(run.runId, nextStatus, exitCode, endedAt);
30
+ run.status = nextStatus;
22
31
  run.exitCode = exitCode;
23
- store.updatePersistedRun(run.runId, run.status, exitCode, endedAt);
24
32
  };
@@ -1,4 +1,5 @@
1
1
  import type { AgentRunSnapshot } from './agent-manager.js';
2
2
  export interface LiveAgentRun extends AgentRunSnapshot {
3
3
  startedAt: number;
4
+ userStopped?: boolean;
4
5
  }
@@ -5,5 +5,6 @@ import type { AgentRunStorePort, AgentSessionStorePort } from './agent-runtime-p
5
5
  import type { CommandPresetRecord } from './command-preset-store.js';
6
6
  import type { FeatureFlags } from './feature-flags.js';
7
7
  import { type RestartPolicy } from './restart-policy.js';
8
- export declare const createAgentRuntime: (agentManager: AgentManager | undefined, agentRunStore: AgentRunStorePort, sessionStore: AgentSessionStorePort, getCommandPreset: (id: string) => CommandPresetRecord | undefined, onAgentExit: (workspaceId: string, agentId: string) => void, restartPolicy?: RestartPolicy, getAgent?: (workspaceId: string, agentId: string) => AgentSummary | undefined, getFlags?: () => FeatureFlags) => AgentRuntime;
8
+ import type { TeamMemoryInjectionService } from './team-memory-injection.js';
9
+ export declare const createAgentRuntime: (agentManager: AgentManager | undefined, agentRunStore: AgentRunStorePort, sessionStore: AgentSessionStorePort, getCommandPreset: (id: string) => CommandPresetRecord | undefined, onAgentExit: (workspaceId: string, agentId: string) => void, restartPolicy?: RestartPolicy, getAgent?: (workspaceId: string, agentId: string) => AgentSummary | undefined, getFlags?: () => FeatureFlags, memoryInjection?: TeamMemoryInjectionService) => AgentRuntime;
9
10
  export type { AgentRuntime };
@@ -10,7 +10,7 @@ import { createAgentStdinDispatcher } from './agent-stdin-dispatcher.js';
10
10
  import { createAgentTokenRegistry } from './agent-tokens.js';
11
11
  import { createLiveRunRegistry } from './live-run-registry.js';
12
12
  import { createNoopRestartPolicy } from './restart-policy.js';
13
- export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, getCommandPreset, onAgentExit, restartPolicy = createNoopRestartPolicy(), getAgent, getFlags) => {
13
+ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, getCommandPreset, onAgentExit, restartPolicy = createNoopRestartPolicy(), getAgent, getFlags, memoryInjection) => {
14
14
  const registry = createLiveRunRegistry();
15
15
  const launchCache = createAgentLaunchCache(agentRunStore);
16
16
  const tokenRegistry = createAgentTokenRegistry();
@@ -30,6 +30,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
30
30
  registry,
31
31
  syncRun,
32
32
  ...(getFlags ? { getFlags } : {}),
33
+ ...(memoryInjection ? { memoryInjection } : {}),
33
34
  });
34
35
  const startLiveRun = createAgentRunStarter({
35
36
  agentManager,
@@ -42,6 +43,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
42
43
  getAgent,
43
44
  restartPolicy,
44
45
  ...(getFlags ? { getFlags } : {}),
46
+ ...(memoryInjection ? { memoryInjection } : {}),
45
47
  });
46
48
  return {
47
49
  async close() {
@@ -105,7 +107,12 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
105
107
  return startPromise;
106
108
  },
107
109
  stopAgentRun(runId) {
108
- stopLiveRun(agentManager, registry, syncRun, runId, (stoppedRunId) => restartPolicy.markUserStopped(stoppedRunId));
110
+ stopLiveRun(agentManager, registry, syncRun, runId, (stoppedRunId) => {
111
+ const liveRun = registry.get(stoppedRunId);
112
+ if (liveRun)
113
+ liveRun.userStopped = true;
114
+ restartPolicy.markUserStopped(stoppedRunId);
115
+ });
109
116
  },
110
117
  validateAgentToken: tokenRegistry.validate,
111
118
  writeReportPrompt(workspaceId, workerName, _workerId, text, artifacts, input = {}) {
@@ -8,8 +8,9 @@ export declare const buildAgentLegacyIdentityMarker: ({ agent, workspace, }: {
8
8
  agent: AgentSummary;
9
9
  workspace: WorkspaceSummary;
10
10
  }) => string;
11
- export declare const buildAgentStartupInstructions: ({ agent, workspace, flags, }: {
11
+ export declare const buildAgentStartupInstructions: ({ agent, memoryDigest, workspace, flags, }: {
12
12
  agent: AgentSummary;
13
+ memoryDigest?: string | null | undefined;
13
14
  workspace: WorkspaceSummary;
14
15
  /** Live experimental flags. `workflowsEnabled` gates the `team workflow`
15
16
  * command line + the workflow-authoring rule (so a fresh orchestrator isn't
@@ -1,9 +1,10 @@
1
+ import { BUILTIN_COMMAND_PRESET_CLI_LIST } from './command-preset-defaults.js';
1
2
  import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
2
3
  import { getHiveTeamRules } from './hive-team-guidance.js';
3
4
  import { TASKS_RELATIVE_PATH } from './tasks-file.js';
4
5
  export const buildAgentSessionBindingMarker = ({ agent, workspace, }) => `Hive session binding: workspace_id=${workspace.id}; agent_id=${agent.id}`;
5
6
  export const buildAgentLegacyIdentityMarker = ({ agent, workspace, }) => `You are ${agent.name} (${agent.role}) in workspace ${workspace.name}.`;
6
- export const buildAgentStartupInstructions = ({ agent, workspace, flags = FEATURE_FLAGS_ALL_OFF, }) => {
7
+ export const buildAgentStartupInstructions = ({ agent, memoryDigest, workspace, flags = FEATURE_FLAGS_ALL_OFF, }) => {
7
8
  const { workflowsEnabled } = flags;
8
9
  const lines = [
9
10
  '<hive-message kind="startup">',
@@ -18,15 +19,18 @@ export const buildAgentStartupInstructions = ({ agent, workspace, flags = FEATUR
18
19
  `Your role: ${agent.description}`,
19
20
  '',
20
21
  ];
22
+ if (memoryDigest) {
23
+ lines.push(memoryDigest, '');
24
+ }
21
25
  if (agent.role === 'orchestrator') {
22
- lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH}`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team send "<worker-name>" "<task>"', '- team spawn <role> [--name <n>] [--cli claude|codex|opencode|gemini|hermes] [--ephemeral]', '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
26
+ lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH}`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team recall "<query>" [--limit <n>] [--window <n>]', '- team memory add "<body>" [--kind fact|preference|decision|pitfall|procedure_ref] [--tag <tag>]', '- team memory show <memory-id>', '- team memory search "<query>" [--limit <n>]', '- team memory forget <memory-id>', '- team send "<worker-name>" "<task>"', `- team spawn <role> [--name <n>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>] [--ephemeral]`, '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
23
27
  ? [
24
28
  '- team workflow run --stdin (fan-out / staged work — see .hive/PROTOCOL.md for the DSL)',
25
29
  ]
26
- : []), '', 'Always dispatch by worker name, never by worker id.', 'Always cancel an open dispatch by its dispatch id.', '', 'Hive worker dispatch rules:', ...getHiveTeamRules(agent, flags));
30
+ : []), '', 'Always dispatch by worker name, never by worker id.', 'Always cancel an open dispatch by its dispatch id.', 'Search memory before adding: use `team memory search "<query>"` to avoid duplicates.', 'Use `team memory add` only for rare, evidence-backed workspace facts/decisions/pitfalls that should help future Hive agents across sessions.', 'Nothing worth saving is a normal outcome; do not add memory just to prove you used it.', 'Use `team memory forget` only to archive obsolete workspace memory; it does not physically delete evidence.', '', 'Hive worker dispatch rules:', ...getHiveTeamRules(agent, flags));
27
31
  }
28
32
  else {
29
- lines.push('Available team commands:', '- team report "<result>" [--dispatch <id>] [--artifact <path>] report done / failed / blocked', '- team report --stdin [--dispatch <id>] [--artifact <path>] same, body read from stdin (multi-line / quotes / special chars)', '- team status "<state>" [--artifact <path>] mid-task progress / standby / connected status', '- team status --stdin [--artifact <path>] same, body read from stdin', '- team list list the workspace workers (with status)', '- team --help command syntax only; NOT a way to report', '', 'Syntax notes:', '- The body is the first positional argument; flag order is free: `team report "result" --dispatch X` and `team report --dispatch X "result"` are both valid.', "- Long bodies (multi-line / quotes / shell metacharacters) always go through `--stdin`, piped in via your shell (POSIX: a quoted heredoc `<<'EOF' … EOF` to stop $var / backtick expansion; Windows cmd: `type body.txt |` or `< body.txt`). `--stdin` only reads from stdin and relies on no shell syntax of its own.", '- On error the CLI also prints USAGE — fix the arguments against it.', '', 'When a task is done you MUST run `team report "<result>"`.', 'Failure, blocked, or partial completion are also reported with `team report "<current state and reason>"`.', 'When no task is in progress, report connection / standby / blocked state with `team status "<state>"`.', 'Do not call team send; workers cannot dispatch to each other.', '', 'Hive worker boundaries:', ...getHiveTeamRules(agent, flags));
33
+ lines.push('Available team commands:', '- team report "<result>" [--dispatch <id>] [--artifact <path>] report done / failed / blocked', '- team report --stdin [--dispatch <id>] [--artifact <path>] same, body read from stdin (multi-line / quotes / special chars)', '- team status "<state>" [--artifact <path>] mid-task progress / standby / connected status', '- team status --stdin [--artifact <path>] same, body read from stdin', '- team recall "<query>" [--limit <n>] [--window <n>] search prior team messages/reports in this workspace', '- team memory show <memory-id> inspect a memory entry and its evidence', '- team memory search "<query>" [--limit <n>] search active workspace memory', '- team list list the workspace workers (with status)', '- team --help command syntax only; NOT a way to report', '', 'Syntax notes:', '- The body is the first positional argument; flag order is free: `team report "result" --dispatch X` and `team report --dispatch X "result"` are both valid.', "- Long bodies (multi-line / quotes / shell metacharacters) always go through `--stdin`, piped in via your shell (POSIX: a quoted heredoc `<<'EOF' … EOF` to stop $var / backtick expansion; Windows cmd: `type body.txt |` or `< body.txt`; PowerShell: `Get-Content -Raw -Encoding utf8 body.txt |`). `--stdin` only reads from stdin and relies on no shell syntax of its own.", '- On error the CLI also prints USAGE — fix the arguments against it.', '', 'When a task is done you MUST run `team report "<result>"`.', 'Failure, blocked, or partial completion are also reported with `team report "<current state and reason>"`.', 'When no task is in progress, report connection / standby / blocked state with `team status "<state>"`.', 'Use `team recall "<query>"` when prior team messages or reports may contain useful evidence.', 'Use `team memory search "<query>"` to look up active durable workspace memory.', 'Include durable findings in `team report`; workers cannot add or forget memory.', 'Do not call team send; workers cannot dispatch to each other.', '', 'Hive worker boundaries:', ...getHiveTeamRules(agent, flags));
30
34
  }
31
35
  lines.push('', '</hive-message>', '');
32
36
  return lines.join('\n');
@@ -3,12 +3,14 @@ import type { AgentLaunchConfigInput } from './agent-run-store.js';
3
3
  import type { LiveAgentRun } from './agent-runtime-types.js';
4
4
  import { type FeatureFlags } from './feature-flags.js';
5
5
  import type { LiveRunRegistry } from './live-run-registry.js';
6
+ import { type TeamMemoryInjectionService } from './team-memory-injection.js';
6
7
  interface AgentStdinDispatcherInput {
7
8
  agentManager: AgentManager | undefined;
8
9
  getLaunchConfig: (workspaceId: string, agentId: string) => AgentLaunchConfigInput | undefined;
9
10
  getWorkspaceId: (agentId: string) => string | undefined;
10
11
  registry: LiveRunRegistry;
11
12
  syncRun: (run: LiveAgentRun) => LiveAgentRun;
13
+ memoryInjection?: TeamMemoryInjectionService;
12
14
  /** Resolves the live experimental flags. The orchestrator reminder tail
13
15
  * appended to every injected message reads `workflowsEnabled` from it.
14
16
  * Optional; omitted → all flags off. */
@@ -17,9 +19,9 @@ interface AgentStdinDispatcherInput {
17
19
  export declare const buildOrchestratorReportPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
18
20
  export declare const buildOrchestratorStatusPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
19
21
  export declare const buildOrchestratorUserInputPayload: (text: string, flags?: FeatureFlags) => string;
20
- export declare const buildWorkerDispatchPayload: (fromAgentName: string, workerDescription: string, dispatchId: string, text: string) => string;
22
+ export declare const buildWorkerDispatchPayload: (fromAgentName: string, workerDescription: string, dispatchId: string, text: string, memoryDigest?: string | null) => string;
21
23
  export declare const buildWorkerCancelPayload: (dispatchId: string, reason: string) => string;
22
- export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, getFlags, }: AgentStdinDispatcherInput) => {
24
+ export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, memoryInjection, getFlags, }: AgentStdinDispatcherInput) => {
23
25
  writeReportPrompt(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
24
26
  requireActiveRun?: boolean;
25
27
  }): void;