@tt-a1i/hive 1.7.0 → 2.0.1

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 +51 -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 +8 -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-C86CwNgQ.js +2 -0
  221. package/web/dist/assets/AddWorkspaceFlow-Bm2Jz34D.js +1 -0
  222. package/web/dist/assets/FirstRunWizard-XzBoEpA5.js +1 -0
  223. package/web/dist/assets/MarketplaceDrawer-BFfGT8hH.js +67 -0
  224. package/web/dist/assets/TaskGraphDrawer-_uVH_0C1.js +1 -0
  225. package/web/dist/assets/{WhatsNewDialog-CHkZeINH.js → WhatsNewDialog-DkJHmkMs.js} +1 -1
  226. package/web/dist/assets/WorkerModal-BtMJEOG9.js +1 -0
  227. package/web/dist/assets/WorkflowsDrawer-CiIdHS6_.js +1 -0
  228. package/web/dist/assets/WorkspaceMemoryDrawer-C6sNocl_.js +1 -0
  229. package/web/dist/assets/WorkspaceTaskDrawer-CyhhEB1Z.js +1 -0
  230. package/web/dist/assets/index-BAiLYajK.css +1 -0
  231. package/web/dist/assets/index-K-GG8UwR.js +73 -0
  232. package/web/dist/assets/search-BtRkkEmS.js +1 -0
  233. package/web/dist/assets/square-terminal-lEeQUWb3.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,5 +1,5 @@
1
1
  import type { AgentSummary } from '../shared/types.js';
2
- export type TeamCommand = 'send' | 'list' | 'next' | 'report' | 'status' | 'cancel' | 'help' | 'spawn' | 'dismiss' | 'workflow';
2
+ export type TeamCommand = 'send' | 'list' | 'next' | 'report' | 'recall' | 'memory_add' | 'memory_forget' | 'memory_search' | 'memory_show' | 'status' | 'cancel' | 'help' | 'spawn' | 'dismiss' | 'workflow';
3
3
  export declare const commandAllowedForRole: (role: AgentSummary["role"], command: TeamCommand) => boolean;
4
4
  interface AuthenticateInput {
5
5
  fromAgentId: string | undefined;
@@ -5,11 +5,23 @@ const ORCHESTRATOR_COMMANDS = new Set([
5
5
  'next',
6
6
  'cancel',
7
7
  'help',
8
+ 'recall',
9
+ 'memory_add',
10
+ 'memory_forget',
11
+ 'memory_search',
12
+ 'memory_show',
8
13
  'spawn',
9
14
  'dismiss',
10
15
  'workflow',
11
16
  ]);
12
- const WORKER_COMMANDS = new Set(['report', 'status', 'help']);
17
+ const WORKER_COMMANDS = new Set([
18
+ 'report',
19
+ 'status',
20
+ 'help',
21
+ 'recall',
22
+ 'memory_search',
23
+ 'memory_show',
24
+ ]);
13
25
  const WORKER_ROLES = new Set(['coder', 'reviewer', 'tester', 'custom']);
14
26
  export const commandAllowedForRole = (role, command) => {
15
27
  if (role === 'orchestrator')
@@ -1,3 +1,4 @@
1
+ import { getBuiltinCommandPresetByCommand } from './command-preset-defaults.js';
1
2
  /**
2
3
  * Resolves the built-in command preset id for a worker. Mirrors the launch-time
3
4
  * lookup in `agent-run-bootstrap.ts::resolveLaunchPreset`: explicit
@@ -16,7 +17,8 @@ export const resolveCommandPresetId = (store, workspaceId, workerId) => {
16
17
  return null;
17
18
  if (config.commandPresetId)
18
19
  return config.commandPresetId;
19
- const implicit = store.settings.getCommandPreset(config.command);
20
+ const implicitBuiltin = getBuiltinCommandPresetByCommand(config.command);
21
+ const implicit = store.settings.getCommandPreset(implicitBuiltin?.id ?? config.command);
20
22
  if (!implicit || implicit.command !== config.command)
21
23
  return null;
22
24
  return implicit.id;
@@ -0,0 +1,52 @@
1
+ import type { MemoryEntryWithSources, MemorySearchResult } from './team-memory-store.js';
2
+ export declare const STARTUP_MEMORY_BUDGET_CHARS = 1200;
3
+ export declare const RECOVERY_MEMORY_BUDGET_CHARS = 800;
4
+ export declare const DISPATCH_MEMORY_BUDGET_CHARS = 1500;
5
+ export declare const MEMORY_DIGEST_ENTRY_LIMIT = 20;
6
+ export declare const DISPATCH_MEMORY_ENTRY_LIMIT = 5;
7
+ export declare const DISPATCH_MEMORY_CANDIDATE_LIMIT = 20;
8
+ export declare const DISPATCH_MEMORY_MIN_CONFIDENCE = 0.5;
9
+ export declare const DISPATCH_MEMORY_RECENCY_DECAY_MS: number;
10
+ export type MemoryDigestContext = 'recovery' | 'startup';
11
+ export interface MemoryDigestPayload {
12
+ memoryIds: string[];
13
+ text: string;
14
+ }
15
+ export interface WorkspaceMemoryDigestProvider {
16
+ buildDigest: (input: {
17
+ contextType: MemoryDigestContext;
18
+ workspaceId: string;
19
+ }) => MemoryDigestPayload | null;
20
+ buildDispatchDigest: (input: {
21
+ taskText: string;
22
+ workerDescription: string;
23
+ workspaceId: string;
24
+ }) => MemoryDigestPayload | null;
25
+ }
26
+ interface AppStateReader {
27
+ getAppState: (key: string) => {
28
+ value: string | null;
29
+ } | undefined;
30
+ }
31
+ interface MemoryDigestStore {
32
+ listDigestEntries: (workspaceId: string, options?: {
33
+ limit?: number;
34
+ }) => MemoryEntryWithSources[];
35
+ searchEntries?: (workspaceId: string, query: string, options?: {
36
+ limit?: number;
37
+ statuses?: Array<'active' | 'archived' | 'candidate' | 'rejected'>;
38
+ }) => MemorySearchResult[];
39
+ }
40
+ export declare const formatMemoryDigestBlock: ({ budget, contextType, entries, }: {
41
+ budget: number;
42
+ contextType: MemoryDigestContext;
43
+ entries: MemoryEntryWithSources[];
44
+ }) => MemoryDigestPayload | null;
45
+ export declare const formatDispatchMemoryBlock: ({ entries, }: {
46
+ entries: MemorySearchResult[];
47
+ }) => MemoryDigestPayload | null;
48
+ export declare const createWorkspaceMemoryDigestProvider: ({ memoryStore, settings, }: {
49
+ memoryStore: MemoryDigestStore;
50
+ settings: AppStateReader;
51
+ }) => WorkspaceMemoryDigestProvider;
52
+ export {};
@@ -0,0 +1,200 @@
1
+ import { readWorkspaceMemoryEnabled, workspaceMemoryEnabledKey } from './team-memory-feature.js';
2
+ export const STARTUP_MEMORY_BUDGET_CHARS = 1200;
3
+ export const RECOVERY_MEMORY_BUDGET_CHARS = 800;
4
+ export const DISPATCH_MEMORY_BUDGET_CHARS = 1500;
5
+ export const MEMORY_DIGEST_ENTRY_LIMIT = 20;
6
+ export const DISPATCH_MEMORY_ENTRY_LIMIT = 5;
7
+ export const DISPATCH_MEMORY_CANDIDATE_LIMIT = 20;
8
+ export const DISPATCH_MEMORY_MIN_CONFIDENCE = 0.5;
9
+ export const DISPATCH_MEMORY_RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
10
+ const charLength = (value) => [...value].length;
11
+ const truncateChars = (value, maxChars) => {
12
+ if (charLength(value) <= maxChars)
13
+ return value;
14
+ if (maxChars <= 3)
15
+ return '.'.repeat(Math.max(0, maxChars));
16
+ return `${[...value].slice(0, maxChars - 3).join('')}...`;
17
+ };
18
+ const escapeMemoryText = (value) => value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
19
+ const formatEntryLine = (entry) => {
20
+ const labels = [entry.kind];
21
+ if (entry.pinned)
22
+ labels.push('pinned');
23
+ if (entry.source === 'dream')
24
+ labels.push('dream');
25
+ const source = entry.sources[0];
26
+ if (source?.actorNameSnapshot)
27
+ labels.push(`from: ${escapeMemoryText(source.actorNameSnapshot)}`);
28
+ if (entry.tags.length > 0) {
29
+ labels.push(`tags: ${entry.tags.map(escapeMemoryText).join(', ')}`);
30
+ }
31
+ return `- [${labels.join(', ')}] ${escapeMemoryText(entry.body)}`;
32
+ };
33
+ const appendWithinBudget = (lines, line, budget, tail) => {
34
+ const candidate = [...lines, line, tail].join('\n');
35
+ if (charLength(candidate) <= budget)
36
+ return line;
37
+ const base = [...lines, tail].join('\n');
38
+ const remaining = budget - charLength(base) - 1;
39
+ if (remaining < 24)
40
+ return null;
41
+ const truncated = truncateChars(line, remaining);
42
+ return charLength([...lines, truncated, tail].join('\n')) <= budget ? truncated : null;
43
+ };
44
+ const appendSection = (lines, title, entries, includedIds, budget, tail) => {
45
+ let titleAdded = false;
46
+ for (const entry of entries) {
47
+ const sectionLines = titleAdded ? lines : [...lines, title];
48
+ const line = appendWithinBudget(sectionLines, formatEntryLine(entry), budget, tail);
49
+ if (!line)
50
+ break;
51
+ if (!titleAdded) {
52
+ lines.push(title);
53
+ titleAdded = true;
54
+ }
55
+ lines.push(line);
56
+ includedIds.push(entry.id);
57
+ }
58
+ };
59
+ export const formatMemoryDigestBlock = ({ budget, contextType, entries, }) => {
60
+ const activeEntries = entries.filter((entry) => entry.status === 'active' && !entry.disabled);
61
+ if (activeEntries.length === 0)
62
+ return null;
63
+ const tail = '</hive-memory>';
64
+ const lines = [
65
+ `<hive-memory context="${contextType}">`,
66
+ 'Workspace memory that may be relevant. Verify before relying on it.',
67
+ ];
68
+ const includedIds = [];
69
+ const pinned = activeEntries.filter((entry) => entry.pinned);
70
+ const digest = activeEntries.filter((entry) => !entry.pinned);
71
+ appendSection(lines, 'Pinned:', pinned, includedIds, budget, tail);
72
+ appendSection(lines, 'Digest:', digest, includedIds, budget, tail);
73
+ if (includedIds.length === 0)
74
+ return null;
75
+ lines.push(tail);
76
+ return {
77
+ memoryIds: includedIds,
78
+ text: lines.join('\n'),
79
+ };
80
+ };
81
+ const confidenceForDispatch = (entry) => entry.confidence ?? (entry.source === 'manual' ? 1 : 0);
82
+ // pinned = the operator's explicit "always surface this" signal: it ranks ahead of
83
+ // everything and skips recency decay, so a deliberately pinned fact never sinks out of
84
+ // the dispatch budget just because it's old or low-confidence.
85
+ const dispatchRank = (entry, newestUpdatedAt) => ({
86
+ adjustedScore: entry.score +
87
+ (entry.pinned
88
+ ? 0
89
+ : Math.max(0, newestUpdatedAt - entry.updatedAt) / DISPATCH_MEMORY_RECENCY_DECAY_MS),
90
+ confidence: confidenceForDispatch(entry),
91
+ pinnedRank: entry.pinned ? 0 : 1,
92
+ sourceRank: entry.source === 'manual' ? 0 : 1,
93
+ });
94
+ const sortDispatchEntries = (entries) => {
95
+ const newestUpdatedAt = Math.max(...entries.map((entry) => entry.updatedAt), 0);
96
+ return [...entries].sort((left, right) => {
97
+ const leftRank = dispatchRank(left, newestUpdatedAt);
98
+ const rightRank = dispatchRank(right, newestUpdatedAt);
99
+ return (leftRank.pinnedRank - rightRank.pinnedRank ||
100
+ leftRank.sourceRank - rightRank.sourceRank ||
101
+ rightRank.confidence - leftRank.confidence ||
102
+ leftRank.adjustedScore - rightRank.adjustedScore ||
103
+ right.updatedAt - left.updatedAt ||
104
+ right.createdAt - left.createdAt ||
105
+ left.id.localeCompare(right.id));
106
+ });
107
+ };
108
+ const toDispatchSearchTerms = (value) => value
109
+ .replace(/[^\p{L}\p{N}_-]+/gu, ' ')
110
+ .trim()
111
+ .split(/\s+/)
112
+ .filter((term) => [...term].length >= 2);
113
+ const unique = (values) => {
114
+ const seen = new Set();
115
+ const result = [];
116
+ for (const value of values) {
117
+ const normalized = value.trim();
118
+ if (!normalized || seen.has(normalized))
119
+ continue;
120
+ seen.add(normalized);
121
+ result.push(normalized);
122
+ }
123
+ return result;
124
+ };
125
+ const buildDispatchQueries = (text, maxTerms) => unique([truncateChars(text, 500), ...toDispatchSearchTerms(text).slice(0, maxTerms)]);
126
+ const mergeSearchResults = (results) => {
127
+ const byId = new Map();
128
+ for (const result of results) {
129
+ const previous = byId.get(result.id);
130
+ if (!previous || result.score < previous.score)
131
+ byId.set(result.id, result);
132
+ }
133
+ return [...byId.values()];
134
+ };
135
+ export const formatDispatchMemoryBlock = ({ entries, }) => {
136
+ const activeEntries = sortDispatchEntries(entries.filter((entry) => entry.status === 'active' &&
137
+ !entry.disabled &&
138
+ (entry.pinned || confidenceForDispatch(entry) >= DISPATCH_MEMORY_MIN_CONFIDENCE))).slice(0, DISPATCH_MEMORY_ENTRY_LIMIT);
139
+ if (activeEntries.length === 0)
140
+ return null;
141
+ const tail = '</hive-memory>';
142
+ const lines = [
143
+ '<hive-memory context="dispatch">',
144
+ 'Team memory that may be relevant (workspace knowledge, verify before relying on it):',
145
+ ];
146
+ const includedIds = [];
147
+ for (const entry of activeEntries) {
148
+ const line = appendWithinBudget(lines, formatEntryLine(entry), DISPATCH_MEMORY_BUDGET_CHARS, tail);
149
+ if (!line)
150
+ break;
151
+ lines.push(line);
152
+ includedIds.push(entry.id);
153
+ }
154
+ if (includedIds.length === 0)
155
+ return null;
156
+ lines.push(tail);
157
+ return {
158
+ memoryIds: includedIds,
159
+ text: lines.join('\n'),
160
+ };
161
+ };
162
+ export const createWorkspaceMemoryDigestProvider = ({ memoryStore, settings, }) => {
163
+ const enabledFor = (workspaceId) => readWorkspaceMemoryEnabled(settings.getAppState(workspaceMemoryEnabledKey(workspaceId))?.value ?? null);
164
+ return {
165
+ buildDigest({ contextType, workspaceId }) {
166
+ if (!enabledFor(workspaceId))
167
+ return null;
168
+ const entries = memoryStore.listDigestEntries(workspaceId, {
169
+ limit: MEMORY_DIGEST_ENTRY_LIMIT,
170
+ });
171
+ return formatMemoryDigestBlock({
172
+ budget: contextType === 'startup' ? STARTUP_MEMORY_BUDGET_CHARS : RECOVERY_MEMORY_BUDGET_CHARS,
173
+ contextType,
174
+ entries,
175
+ });
176
+ },
177
+ buildDispatchDigest({ taskText, workerDescription, workspaceId }) {
178
+ if (!enabledFor(workspaceId) || !memoryStore.searchEntries)
179
+ return null;
180
+ const search = (queries) => mergeSearchResults(queries.flatMap((query) => memoryStore.searchEntries?.(workspaceId, query, {
181
+ limit: DISPATCH_MEMORY_CANDIDATE_LIMIT,
182
+ statuses: ['active'],
183
+ }) ?? []));
184
+ const taskEntries = search(buildDispatchQueries(taskText, 8));
185
+ if (taskEntries.length === 0)
186
+ return null;
187
+ const roleMatches = new Map(search(buildDispatchQueries(workerDescription, 6)).map((entry) => [entry.id, entry]));
188
+ const entries = taskEntries.map((entry) => {
189
+ const roleMatch = roleMatches.get(entry.id);
190
+ if (!roleMatch)
191
+ return entry;
192
+ return {
193
+ ...entry,
194
+ score: Math.min(entry.score, roleMatch.score),
195
+ };
196
+ });
197
+ return formatDispatchMemoryBlock({ entries });
198
+ },
199
+ };
200
+ };
@@ -0,0 +1,5 @@
1
+ import type { Database } from 'better-sqlite3';
2
+ import { type DreamRunRecord } from './team-memory-dream-types.js';
3
+ export declare const createDreamOperationApplier: (db: Database) => {
4
+ applyAndCompleteRun: (workspaceId: string, runId: string, rawOps: unknown) => DreamRunRecord;
5
+ };
@@ -0,0 +1,234 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { DreamRunValidationError, parseDreamOperations, } from './team-memory-dream-ops.js';
3
+ import { toDreamRunRecord, } from './team-memory-dream-types.js';
4
+ const hashText = (text) => createHash('sha256').update(text).digest('hex');
5
+ const DREAM_SOURCE_MESSAGE_TYPES = "'user_input', 'send', 'report'";
6
+ const excerptFor = (text) => (text ? [...text].slice(0, 500).join('') : null);
7
+ const parseTags = (tags) => {
8
+ if (!tags)
9
+ return [];
10
+ const parsed = JSON.parse(tags);
11
+ return Array.isArray(parsed) ? parsed.filter((tag) => typeof tag === 'string') : [];
12
+ };
13
+ export const createDreamOperationApplier = (db) => {
14
+ const requireWorkspace = (workspaceId) => {
15
+ const row = db.prepare('SELECT id FROM workspaces WHERE id = ? LIMIT 1').get(workspaceId);
16
+ if (!row)
17
+ throw new DreamRunValidationError('Dream workspace no longer exists');
18
+ };
19
+ const requireRunningRunRow = (workspaceId, runId) => {
20
+ const row = db
21
+ .prepare(`SELECT *
22
+ FROM dream_runs
23
+ WHERE id = ?
24
+ AND workspace_id = ?
25
+ AND status = 'running'
26
+ LIMIT 1`)
27
+ .get(runId, workspaceId);
28
+ if (!row)
29
+ throw new DreamRunValidationError('Dream run is no longer running');
30
+ return row;
31
+ };
32
+ const getMemoryRow = (workspaceId, memoryId) => db
33
+ .prepare(`SELECT *
34
+ FROM memory_entries
35
+ WHERE id = ?
36
+ AND scope = 'workspace'
37
+ AND workspace_id = ?
38
+ LIMIT 1`)
39
+ .get(memoryId, workspaceId);
40
+ const requireMemoryRow = (workspaceId, memoryId) => {
41
+ const row = getMemoryRow(workspaceId, memoryId);
42
+ if (!row)
43
+ throw new DreamRunValidationError('Dream op memory id is outside this workspace');
44
+ return row;
45
+ };
46
+ const listSourceRows = (memoryId) => db
47
+ .prepare(`SELECT *
48
+ FROM memory_sources
49
+ WHERE memory_id = ?
50
+ ORDER BY created_at ASC, id ASC`)
51
+ .all(memoryId);
52
+ const nextFtsRowid = () => db.prepare('SELECT COALESCE(MAX(fts_rowid), 0) + 1 AS next FROM memory_entries').get().next;
53
+ const getMessageSource = (workspaceId, run, sequence) => {
54
+ if (run.input_seq_from === null || run.input_seq_to === null)
55
+ return undefined;
56
+ return db
57
+ .prepare(`SELECT sequence, text
58
+ FROM messages
59
+ WHERE workspace_id = ?
60
+ AND sequence = ?
61
+ AND sequence BETWEEN ? AND ?
62
+ AND type IN (${DREAM_SOURCE_MESSAGE_TYPES})
63
+ LIMIT 1`)
64
+ .get(workspaceId, sequence, run.input_seq_from, run.input_seq_to);
65
+ };
66
+ const rememberPrior = (prior, workspaceId, memoryId) => {
67
+ if (prior.has(memoryId))
68
+ return;
69
+ const row = requireMemoryRow(workspaceId, memoryId);
70
+ prior.set(memoryId, { entry: row, sources: listSourceRows(memoryId) });
71
+ };
72
+ const validateTouchedIds = (operations) => {
73
+ const touched = new Set();
74
+ for (const op of operations) {
75
+ const ids = op.op === 'add' ? [] : op.op === 'merge' ? [op.into, ...op.from] : [op.id];
76
+ for (const id of ids) {
77
+ if (touched.has(id)) {
78
+ throw new DreamRunValidationError('Dream ops must not touch the same memory twice');
79
+ }
80
+ touched.add(id);
81
+ }
82
+ }
83
+ };
84
+ const insertDreamSource = (memoryId, sourceSequence, messageText, now) => {
85
+ const sourceType = sourceSequence === null ? 'dream' : 'message';
86
+ db.prepare(`INSERT INTO memory_sources (
87
+ id,
88
+ memory_id,
89
+ source_type,
90
+ source_id,
91
+ source_sequence,
92
+ excerpt,
93
+ text_hash,
94
+ actor_agent_id_snapshot,
95
+ actor_name_snapshot,
96
+ actor_role_snapshot,
97
+ created_at
98
+ ) VALUES (?, ?, ?, NULL, ?, ?, ?, NULL, NULL, NULL, ?)`).run(randomUUID(), memoryId, sourceType, sourceSequence, excerptFor(messageText), messageText ? hashText(messageText) : null, now);
99
+ };
100
+ const insertDreamMemory = (workspaceId, run, op, now) => {
101
+ const id = randomUUID();
102
+ db.prepare(`INSERT INTO memory_entries (
103
+ id,
104
+ workspace_id,
105
+ scope,
106
+ fts_rowid,
107
+ kind,
108
+ body,
109
+ tags,
110
+ status,
111
+ source,
112
+ confidence,
113
+ pinned,
114
+ disabled,
115
+ created_at,
116
+ updated_at,
117
+ archived_at,
118
+ last_injected_at
119
+ ) VALUES (?, ?, 'workspace', ?, ?, ?, ?, 'active', 'dream', ?, 0, 0, ?, ?, NULL, NULL)`).run(id, workspaceId, nextFtsRowid(), op.kind, op.body, JSON.stringify(op.tags), op.confidence, now, now);
120
+ if (op.sources.length === 0) {
121
+ insertDreamSource(id, null, null, now);
122
+ }
123
+ else {
124
+ for (const sequence of op.sources) {
125
+ const source = getMessageSource(workspaceId, run, sequence);
126
+ if (!source)
127
+ throw new DreamRunValidationError('Dream op source is outside this run input');
128
+ insertDreamSource(id, sequence, source.text, now);
129
+ }
130
+ }
131
+ return { body: op.body, id, kind: op.kind };
132
+ };
133
+ const updateEntryBody = (workspaceId, memoryId, input, now) => {
134
+ const current = requireMemoryRow(workspaceId, memoryId);
135
+ db.prepare(`UPDATE memory_entries
136
+ SET body = ?,
137
+ tags = ?,
138
+ kind = ?,
139
+ confidence = ?,
140
+ updated_at = ?
141
+ WHERE id = ?
142
+ AND workspace_id = ?
143
+ AND scope = 'workspace'`).run(input.body, JSON.stringify(input.tags ?? parseTags(current.tags)), input.kind ?? current.kind, input.confidence === undefined ? current.confidence : input.confidence, now, memoryId, workspaceId);
144
+ insertDreamSource(memoryId, null, null, now);
145
+ };
146
+ const archiveEntry = (workspaceId, memoryId, now) => {
147
+ requireMemoryRow(workspaceId, memoryId);
148
+ db.prepare(`UPDATE memory_entries
149
+ SET status = 'archived',
150
+ archived_at = COALESCE(archived_at, ?),
151
+ updated_at = ?
152
+ WHERE id = ?
153
+ AND workspace_id = ?
154
+ AND scope = 'workspace'`).run(now, now, memoryId, workspaceId);
155
+ insertDreamSource(memoryId, null, null, now);
156
+ };
157
+ const buildPriorState = (workspaceId, run, operations) => {
158
+ validateTouchedIds(operations);
159
+ const prior = new Map();
160
+ for (const op of operations) {
161
+ if (op.op === 'add') {
162
+ for (const sequence of op.sources) {
163
+ if (!getMessageSource(workspaceId, run, sequence)) {
164
+ throw new DreamRunValidationError('Dream op source is outside this run input');
165
+ }
166
+ }
167
+ continue;
168
+ }
169
+ if (op.op === 'merge' && op.from.includes(op.into)) {
170
+ throw new DreamRunValidationError('Dream merge cannot merge a memory into itself');
171
+ }
172
+ const ids = op.op === 'merge' ? [op.into, ...op.from] : [op.id];
173
+ for (const id of ids)
174
+ rememberPrior(prior, workspaceId, id);
175
+ }
176
+ return prior;
177
+ };
178
+ const applyOperations = (workspaceId, run, operations) => {
179
+ const prior = buildPriorState(workspaceId, run, operations);
180
+ const report = { added: [], archived: [], merged: [], rewritten: [] };
181
+ const addedEntryIds = [];
182
+ const now = Date.now();
183
+ for (const op of operations) {
184
+ if (op.op === 'add') {
185
+ const added = insertDreamMemory(workspaceId, run, op, now);
186
+ addedEntryIds.push(added.id);
187
+ report.added.push(added);
188
+ }
189
+ else if (op.op === 'archive') {
190
+ archiveEntry(workspaceId, op.id, now);
191
+ report.archived.push({ id: op.id, reason: op.reason });
192
+ }
193
+ else if (op.op === 'rewrite') {
194
+ updateEntryBody(workspaceId, op.id, op, now);
195
+ report.rewritten.push({ id: op.id });
196
+ }
197
+ else {
198
+ updateEntryBody(workspaceId, op.into, op, now);
199
+ for (const id of op.from)
200
+ archiveEntry(workspaceId, id, now);
201
+ report.merged.push({ from: op.from, into: op.into });
202
+ }
203
+ }
204
+ return {
205
+ report,
206
+ revertBlob: {
207
+ added_entry_ids: addedEntryIds,
208
+ prior_entries: [...prior.values()],
209
+ },
210
+ };
211
+ };
212
+ const applyAndCompleteRunTransaction = db.transaction((workspaceId, runId, rawOps) => {
213
+ requireWorkspace(workspaceId);
214
+ const run = requireRunningRunRow(workspaceId, runId);
215
+ const { report, revertBlob } = applyOperations(workspaceId, run, parseDreamOperations(rawOps));
216
+ db.prepare(`UPDATE dream_runs
217
+ SET status = 'completed',
218
+ finished_at = ?,
219
+ report = ?,
220
+ revert_blob = ?,
221
+ error = NULL
222
+ WHERE id = ?
223
+ AND workspace_id = ?
224
+ AND status = 'running'`).run(Date.now(), JSON.stringify(report), JSON.stringify(revertBlob), runId, workspaceId);
225
+ const completedRow = db
226
+ .prepare('SELECT * FROM dream_runs WHERE id = ? AND workspace_id = ? LIMIT 1')
227
+ .get(runId, workspaceId);
228
+ if (!completedRow)
229
+ throw new DreamRunValidationError('Dream run disappeared');
230
+ return toDreamRunRecord(completedRow);
231
+ });
232
+ const applyAndCompleteRun = (workspaceId, runId, rawOps) => applyAndCompleteRunTransaction(workspaceId, runId, rawOps);
233
+ return { applyAndCompleteRun };
234
+ };
@@ -0,0 +1,13 @@
1
+ import type { DreamRunRecord } from './team-memory-dream-store.js';
2
+ export declare const serializeDreamRun: (run: DreamRunRecord) => {
3
+ error: string | null;
4
+ finished_at: number | null;
5
+ id: string;
6
+ input_seq_from: number | null;
7
+ input_seq_to: number | null;
8
+ report: import("./team-memory-dream-types.js").DreamRunReport | null;
9
+ started_at: number;
10
+ status: import("./team-memory-dream-types.js").DreamRunStatus;
11
+ trigger: import("./team-memory-dream-types.js").DreamRunTrigger;
12
+ workspace_id: string;
13
+ };
@@ -0,0 +1,12 @@
1
+ export const serializeDreamRun = (run) => ({
2
+ error: run.error,
3
+ finished_at: run.finishedAt,
4
+ id: run.id,
5
+ input_seq_from: run.inputSeqFrom,
6
+ input_seq_to: run.inputSeqTo,
7
+ report: run.report,
8
+ started_at: run.startedAt,
9
+ status: run.status,
10
+ trigger: run.trigger,
11
+ workspace_id: run.workspaceId,
12
+ });
@@ -0,0 +1,40 @@
1
+ import { type MemoryKind } from '../shared/team-memory.js';
2
+ interface DreamOperationBase {
3
+ op: string;
4
+ }
5
+ export interface DreamAddOperation extends DreamOperationBase {
6
+ body: string;
7
+ confidence: number;
8
+ kind: MemoryKind;
9
+ op: 'add';
10
+ sources: number[];
11
+ tags: string[];
12
+ }
13
+ export interface DreamRewriteOperation extends DreamOperationBase {
14
+ body: string;
15
+ confidence?: number | null | undefined;
16
+ id: string;
17
+ kind?: MemoryKind | undefined;
18
+ op: 'rewrite';
19
+ tags?: string[] | undefined;
20
+ }
21
+ export interface DreamArchiveOperation extends DreamOperationBase {
22
+ id: string;
23
+ op: 'archive';
24
+ reason: string | null;
25
+ }
26
+ export interface DreamMergeOperation extends DreamOperationBase {
27
+ body: string;
28
+ confidence?: number | null | undefined;
29
+ from: string[];
30
+ into: string;
31
+ kind?: MemoryKind | undefined;
32
+ op: 'merge';
33
+ tags?: string[] | undefined;
34
+ }
35
+ export type DreamOperation = DreamAddOperation | DreamArchiveOperation | DreamMergeOperation | DreamRewriteOperation;
36
+ export declare class DreamRunValidationError extends Error {
37
+ readonly code = "dream_validation_failed";
38
+ }
39
+ export declare const parseDreamOperations: (rawOps: unknown) => DreamOperation[];
40
+ export {};