@tt-a1i/hive 2.1.6 → 2.1.8
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 +27 -0
- package/dist/src/server/agent-runtime-contract.d.ts +1 -9
- package/dist/src/server/agent-runtime.js +1 -7
- package/dist/src/server/agent-stdin-dispatcher.d.ts +2 -11
- package/dist/src/server/agent-stdin-dispatcher.js +14 -12
- package/dist/src/server/hive-team-guidance.js +12 -11
- package/dist/src/server/post-start-input-writer.js +1 -1
- package/dist/src/server/report-outbox-store.d.ts +10 -8
- package/dist/src/server/report-outbox-store.js +10 -1
- package/dist/src/server/role-templates.js +8 -4
- package/dist/src/server/routes-remote.js +46 -14
- package/dist/src/server/routes-team.js +1 -1
- package/dist/src/server/routes-workspaces.js +3 -6
- package/dist/src/server/runtime-store-contract.d.ts +2 -2
- package/dist/src/server/runtime-store-helpers.d.ts +4 -0
- package/dist/src/server/runtime-store-helpers.js +34 -11
- package/dist/src/server/runtime-store-worker-mutations.js +12 -6
- package/dist/src/server/runtime-store-workflows.js +7 -1
- package/dist/src/server/team-operations.d.ts +12 -5
- package/dist/src/server/team-operations.js +218 -159
- package/dist/src/shared/remote-bridge-routing.js +3 -1
- package/package.json +1 -1
- package/web/dist/assets/{AddWorkerDialog-DFNkbR_Q.js → AddWorkerDialog-Cd53ifv2.js} +2 -2
- package/web/dist/assets/{AddWorkspaceFlow-BjpjCuRe.js → AddWorkspaceFlow-3sR25gDy.js} +1 -1
- package/web/dist/assets/{FirstRunWizard-BuLgUAny.js → FirstRunWizard-DU8PipxA.js} +1 -1
- package/web/dist/assets/{MarketplaceDrawer-BALuhrnd.js → MarketplaceDrawer-BkNcknv0.js} +1 -1
- package/web/dist/assets/{TaskGraphDrawer-DQTS6JPI.js → TaskGraphDrawer-9mXNimSE.js} +1 -1
- package/web/dist/assets/{WhatsNewDialog-DpgjEIaA.js → WhatsNewDialog-C7awVYub.js} +1 -1
- package/web/dist/assets/WorkerModal-BzgrOKzF.js +1 -0
- package/web/dist/assets/{WorkflowsDrawer-DPWlZs4S.js → WorkflowsDrawer-C4yjTdY7.js} +1 -1
- package/web/dist/assets/{WorkspaceMemoryDrawer-C0vny4zK.js → WorkspaceMemoryDrawer-BlDznlGm.js} +1 -1
- package/web/dist/assets/{WorkspaceTaskDrawer-CJcFZh8C.js → WorkspaceTaskDrawer-CpGGZkp3.js} +1 -1
- package/web/dist/assets/index-BEyvsWk6.js +84 -0
- package/web/dist/assets/index-VHK8pAJq.css +1 -0
- package/web/dist/assets/{search-Bl5O-SfR.js → search-Cv0KnMjw.js} +1 -1
- package/web/dist/assets/{square-terminal-DCDaflg3.js → square-terminal-BZ7EavxU.js} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +1 -1
- package/web/dist/assets/WorkerModal-1y-Xdwv-.js +0 -1
- package/web/dist/assets/index-CEP_bvOg.css +0 -1
- package/web/dist/assets/index-CR1SPGBZ.js +0 -84
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 2.1.8 - 2026-06-23
|
|
6
|
+
|
|
7
|
+
Codex terminal editing and member-window polish.
|
|
8
|
+
|
|
9
|
+
- Fixes Codex terminal input repainting for Chinese/CJK text so pressing
|
|
10
|
+
backspace updates the visible input line immediately instead of leaving stale
|
|
11
|
+
characters on screen.
|
|
12
|
+
- Removes the visible desktop member-window close button from the terminal
|
|
13
|
+
corner and adds an outside-click close hint, giving the terminal more clean
|
|
14
|
+
space while keeping mobile's full-screen close affordance.
|
|
15
|
+
|
|
16
|
+
## 2.1.7 - 2026-06-23
|
|
17
|
+
|
|
18
|
+
Team delivery recovery and remote-access hardening.
|
|
19
|
+
|
|
20
|
+
- Makes worker reports durable when the Orchestrator is offline or restarting,
|
|
21
|
+
so completed work is queued for redelivery instead of being silently lost.
|
|
22
|
+
- Tightens cancel, worker-dismiss, and queued-dispatch recovery paths so stale
|
|
23
|
+
work gets a clear dropped/cancelled outcome instead of leaving agents waiting.
|
|
24
|
+
- Makes user input delivery truthful: if the Orchestrator terminal is offline,
|
|
25
|
+
Hive rejects the input instead of recording a message that was never sent.
|
|
26
|
+
- Standardizes remote-access HTTP responses on snake_case fields and keeps the
|
|
27
|
+
web UI mapping them back into its internal camelCase model.
|
|
28
|
+
- Blocks remote devices from reading or approving desktop-only pairing
|
|
29
|
+
approvals through the tunnel, while preserving normal equal-authority device
|
|
30
|
+
management routes.
|
|
31
|
+
|
|
5
32
|
## 2.1.6 - 2026-06-21
|
|
6
33
|
|
|
7
34
|
Team UX polish and release visibility.
|
|
@@ -23,26 +23,18 @@ export interface AgentRuntime {
|
|
|
23
23
|
startAgent: (workspace: WorkspaceSummary, agentId: string, input: StartAgentOptions) => Promise<LiveAgentRun>;
|
|
24
24
|
stopAgentRun: (runId: string) => void;
|
|
25
25
|
validateAgentToken: AgentTokenRegistry['validate'];
|
|
26
|
-
writeReportPrompt: (workspaceId: string, workerName: string, workerId: string, text: string, artifacts: string[], input?: {
|
|
27
|
-
requireActiveRun?: boolean;
|
|
28
|
-
}) => void;
|
|
29
26
|
writeStatusPrompt: (workspaceId: string, workerName: string, workerId: string, text: string, artifacts: string[], input?: {
|
|
30
27
|
requireActiveRun?: boolean;
|
|
31
28
|
}) => void;
|
|
32
29
|
writeSendPrompt: (workspaceId: string, workerId: string, dispatchId: string, fromAgentName: string, workerDescription: string, text: string) => Promise<void>;
|
|
33
30
|
writeCancelPrompt: (workspaceId: string, workerId: string, dispatchId: string, reason: string, input?: {
|
|
34
31
|
requireActiveRun?: boolean;
|
|
35
|
-
}) => void
|
|
32
|
+
}) => Promise<void>;
|
|
36
33
|
writeUserInputPrompt: (workspaceId: string, text: string) => void;
|
|
37
34
|
writeSystemMessageToAgent: (workspaceId: string, agentId: string, text: string) => void;
|
|
38
35
|
deliverUserInputToOrchestrator: (workspaceId: string, text: string, input?: {
|
|
39
36
|
requireActiveRun?: boolean;
|
|
40
37
|
}) => Promise<void>;
|
|
41
|
-
/** Awaitable report delivery — rejects if the orchestrator PTY write fails,
|
|
42
|
-
* so the caller can persist the report to the redelivery outbox. */
|
|
43
|
-
deliverReportToOrchestrator: (workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
44
|
-
requireActiveRun?: boolean;
|
|
45
|
-
}) => Promise<void>;
|
|
46
38
|
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
47
39
|
* is marked delivered only after the PTY write resolves. */
|
|
48
40
|
deliverSystemMessageToAgent: (workspaceId: string, agentId: string, text: string, input?: {
|
|
@@ -139,9 +139,6 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
139
139
|
});
|
|
140
140
|
},
|
|
141
141
|
validateAgentToken: tokenRegistry.validate,
|
|
142
|
-
writeReportPrompt(workspaceId, workerName, _workerId, text, artifacts, input = {}) {
|
|
143
|
-
stdinDispatcher.writeReportPrompt(workspaceId, workerName, text, artifacts, input);
|
|
144
|
-
},
|
|
145
142
|
writeStatusPrompt(workspaceId, workerName, _workerId, text, artifacts, input = {}) {
|
|
146
143
|
stdinDispatcher.writeStatusPrompt(workspaceId, workerName, text, artifacts, input);
|
|
147
144
|
},
|
|
@@ -149,7 +146,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
149
146
|
return stdinDispatcher.writeSendPrompt(workspaceId, workerId, dispatchId, fromAgentName, workerDescription, text);
|
|
150
147
|
},
|
|
151
148
|
writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input = {}) {
|
|
152
|
-
stdinDispatcher.writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input);
|
|
149
|
+
return stdinDispatcher.writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input);
|
|
153
150
|
},
|
|
154
151
|
writeUserInputPrompt(workspaceId, text) {
|
|
155
152
|
stdinDispatcher.writeUserInputPrompt(workspaceId, text);
|
|
@@ -160,9 +157,6 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
160
157
|
deliverUserInputToOrchestrator(workspaceId, text, input = {}) {
|
|
161
158
|
return stdinDispatcher.deliverUserInputToOrchestrator(workspaceId, text, input);
|
|
162
159
|
},
|
|
163
|
-
deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input = {}) {
|
|
164
|
-
return stdinDispatcher.deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input);
|
|
165
|
-
},
|
|
166
160
|
deliverSystemMessageToAgent(workspaceId, agentId, text, input = {}) {
|
|
167
161
|
return stdinDispatcher.deliverSystemMessageToAgent(workspaceId, agentId, text, input);
|
|
168
162
|
},
|
|
@@ -16,22 +16,19 @@ interface AgentStdinDispatcherInput {
|
|
|
16
16
|
* Optional; omitted → all flags off. */
|
|
17
17
|
getFlags?: () => FeatureFlags;
|
|
18
18
|
}
|
|
19
|
-
export declare const buildOrchestratorReportPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
|
|
19
|
+
export declare const buildOrchestratorReportPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags, dispatchId?: string) => string;
|
|
20
20
|
export declare const buildOrchestratorStatusPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
|
|
21
21
|
export declare const buildOrchestratorUserInputPayload: (text: string, flags?: FeatureFlags) => string;
|
|
22
22
|
export declare const buildWorkerDispatchPayload: (fromAgentName: string, workerDescription: string, dispatchId: string, text: string, memoryDigest?: string | null) => string;
|
|
23
23
|
export declare const buildWorkerCancelPayload: (dispatchId: string, reason: string) => string;
|
|
24
24
|
export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, memoryInjection, getFlags, }: AgentStdinDispatcherInput) => {
|
|
25
|
-
writeReportPrompt(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
26
|
-
requireActiveRun?: boolean;
|
|
27
|
-
}): void;
|
|
28
25
|
writeStatusPrompt(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
29
26
|
requireActiveRun?: boolean;
|
|
30
27
|
}): void;
|
|
31
28
|
writeSendPrompt(workspaceId: string, workerId: string, dispatchId: string, fromAgentName: string, workerDescription: string, text: string): Promise<void>;
|
|
32
29
|
writeCancelPrompt(workspaceId: string, workerId: string, dispatchId: string, reason: string, input?: {
|
|
33
30
|
requireActiveRun?: boolean;
|
|
34
|
-
}): void
|
|
31
|
+
}): Promise<void>;
|
|
35
32
|
writeUserInputPrompt(workspaceId: string, text: string): void;
|
|
36
33
|
deliverUserInputToOrchestrator(workspaceId: string, text: string, input?: {
|
|
37
34
|
requireActiveRun?: boolean;
|
|
@@ -40,12 +37,6 @@ export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfi
|
|
|
40
37
|
* Used by the workflow runner to notify the triggering orchestrator
|
|
41
38
|
* when a run finishes (mirrors Claude Code's <task-notification>). */
|
|
42
39
|
writeSystemMessageToAgent(workspaceId: string, agentId: string, text: string): void;
|
|
43
|
-
/** Awaitable report delivery — same payload as writeReportPrompt but the
|
|
44
|
-
* promise is returned so the caller can persist the report to the
|
|
45
|
-
* redelivery outbox if the orchestrator PTY write rejects. */
|
|
46
|
-
deliverReportToOrchestrator(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
47
|
-
requireActiveRun?: boolean;
|
|
48
|
-
}): Promise<void>;
|
|
49
40
|
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
50
41
|
* is marked delivered only after the PTY write actually resolves. */
|
|
51
42
|
deliverSystemMessageToAgent(workspaceId: string, agentId: string, text: string, input?: {
|
|
@@ -4,9 +4,20 @@ import { buildOrchestratorReminderTail, buildWorkerReminderTail } from './hive-t
|
|
|
4
4
|
import { PtyInactiveError } from './http-errors.js';
|
|
5
5
|
import { createPostStartInputWriter } from './post-start-input-writer.js';
|
|
6
6
|
import { buildDispatchMemoryDigestSafely, logMemoryDigestInjection, rollbackMemoryDigestInjection, } from './team-memory-injection.js';
|
|
7
|
-
export const buildOrchestratorReportPayload = (workerName, text, artifacts, flags = FEATURE_FLAGS_ALL_OFF) => {
|
|
7
|
+
export const buildOrchestratorReportPayload = (workerName, text, artifacts, flags = FEATURE_FLAGS_ALL_OFF, dispatchId) => {
|
|
8
|
+
const dispatchAttribute = dispatchId
|
|
9
|
+
? ` dispatch="${escapeHiveEnvelopeAttribute(dispatchId)}"`
|
|
10
|
+
: '';
|
|
8
11
|
const lines = [
|
|
9
|
-
`<hive-message kind="report" from="@${escapeHiveEnvelopeAttribute(workerName)}">`,
|
|
12
|
+
`<hive-message kind="report" from="@${escapeHiveEnvelopeAttribute(workerName)}"${dispatchAttribute}>`,
|
|
13
|
+
...(dispatchId
|
|
14
|
+
? [
|
|
15
|
+
'',
|
|
16
|
+
`dispatch_id: ${escapeHiveEnvelopeText(dispatchId)}`,
|
|
17
|
+
'If this dispatch_id report was already processed, treat this as a duplicate redelivery and ignore it.',
|
|
18
|
+
'',
|
|
19
|
+
]
|
|
20
|
+
: []),
|
|
10
21
|
escapeHiveEnvelopeText(text),
|
|
11
22
|
];
|
|
12
23
|
for (const artifact of artifacts)
|
|
@@ -166,9 +177,6 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
166
177
|
});
|
|
167
178
|
};
|
|
168
179
|
return {
|
|
169
|
-
writeReportPrompt(workspaceId, workerName, text, artifacts, input = {}) {
|
|
170
|
-
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorReportPayload(workerName, text, artifacts, flags()), input));
|
|
171
|
-
},
|
|
172
180
|
writeStatusPrompt(workspaceId, workerName, text, artifacts, input = {}) {
|
|
173
181
|
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorStatusPayload(workerName, text, artifacts, flags()), input));
|
|
174
182
|
},
|
|
@@ -206,7 +214,7 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
206
214
|
}
|
|
207
215
|
},
|
|
208
216
|
writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input = {}) {
|
|
209
|
-
|
|
217
|
+
return writeToActiveAgentRun(workspaceId, workerId, buildWorkerCancelPayload(dispatchId, reason), input);
|
|
210
218
|
},
|
|
211
219
|
writeUserInputPrompt(workspaceId, text) {
|
|
212
220
|
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorUserInputPayload(text, flags())));
|
|
@@ -220,12 +228,6 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
220
228
|
writeSystemMessageToAgent(workspaceId, agentId, text) {
|
|
221
229
|
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, agentId, text));
|
|
222
230
|
},
|
|
223
|
-
/** Awaitable report delivery — same payload as writeReportPrompt but the
|
|
224
|
-
* promise is returned so the caller can persist the report to the
|
|
225
|
-
* redelivery outbox if the orchestrator PTY write rejects. */
|
|
226
|
-
deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input = {}) {
|
|
227
|
-
return writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorReportPayload(workerName, text, artifacts, flags()), input);
|
|
228
|
-
},
|
|
229
231
|
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
230
232
|
* is marked delivered only after the PTY write actually resolves. */
|
|
231
233
|
deliverSystemMessageToAgent(workspaceId, agentId, text, input = {}) {
|
|
@@ -20,8 +20,8 @@ import { DEFAULT_WORKFLOW_CLI_POLICY } from './workflow-cli-policy.js';
|
|
|
20
20
|
*/
|
|
21
21
|
export const buildOrchestratorReminderTail = ({ workflowsEnabled }) => {
|
|
22
22
|
const body = 'You are the Hive Orchestrator. Reply with one of: ' +
|
|
23
|
-
'(a) `team send "<worker-name>" "<task>"` to dispatch
|
|
24
|
-
`If no worker fits,
|
|
23
|
+
'(a) `team list`, then `team send "<worker-name>" "<task>"` to dispatch to a suitable existing worker by name. Prefer user-created/user-managed workers already in the roster; stale names fail. ' +
|
|
24
|
+
`If no existing worker fits, a worker is stopped/queued/not prompt-ready, or independent branches need more workers, report that condition and recommend what worker the user may start or add; do not take a branch yourself. Use \`team spawn <role> [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>] [--ephemeral]\` only when the user explicitly authorizes it or workspace policy permits autonomous staffing for this task. ` +
|
|
25
25
|
'(b) `team cancel --dispatch <id> "<reason>"` to close an obsolete dispatch. ' +
|
|
26
26
|
(workflowsEnabled
|
|
27
27
|
? '(c) `team workflow run --stdin` to fan out across 3+ workers or run a staged review→fix — never a loop of `team send` (no barrier, no UI group, no stop button). (d) plain text only for clarification, status/final synthesis, or the explicitly allowed trivial check. '
|
|
@@ -52,16 +52,17 @@ export const buildWorkerReminderTail = (dispatchId) => '<hive-system-reminder>\n
|
|
|
52
52
|
const CORE_ORCHESTRATOR_RULES = [
|
|
53
53
|
'A Hive worker is a real CLI agent shown as a card on the right — NOT a subagent of your own CLI.',
|
|
54
54
|
'Dispatch against the current roster: re-run `team list` before a `team send` whenever a user reply or one of your own dispatches/cancels has happened since your last list. Hive never pushes membership changes, so do not dispatch from a remembered roster — a renamed or removed worker fails.',
|
|
55
|
-
'Default to dispatching: parallelism, long execution, audit/review/test/validation work, multi-file code changes, test-writing, a dedicated role, or the user asking for a worker all mean `team
|
|
56
|
-
'
|
|
55
|
+
'Default to dispatching through the existing roster: parallelism, long execution, audit/review/test/validation work, multi-file code changes, test-writing, a dedicated role, or the user asking for a worker all mean `team list` then `team send` to suitable current workers first. The only work you may do yourself is this closed exception: a trivial single-file read-only inspection or config value check that needs no tests, no audit/review/validation judgement, no edits, and no parallel branch. Any edit, even a typo fix, goes through a Hive worker or Hive workflow. If you would write tests, inspect a diff for correctness/security, touch files, or run a review/fix chain, dispatch it.',
|
|
56
|
+
'Prefer user-created/user-managed workers. If you cannot see ownership in the current output, treat existing named workers as user-managed unless the name was just returned by your own `team spawn`.',
|
|
57
|
+
'When work splits into independent branches and the roster lacks enough suitable workers, explain the role/capacity gap and recommend additional workers the user may add or start; spawn additional workers yourself only when the user explicitly authorizes it or workspace policy permits autonomous staffing for this task; do not keep one branch for yourself as a way to parallelize.',
|
|
57
58
|
'If exactly one worker is available, dispatch to it directly with `team send <worker-name> "<task>"` — do not bounce the choice back to the user.',
|
|
58
59
|
'When the user says "have a worker do X", dispatch it with `team send <worker-name> "<task>"`.',
|
|
59
|
-
`If the roster is empty or lacks the role the task needs,
|
|
60
|
-
'`team spawn` is PERSISTENT by default (a normal member that stays in the workspace); add `--ephemeral` for a one-shot worker that auto-dismisses after its first `team report`.
|
|
60
|
+
`If the roster is empty or lacks the role the task needs, report the gap to the user and recommend the missing worker role. Use \`team spawn <role> [--name <n>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>]\` only when the user explicitly asks you to create workers, the user has already granted permission for autonomous staffing, or workspace policy clearly permits it. Without \`--name\` the worker is named after the bare role label when that name is free (\`team spawn researcher\` → \`team send researcher "<task>"\`); on a collision the name gets a uuid suffix — the spawn response always echoes the final \`name\`, so dispatch to the echoed name.`,
|
|
61
|
+
'`team spawn` is PERSISTENT by default (a normal member that stays in the workspace); add `--ephemeral` for a one-shot worker that auto-dismisses after its first `team report`. If you are authorized to spawn for one task, prefer `--ephemeral` unless the user asks for persistent capacity.',
|
|
61
62
|
'All Hive workers in one workspace share the same filesystem root with no per-worker isolation. Split dispatches so no two workers edit the same files/modules at the same time; if work would collide, serialize it or assign one owner.',
|
|
62
|
-
'When you spawn a reviewer to audit work another CLI produced, prefer a different `--cli` than the implementer used — cross-provider review catches blind spots a model shares with itself.',
|
|
63
|
+
'When you are authorized to spawn a reviewer to audit work another CLI produced, prefer a different `--cli` than the implementer used — cross-provider review catches blind spots a model shares with itself.',
|
|
63
64
|
'When the user cancels or changes direction on an open dispatch, close it explicitly with `team cancel --dispatch <id> "<reason>"` — do not just say "cancel" in prose.',
|
|
64
|
-
'A `team send` to a user-added STOPPED worker parks the dispatch (the response carries `queued: true`): it is delivered automatically when the user starts that worker.
|
|
65
|
+
'A `team send` to a user-added STOPPED worker parks the dispatch (the response carries `queued: true`): it is delivered automatically when the user starts that worker. Treat stopped, queued, delivery-failed, or prompt-readiness-timeout states as runtime/roster conditions to report or retry against existing workers; do not treat them as proof the worker is unsuitable. Workers you created with `team spawn` are woken by the follow-up `team send`.',
|
|
65
66
|
'Each `team send` opens a SEPARATE dispatch with its own pending count and its own required report — it is not a way to tack context onto a dispatch already in flight. Send the same worker twice and it owes you TWO reports; one report closes only one dispatch (the one its `--dispatch <id>` names, or the oldest open one if the flag is omitted), so the other stays open and the worker is pinned on `working`. To change or extend an in-flight task, `team cancel --dispatch <id> "<reason>"` the stale dispatch and re-send the whole task, or wait for the worker to report and dispatch the follow-up after.',
|
|
66
67
|
'Only orchestrators can add memory directly; workers should report durable findings for the orchestrator or Dream to capture. Search memory before adding: use `team memory search "<query>"` to avoid duplicates. Use `team memory add "<body>"` only for rare, evidence-backed workspace facts, decisions, and 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 <memory-id>` only to archive obsolete memory.',
|
|
67
68
|
"Never substitute your CLI's own built-in background agents, exploration helpers, subagent runners, or workflow runners for Hive workers or Hive workflows — they run inside your CLI process, bypass Hive's PTY fleet, never appear in the UI or `team list`, and the stop button cannot reach them.",
|
|
@@ -89,7 +90,7 @@ const WORKFLOW_ORCHESTRATOR_RULES = [
|
|
|
89
90
|
* workflows are available it defers one-shot batch fan-out to `team workflow
|
|
90
91
|
* run` so the two experiments don't give the orchestrator competing advice.
|
|
91
92
|
*/
|
|
92
|
-
const buildAutostaffRule = (workflowsEnabled) => '
|
|
93
|
+
const buildAutostaffRule = (workflowsEnabled) => 'Auto-staff guidance is available: you may size the team to the task after checking the current roster, but existing user-created/user-managed workers still have priority. If extra parallel capacity would materially help, state the missing role/count and prefer recommending those additions to the user. Issue individual `team spawn <role> --ephemeral` commands yourself only when the user has authorized autonomous staffing or workspace policy explicitly permits it — one command per member (there is no batch form). Match the count to the work: more agents is not faster once they would collide or sit idle. Use `--ephemeral` so task-scoped staff auto-dismiss after reporting and do not pile up.' +
|
|
93
94
|
(workflowsEnabled
|
|
94
95
|
? ' When the work is a one-shot fan-out across 3+ workers or a staged review→fix that runs to completion, prefer `team workflow run` (barrier, phase tree, stop button) over a batch of `team spawn`; reserve up-front staffing for a standing team you direct interactively across several turns.'
|
|
95
96
|
: '');
|
|
@@ -327,8 +328,8 @@ export const buildProtocolDoc = (cliPolicy = DEFAULT_WORKFLOW_CLI_POLICY, flags
|
|
|
327
328
|
'- `team memory apply --run <dream-run-id> --stdin` — apply strict JSON Dream ops for a pending maintenance run',
|
|
328
329
|
'- `team memory forget <memory-id>` — archive obsolete memory (orchestrator only; does not physically delete evidence)',
|
|
329
330
|
'- `team send "<worker-name>" "<task>"` — dispatch to a worker by name (never id)',
|
|
330
|
-
`- \`team spawn <role> [--name <name>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>]\` — create a PERSISTENT member when
|
|
331
|
-
'- `team spawn <role> --ephemeral [other-flags]` — create
|
|
331
|
+
`- \`team spawn <role> [--name <name>] [--cli <${BUILTIN_COMMAND_PRESET_CLI_LIST}>]\` — create a PERSISTENT member only when the user or workspace policy has authorized autonomous staffing`,
|
|
332
|
+
'- `team spawn <role> --ephemeral [other-flags]` — create an authorized one-shot worker that auto-dismisses after its first `team report`',
|
|
332
333
|
'- `team dismiss <worker-name>` — remove a worker that is no longer needed (works on any worker, including persistent ones; ephemeral workers auto-dismiss after their first report)',
|
|
333
334
|
'- `team cancel --dispatch <id> "<reason>"` — cancel an obsolete open dispatch',
|
|
334
335
|
...workflowCliCommands,
|
|
@@ -8,7 +8,7 @@ const MIN_SUBMIT_AFTER_PASTE_DELAY_MS = 600;
|
|
|
8
8
|
const MAX_SUBMIT_AFTER_PASTE_DELAY_MS = 1500;
|
|
9
9
|
const PASTE_CHARS_PER_DELAY_MS = 4;
|
|
10
10
|
const PASTE_ACK_CHECK_INTERVAL_MS = 50;
|
|
11
|
-
const PASTE_ACK_SETTLE_DELAY_MS =
|
|
11
|
+
const PASTE_ACK_SETTLE_DELAY_MS = 250;
|
|
12
12
|
const CODEX_PASTE_ACK_SETTLE_DELAY_MS = 250;
|
|
13
13
|
const PASTE_ACK_TIMEOUT_MS = 3000;
|
|
14
14
|
const CLAUDE_HIVE_PASTE_ACK_TIMEOUT_MS = 10000;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { Database } from 'better-sqlite3';
|
|
2
2
|
/**
|
|
3
|
-
* Durable redelivery queue for
|
|
4
|
-
* receive. `team report
|
|
5
|
-
* report into the orchestrator's stdin
|
|
6
|
-
* PTY exited / is mid-restart, or the orchestrator was down at report
|
|
7
|
-
* the report would otherwise be lost — the ledger says "reported" yet the
|
|
8
|
-
* orchestrator waits forever, indistinguishable from a hang.
|
|
3
|
+
* Durable redelivery queue for protocol messages a live agent could not
|
|
4
|
+
* receive. The primary producer is `team report`: it persists the dispatch as
|
|
5
|
+
* reported and forwards the report into the orchestrator's stdin; if that write
|
|
6
|
+
* fails (the PTY exited / is mid-restart, or the orchestrator was down at report
|
|
7
|
+
* time) the report would otherwise be lost — the ledger says "reported" yet the
|
|
8
|
+
* orchestrator waits forever, indistinguishable from a hang. Dispatch-drop
|
|
9
|
+
* notifications use the same queue for their issuer.
|
|
9
10
|
*
|
|
10
11
|
* Entries are keyed by dispatch id (UNIQUE) so a report enqueues at most once,
|
|
11
|
-
* and drain marks them delivered only after the
|
|
12
|
-
*
|
|
12
|
+
* and drain marks them delivered only after the target PTY write actually
|
|
13
|
+
* resolves, so a failed redelivery stays pending for the next drain.
|
|
13
14
|
*/
|
|
14
15
|
export interface ReportOutboxEntry {
|
|
15
16
|
id: number;
|
|
@@ -27,6 +28,7 @@ interface EnqueueInput {
|
|
|
27
28
|
payload: string;
|
|
28
29
|
}
|
|
29
30
|
export declare const createReportOutboxStore: (db: Database) => {
|
|
31
|
+
deletePendingForDispatch: (dispatchId: string) => void;
|
|
30
32
|
enqueue: (input: EnqueueInput) => void;
|
|
31
33
|
listPending: (workspaceId: string, targetAgentId: string) => ReportOutboxEntry[];
|
|
32
34
|
markDelivered: (id: number) => void;
|
|
@@ -25,9 +25,18 @@ export const createReportOutboxStore = (db) => {
|
|
|
25
25
|
const markDelivered = (id) => {
|
|
26
26
|
db.prepare(`UPDATE report_outbox SET delivered_at = ? WHERE id = ? AND delivered_at IS NULL`).run(Date.now(), id);
|
|
27
27
|
};
|
|
28
|
+
const deletePendingForDispatch = (dispatchId) => {
|
|
29
|
+
db.prepare('DELETE FROM report_outbox WHERE dispatch_id = ? AND delivered_at IS NULL').run(dispatchId);
|
|
30
|
+
};
|
|
28
31
|
const pendingCount = (workspaceId, targetAgentId) => db
|
|
29
32
|
.prepare(`SELECT COUNT(*) AS n FROM report_outbox
|
|
30
33
|
WHERE workspace_id = ? AND target_agent_id = ? AND delivered_at IS NULL`)
|
|
31
34
|
.get(workspaceId, targetAgentId).n;
|
|
32
|
-
return {
|
|
35
|
+
return {
|
|
36
|
+
deletePendingForDispatch,
|
|
37
|
+
enqueue,
|
|
38
|
+
listPending,
|
|
39
|
+
markDelivered,
|
|
40
|
+
pendingCount,
|
|
41
|
+
};
|
|
33
42
|
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { TASKS_RELATIVE_PATH } from './tasks-file.js';
|
|
2
2
|
export const ORCHESTRATOR_ROLE_DESCRIPTION = [
|
|
3
|
-
'You are the Hive Orchestrator. You
|
|
3
|
+
'You are the Hive Orchestrator. You interface with the user and coordinate the other agent members in the current Hive workspace to get the work done.',
|
|
4
4
|
'How to work:',
|
|
5
5
|
'- Clarify the goal and split it into dispatchable tasks.',
|
|
6
|
-
'- Default to Hive dispatch: use `team
|
|
6
|
+
'- Default to Hive dispatch through the existing roster: use `team list`, then `team send` to suitable user-created/user-managed workers for implementation, audit/review, test, validation, multi-file, or parallel work.',
|
|
7
|
+
'- Do not create new members by default. Based on the task goal, if the current team lacks a suitable member, lacks enough parallel capacity, or adding a member would clearly improve speed and efficiency, explain the gap and recommend which agent member the user should add or start; use `team spawn` only when explicitly authorized by the user or the current workspace rules allow it.',
|
|
8
|
+
'- Do not use your CLI built-in subagents/workflows or keep a non-trivial branch for yourself.',
|
|
7
9
|
`- Maintain ${TASKS_RELATIVE_PATH} so plan, progress, and blockers stay trackable.`,
|
|
8
10
|
'- Drive the next step from worker reports; do not bounce choices back to the user unless a real decision is missing.',
|
|
9
11
|
].join('\n');
|
|
@@ -51,10 +53,12 @@ export const CUSTOM_ROLE_DESCRIPTION = [
|
|
|
51
53
|
'- Done criteria: what results, risks, and blockers to report.',
|
|
52
54
|
].join('\n');
|
|
53
55
|
export const ORCHESTRATOR_ROLE_DESCRIPTION_ZH = [
|
|
54
|
-
'你是 Hive Orchestrator
|
|
56
|
+
'你是 Hive Orchestrator,负责对接用户,并组织协调当前 Hive workspace 中的其他 agent 成员协作完成任务。',
|
|
55
57
|
'工作方式:',
|
|
56
58
|
'- 澄清目标,把需求拆成可派发的小任务。',
|
|
57
|
-
'-
|
|
59
|
+
'- 默认通过当前团队中已有的 agent 成员走 Hive 派单:先用 `team list` 刷新成员列表,再把实现、审计/复核、测试、验证、多文件或并行任务用 `team send` 派给合适的用户创建/用户管理成员。',
|
|
60
|
+
'- 不要默认创建新成员。根据任务目标,若当前团队缺少合适成员、并行能力不足,或添加成员能明显提高效率和速度时,先说明缺口,并建议用户添加或启动对应的 agent 成员;只有用户明确授权或当前 workspace 规则允许时,才使用 `team spawn`。',
|
|
61
|
+
'- 不要用当前 CLI 内建子代理/工作流,也不要把非平凡分支留给自己。',
|
|
58
62
|
`- 维护 ${TASKS_RELATIVE_PATH},让当前计划、进度和阻塞可追踪。`,
|
|
59
63
|
'- 根据成员汇报推进下一步,不把选择题无谓丢回给用户。',
|
|
60
64
|
].join('\n');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ForbiddenError } from './http-errors.js';
|
|
2
2
|
import { REMOTE_DAEMON_TOKEN_KEY, REMOTE_ENABLED_KEY, REMOTE_GATEWAY_URL_KEY, } from './remote-config-keys.js';
|
|
3
|
+
import { HIVE_REMOTE_DEVICE_HEADER } from './remote-loopback-auth.js';
|
|
3
4
|
import { getRequiredParam, readJsonBody, route, sendJson } from './route-helpers.js';
|
|
4
5
|
import { requireUiTokenFromRequest } from './ui-auth-helpers.js';
|
|
5
6
|
// Remote-access device-management + pairing routes (M4). Two gate classes:
|
|
@@ -23,8 +24,11 @@ const gateUi = ({ request, store }) => {
|
|
|
23
24
|
// check, so even the short-circuit can't admit a tunnel request that slipped a cookie too.
|
|
24
25
|
const gateLocalDesktopOnly = ({ request, store }) => {
|
|
25
26
|
if (store.authorizeRemoteTunnelRequest(request)) {
|
|
27
|
+
const rawDeviceId = request.headers[HIVE_REMOTE_DEVICE_HEADER];
|
|
26
28
|
store.getRemoteAuditStore().enqueue({
|
|
27
29
|
action: 'reject',
|
|
30
|
+
deviceId: typeof rawDeviceId === 'string' ? rawDeviceId : null,
|
|
31
|
+
endpoint: request.url ?? null,
|
|
28
32
|
result: 'rejected',
|
|
29
33
|
rejectReason: 'pairing_confirm_forbidden',
|
|
30
34
|
});
|
|
@@ -38,8 +42,8 @@ const remoteStatus = (store) => {
|
|
|
38
42
|
const status = store.getRemoteTunnelStatus();
|
|
39
43
|
return {
|
|
40
44
|
enabled: store.settings.getAppState(REMOTE_ENABLED_KEY)?.value === 'true',
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
logged_in: isLoggedIn(store),
|
|
46
|
+
gateway_url: store.settings.getAppState(REMOTE_GATEWAY_URL_KEY)?.value ?? null,
|
|
43
47
|
connected: status === 'online',
|
|
44
48
|
// The FULL tunnel state, not just online/offline — the desktop dot was stuck looking "connected or
|
|
45
49
|
// not" and couldn't show connecting / reconnecting / revoked / logged-out. (connecting+reconnecting
|
|
@@ -47,15 +51,41 @@ const remoteStatus = (store) => {
|
|
|
47
51
|
connection: status,
|
|
48
52
|
};
|
|
49
53
|
};
|
|
50
|
-
//
|
|
51
|
-
|
|
54
|
+
// HTTP responses stay snake_case even though the store uses camelCase records.
|
|
55
|
+
const toPairingTicketView = (ticket) => ({
|
|
56
|
+
pairing_id: ticket.pairingId,
|
|
57
|
+
qr: ticket.qr,
|
|
58
|
+
code: ticket.code,
|
|
59
|
+
expires_at: ticket.expiresAt,
|
|
60
|
+
});
|
|
61
|
+
const toPendingPairingView = (pending) => ({
|
|
62
|
+
pairing_id: pending.pairingId,
|
|
63
|
+
device_name: pending.deviceName,
|
|
64
|
+
sas: pending.sas,
|
|
65
|
+
expires_at: pending.expiresAt,
|
|
66
|
+
});
|
|
52
67
|
const toDeviceView = (record) => ({
|
|
53
68
|
id: record.id,
|
|
54
69
|
name: record.name,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
created_at: record.createdAt,
|
|
71
|
+
last_active: record.lastActive,
|
|
72
|
+
revoked_at: record.revokedAt,
|
|
73
|
+
});
|
|
74
|
+
const toAuditView = (record) => ({
|
|
75
|
+
id: record.id,
|
|
76
|
+
device_id: record.deviceId,
|
|
77
|
+
ts: record.ts,
|
|
78
|
+
workspace_id: record.workspaceId,
|
|
79
|
+
action: record.action,
|
|
80
|
+
endpoint: record.endpoint,
|
|
81
|
+
result: record.result,
|
|
82
|
+
reject_reason: record.rejectReason,
|
|
83
|
+
byte_count: record.byteCount,
|
|
84
|
+
preview: record.preview,
|
|
58
85
|
});
|
|
86
|
+
const getSearchParams = (url) => new URL(url ?? '', 'http://x').searchParams;
|
|
87
|
+
const hasCompatFlag = (params, snakeName, camelName) => params.has(snakeName) || params.has(camelName);
|
|
88
|
+
const getCompatParam = (params, snakeName, camelName) => params.get(snakeName) ?? params.get(camelName);
|
|
59
89
|
export const remoteRoutes = [
|
|
60
90
|
route('GET', '/api/remote/status', (ctx) => {
|
|
61
91
|
gateUi(ctx);
|
|
@@ -83,7 +113,7 @@ export const remoteRoutes = [
|
|
|
83
113
|
}
|
|
84
114
|
try {
|
|
85
115
|
const ticket = ctx.store.getRemotePairing().beginPairing();
|
|
86
|
-
sendJson(ctx.response, 200, ticket);
|
|
116
|
+
sendJson(ctx.response, 200, toPairingTicketView(ticket));
|
|
87
117
|
}
|
|
88
118
|
catch {
|
|
89
119
|
// beginPairing throws if gateway/daemon id vanished between the status read and here.
|
|
@@ -94,7 +124,7 @@ export const remoteRoutes = [
|
|
|
94
124
|
// HARDEN minor: desktop-only. The confirm dialog backs this; a phone has no use for another
|
|
95
125
|
// device's in-flight SAS, and exposing it would needlessly widen the secret surface (invariant 7).
|
|
96
126
|
gateLocalDesktopOnly(ctx);
|
|
97
|
-
sendJson(ctx.response, 200, ctx.store.getRemotePairing().listPending());
|
|
127
|
+
sendJson(ctx.response, 200, ctx.store.getRemotePairing().listPending().map(toPendingPairingView));
|
|
98
128
|
}),
|
|
99
129
|
route('POST', '/api/remote/pairings/:pairingId/confirm', async (ctx) => {
|
|
100
130
|
const { params, request, response, store } = ctx;
|
|
@@ -139,7 +169,8 @@ export const remoteRoutes = [
|
|
|
139
169
|
// ── equal-authority device management ──────────────────────────────────────────────────────────
|
|
140
170
|
route('GET', '/api/remote/devices', (ctx) => {
|
|
141
171
|
gateUi(ctx);
|
|
142
|
-
const
|
|
172
|
+
const params = getSearchParams(ctx.request.url);
|
|
173
|
+
const includeRevoked = hasCompatFlag(params, 'include_revoked', 'includeRevoked');
|
|
143
174
|
sendJson(ctx.response, 200, ctx.store.getRemoteDeviceStore().list(includeRevoked).map(toDeviceView));
|
|
144
175
|
}),
|
|
145
176
|
route('POST', '/api/remote/devices/:deviceId/revoke', (ctx) => {
|
|
@@ -156,11 +187,12 @@ export const remoteRoutes = [
|
|
|
156
187
|
}),
|
|
157
188
|
route('GET', '/api/remote/audit', (ctx) => {
|
|
158
189
|
gateUi(ctx);
|
|
159
|
-
const
|
|
160
|
-
const rawLimit = Number(
|
|
190
|
+
const params = getSearchParams(ctx.request.url);
|
|
191
|
+
const rawLimit = Number(params.get('limit'));
|
|
161
192
|
const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 500) : 100;
|
|
162
|
-
const deviceId =
|
|
193
|
+
const deviceId = getCompatParam(params, 'device_id', 'deviceId');
|
|
163
194
|
const audit = ctx.store.getRemoteAuditStore();
|
|
164
|
-
|
|
195
|
+
const records = deviceId ? audit.listForDevice(deviceId, limit) : audit.list(limit);
|
|
196
|
+
sendJson(ctx.response, 200, records.map(toAuditView));
|
|
165
197
|
}),
|
|
166
198
|
];
|
|
@@ -306,7 +306,7 @@ export const teamRoutes = [
|
|
|
306
306
|
workspaceId: projectId,
|
|
307
307
|
});
|
|
308
308
|
requireCommandForRole(agent, 'cancel');
|
|
309
|
-
const result = store.cancelTask(projectId, dispatchId, { fromAgentId, reason });
|
|
309
|
+
const result = await store.cancelTask(projectId, dispatchId, { fromAgentId, reason });
|
|
310
310
|
sendJson(response, 202, {
|
|
311
311
|
dispatch_id: result.dispatch?.id ?? null,
|
|
312
312
|
forward_error: result.forwardError,
|
|
@@ -109,11 +109,9 @@ export const workspaceRoutes = [
|
|
|
109
109
|
workspaceId,
|
|
110
110
|
});
|
|
111
111
|
requireCommandForRole(agent, 'list');
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
// for non-orchestrator callers.
|
|
116
|
-
store.drainReportOutbox(workspaceId);
|
|
112
|
+
// Polling `team list` is a natural post-restart wakeup: flush any durable
|
|
113
|
+
// notices stranded for the caller now that its PTY is reachable again.
|
|
114
|
+
store.drainReportOutbox(workspaceId, agent.id);
|
|
117
115
|
sendJson(response, 200, serializeTeamListWithOpenDispatches(store, workspaceId));
|
|
118
116
|
}),
|
|
119
117
|
route('POST', '/api/workspaces/:workspaceId/workers', async ({ params, request, response, store }) => {
|
|
@@ -198,7 +196,6 @@ export const workspaceRoutes = [
|
|
|
198
196
|
}
|
|
199
197
|
const orchestratorId = getOrchestratorId(workspaceId);
|
|
200
198
|
if (!store.getActiveRunByAgentId(workspaceId, orchestratorId)) {
|
|
201
|
-
store.recordUserInput(workspaceId, orchestratorId, body.text);
|
|
202
199
|
throw new PtyInactiveError(`No active run for agent: ${orchestratorId}`);
|
|
203
200
|
}
|
|
204
201
|
await store.deliverUserInput(workspaceId, orchestratorId, body.text);
|
|
@@ -44,9 +44,9 @@ export interface RuntimeStore {
|
|
|
44
44
|
reportTask: (workspaceId: string, workerId: string, input?: ReportTaskInput) => ReportTaskResult;
|
|
45
45
|
/** Flush any reports stranded by a prior orchestrator outage. Safe no-op
|
|
46
46
|
* when the orchestrator is down or the outbox is empty. */
|
|
47
|
-
drainReportOutbox: (workspaceId: string) => void;
|
|
47
|
+
drainReportOutbox: (workspaceId: string, targetAgentId?: string) => void;
|
|
48
48
|
statusTask: (workspaceId: string, workerId: string, input?: StatusTaskInput) => ReportTaskResult;
|
|
49
|
-
cancelTask: (workspaceId: string, dispatchId: string, input: CancelTaskInput) => ReportTaskResult
|
|
49
|
+
cancelTask: (workspaceId: string, dispatchId: string, input: CancelTaskInput) => Promise<ReportTaskResult>;
|
|
50
50
|
listDispatches: (workspaceId: string, options?: ListDispatchesOptions) => DispatchRecord[];
|
|
51
51
|
listOpenDispatches: (workspaceId: string) => DispatchRecord[];
|
|
52
52
|
listRecentDispatches: (workspaceId: string, limit?: number) => DispatchRecord[];
|
|
@@ -10,6 +10,7 @@ import { type RemoteAuditStore } from './remote-audit-store.js';
|
|
|
10
10
|
import type { DeviceSessionProvider } from './remote-device-session.js';
|
|
11
11
|
import { type RemoteDeviceStore } from './remote-device-store.js';
|
|
12
12
|
import { type RemotePairing } from './remote-pairing.js';
|
|
13
|
+
import { createReportOutboxStore } from './report-outbox-store.js';
|
|
13
14
|
import { openRuntimeDatabase } from './runtime-database.js';
|
|
14
15
|
import { createSentinelHeartbeatService } from './sentinel-heartbeat.js';
|
|
15
16
|
import { createSettingsStore } from './settings-store.js';
|
|
@@ -39,6 +40,8 @@ export interface RuntimeStoreServices {
|
|
|
39
40
|
agentRuntime: ReturnType<typeof createAgentRuntime>;
|
|
40
41
|
db: ReturnType<typeof openRuntimeDatabase>;
|
|
41
42
|
dispatchLedgerStore: ReturnType<typeof createDispatchLedgerStore>;
|
|
43
|
+
isRuntimeClosing: () => boolean;
|
|
44
|
+
markRuntimeClosing: () => void;
|
|
42
45
|
messageLogStore: ReturnType<typeof createMessageLogStore>;
|
|
43
46
|
remoteAuditStore: RemoteAuditStore;
|
|
44
47
|
remoteDeviceSessions: DeviceSessionProvider;
|
|
@@ -53,6 +56,7 @@ export interface RuntimeStoreServices {
|
|
|
53
56
|
teamMemoryDreamScheduler: ReturnType<typeof createTeamMemoryDreamScheduler>;
|
|
54
57
|
sentinelHeartbeat: ReturnType<typeof createSentinelHeartbeatService>;
|
|
55
58
|
protocolEventStats: ReturnType<typeof createProtocolEventStats>;
|
|
59
|
+
reportOutbox: ReturnType<typeof createReportOutboxStore>;
|
|
56
60
|
teamMemoryDreamStore: ReturnType<typeof createTeamMemoryDreamStore>;
|
|
57
61
|
teamMemoryDiagnostics: ReturnType<typeof createTeamMemoryDiagnostics>;
|
|
58
62
|
teamMemoryStore: ReturnType<typeof createTeamMemoryStore>;
|