@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.
- package/CHANGELOG.md +60 -0
- package/README.en.md +73 -11
- package/README.md +41 -8
- package/dist/src/cli/hive-remote.d.ts +46 -0
- package/dist/src/cli/hive-remote.js +257 -0
- package/dist/src/cli/hive-update.js +7 -2
- package/dist/src/cli/hive.d.ts +6 -0
- package/dist/src/cli/hive.js +64 -0
- package/dist/src/cli/team.d.ts +22 -0
- package/dist/src/cli/team.js +255 -5
- package/dist/src/server/agent-command-resolver.js +10 -3
- package/dist/src/server/agent-exit-classification.d.ts +6 -0
- package/dist/src/server/agent-exit-classification.js +6 -0
- package/dist/src/server/agent-manager-support.d.ts +2 -1
- package/dist/src/server/agent-manager-support.js +59 -15
- package/dist/src/server/agent-manager.d.ts +3 -0
- package/dist/src/server/agent-manager.js +22 -7
- package/dist/src/server/agent-run-bootstrap.d.ts +14 -0
- package/dist/src/server/agent-run-bootstrap.js +11 -4
- package/dist/src/server/agent-run-exit-handler.js +14 -8
- package/dist/src/server/agent-run-starter.d.ts +3 -1
- package/dist/src/server/agent-run-starter.js +22 -5
- package/dist/src/server/agent-run-sync.js +13 -5
- package/dist/src/server/agent-runtime-types.d.ts +1 -0
- package/dist/src/server/agent-runtime.d.ts +2 -1
- package/dist/src/server/agent-runtime.js +9 -2
- package/dist/src/server/agent-startup-instructions.d.ts +2 -1
- package/dist/src/server/agent-startup-instructions.js +8 -4
- package/dist/src/server/agent-stdin-dispatcher.d.ts +4 -2
- package/dist/src/server/agent-stdin-dispatcher.js +35 -3
- package/dist/src/server/command-preset-defaults.d.ts +6 -1
- package/dist/src/server/command-preset-defaults.js +56 -0
- package/dist/src/server/fs-browse.d.ts +2 -0
- package/dist/src/server/fs-browse.js +165 -31
- package/dist/src/server/fs-pick-folder.js +6 -69
- package/dist/src/server/fs-sandbox.d.ts +5 -3
- package/dist/src/server/fs-sandbox.js +5 -3
- package/dist/src/server/hive-team-guidance.js +18 -6
- package/dist/src/server/machine-name.d.ts +2 -0
- package/dist/src/server/machine-name.js +13 -0
- package/dist/src/server/open-target-commands.d.ts +1 -0
- package/dist/src/server/open-target-commands.js +4 -1
- package/dist/src/server/orchestrator-autostart.js +1 -1
- package/dist/src/server/platform-path.d.ts +1 -0
- package/dist/src/server/platform-path.js +14 -1
- package/dist/src/server/post-start-input-writer.js +50 -13
- package/dist/src/server/preset-launch-support.js +1 -0
- package/dist/src/server/recovery-summary.d.ts +2 -1
- package/dist/src/server/recovery-summary.js +2 -1
- package/dist/src/server/remote-audit-store.d.ts +51 -0
- package/dist/src/server/remote-audit-store.js +108 -0
- package/dist/src/server/remote-config-keys.d.ts +17 -0
- package/dist/src/server/remote-config-keys.js +27 -0
- package/dist/src/server/remote-control-constants.d.ts +30 -0
- package/dist/src/server/remote-control-constants.js +29 -0
- package/dist/src/server/remote-device-session.d.ts +40 -0
- package/dist/src/server/remote-device-session.js +22 -0
- package/dist/src/server/remote-device-store.d.ts +36 -0
- package/dist/src/server/remote-device-store.js +67 -0
- package/dist/src/server/remote-frame-bridge.d.ts +102 -0
- package/dist/src/server/remote-frame-bridge.js +791 -0
- package/dist/src/server/remote-gateway-client.d.ts +14 -0
- package/dist/src/server/remote-gateway-client.js +36 -0
- package/dist/src/server/remote-loopback-auth.d.ts +6 -0
- package/dist/src/server/remote-loopback-auth.js +112 -0
- package/dist/src/server/remote-pairing-tunnel.d.ts +59 -0
- package/dist/src/server/remote-pairing-tunnel.js +146 -0
- package/dist/src/server/remote-pairing.d.ts +58 -0
- package/dist/src/server/remote-pairing.js +237 -0
- package/dist/src/server/remote-tunnel.d.ts +113 -0
- package/dist/src/server/remote-tunnel.js +514 -0
- package/dist/src/server/restart-policy-support.d.ts +4 -1
- package/dist/src/server/restart-policy-support.js +3 -1
- package/dist/src/server/restart-policy.d.ts +1 -1
- package/dist/src/server/restart-policy.js +19 -3
- package/dist/src/server/route-types.d.ts +1 -1
- package/dist/src/server/routes-dispatches.js +1 -1
- package/dist/src/server/routes-fs.js +3 -3
- package/dist/src/server/routes-marketplace.js +2 -2
- package/dist/src/server/routes-open-workspace.js +1 -1
- package/dist/src/server/routes-remote.d.ts +2 -0
- package/dist/src/server/routes-remote.js +166 -0
- package/dist/src/server/routes-runtime.js +6 -6
- package/dist/src/server/routes-settings.js +16 -16
- package/dist/src/server/routes-tasks.js +2 -2
- package/dist/src/server/routes-team-memory.d.ts +2 -0
- package/dist/src/server/routes-team-memory.js +154 -0
- package/dist/src/server/routes-team-recall.d.ts +2 -0
- package/dist/src/server/routes-team-recall.js +119 -0
- package/dist/src/server/routes-team.js +31 -9
- package/dist/src/server/routes-ui.js +11 -1
- package/dist/src/server/routes-workflow-schedules.js +3 -3
- package/dist/src/server/routes-workflows.js +5 -5
- package/dist/src/server/routes-workspace-memory-dreams.d.ts +2 -0
- package/dist/src/server/routes-workspace-memory-dreams.js +105 -0
- package/dist/src/server/routes-workspace-memory.d.ts +2 -0
- package/dist/src/server/routes-workspace-memory.js +215 -0
- package/dist/src/server/routes-workspaces.js +9 -9
- package/dist/src/server/routes.js +10 -0
- package/dist/src/server/runtime-database.d.ts +1 -0
- package/dist/src/server/runtime-database.js +27 -2
- package/dist/src/server/runtime-restart-policy.d.ts +3 -1
- package/dist/src/server/runtime-restart-policy.js +2 -1
- package/dist/src/server/runtime-store-contract.d.ts +37 -0
- package/dist/src/server/runtime-store-dream.d.ts +23 -0
- package/dist/src/server/runtime-store-dream.js +16 -0
- package/dist/src/server/runtime-store-helpers.d.ts +20 -0
- package/dist/src/server/runtime-store-helpers.js +81 -7
- package/dist/src/server/runtime-store-memory.d.ts +33 -0
- package/dist/src/server/runtime-store-memory.js +37 -0
- package/dist/src/server/runtime-store-remote.d.ts +5 -0
- package/dist/src/server/runtime-store-remote.js +45 -0
- package/dist/src/server/runtime-store-workflows.js +2 -0
- package/dist/src/server/runtime-store.js +14 -3
- package/dist/src/server/session-capture-claude.d.ts +1 -1
- package/dist/src/server/session-capture-claude.js +7 -4
- package/dist/src/server/session-capture-codex.js +4 -5
- package/dist/src/server/session-capture-gemini.js +4 -5
- package/dist/src/server/session-capture-opencode.d.ts +4 -4
- package/dist/src/server/session-capture-opencode.js +20 -12
- package/dist/src/server/session-capture-qwen.d.ts +5 -0
- package/dist/src/server/session-capture-qwen.js +104 -0
- package/dist/src/server/session-capture.d.ts +17 -0
- package/dist/src/server/session-capture.js +16 -0
- package/dist/src/server/sqlite-schema-v23.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v23.js +43 -0
- package/dist/src/server/sqlite-schema-v24.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v24.js +34 -0
- package/dist/src/server/sqlite-schema-v25.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v25.js +127 -0
- package/dist/src/server/sqlite-schema-v26.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v26.js +56 -0
- package/dist/src/server/sqlite-schema-v27.d.ts +6 -0
- package/dist/src/server/sqlite-schema-v27.js +92 -0
- package/dist/src/server/sqlite-schema-v28.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v28.js +19 -0
- package/dist/src/server/sqlite-schema-v29.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v29.js +27 -0
- package/dist/src/server/sqlite-schema-v30.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v30.js +27 -0
- package/dist/src/server/sqlite-schema-v31.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v31.js +30 -0
- package/dist/src/server/sqlite-schema.d.ts +1 -1
- package/dist/src/server/sqlite-schema.js +49 -1
- package/dist/src/server/startup-command-parser.js +5 -1
- package/dist/src/server/tasks-file-watcher.d.ts +2 -0
- package/dist/src/server/tasks-file-watcher.js +15 -6
- package/dist/src/server/tasks-file.js +30 -5
- package/dist/src/server/tasks-websocket-server.js +4 -0
- package/dist/src/server/team-authz.d.ts +1 -1
- package/dist/src/server/team-authz.js +13 -1
- package/dist/src/server/team-list-enrichment.js +3 -1
- package/dist/src/server/team-memory-digest.d.ts +52 -0
- package/dist/src/server/team-memory-digest.js +200 -0
- package/dist/src/server/team-memory-dream-applier.d.ts +5 -0
- package/dist/src/server/team-memory-dream-applier.js +234 -0
- package/dist/src/server/team-memory-dream-http-serializers.d.ts +13 -0
- package/dist/src/server/team-memory-dream-http-serializers.js +12 -0
- package/dist/src/server/team-memory-dream-ops.d.ts +40 -0
- package/dist/src/server/team-memory-dream-ops.js +153 -0
- package/dist/src/server/team-memory-dream-reverter.d.ts +22 -0
- package/dist/src/server/team-memory-dream-reverter.js +221 -0
- package/dist/src/server/team-memory-dream-run-store.d.ts +23 -0
- package/dist/src/server/team-memory-dream-run-store.js +211 -0
- package/dist/src/server/team-memory-dream-runner.d.ts +37 -0
- package/dist/src/server/team-memory-dream-runner.js +178 -0
- package/dist/src/server/team-memory-dream-scheduler.d.ts +32 -0
- package/dist/src/server/team-memory-dream-scheduler.js +115 -0
- package/dist/src/server/team-memory-dream-store.d.ts +19 -0
- package/dist/src/server/team-memory-dream-store.js +16 -0
- package/dist/src/server/team-memory-dream-types.d.ts +104 -0
- package/dist/src/server/team-memory-dream-types.js +23 -0
- package/dist/src/server/team-memory-export.d.ts +22 -0
- package/dist/src/server/team-memory-export.js +220 -0
- package/dist/src/server/team-memory-feature.d.ts +12 -0
- package/dist/src/server/team-memory-feature.js +12 -0
- package/dist/src/server/team-memory-http-serializers.d.ts +102 -0
- package/dist/src/server/team-memory-http-serializers.js +46 -0
- package/dist/src/server/team-memory-injection.d.ts +31 -0
- package/dist/src/server/team-memory-injection.js +49 -0
- package/dist/src/server/team-memory-store.d.ts +116 -0
- package/dist/src/server/team-memory-store.js +513 -0
- package/dist/src/server/team-operations.d.ts +5 -1
- package/dist/src/server/team-operations.js +46 -16
- package/dist/src/server/team-recall-store.d.ts +38 -0
- package/dist/src/server/team-recall-store.js +205 -0
- package/dist/src/server/terminal-input-profile.d.ts +1 -1
- package/dist/src/server/terminal-input-profile.js +18 -0
- package/dist/src/server/terminal-ws-server.js +6 -0
- package/dist/src/server/ui-auth-helpers.d.ts +1 -1
- package/dist/src/server/ui-auth-helpers.js +7 -1
- package/dist/src/server/ui-auth.d.ts +3 -0
- package/dist/src/server/ui-auth.js +21 -1
- package/dist/src/server/workflow-cli-policy.d.ts +2 -3
- package/dist/src/server/workflow-cli-policy.js +3 -3
- package/dist/src/server/workflow-runner.d.ts +1 -0
- package/dist/src/server/workflow-runner.js +9 -4
- package/dist/src/server/workspace-path-validation.js +6 -2
- package/dist/src/server/workspace-store.d.ts +1 -1
- package/dist/src/server/workspace-store.js +35 -9
- package/dist/src/shared/fs-browse.d.ts +1 -0
- package/dist/src/shared/fs-browse.js +1 -0
- package/dist/src/shared/path-input.d.ts +12 -0
- package/dist/src/shared/path-input.js +22 -0
- package/dist/src/shared/remote-bridge-routing.d.ts +19 -0
- package/dist/src/shared/remote-bridge-routing.js +141 -0
- package/dist/src/shared/remote-crypto.d.ts +138 -0
- package/dist/src/shared/remote-crypto.js +427 -0
- package/dist/src/shared/remote-pairing-code.d.ts +7 -0
- package/dist/src/shared/remote-pairing-code.js +47 -0
- package/dist/src/shared/remote-protocol.d.ts +160 -0
- package/dist/src/shared/remote-protocol.js +526 -0
- package/dist/src/shared/team-memory.d.ts +11 -0
- package/dist/src/shared/team-memory.js +10 -0
- package/dist/src/shared/team-recall.d.ts +1 -0
- package/dist/src/shared/team-recall.js +1 -0
- package/dist/src/shared/types.d.ts +4 -5
- package/package.json +12 -5
- package/scripts/postinstall-native-artifacts.mjs +113 -0
- package/web/dist/assets/AddWorkerDialog-CbV75qUX.js +2 -0
- package/web/dist/assets/AddWorkspaceFlow-CwV-7wPx.js +1 -0
- package/web/dist/assets/FirstRunWizard-a6PWIK3x.js +1 -0
- package/web/dist/assets/MarketplaceDrawer-Dd8WIA8T.js +67 -0
- package/web/dist/assets/TaskGraphDrawer-Bk5WFIk_.js +1 -0
- package/web/dist/assets/{WhatsNewDialog-CHkZeINH.js → WhatsNewDialog-C2VZaip0.js} +1 -1
- package/web/dist/assets/WorkerModal-DucW-9YT.js +1 -0
- package/web/dist/assets/WorkflowsDrawer-Bjf4olbR.js +1 -0
- package/web/dist/assets/WorkspaceMemoryDrawer-DglCy_5f.js +1 -0
- package/web/dist/assets/WorkspaceTaskDrawer-BIWwISvA.js +1 -0
- package/web/dist/assets/index-BAiLYajK.css +1 -0
- package/web/dist/assets/index-BV2k9Dts.js +73 -0
- package/web/dist/assets/search-Bk2HQvO7.js +1 -0
- package/web/dist/assets/square-terminal-D93m9hfY.js +1 -0
- package/web/dist/cli-icons/agy.png +0 -0
- package/web/dist/cli-icons/cursor.ico +0 -0
- package/web/dist/cli-icons/grok.ico +0 -0
- package/web/dist/cli-icons/qwen.png +0 -0
- package/web/dist/index.html +8 -3
- package/web/dist/sw.js +1 -1
- package/scripts/fix-runtime-artifacts.mjs +0 -33
- package/web/dist/assets/AddWorkerDialog-BRUxpa3f.js +0 -2
- package/web/dist/assets/AddWorkspaceDialog-D56x5JCb.js +0 -1
- package/web/dist/assets/FirstRunWizard-BFVaMIsE.js +0 -1
- package/web/dist/assets/MarketplaceDrawer-DeEZ35dN.js +0 -76
- package/web/dist/assets/WorkerModal-BBCuMLIa.js +0 -1
- package/web/dist/assets/WorkspaceTaskDrawer-CpZHAcj1.js +0 -1
- package/web/dist/assets/WorkspaceTerminalPanels-7If2mDyp.js +0 -1
- package/web/dist/assets/WorkspaceTerminalPanels-DDGTF8rc.css +0 -1
- package/web/dist/assets/index-5zh61jMg.css +0 -1
- package/web/dist/assets/index-CxNL0O-C.js +0 -73
- package/web/dist/assets/path-join-7MR1s7b1.js +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { DreamRunAlreadyRunningError } from './team-memory-dream-store.js';
|
|
3
|
+
const DREAM_CLI_TIMEOUT_MS = 120_000;
|
|
4
|
+
export const defaultDreamCliCommand = () => ({
|
|
5
|
+
args: [],
|
|
6
|
+
command: 'claude',
|
|
7
|
+
});
|
|
8
|
+
export const dreamCliCommandForLaunchCommand = (command) => {
|
|
9
|
+
const normalized = command.trim();
|
|
10
|
+
const executable = normalized.split(/[\\/]/).at(-1)?.toLowerCase() ?? normalized.toLowerCase();
|
|
11
|
+
if (executable === 'claude' || executable === 'claude.exe') {
|
|
12
|
+
return { args: ['-p'], command: normalized };
|
|
13
|
+
}
|
|
14
|
+
return { args: [], command: normalized };
|
|
15
|
+
};
|
|
16
|
+
const formatMessages = (messages) => {
|
|
17
|
+
if (messages.length === 0)
|
|
18
|
+
return 'No new protocol messages.';
|
|
19
|
+
return messages
|
|
20
|
+
.map((message) => [
|
|
21
|
+
`#${message.sequence} ${message.type} worker=${message.workerId}`,
|
|
22
|
+
message.status ? `status=${message.status}` : null,
|
|
23
|
+
message.artifacts ? `artifacts=${message.artifacts}` : null,
|
|
24
|
+
message.text?.trim() || '(empty)',
|
|
25
|
+
]
|
|
26
|
+
.filter((line) => Boolean(line))
|
|
27
|
+
.join('\n'))
|
|
28
|
+
.join('\n\n');
|
|
29
|
+
};
|
|
30
|
+
const formatMemories = (memories) => {
|
|
31
|
+
if (memories.length === 0)
|
|
32
|
+
return 'No current memory entries.';
|
|
33
|
+
return memories
|
|
34
|
+
.map((memory) => [
|
|
35
|
+
`id=${memory.id} status=${memory.status} kind=${memory.kind} source=${memory.source}`,
|
|
36
|
+
memory.body,
|
|
37
|
+
memory.tags.length > 0 ? `tags=${memory.tags.join(', ')}` : null,
|
|
38
|
+
]
|
|
39
|
+
.filter((line) => Boolean(line))
|
|
40
|
+
.join('\n'))
|
|
41
|
+
.join('\n\n');
|
|
42
|
+
};
|
|
43
|
+
export const buildDreamPrompt = (input) => [
|
|
44
|
+
'You are Hive Dream, an offline memory consolidation agent.',
|
|
45
|
+
'Read only the protocol messages and current Hive memory entries below.',
|
|
46
|
+
'Return strict JSON only, with shape {"ops":[...]} and no prose.',
|
|
47
|
+
'',
|
|
48
|
+
'Allowed ops:',
|
|
49
|
+
'- {"op":"add","kind":"fact|preference|decision|pitfall|procedure_ref","body":"...","tags":[],"confidence":0.0-1.0,"sources":[{"sequence":123}]}',
|
|
50
|
+
'- {"op":"rewrite","id":"<memory-id>","body":"...","tags":[]}',
|
|
51
|
+
'- {"op":"archive","id":"<memory-id>","reason":"..."}',
|
|
52
|
+
'- {"op":"merge","into":"<memory-id>","from":["<memory-id>"],"body":"..."}',
|
|
53
|
+
'',
|
|
54
|
+
'Rules: add at most 10 entries; every body must be 500 characters or fewer; archive never deletes; if nothing is worth remembering, return {"ops":[]}.',
|
|
55
|
+
'Use protocol evidence only: report text, dispatch status, user input, and artifacts. Do not trust self-praise without a concrete report or failure signal.',
|
|
56
|
+
'If newer protocol evidence contradicts an active memory entry, add or rewrite the newer durable fact and archive the contradicted old memory with a supersession reason. Do not leave contradictory active entries side by side.',
|
|
57
|
+
'',
|
|
58
|
+
`Workspace: ${input.workspaceId}`,
|
|
59
|
+
'',
|
|
60
|
+
'## New protocol messages',
|
|
61
|
+
formatMessages(input.messages),
|
|
62
|
+
'',
|
|
63
|
+
'## Current memory entries',
|
|
64
|
+
formatMemories(input.memories),
|
|
65
|
+
].join('\n');
|
|
66
|
+
const parseJson = (value) => JSON.parse(value);
|
|
67
|
+
const extractDreamOutput = (stdout) => {
|
|
68
|
+
const trimmed = stdout.trim();
|
|
69
|
+
if (!trimmed)
|
|
70
|
+
throw new Error('Dream CLI returned empty output');
|
|
71
|
+
try {
|
|
72
|
+
return parseJson(trimmed);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
76
|
+
if (fenced?.[1])
|
|
77
|
+
return parseJson(fenced[1].trim());
|
|
78
|
+
throw new Error('Dream CLI output did not contain valid JSON');
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const getOps = (parsed) => {
|
|
82
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
83
|
+
throw new Error('Dream CLI JSON must be an object');
|
|
84
|
+
}
|
|
85
|
+
const ops = parsed.ops;
|
|
86
|
+
if (!Array.isArray(ops))
|
|
87
|
+
throw new Error('Dream CLI JSON must include ops array');
|
|
88
|
+
return ops;
|
|
89
|
+
};
|
|
90
|
+
const truncateError = (value) => [...value].slice(0, 1000).join('');
|
|
91
|
+
const runHeadlessCli = async (input) => new Promise((resolve, reject) => {
|
|
92
|
+
const child = spawn(input.command.command, input.command.args, {
|
|
93
|
+
cwd: input.cwd,
|
|
94
|
+
env: { ...process.env, HIVE_DREAM_RUN: '1' },
|
|
95
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
96
|
+
});
|
|
97
|
+
let stdout = '';
|
|
98
|
+
let stderr = '';
|
|
99
|
+
let settled = false;
|
|
100
|
+
let forceKillTimer;
|
|
101
|
+
const timeout = setTimeout(() => {
|
|
102
|
+
if (settled)
|
|
103
|
+
return;
|
|
104
|
+
settled = true;
|
|
105
|
+
child.kill('SIGTERM');
|
|
106
|
+
forceKillTimer = setTimeout(() => child.kill('SIGKILL'), 1000);
|
|
107
|
+
forceKillTimer.unref?.();
|
|
108
|
+
reject(new Error('Dream CLI timed out'));
|
|
109
|
+
}, DREAM_CLI_TIMEOUT_MS);
|
|
110
|
+
child.stdout.setEncoding('utf8');
|
|
111
|
+
child.stdout.on('data', (chunk) => {
|
|
112
|
+
stdout += chunk;
|
|
113
|
+
});
|
|
114
|
+
child.stderr.setEncoding('utf8');
|
|
115
|
+
child.stderr.on('data', (chunk) => {
|
|
116
|
+
stderr += chunk;
|
|
117
|
+
});
|
|
118
|
+
child.on('error', (error) => {
|
|
119
|
+
if (settled)
|
|
120
|
+
return;
|
|
121
|
+
settled = true;
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
reject(error);
|
|
124
|
+
});
|
|
125
|
+
child.on('close', (code) => {
|
|
126
|
+
if (forceKillTimer)
|
|
127
|
+
clearTimeout(forceKillTimer);
|
|
128
|
+
if (settled)
|
|
129
|
+
return;
|
|
130
|
+
settled = true;
|
|
131
|
+
clearTimeout(timeout);
|
|
132
|
+
if (code === 0) {
|
|
133
|
+
resolve(stdout);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
reject(new Error(`Dream CLI exited ${code}: ${truncateError(stderr)}`));
|
|
137
|
+
});
|
|
138
|
+
child.stdin.end(input.prompt);
|
|
139
|
+
});
|
|
140
|
+
export const createTeamMemoryDreamRunner = (deps) => {
|
|
141
|
+
const runningWorkspaceIds = new Set();
|
|
142
|
+
const run = async (workspaceId, trigger) => {
|
|
143
|
+
if (runningWorkspaceIds.has(workspaceId))
|
|
144
|
+
throw new DreamRunAlreadyRunningError(workspaceId);
|
|
145
|
+
runningWorkspaceIds.add(workspaceId);
|
|
146
|
+
let runRecord;
|
|
147
|
+
try {
|
|
148
|
+
runRecord = deps.dreamStore.createRun({ trigger, workspaceId });
|
|
149
|
+
const messages = deps.dreamStore.listInputMessages(workspaceId, runRecord.inputSeqFrom, runRecord.inputSeqTo);
|
|
150
|
+
const memories = deps.memoryStore.listAllEntries(workspaceId);
|
|
151
|
+
const prompt = buildDreamPrompt({ memories, messages, workspaceId });
|
|
152
|
+
const stdout = await runHeadlessCli({
|
|
153
|
+
command: deps.getDreamCliCommand?.(workspaceId) ?? defaultDreamCliCommand(),
|
|
154
|
+
cwd: deps.getWorkspacePath(workspaceId),
|
|
155
|
+
prompt,
|
|
156
|
+
});
|
|
157
|
+
const ops = getOps(extractDreamOutput(stdout));
|
|
158
|
+
const completed = deps.dreamStore.applyAndCompleteRun(workspaceId, runRecord.id, ops);
|
|
159
|
+
deps.scheduleExport(workspaceId);
|
|
160
|
+
return completed;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (!runRecord)
|
|
164
|
+
throw error;
|
|
165
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
166
|
+
const failed = deps.dreamStore.markFailed(runRecord.id, truncateError(message), runRecord);
|
|
167
|
+
deps.scheduleExport(workspaceId);
|
|
168
|
+
return failed;
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
runningWorkspaceIds.delete(workspaceId);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
runManual: (workspaceId) => run(workspaceId, 'manual'),
|
|
176
|
+
runScheduled: (workspaceId) => run(workspaceId, 'scheduled'),
|
|
177
|
+
};
|
|
178
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AgentSummary, WorkspaceSummary } from '../shared/types.js';
|
|
2
|
+
import type { SettingsStore } from './settings-store.js';
|
|
3
|
+
import type { DreamScheduleState } from './team-memory-dream-store.js';
|
|
4
|
+
export declare const DREAM_SCHEDULER_FLOOR_MS: number;
|
|
5
|
+
export declare const DREAM_SCHEDULER_BACKOFF_CAP = 5;
|
|
6
|
+
export declare const DREAM_SCHEDULER_IDLE_DEBOUNCE_MS = 60000;
|
|
7
|
+
export declare const DREAM_SCHEDULER_MIN_MESSAGES = 1;
|
|
8
|
+
export declare const DREAM_SCHEDULER_TICK_INTERVAL_MS = 30000;
|
|
9
|
+
interface WorkspaceSnapshot {
|
|
10
|
+
agents: AgentSummary[];
|
|
11
|
+
}
|
|
12
|
+
export interface TeamMemoryDreamSchedulerDeps {
|
|
13
|
+
floorMs?: number;
|
|
14
|
+
getScheduleState: (workspaceId: string) => DreamScheduleState;
|
|
15
|
+
getWorkspaceSnapshot: (workspaceId: string) => WorkspaceSnapshot;
|
|
16
|
+
idleDebounceMs?: number;
|
|
17
|
+
listWorkspaces: () => WorkspaceSummary[];
|
|
18
|
+
logError?: (workspaceId: string, error: unknown) => void;
|
|
19
|
+
minMessages?: number;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
runScheduled: (workspaceId: string) => Promise<unknown>;
|
|
22
|
+
settings: SettingsStore;
|
|
23
|
+
}
|
|
24
|
+
export interface TeamMemoryDreamScheduler {
|
|
25
|
+
close: () => Promise<void>;
|
|
26
|
+
start: (input?: {
|
|
27
|
+
tickIntervalMs?: number;
|
|
28
|
+
}) => void;
|
|
29
|
+
tick: (now?: number) => Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare const createTeamMemoryDreamScheduler: (deps: TeamMemoryDreamSchedulerDeps) => TeamMemoryDreamScheduler;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { readWorkspaceMemoryDreamEnabled, readWorkspaceMemoryEnabled, workspaceMemoryDreamEnabledKey, workspaceMemoryEnabledKey, } from './team-memory-feature.js';
|
|
2
|
+
export const DREAM_SCHEDULER_FLOOR_MS = 20 * 60 * 1000;
|
|
3
|
+
// The first failure still retries at the base floor (transient hiccups recover fast);
|
|
4
|
+
// each *additional* consecutive scheduled failure doubles the floor (capped), so a window
|
|
5
|
+
// that keeps failing is retried ever more slowly instead of burning the CLI every floor.
|
|
6
|
+
// At 20min × 2^5 the slowest retry is ~10.6h; a success resets the count and the floor.
|
|
7
|
+
export const DREAM_SCHEDULER_BACKOFF_CAP = 5;
|
|
8
|
+
export const DREAM_SCHEDULER_IDLE_DEBOUNCE_MS = 60_000;
|
|
9
|
+
export const DREAM_SCHEDULER_MIN_MESSAGES = 1;
|
|
10
|
+
export const DREAM_SCHEDULER_TICK_INTERVAL_MS = 30_000;
|
|
11
|
+
const hasWorkingAgent = (agents) => agents.some((agent) => agent.status === 'working');
|
|
12
|
+
const isDreamEnabled = (settings, workspaceId) => readWorkspaceMemoryEnabled(settings.getAppState(workspaceMemoryEnabledKey(workspaceId))?.value) &&
|
|
13
|
+
readWorkspaceMemoryDreamEnabled(settings.getAppState(workspaceMemoryDreamEnabledKey(workspaceId))?.value);
|
|
14
|
+
export const createTeamMemoryDreamScheduler = (deps) => {
|
|
15
|
+
const floorMs = deps.floorMs ?? DREAM_SCHEDULER_FLOOR_MS;
|
|
16
|
+
const idleDebounceMs = deps.idleDebounceMs ?? DREAM_SCHEDULER_IDLE_DEBOUNCE_MS;
|
|
17
|
+
const minMessages = deps.minMessages ?? DREAM_SCHEDULER_MIN_MESSAGES;
|
|
18
|
+
const now = deps.now ?? (() => Date.now());
|
|
19
|
+
const logError = deps.logError ??
|
|
20
|
+
((workspaceId, error) => {
|
|
21
|
+
console.error('[hive] memory dream scheduler failed', { workspaceId, error });
|
|
22
|
+
});
|
|
23
|
+
let timer;
|
|
24
|
+
let closed = false;
|
|
25
|
+
let tickInFlight = false;
|
|
26
|
+
let tickPromise;
|
|
27
|
+
const idleSinceByWorkspace = new Map();
|
|
28
|
+
const clearTimer = () => {
|
|
29
|
+
if (!timer)
|
|
30
|
+
return;
|
|
31
|
+
clearInterval(timer);
|
|
32
|
+
timer = undefined;
|
|
33
|
+
};
|
|
34
|
+
const scheduler = {
|
|
35
|
+
async close() {
|
|
36
|
+
closed = true;
|
|
37
|
+
clearTimer();
|
|
38
|
+
await tickPromise?.catch((error) => {
|
|
39
|
+
console.error('[hive] swallowed:memory-dream-scheduler.close', error);
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
start({ tickIntervalMs = DREAM_SCHEDULER_TICK_INTERVAL_MS } = {}) {
|
|
43
|
+
closed = false;
|
|
44
|
+
clearTimer();
|
|
45
|
+
timer = setInterval(() => {
|
|
46
|
+
void scheduler.tick().catch((error) => {
|
|
47
|
+
console.error('[hive] swallowed:memory-dream-scheduler.tick', error);
|
|
48
|
+
});
|
|
49
|
+
}, tickIntervalMs);
|
|
50
|
+
timer.unref?.();
|
|
51
|
+
},
|
|
52
|
+
async tick(tickNow = now()) {
|
|
53
|
+
if (closed)
|
|
54
|
+
return;
|
|
55
|
+
if (tickInFlight) {
|
|
56
|
+
await tickPromise;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
tickInFlight = true;
|
|
60
|
+
tickPromise = (async () => {
|
|
61
|
+
const eligibleWorkspaces = [];
|
|
62
|
+
for (const workspace of deps.listWorkspaces()) {
|
|
63
|
+
try {
|
|
64
|
+
if (!isDreamEnabled(deps.settings, workspace.id)) {
|
|
65
|
+
idleSinceByWorkspace.delete(workspace.id);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (hasWorkingAgent(deps.getWorkspaceSnapshot(workspace.id).agents)) {
|
|
69
|
+
idleSinceByWorkspace.delete(workspace.id);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const previousIdleSince = idleSinceByWorkspace.get(workspace.id);
|
|
73
|
+
const idleSince = previousIdleSince === undefined || tickNow < previousIdleSince
|
|
74
|
+
? tickNow
|
|
75
|
+
: previousIdleSince;
|
|
76
|
+
idleSinceByWorkspace.set(workspace.id, idleSince);
|
|
77
|
+
if (tickNow - idleSince < idleDebounceMs)
|
|
78
|
+
continue;
|
|
79
|
+
const state = deps.getScheduleState(workspace.id);
|
|
80
|
+
if (state.hasRunningRun)
|
|
81
|
+
continue;
|
|
82
|
+
if (state.pendingMessageCount < minMessages)
|
|
83
|
+
continue;
|
|
84
|
+
const effectiveFloorMs = floorMs *
|
|
85
|
+
2 **
|
|
86
|
+
Math.min(Math.max(0, state.consecutiveScheduledFailures - 1), DREAM_SCHEDULER_BACKOFF_CAP);
|
|
87
|
+
const sinceLastScheduled = state.lastScheduledAt === null ? null : tickNow - state.lastScheduledAt;
|
|
88
|
+
if (sinceLastScheduled !== null && sinceLastScheduled < effectiveFloorMs)
|
|
89
|
+
continue;
|
|
90
|
+
eligibleWorkspaces.push(workspace);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logError(workspace.id, error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await Promise.all(eligibleWorkspaces.map(async (workspace) => {
|
|
97
|
+
try {
|
|
98
|
+
await deps.runScheduled(workspace.id);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
logError(workspace.id, error);
|
|
102
|
+
}
|
|
103
|
+
}));
|
|
104
|
+
})();
|
|
105
|
+
try {
|
|
106
|
+
await tickPromise;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
tickPromise = undefined;
|
|
110
|
+
tickInFlight = false;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
return scheduler;
|
|
115
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Database } from 'better-sqlite3';
|
|
2
|
+
export { DreamRunValidationError } from './team-memory-dream-ops.js';
|
|
3
|
+
export { DreamRunNotFoundError, DreamRunRevertDataError, DreamRunRevertStatusError, } from './team-memory-dream-reverter.js';
|
|
4
|
+
export { DREAM_RUNNING_STALE_MS, DreamRunAlreadyRunningError, DreamWorkspaceMissingError, } from './team-memory-dream-run-store.js';
|
|
5
|
+
export type { DreamMessageInput, DreamRunRecord, DreamRunReport, DreamRunRevertBlob, DreamRunStatus, DreamRunTrigger, DreamScheduleState, } from './team-memory-dream-types.js';
|
|
6
|
+
export declare const createTeamMemoryDreamStore: (db: Database) => {
|
|
7
|
+
revertRun: (workspaceId: string, runId: string) => import("./team-memory-dream-types.js").DreamRunRecord;
|
|
8
|
+
applyAndCompleteRun: (workspaceId: string, runId: string, rawOps: unknown) => import("./team-memory-dream-types.js").DreamRunRecord;
|
|
9
|
+
createRun: (input: {
|
|
10
|
+
trigger: import("./team-memory-dream-types.js").DreamRunTrigger;
|
|
11
|
+
workspaceId: string;
|
|
12
|
+
}) => import("./team-memory-dream-types.js").DreamRunRecord;
|
|
13
|
+
deleteWorkspaceDreamRuns: (workspaceId: string) => void;
|
|
14
|
+
getScheduleState: (workspaceId: string) => import("./team-memory-dream-types.js").DreamScheduleState;
|
|
15
|
+
getRun: (runId: string) => import("./team-memory-dream-types.js").DreamRunRecord | undefined;
|
|
16
|
+
listInputMessages: (workspaceId: string, from: number | null, to: number | null) => import("./team-memory-dream-types.js").DreamMessageInput[];
|
|
17
|
+
listRuns: (workspaceId: string, limit?: number) => import("./team-memory-dream-types.js").DreamRunRecord[];
|
|
18
|
+
markFailed: (runId: string, error: string, fallback?: import("./team-memory-dream-types.js").DreamRunRecord) => import("./team-memory-dream-types.js").DreamRunRecord;
|
|
19
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createDreamOperationApplier } from './team-memory-dream-applier.js';
|
|
2
|
+
import { createDreamRunReverter } from './team-memory-dream-reverter.js';
|
|
3
|
+
import { createDreamRunStore } from './team-memory-dream-run-store.js';
|
|
4
|
+
export { DreamRunValidationError } from './team-memory-dream-ops.js';
|
|
5
|
+
export { DreamRunNotFoundError, DreamRunRevertDataError, DreamRunRevertStatusError, } from './team-memory-dream-reverter.js';
|
|
6
|
+
export { DREAM_RUNNING_STALE_MS, DreamRunAlreadyRunningError, DreamWorkspaceMissingError, } from './team-memory-dream-run-store.js';
|
|
7
|
+
export const createTeamMemoryDreamStore = (db) => {
|
|
8
|
+
const runStore = createDreamRunStore(db);
|
|
9
|
+
const applier = createDreamOperationApplier(db);
|
|
10
|
+
const reverter = createDreamRunReverter(db);
|
|
11
|
+
return {
|
|
12
|
+
...runStore,
|
|
13
|
+
...applier,
|
|
14
|
+
...reverter,
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { MemoryKind } from '../shared/team-memory.js';
|
|
2
|
+
import type { MemorySource, MemorySourceType, MemoryStatus } from './team-memory-store.js';
|
|
3
|
+
export type DreamRunTrigger = 'manual' | 'scheduled';
|
|
4
|
+
export type DreamRunStatus = 'running' | 'completed' | 'failed' | 'reverted';
|
|
5
|
+
export interface DreamRunReport {
|
|
6
|
+
added: Array<{
|
|
7
|
+
body: string;
|
|
8
|
+
id: string;
|
|
9
|
+
kind: MemoryKind;
|
|
10
|
+
}>;
|
|
11
|
+
archived: Array<{
|
|
12
|
+
id: string;
|
|
13
|
+
reason: string | null;
|
|
14
|
+
}>;
|
|
15
|
+
merged: Array<{
|
|
16
|
+
from: string[];
|
|
17
|
+
into: string;
|
|
18
|
+
}>;
|
|
19
|
+
rewritten: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface MemoryEntryRow {
|
|
24
|
+
archived_at: number | null;
|
|
25
|
+
body: string;
|
|
26
|
+
confidence: number | null;
|
|
27
|
+
created_at: number;
|
|
28
|
+
disabled: number;
|
|
29
|
+
fts_rowid: number;
|
|
30
|
+
id: string;
|
|
31
|
+
kind: MemoryKind;
|
|
32
|
+
last_injected_at: number | null;
|
|
33
|
+
pinned: number;
|
|
34
|
+
scope: 'workspace' | 'user';
|
|
35
|
+
source: MemorySource;
|
|
36
|
+
status: MemoryStatus;
|
|
37
|
+
tags: string | null;
|
|
38
|
+
updated_at: number;
|
|
39
|
+
workspace_id: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface MemorySourceRow {
|
|
42
|
+
actor_agent_id_snapshot: string | null;
|
|
43
|
+
actor_name_snapshot: string | null;
|
|
44
|
+
actor_role_snapshot: string | null;
|
|
45
|
+
created_at: number;
|
|
46
|
+
excerpt: string | null;
|
|
47
|
+
id: string;
|
|
48
|
+
memory_id: string;
|
|
49
|
+
source_id: string | null;
|
|
50
|
+
source_sequence: number | null;
|
|
51
|
+
source_type: MemorySourceType;
|
|
52
|
+
text_hash: string | null;
|
|
53
|
+
}
|
|
54
|
+
export interface DreamRunRevertBlob {
|
|
55
|
+
added_entry_ids: string[];
|
|
56
|
+
prior_entries: Array<{
|
|
57
|
+
entry: MemoryEntryRow;
|
|
58
|
+
sources: MemorySourceRow[];
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
export interface DreamRunRecord {
|
|
62
|
+
error: string | null;
|
|
63
|
+
finishedAt: number | null;
|
|
64
|
+
id: string;
|
|
65
|
+
inputSeqFrom: number | null;
|
|
66
|
+
inputSeqTo: number | null;
|
|
67
|
+
report: DreamRunReport | null;
|
|
68
|
+
revertBlob: DreamRunRevertBlob | null;
|
|
69
|
+
startedAt: number;
|
|
70
|
+
status: DreamRunStatus;
|
|
71
|
+
trigger: DreamRunTrigger;
|
|
72
|
+
workspaceId: string;
|
|
73
|
+
}
|
|
74
|
+
export interface DreamScheduleState {
|
|
75
|
+
consecutiveScheduledFailures: number;
|
|
76
|
+
hasRunningRun: boolean;
|
|
77
|
+
lastScheduledAt: number | null;
|
|
78
|
+
pendingMessageCount: number;
|
|
79
|
+
}
|
|
80
|
+
export interface DreamMessageInput {
|
|
81
|
+
artifacts: string | null;
|
|
82
|
+
createdAt: number;
|
|
83
|
+
fromAgentId: string | null;
|
|
84
|
+
sequence: number;
|
|
85
|
+
status: string | null;
|
|
86
|
+
text: string | null;
|
|
87
|
+
toAgentId: string | null;
|
|
88
|
+
type: string;
|
|
89
|
+
workerId: string;
|
|
90
|
+
}
|
|
91
|
+
export interface DreamRunRow {
|
|
92
|
+
error: string | null;
|
|
93
|
+
finished_at: number | null;
|
|
94
|
+
id: string;
|
|
95
|
+
input_seq_from: number | null;
|
|
96
|
+
input_seq_to: number | null;
|
|
97
|
+
report: string | null;
|
|
98
|
+
revert_blob: string | null;
|
|
99
|
+
started_at: number;
|
|
100
|
+
status: DreamRunStatus;
|
|
101
|
+
trigger: DreamRunTrigger;
|
|
102
|
+
workspace_id: string;
|
|
103
|
+
}
|
|
104
|
+
export declare const toDreamRunRecord: (row: DreamRunRow) => DreamRunRecord;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const parseJsonField = (value) => {
|
|
2
|
+
if (!value)
|
|
3
|
+
return null;
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(value);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const toDreamRunRecord = (row) => ({
|
|
12
|
+
error: row.error,
|
|
13
|
+
finishedAt: row.finished_at,
|
|
14
|
+
id: row.id,
|
|
15
|
+
inputSeqFrom: row.input_seq_from,
|
|
16
|
+
inputSeqTo: row.input_seq_to,
|
|
17
|
+
report: parseJsonField(row.report),
|
|
18
|
+
revertBlob: parseJsonField(row.revert_blob),
|
|
19
|
+
startedAt: row.started_at,
|
|
20
|
+
status: row.status,
|
|
21
|
+
trigger: row.trigger,
|
|
22
|
+
workspaceId: row.workspace_id,
|
|
23
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DreamRunRecord } from './team-memory-dream-store.js';
|
|
2
|
+
import type { MemoryEntryWithSources } from './team-memory-store.js';
|
|
3
|
+
export declare const MEMORY_FILE_NAME = "memory.md";
|
|
4
|
+
export declare const MEMORY_RELATIVE_PATH = ".hive/memory.md";
|
|
5
|
+
export declare const MEMORY_EXPORT_DEBOUNCE_MS = 2000;
|
|
6
|
+
export declare const MEMORY_EXPORT_DREAM_CHANGELOG_LIMIT = 10;
|
|
7
|
+
export declare const getMemoryFilePath: (workspacePath: string) => string;
|
|
8
|
+
export declare const renderMemoryExport: (entries: MemoryEntryWithSources[], dreamRuns?: DreamRunRecord[]) => string;
|
|
9
|
+
export interface TeamMemoryExportService {
|
|
10
|
+
cancel: (workspaceId: string) => void;
|
|
11
|
+
close: () => Promise<void>;
|
|
12
|
+
flush: (workspaceId: string) => Promise<void>;
|
|
13
|
+
schedule: (workspaceId: string) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare const createTeamMemoryExportService: ({ debounceMs, getWorkspacePath, listDreamRuns, listEntries, logError, now, }: {
|
|
16
|
+
debounceMs?: number;
|
|
17
|
+
getWorkspacePath: (workspaceId: string) => string;
|
|
18
|
+
listDreamRuns?: (workspaceId: string) => DreamRunRecord[];
|
|
19
|
+
listEntries: (workspaceId: string) => MemoryEntryWithSources[];
|
|
20
|
+
logError?: (workspaceId: string, error: unknown) => void;
|
|
21
|
+
now?: () => number;
|
|
22
|
+
}) => TeamMemoryExportService;
|