@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.
- package/CHANGELOG.md +51 -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 +8 -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-C86CwNgQ.js +2 -0
- package/web/dist/assets/AddWorkspaceFlow-Bm2Jz34D.js +1 -0
- package/web/dist/assets/FirstRunWizard-XzBoEpA5.js +1 -0
- package/web/dist/assets/MarketplaceDrawer-BFfGT8hH.js +67 -0
- package/web/dist/assets/TaskGraphDrawer-_uVH_0C1.js +1 -0
- package/web/dist/assets/{WhatsNewDialog-CHkZeINH.js → WhatsNewDialog-DkJHmkMs.js} +1 -1
- package/web/dist/assets/WorkerModal-BtMJEOG9.js +1 -0
- package/web/dist/assets/WorkflowsDrawer-CiIdHS6_.js +1 -0
- package/web/dist/assets/WorkspaceMemoryDrawer-C6sNocl_.js +1 -0
- package/web/dist/assets/WorkspaceTaskDrawer-CyhhEB1Z.js +1 -0
- package/web/dist/assets/index-BAiLYajK.css +1 -0
- package/web/dist/assets/index-K-GG8UwR.js +73 -0
- package/web/dist/assets/search-BtRkkEmS.js +1 -0
- package/web/dist/assets/square-terminal-lEeQUWb3.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
|
@@ -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
|
|
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
|
|
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
|
|
110
|
+
run.status = classifyCompletedRunStatus(exitCode);
|
|
75
111
|
run.exitCode = exitCode;
|
|
76
|
-
|
|
77
|
-
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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,
|
|
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 (
|
|
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
|
-
|
|
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
|
|
8
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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 (!
|
|
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
|
|
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
|
-
|
|
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
|
};
|
|
@@ -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
|
-
|
|
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) =>
|
|
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>"',
|
|
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;
|