@tt-a1i/hive 2.1.14 → 2.1.16
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 +32 -0
- package/dist/src/cli/team.js +19 -6
- package/dist/src/server/agent-run-bootstrap.d.ts +3 -0
- package/dist/src/server/agent-run-bootstrap.js +1 -0
- package/dist/src/server/agent-run-exit-handler.js +2 -7
- package/dist/src/server/agent-run-start-context.d.ts +4 -4
- package/dist/src/server/agent-run-starter.js +12 -5
- package/dist/src/server/agent-startup-instructions.d.ts +1 -0
- package/dist/src/server/agent-startup-instructions.js +4 -1
- package/dist/src/server/hive-team-guidance.js +2 -0
- package/dist/src/server/resumed-session-cleanup.d.ts +15 -0
- package/dist/src/server/resumed-session-cleanup.js +26 -0
- package/dist/src/server/route-types.d.ts +1 -0
- package/dist/src/server/routes-team.js +3 -0
- package/dist/src/server/routes-workers.d.ts +2 -0
- package/dist/src/server/routes-workers.js +112 -0
- package/dist/src/server/routes-workspaces.js +4 -85
- package/dist/src/server/routes.js +2 -0
- package/dist/src/server/runtime-store-contract.d.ts +5 -0
- package/dist/src/server/runtime-store.js +2 -0
- package/dist/src/server/session-capture-codex.d.ts +1 -0
- package/dist/src/server/session-capture-codex.js +22 -2
- package/dist/src/server/session-capture.d.ts +1 -0
- package/dist/src/server/session-capture.js +5 -4
- package/dist/src/server/sqlite-schema-v39.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v39.js +6 -0
- package/dist/src/server/sqlite-schema.d.ts +1 -1
- package/dist/src/server/sqlite-schema.js +8 -1
- package/dist/src/server/team-list-serializer.d.ts +5 -1
- package/dist/src/server/team-list-serializer.js +2 -1
- package/dist/src/server/team-memory-dream-prompt.js +18 -5
- package/dist/src/server/team-operations.d.ts +4 -0
- package/dist/src/server/team-operations.js +18 -5
- package/dist/src/server/workspace-store-contract.d.ts +6 -0
- package/dist/src/server/workspace-store-hydration.js +2 -1
- package/dist/src/server/workspace-store-support.d.ts +1 -0
- package/dist/src/server/workspace-store.js +57 -2
- package/dist/src/shared/types.d.ts +4 -0
- package/dist/src/shared/worker-avatar.d.ts +2 -0
- package/dist/src/shared/worker-avatar.js +55 -0
- package/package.json +1 -1
- package/web/dist/assets/AddWorkerDialog-CPQkMvDz.js +2 -0
- package/web/dist/assets/AddWorkspaceFlow-CkOOz4Kj.js +1 -0
- package/web/dist/assets/FirstRunWizard-DzAnGniE.js +1 -0
- package/web/dist/assets/{MarketplaceDrawer-BHTvxLMz.js → MarketplaceDrawer-DAWF9idk.js} +1 -1
- package/web/dist/assets/{TaskGraphDrawer-woCXhUwp.js → TaskGraphDrawer-DRVJ4Z7z.js} +1 -1
- package/web/dist/assets/WhatsNewDialog-BDsPg5Fa.js +1 -0
- package/web/dist/assets/WorkerModal-BN3jQTBO.js +1 -0
- package/web/dist/assets/{WorkflowsDrawer-Diw0TiiJ.js → WorkflowsDrawer-Clv5ROhE.js} +1 -1
- package/web/dist/assets/WorkspaceMemoryDrawer-DVZT9TqV.js +1 -0
- package/web/dist/assets/{WorkspaceTaskDrawer-D10RcAUj.js → WorkspaceTaskDrawer-C14sALb8.js} +1 -1
- package/web/dist/assets/index-Cs7E1UKt.css +1 -0
- package/web/dist/assets/index-DoOf8jsj.js +84 -0
- package/web/dist/assets/{search-D6bjVJKH.js → search-CPePg8x3.js} +1 -1
- package/web/dist/assets/{square-terminal-BUBEjTQZ.js → square-terminal-DwJxHx2m.js} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +1 -1
- package/web/dist/assets/AddWorkerDialog-BdIc_ZDz.js +0 -2
- package/web/dist/assets/AddWorkspaceFlow-h-UH433o.js +0 -1
- package/web/dist/assets/FirstRunWizard-ChuB1siy.js +0 -1
- package/web/dist/assets/WhatsNewDialog-BcRbRAJI.js +0 -1
- package/web/dist/assets/WorkerModal-CTf1k881.js +0 -1
- package/web/dist/assets/WorkspaceMemoryDrawer-B7Z1_COx.js +0 -1
- package/web/dist/assets/index-BTaZgzo0.js +0 -84
- package/web/dist/assets/index-DYIPzuPD.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 2.1.16 - 2026-07-08
|
|
6
|
+
|
|
7
|
+
Codex resume context reliability.
|
|
8
|
+
|
|
9
|
+
- Preserves a Codex worker's saved conversation pointer when a resumed start
|
|
10
|
+
exits because of a temporary CLI, configuration, or resource failure and the
|
|
11
|
+
underlying Codex session still exists.
|
|
12
|
+
- Treats matching but temporarily unreadable Codex session files as
|
|
13
|
+
unverifiable instead of clearing the saved session too aggressively.
|
|
14
|
+
- Clears truly stale or missing saved Codex session pointers after a failed
|
|
15
|
+
resume, so Hive can start fresh instead of repeatedly retrying a broken
|
|
16
|
+
session id.
|
|
17
|
+
- Uses one shared session-existence path for supported native session stores,
|
|
18
|
+
keeping resume cleanup behavior consistent across CLI presets.
|
|
19
|
+
|
|
20
|
+
## 2.1.15 - 2026-07-02
|
|
21
|
+
|
|
22
|
+
Worker avatars, terminal rendering reliability, and clearer team report delivery.
|
|
23
|
+
|
|
24
|
+
- Adds custom worker avatars, including upload, crop, validation, persistence,
|
|
25
|
+
and display across the team UI.
|
|
26
|
+
- Keeps worker avatars out of CLI team-list responses while still showing them
|
|
27
|
+
in the browser workspace.
|
|
28
|
+
- Improves terminal rendering under heavy output and reconnect/restore flows,
|
|
29
|
+
reducing stale or duplicated terminal frames.
|
|
30
|
+
- Tightens Dream memory consolidation instructions so procedure references are
|
|
31
|
+
only used for real saved workflows, skills, procedures, templates, or docs.
|
|
32
|
+
- Makes `team report` delivery wording more accurate when Hive accepts a report
|
|
33
|
+
and durable Orchestrator delivery is still in progress.
|
|
34
|
+
- Adjusts Orchestrator guidance so accepted dispatches are usually left alone
|
|
35
|
+
until a member reports, reducing premature status checks or cancels.
|
|
36
|
+
|
|
5
37
|
## 2.1.14 - 2026-06-25
|
|
6
38
|
|
|
7
39
|
Terminal focus and Dream memory reliability.
|
package/dist/src/cli/team.js
CHANGED
|
@@ -124,6 +124,23 @@ const GOAL_REPORT_USAGE = 'Usage: team goal report --goal <goal-id> --status pro
|
|
|
124
124
|
const GOAL_REPORT_STATUSES = new Set(['progress', 'done', 'blocked', 'failed']);
|
|
125
125
|
const usageFor = (command) => (command === 'status' ? STATUS_USAGE : REPORT_USAGE);
|
|
126
126
|
const withUsage = (message, command) => `${message}\n\n${usageFor(command)}`;
|
|
127
|
+
const printOrchestratorDeliveryWarning = (action, payload) => {
|
|
128
|
+
if (payload.delivery_state === 'delivered' || payload.delivery_state === 'delivering')
|
|
129
|
+
return;
|
|
130
|
+
if (payload.delivery_state === 'queued') {
|
|
131
|
+
const detail = payload.forward_error ? `: ${payload.forward_error}` : '.';
|
|
132
|
+
console.error(`Hive recorded the ${action}, but Orchestrator did not receive it in real time. It is queued for durable delivery${detail}`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (payload.delivery_state === 'failed') {
|
|
136
|
+
const detail = payload.forward_error ? `: ${payload.forward_error}` : '.';
|
|
137
|
+
console.error(`Hive recorded the ${action}, but could not deliver it to Orchestrator or confirm durable queueing${detail}`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (payload.forwarded === false && payload.forward_error) {
|
|
141
|
+
console.error(`Hive recorded the ${action}, but could not deliver it to Orchestrator in real time: ${payload.forward_error}`);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
127
144
|
const readGeneratedProtocolGuide = (topic) => {
|
|
128
145
|
const protocolPath = join(process.cwd(), '.hive', 'PROTOCOL.md');
|
|
129
146
|
if (!existsSync(protocolPath))
|
|
@@ -1043,9 +1060,7 @@ export const runTeamCommand = async (argv) => {
|
|
|
1043
1060
|
artifacts: report.artifacts,
|
|
1044
1061
|
});
|
|
1045
1062
|
const payload = (await response.json());
|
|
1046
|
-
|
|
1047
|
-
console.error(`Hive recorded the status update, but could not deliver it to Orchestrator in real time: ${payload.forward_error}`);
|
|
1048
|
-
}
|
|
1063
|
+
printOrchestratorDeliveryWarning('status update', payload);
|
|
1049
1064
|
if (payload.pending_warning)
|
|
1050
1065
|
console.error(payload.pending_warning);
|
|
1051
1066
|
return;
|
|
@@ -1064,9 +1079,7 @@ export const runTeamCommand = async (argv) => {
|
|
|
1064
1079
|
artifacts: report.artifacts,
|
|
1065
1080
|
});
|
|
1066
1081
|
const payload = (await response.json());
|
|
1067
|
-
|
|
1068
|
-
console.error(`Hive recorded the report, but could not deliver it to Orchestrator in real time: ${payload.forward_error}`);
|
|
1069
|
-
}
|
|
1082
|
+
printOrchestratorDeliveryWarning('report', payload);
|
|
1070
1083
|
if (payload.pending_warning)
|
|
1071
1084
|
console.error(payload.pending_warning);
|
|
1072
1085
|
return;
|
|
@@ -21,6 +21,9 @@ import { type SessionCaptureSnapshot } from './session-capture.js';
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const buildSpawnPathEnvEntry: (parentEnv: NodeJS.ProcessEnv, hiveBinDir: string, platform: NodeJS.Platform) => NodeJS.ProcessEnv;
|
|
23
23
|
export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agentId: string, config: AgentLaunchConfigInput, sessionStore: AgentSessionStorePort, getCommandPreset: (id: string) => CommandPresetRecord | undefined, agent?: AgentSummary) => {
|
|
24
|
+
sessionCaptureDiscriminator: {
|
|
25
|
+
contentIncludes: string[];
|
|
26
|
+
} | undefined;
|
|
24
27
|
sessionCaptureSnapshot: {
|
|
25
28
|
discriminator?: {
|
|
26
29
|
contentIncludes: string | readonly string[];
|
|
@@ -79,6 +79,7 @@ export const buildAgentRunBootstrap = (workspace, agentId, config, sessionStore,
|
|
|
79
79
|
? undefined
|
|
80
80
|
: snapshotSessionIdsForCapture(workspace.path, startConfig.sessionIdCapture, discriminator);
|
|
81
81
|
return {
|
|
82
|
+
sessionCaptureDiscriminator: discriminator,
|
|
82
83
|
sessionCaptureSnapshot,
|
|
83
84
|
startConfig,
|
|
84
85
|
startEnv: {
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import { shouldClearResumedSessionOnExit } from './agent-exit-classification.js';
|
|
2
1
|
import { completeLiveRun } from './agent-run-sync.js';
|
|
3
|
-
|
|
4
|
-
if (shouldClearResumedSessionOnExit(exitCode) && context.startConfig.resumedSessionId) {
|
|
5
|
-
context.sessionStore.clearLastSessionId(context.workspace.id, context.agentId);
|
|
6
|
-
}
|
|
7
|
-
};
|
|
2
|
+
import { clearResumedSessionAfterExitIfStale } from './resumed-session-cleanup.js';
|
|
8
3
|
export const handleAgentRunExit = (context, { exitCode, endedAt, runId }) => {
|
|
9
4
|
context.registry.setPendingExitCode(runId, exitCode);
|
|
10
5
|
const liveRun = context.registry.get(runId);
|
|
@@ -20,7 +15,7 @@ export const handleAgentRunExit = (context, { exitCode, endedAt, runId }) => {
|
|
|
20
15
|
try {
|
|
21
16
|
completeLiveRun(liveRun, exitCode, endedAt, context.store);
|
|
22
17
|
if (!liveRun.userStopped)
|
|
23
|
-
|
|
18
|
+
clearResumedSessionAfterExitIfStale({ ...context, exitCode });
|
|
24
19
|
context.onAgentExit(context.workspace.id, context.agentId);
|
|
25
20
|
return true;
|
|
26
21
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { WorkspaceSummary } from '../shared/types.js';
|
|
2
|
-
import type { PersistedAgentRun } from './agent-run-store.js';
|
|
2
|
+
import type { AgentLaunchConfigInput, PersistedAgentRun } from './agent-run-store.js';
|
|
3
3
|
import type { AgentSessionStorePort } from './agent-runtime-ports.js';
|
|
4
4
|
import type { AgentTokenRegistry } from './agent-tokens.js';
|
|
5
5
|
import type { LiveRunRegistry } from './live-run-registry.js';
|
|
6
|
+
import type { SessionCaptureSnapshot } from './session-capture.js';
|
|
6
7
|
export type PersistedRunStatus = PersistedAgentRun['status'];
|
|
7
8
|
export interface AgentRunStarterStorePort {
|
|
8
9
|
insertAgentRun: (runId: string, agentId: string, startedAt: number, pid: number | null, status?: PersistedRunStatus, exitCode?: number | null, endedAt?: number | null) => void;
|
|
@@ -13,10 +14,9 @@ export interface AgentRunExitContext {
|
|
|
13
14
|
handledRunExits: Set<string>;
|
|
14
15
|
onAgentExit: (workspaceId: string, agentId: string) => void;
|
|
15
16
|
registry: LiveRunRegistry;
|
|
17
|
+
sessionCaptureDiscriminator?: SessionCaptureSnapshot['discriminator'];
|
|
16
18
|
sessionStore: AgentSessionStorePort;
|
|
17
|
-
startConfig:
|
|
18
|
-
resumedSessionId?: string | null;
|
|
19
|
-
};
|
|
19
|
+
startConfig: Pick<AgentLaunchConfigInput, 'resumedSessionId' | 'sessionIdCapture'>;
|
|
20
20
|
store: AgentRunStarterStorePort;
|
|
21
21
|
token: string;
|
|
22
22
|
tokenRegistry: AgentTokenRegistry;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { classifyCompletedRunStatus
|
|
1
|
+
import { classifyCompletedRunStatus } from './agent-exit-classification.js';
|
|
2
2
|
import { buildAgentRunBootstrap, startAgentRunCapture } from './agent-run-bootstrap.js';
|
|
3
3
|
import { handleAgentRunExit } from './agent-run-exit-handler.js';
|
|
4
4
|
import { buildAgentStartupInstructions, buildWorkflowAgentStartupInstructions, } from './agent-startup-instructions.js';
|
|
@@ -7,13 +7,14 @@ import { ensureCodexDirectoryTrusted } from './codex-trust-store.js';
|
|
|
7
7
|
import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
|
|
8
8
|
import { createPostStartInputWriter, isInteractiveAgentCommand } from './post-start-input-writer.js';
|
|
9
9
|
import { isResumeLaunchConfig } from './preset-launch-support.js';
|
|
10
|
+
import { clearResumedSessionAfterExitIfStale } from './resumed-session-cleanup.js';
|
|
10
11
|
import { normalizeExecutableToken } from './startup-command-parser.js';
|
|
11
12
|
import { buildMemoryDigestSafely, logMemoryDigestInjection, rollbackMemoryDigestInjection, } from './team-memory-injection.js';
|
|
12
13
|
export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, memoryInjection, }) => async (workspace, agentId, config, hivePort) => {
|
|
13
14
|
if (!agentManager)
|
|
14
15
|
throw new Error('Agent manager is required to start agents');
|
|
15
16
|
const agent = getAgent?.(workspace.id, agentId);
|
|
16
|
-
const { sessionCaptureSnapshot, startConfig, startEnv } = buildAgentRunBootstrap(workspace, agentId, config, sessionStore, getCommandPreset, agent);
|
|
17
|
+
const { sessionCaptureDiscriminator, sessionCaptureSnapshot, startConfig, startEnv } = buildAgentRunBootstrap(workspace, agentId, config, sessionStore, getCommandPreset, agent);
|
|
17
18
|
const handledRunExits = new Set();
|
|
18
19
|
const abortedRunIds = new Set();
|
|
19
20
|
const startedAt = Date.now();
|
|
@@ -23,6 +24,7 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
|
|
|
23
24
|
handledRunExits,
|
|
24
25
|
onAgentExit,
|
|
25
26
|
registry,
|
|
27
|
+
sessionCaptureDiscriminator,
|
|
26
28
|
sessionStore,
|
|
27
29
|
startConfig,
|
|
28
30
|
store,
|
|
@@ -105,9 +107,14 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
|
|
|
105
107
|
if (run.status === 'error') {
|
|
106
108
|
liveRun.status = classifyCompletedRunStatus(run.exitCode);
|
|
107
109
|
store.updatePersistedRun(run.runId, liveRun.status, run.exitCode, Date.now());
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
clearResumedSessionAfterExitIfStale({
|
|
111
|
+
agentId,
|
|
112
|
+
exitCode: run.exitCode,
|
|
113
|
+
sessionCaptureDiscriminator,
|
|
114
|
+
sessionStore,
|
|
115
|
+
startConfig,
|
|
116
|
+
workspace,
|
|
117
|
+
});
|
|
111
118
|
tokenRegistry.revokeIfMatches(agentId, token);
|
|
112
119
|
// Ensure §12 three-state: failed spawn must flip AgentSummary to stopped.
|
|
113
120
|
onAgentExit(workspace.id, agentId);
|
|
@@ -9,6 +9,7 @@ export declare const buildAgentLegacyIdentityMarker: ({ agent, workspace, }: {
|
|
|
9
9
|
workspace: WorkspaceSummary;
|
|
10
10
|
}) => string;
|
|
11
11
|
export declare const WORKER_STARTUP_READY_STATUS = "ready: startup prompt received; Hive CLI channel OK; waiting for dispatch.";
|
|
12
|
+
export declare const REVIEWER_STARTUP_READY_STATUS = "ready: reviewer available as the final review gate. If review finds issues, have them fixed and send the work back to me until no issues remain before reporting completion to the user.";
|
|
12
13
|
export declare const buildAgentStartupInstructions: ({ agent, memoryDigest, workspace, flags, }: {
|
|
13
14
|
agent: AgentSummary;
|
|
14
15
|
memoryDigest?: string | null | undefined;
|
|
@@ -5,6 +5,8 @@ import { TASKS_RELATIVE_PATH } from './tasks-file.js';
|
|
|
5
5
|
export const buildAgentSessionBindingMarker = ({ agent, workspace, }) => `Hive session binding: workspace_id=${workspace.id}; agent_id=${agent.id}`;
|
|
6
6
|
export const buildAgentLegacyIdentityMarker = ({ agent, workspace, }) => `You are ${escapeHiveEnvelopeText(agent.name)} (${agent.role}) in workspace ${escapeHiveEnvelopeText(workspace.name)}.`;
|
|
7
7
|
export const WORKER_STARTUP_READY_STATUS = 'ready: startup prompt received; Hive CLI channel OK; waiting for dispatch.';
|
|
8
|
+
export const REVIEWER_STARTUP_READY_STATUS = 'ready: reviewer available as the final review gate. If review finds issues, have them fixed and send the work back to me until no issues remain before reporting completion to the user.';
|
|
9
|
+
const getStartupReadyStatus = (agent) => agent.role === 'reviewer' ? REVIEWER_STARTUP_READY_STATUS : WORKER_STARTUP_READY_STATUS;
|
|
8
10
|
export const buildAgentStartupInstructions = ({ agent, memoryDigest, workspace, flags = FEATURE_FLAGS_ALL_OFF, }) => {
|
|
9
11
|
const { workflowsEnabled } = flags;
|
|
10
12
|
const lines = [
|
|
@@ -35,7 +37,8 @@ export const buildAgentStartupInstructions = ({ agent, memoryDigest, workspace,
|
|
|
35
37
|
lines.push('Available team commands:', '- team status "<finding>" [--artifact <path>] escalate a patrol finding to the Orchestrator', '- 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 --help command syntax only', '', 'You observe only: no dispatches are ever assigned to you, and `team report` is not available to your role.', '', 'Hive sentinel boundaries:', ...getHiveTeamRules(agent, flags));
|
|
36
38
|
}
|
|
37
39
|
else {
|
|
38
|
-
|
|
40
|
+
const startupReadyStatus = getStartupReadyStatus(agent);
|
|
41
|
+
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>] progress / standby update at any time; never closes a dispatch', '- 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 memory dream show <dream-run-id> inspect a pending Dream run only when the Orchestrator assigns memory review', '- team --help command syntax only; NOT a way to report', '', 'Startup handshake:', `- After reading this startup message, immediately run exactly once: \`team status "${startupReadyStatus}"\`.`, '- This readiness status tells the Orchestrator this member started successfully; it does not close any dispatch.', '- Do not use `team report` for startup readiness. Use `team report` only after you receive an assigned dispatch task.', '', '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.', '', 'Hive member boundaries:', ...getHiveTeamRules(agent, flags));
|
|
39
42
|
}
|
|
40
43
|
lines.push('', '</hive-message>', '');
|
|
41
44
|
return lines.join('\n');
|
|
@@ -23,6 +23,7 @@ export const buildOrchestratorReminderTail = ({ workflowsEnabled }) => {
|
|
|
23
23
|
'(a) `team list`, then `team send "<member-name>" "<task>"` to dispatch to a suitable existing member by name. Prefer user-created/user-managed members already in the current team; stale names fail. ' +
|
|
24
24
|
`If no existing member fits, a member is stopped/queued/not prompt-ready, or independent branches need more members, report that condition and recommend what member 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
|
+
'Accepted dispatches should normally be left alone until the member reports. Do not cancel or send status checks unless progress is genuinely overdue or the user asks. ' +
|
|
26
27
|
(workflowsEnabled
|
|
27
28
|
? '(c) `team workflow run --stdin` to fan out across 3+ members 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. '
|
|
28
29
|
: '(c) plain text only for clarification, status/final synthesis, or the explicitly allowed trivial check. ') +
|
|
@@ -58,6 +59,7 @@ const CORE_ORCHESTRATOR_RULES = [
|
|
|
58
59
|
'Do not keep a non-trivial parallel branch for yourself just to avoid dispatching.',
|
|
59
60
|
'If a dispatch must be changed or cancelled, use `team cancel --dispatch <id> "<reason>"`, then resend the full updated task if needed.',
|
|
60
61
|
'Each `team send` creates a separate dispatch and requires a separate `team report`.',
|
|
62
|
+
'Accepted dispatches should normally be left alone until the member reports. Do not cancel or send status checks unless progress is genuinely overdue or the user asks.',
|
|
61
63
|
'Treat stopped, queued, delivery-failed, and prompt-readiness-timeout as current-team runtime conditions to report or retry, not proof that the member is unsuitable.',
|
|
62
64
|
'`team spawn` is persistent by default. When authorized to create task-scoped capacity, prefer `--ephemeral` unless the user asks for persistent capacity.',
|
|
63
65
|
'All Hive members in one workspace share the same filesystem root with no per-member isolation. Split dispatches so no two members edit the same files/modules at the same time; if work would collide, serialize it or assign one owner.',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { WorkspaceSummary } from '../shared/types.js';
|
|
2
|
+
import type { AgentLaunchConfigInput } from './agent-run-store.js';
|
|
3
|
+
import type { AgentSessionStorePort } from './agent-runtime-ports.js';
|
|
4
|
+
import { type SessionCaptureSnapshot } from './session-capture.js';
|
|
5
|
+
interface ResumedSessionCleanupInput {
|
|
6
|
+
agentId: string;
|
|
7
|
+
exitCode: number | null;
|
|
8
|
+
sessionCaptureDiscriminator?: SessionCaptureSnapshot['discriminator'];
|
|
9
|
+
sessionStore: AgentSessionStorePort;
|
|
10
|
+
startConfig: Pick<AgentLaunchConfigInput, 'resumedSessionId' | 'sessionIdCapture'>;
|
|
11
|
+
workspace: WorkspaceSummary;
|
|
12
|
+
}
|
|
13
|
+
export declare const shouldClearResumedSessionAfterExit: ({ exitCode, sessionCaptureDiscriminator, startConfig, workspace, }: Omit<ResumedSessionCleanupInput, "agentId" | "sessionStore">) => boolean;
|
|
14
|
+
export declare const clearResumedSessionAfterExitIfStale: (input: ResumedSessionCleanupInput) => boolean;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { shouldClearResumedSessionOnExit } from './agent-exit-classification.js';
|
|
2
|
+
import { getCapturedSessionExistence } from './session-capture.js';
|
|
3
|
+
export const shouldClearResumedSessionAfterExit = ({ exitCode, sessionCaptureDiscriminator, startConfig, workspace, }) => {
|
|
4
|
+
if (!shouldClearResumedSessionOnExit(exitCode))
|
|
5
|
+
return false;
|
|
6
|
+
const resumedSessionId = startConfig.resumedSessionId;
|
|
7
|
+
if (!resumedSessionId)
|
|
8
|
+
return false;
|
|
9
|
+
const capture = startConfig.sessionIdCapture;
|
|
10
|
+
if (!capture)
|
|
11
|
+
return true;
|
|
12
|
+
const capturedSessionExists = getCapturedSessionExistence(workspace.path, capture, resumedSessionId, sessionCaptureDiscriminator);
|
|
13
|
+
if (capturedSessionExists === undefined)
|
|
14
|
+
return false;
|
|
15
|
+
return !capturedSessionExists;
|
|
16
|
+
};
|
|
17
|
+
export const clearResumedSessionAfterExitIfStale = (input) => {
|
|
18
|
+
if (!shouldClearResumedSessionAfterExit(input))
|
|
19
|
+
return false;
|
|
20
|
+
if (input.sessionStore.getLastSessionId(input.workspace.id, input.agentId) !==
|
|
21
|
+
input.startConfig.resumedSessionId) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
input.sessionStore.clearLastSessionId(input.workspace.id, input.agentId);
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
@@ -340,6 +340,7 @@ export const teamRoutes = [
|
|
|
340
340
|
status,
|
|
341
341
|
});
|
|
342
342
|
sendJson(response, 202, {
|
|
343
|
+
delivery_state: result.deliveryState,
|
|
343
344
|
dispatch_id: result.dispatch?.id ?? null,
|
|
344
345
|
forward_error: result.forwardError,
|
|
345
346
|
forwarded: result.forwarded,
|
|
@@ -351,6 +352,7 @@ export const teamRoutes = [
|
|
|
351
352
|
else {
|
|
352
353
|
const result = store.reportTask(projectId, fromAgentId, reportInput);
|
|
353
354
|
sendJson(response, 202, {
|
|
355
|
+
delivery_state: result.deliveryState,
|
|
354
356
|
dispatch_id: result.dispatch?.id ?? null,
|
|
355
357
|
forward_error: result.forwardError,
|
|
356
358
|
forwarded: result.forwarded,
|
|
@@ -379,6 +381,7 @@ export const teamRoutes = [
|
|
|
379
381
|
text: resultText,
|
|
380
382
|
});
|
|
381
383
|
sendJson(response, 202, {
|
|
384
|
+
delivery_state: result.deliveryState,
|
|
382
385
|
dispatch_id: result.dispatch?.id ?? null,
|
|
383
386
|
forward_error: result.forwardError,
|
|
384
387
|
forwarded: result.forwarded,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { normalizeWorkerAvatar } from '../shared/worker-avatar.js';
|
|
2
|
+
import { resolveCommandPresetLaunchConfig, resolveStartupCommandLaunchConfig, } from './agent-launch-resolver.js';
|
|
3
|
+
import { BadRequestError } from './http-errors.js';
|
|
4
|
+
import { autostartAgent } from './orchestrator-autostart.js';
|
|
5
|
+
import { getDefaultRoleDescription } from './role-templates.js';
|
|
6
|
+
import { getRequiredParam, readJsonBody, route, sendJson } from './route-helpers.js';
|
|
7
|
+
import { enrichTeamList } from './team-list-enrichment.js';
|
|
8
|
+
import { serializeTeamListItem } from './team-list-serializer.js';
|
|
9
|
+
import { requireUiTokenFromRequest } from './ui-auth-helpers.js';
|
|
10
|
+
import { resolveWorkspaceUiLanguage } from './workspace-ui-language.js';
|
|
11
|
+
const getRuntimePort = (request) => String(request.socket.localPort ?? '');
|
|
12
|
+
const readWorkerAvatar = (value) => {
|
|
13
|
+
try {
|
|
14
|
+
return normalizeWorkerAvatar(value);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw new BadRequestError(error instanceof Error ? error.message : String(error));
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const getSerializedWorker = (workspaceId, workerId, store) => {
|
|
21
|
+
const worker = store.listWorkers(workspaceId).find((item) => item.id === workerId);
|
|
22
|
+
if (!worker) {
|
|
23
|
+
throw new Error(`Worker not found: ${workerId}`);
|
|
24
|
+
}
|
|
25
|
+
const [enriched] = enrichTeamList(workspaceId, store, [worker]);
|
|
26
|
+
if (!enriched)
|
|
27
|
+
throw new Error(`Worker enrichment failed: ${workerId}`);
|
|
28
|
+
return serializeTeamListItem(enriched, undefined, { includeAvatar: true });
|
|
29
|
+
};
|
|
30
|
+
export const workerRoutes = [
|
|
31
|
+
route('POST', '/api/workspaces/:workspaceId/workers', async ({ params, request, response, store }) => {
|
|
32
|
+
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id is required');
|
|
33
|
+
if (!workspaceId) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
37
|
+
const body = await readJsonBody(request);
|
|
38
|
+
const avatar = Object.hasOwn(body, 'avatar') ? readWorkerAvatar(body.avatar) : null;
|
|
39
|
+
const presetId = body.command_preset_id ?? null;
|
|
40
|
+
const startupCommand = typeof body.startup_command === 'string' ? body.startup_command : null;
|
|
41
|
+
const language = resolveWorkspaceUiLanguage(store.settings, workspaceId, body.ui_language);
|
|
42
|
+
const launchConfig = startupCommand?.trim()
|
|
43
|
+
? resolveStartupCommandLaunchConfig(store.settings, startupCommand, presetId)
|
|
44
|
+
: presetId
|
|
45
|
+
? resolveCommandPresetLaunchConfig(store.settings, presetId)
|
|
46
|
+
: undefined;
|
|
47
|
+
if (presetId && !startupCommand?.trim() && !launchConfig) {
|
|
48
|
+
throw new Error(`Command preset not found: ${presetId}`);
|
|
49
|
+
}
|
|
50
|
+
const worker = store.addWorker(workspaceId, {
|
|
51
|
+
...body,
|
|
52
|
+
avatar,
|
|
53
|
+
description: typeof body.description === 'string'
|
|
54
|
+
? body.description
|
|
55
|
+
: getDefaultRoleDescription(body.role, language),
|
|
56
|
+
});
|
|
57
|
+
if (launchConfig) {
|
|
58
|
+
try {
|
|
59
|
+
store.configureAgentLaunch(workspaceId, worker.id, launchConfig);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
store.deleteWorker(workspaceId, worker.id);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const agentStart = body.autostart === true
|
|
67
|
+
? await autostartAgent(store, workspaceId, worker.id, getRuntimePort(request), {
|
|
68
|
+
missingConfigError: 'No worker launch config available',
|
|
69
|
+
})
|
|
70
|
+
: { ok: false, error: null, run_id: null };
|
|
71
|
+
sendJson(response, 201, {
|
|
72
|
+
...getSerializedWorker(workspaceId, worker.id, store),
|
|
73
|
+
agent_start: agentStart,
|
|
74
|
+
});
|
|
75
|
+
}),
|
|
76
|
+
route('DELETE', '/api/workspaces/:workspaceId/workers/:workerId', ({ params, request, response, store }) => {
|
|
77
|
+
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id and worker id are required');
|
|
78
|
+
const workerId = getRequiredParam(response, params, 'workerId', 'Workspace id and worker id are required');
|
|
79
|
+
if (!workspaceId || !workerId) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
83
|
+
store.deleteWorker(workspaceId, workerId);
|
|
84
|
+
response.statusCode = 204;
|
|
85
|
+
response.end();
|
|
86
|
+
}),
|
|
87
|
+
route('PATCH', '/api/workspaces/:workspaceId/workers/:workerId', async ({ params, request, response, store }) => {
|
|
88
|
+
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id and worker id are required');
|
|
89
|
+
const workerId = getRequiredParam(response, params, 'workerId', 'Workspace id and worker id are required');
|
|
90
|
+
if (!workspaceId || !workerId) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
94
|
+
const body = await readJsonBody(request);
|
|
95
|
+
const hasName = Object.hasOwn(body, 'name');
|
|
96
|
+
const hasAvatar = Object.hasOwn(body, 'avatar');
|
|
97
|
+
if (!hasName && !hasAvatar) {
|
|
98
|
+
sendJson(response, 400, { error: 'name or avatar is required' });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (hasName && typeof body.name !== 'string') {
|
|
102
|
+
sendJson(response, 400, { error: 'name must be a string' });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const avatar = hasAvatar ? readWorkerAvatar(body.avatar) : undefined;
|
|
106
|
+
store.updateWorkerProfile(workspaceId, workerId, {
|
|
107
|
+
...(hasName ? { name: body.name } : {}),
|
|
108
|
+
...(hasAvatar ? { avatar: avatar ?? null } : {}),
|
|
109
|
+
});
|
|
110
|
+
sendJson(response, 200, getSerializedWorker(workspaceId, workerId, store));
|
|
111
|
+
}),
|
|
112
|
+
];
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { resolveCommandPresetLaunchConfig, resolveStartupCommandLaunchConfig, } from './agent-launch-resolver.js';
|
|
2
1
|
import { PtyInactiveError } from './http-errors.js';
|
|
3
|
-
import {
|
|
2
|
+
import { autostartOrchestrator } from './orchestrator-autostart.js';
|
|
4
3
|
import { seedOrchestratorLaunchConfig } from './orchestrator-launch.js';
|
|
5
|
-
import { getDefaultRoleDescription } from './role-templates.js';
|
|
6
4
|
import { getRequiredParam, readJsonBody, route, sendJson } from './route-helpers.js';
|
|
7
5
|
import { authenticateCliAgent, requireCommandForRole } from './team-authz.js';
|
|
8
6
|
import { enrichTeamList } from './team-list-enrichment.js';
|
|
@@ -15,7 +13,7 @@ import { resolveWorkspaceUiLanguage, writeWorkspaceUiLanguage } from './workspac
|
|
|
15
13
|
into the team list payload. Display-only ages — no timeout or heartbeat is
|
|
16
14
|
derived from them; `queued` rows age from createdAt (submittedAt is null
|
|
17
15
|
until delivery). */
|
|
18
|
-
const serializeTeamListWithOpenDispatches = (store, workspaceId) => {
|
|
16
|
+
const serializeTeamListWithOpenDispatches = (store, workspaceId, options = {}) => {
|
|
19
17
|
const now = Date.now();
|
|
20
18
|
const workflowAgentId = getWorkflowAgentId(workspaceId);
|
|
21
19
|
const openByWorker = new Map();
|
|
@@ -35,17 +33,7 @@ const serializeTeamListWithOpenDispatches = (store, workspaceId) => {
|
|
|
35
33
|
});
|
|
36
34
|
openByWorker.set(dispatch.toAgentId, list);
|
|
37
35
|
}
|
|
38
|
-
return enrichTeamList(workspaceId, store, store.listWorkers(workspaceId)).map((worker) => serializeTeamListItem(worker, openByWorker.get(worker.id)));
|
|
39
|
-
};
|
|
40
|
-
const getSerializedWorker = (workspaceId, workerId, store) => {
|
|
41
|
-
const worker = store.listWorkers(workspaceId).find((item) => item.id === workerId);
|
|
42
|
-
if (!worker) {
|
|
43
|
-
throw new Error(`Worker not found: ${workerId}`);
|
|
44
|
-
}
|
|
45
|
-
const [enriched] = enrichTeamList(workspaceId, store, [worker]);
|
|
46
|
-
if (!enriched)
|
|
47
|
-
throw new Error(`Worker enrichment failed: ${workerId}`);
|
|
48
|
-
return serializeTeamListItem(enriched);
|
|
36
|
+
return enrichTeamList(workspaceId, store, store.listWorkers(workspaceId)).map((worker) => serializeTeamListItem(worker, openByWorker.get(worker.id), options));
|
|
49
37
|
};
|
|
50
38
|
const getRuntimePort = (request) => String(request.socket.localPort ?? '');
|
|
51
39
|
export const workspaceRoutes = [
|
|
@@ -92,7 +80,7 @@ export const workspaceRoutes = [
|
|
|
92
80
|
return;
|
|
93
81
|
}
|
|
94
82
|
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
95
|
-
sendJson(response, 200, serializeTeamListWithOpenDispatches(store, workspaceId));
|
|
83
|
+
sendJson(response, 200, serializeTeamListWithOpenDispatches(store, workspaceId, { includeAvatar: true }));
|
|
96
84
|
}),
|
|
97
85
|
route('GET', '/api/workspaces/:workspaceId/team', ({ params, request, response, store }) => {
|
|
98
86
|
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id is required');
|
|
@@ -114,75 +102,6 @@ export const workspaceRoutes = [
|
|
|
114
102
|
store.drainReportOutbox(workspaceId, agent.id);
|
|
115
103
|
sendJson(response, 200, serializeTeamListWithOpenDispatches(store, workspaceId));
|
|
116
104
|
}),
|
|
117
|
-
route('POST', '/api/workspaces/:workspaceId/workers', async ({ params, request, response, store }) => {
|
|
118
|
-
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id is required');
|
|
119
|
-
if (!workspaceId) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
123
|
-
const body = await readJsonBody(request);
|
|
124
|
-
const presetId = body.command_preset_id ?? null;
|
|
125
|
-
const startupCommand = typeof body.startup_command === 'string' ? body.startup_command : null;
|
|
126
|
-
const language = resolveWorkspaceUiLanguage(store.settings, workspaceId, body.ui_language);
|
|
127
|
-
const launchConfig = startupCommand?.trim()
|
|
128
|
-
? resolveStartupCommandLaunchConfig(store.settings, startupCommand, presetId)
|
|
129
|
-
: presetId
|
|
130
|
-
? resolveCommandPresetLaunchConfig(store.settings, presetId)
|
|
131
|
-
: undefined;
|
|
132
|
-
if (presetId && !startupCommand?.trim() && !launchConfig) {
|
|
133
|
-
throw new Error(`Command preset not found: ${presetId}`);
|
|
134
|
-
}
|
|
135
|
-
const worker = store.addWorker(workspaceId, {
|
|
136
|
-
...body,
|
|
137
|
-
description: typeof body.description === 'string'
|
|
138
|
-
? body.description
|
|
139
|
-
: getDefaultRoleDescription(body.role, language),
|
|
140
|
-
});
|
|
141
|
-
if (launchConfig) {
|
|
142
|
-
try {
|
|
143
|
-
store.configureAgentLaunch(workspaceId, worker.id, launchConfig);
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
store.deleteWorker(workspaceId, worker.id);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
const agentStart = body.autostart === true
|
|
151
|
-
? await autostartAgent(store, workspaceId, worker.id, getRuntimePort(request), {
|
|
152
|
-
missingConfigError: 'No worker launch config available',
|
|
153
|
-
})
|
|
154
|
-
: { ok: false, error: null, run_id: null };
|
|
155
|
-
sendJson(response, 201, {
|
|
156
|
-
...getSerializedWorker(workspaceId, worker.id, store),
|
|
157
|
-
agent_start: agentStart,
|
|
158
|
-
});
|
|
159
|
-
}),
|
|
160
|
-
route('DELETE', '/api/workspaces/:workspaceId/workers/:workerId', ({ params, request, response, store }) => {
|
|
161
|
-
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id and worker id are required');
|
|
162
|
-
const workerId = getRequiredParam(response, params, 'workerId', 'Workspace id and worker id are required');
|
|
163
|
-
if (!workspaceId || !workerId) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
167
|
-
store.deleteWorker(workspaceId, workerId);
|
|
168
|
-
response.statusCode = 204;
|
|
169
|
-
response.end();
|
|
170
|
-
}),
|
|
171
|
-
route('PATCH', '/api/workspaces/:workspaceId/workers/:workerId', async ({ params, request, response, store }) => {
|
|
172
|
-
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id and worker id are required');
|
|
173
|
-
const workerId = getRequiredParam(response, params, 'workerId', 'Workspace id and worker id are required');
|
|
174
|
-
if (!workspaceId || !workerId) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
requireUiTokenFromRequest(request, store.validateUiToken, store.authorizeRemoteTunnelRequest);
|
|
178
|
-
const body = await readJsonBody(request);
|
|
179
|
-
if (typeof body.name !== 'string') {
|
|
180
|
-
sendJson(response, 400, { error: 'name is required' });
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
store.renameWorker(workspaceId, workerId, body.name);
|
|
184
|
-
sendJson(response, 200, getSerializedWorker(workspaceId, workerId, store));
|
|
185
|
-
}),
|
|
186
105
|
route('POST', '/api/workspaces/:workspaceId/user-input', async ({ params, request, response, store }) => {
|
|
187
106
|
const workspaceId = getRequiredParam(response, params, 'workspaceId', 'Workspace id is required');
|
|
188
107
|
if (!workspaceId) {
|
|
@@ -17,6 +17,7 @@ import { teamMemoryRoutes } from './routes-team-memory.js';
|
|
|
17
17
|
import { teamRecallRoutes } from './routes-team-recall.js';
|
|
18
18
|
import { uiRoutes } from './routes-ui.js';
|
|
19
19
|
import { versionRoutes } from './routes-version.js';
|
|
20
|
+
import { workerRoutes } from './routes-workers.js';
|
|
20
21
|
import { workflowScheduleRoutes } from './routes-workflow-schedules.js';
|
|
21
22
|
import { workflowRoutes } from './routes-workflows.js';
|
|
22
23
|
import { workspaceMemoryRoutes } from './routes-workspace-memory.js';
|
|
@@ -25,6 +26,7 @@ import { workspaceUploadRoutes } from './routes-workspace-uploads.js';
|
|
|
25
26
|
import { workspaceRoutes } from './routes-workspaces.js';
|
|
26
27
|
const routes = [
|
|
27
28
|
...workspaceRoutes,
|
|
29
|
+
...workerRoutes,
|
|
28
30
|
...scenarioRoutes,
|
|
29
31
|
...workspaceUploadRoutes,
|
|
30
32
|
...openWorkspaceRoutes,
|
|
@@ -34,6 +34,11 @@ export interface RuntimeStore {
|
|
|
34
34
|
addWorker: (workspaceId: string, input: WorkerInput) => AgentSummary;
|
|
35
35
|
addWorkerWithLaunch: (workspaceId: string, input: WorkerInput, launchConfig: AgentLaunchConfigInput) => AgentSummary;
|
|
36
36
|
deleteWorker: (workspaceId: string, workerId: string) => void;
|
|
37
|
+
updateWorkerProfile: (workspaceId: string, workerId: string, input: {
|
|
38
|
+
avatar?: string | null;
|
|
39
|
+
name?: string;
|
|
40
|
+
}) => AgentSummary;
|
|
41
|
+
updateWorkerAvatar: (workspaceId: string, workerId: string, avatar: string | null) => AgentSummary;
|
|
37
42
|
renameWorker: (workspaceId: string, workerId: string, name: string) => AgentSummary;
|
|
38
43
|
recordUserInput: (workspaceId: string, orchestratorId: string, text: string) => void;
|
|
39
44
|
deliverUserInput: (workspaceId: string, orchestratorId: string, text: string) => Promise<void>;
|
|
@@ -81,6 +81,8 @@ export const createRuntimeStore = (options = {}) => {
|
|
|
81
81
|
},
|
|
82
82
|
addWorker: (workspaceId, input) => services.workspaceStore.addWorker(workspaceId, input),
|
|
83
83
|
addWorkerWithLaunch: workerMutations.addWorkerWithLaunch,
|
|
84
|
+
updateWorkerProfile: (workspaceId, workerId, input) => services.workspaceStore.updateWorkerProfile(workspaceId, workerId, input),
|
|
85
|
+
updateWorkerAvatar: (workspaceId, workerId, avatar) => services.workspaceStore.updateWorkerAvatar(workspaceId, workerId, avatar),
|
|
84
86
|
renameWorker: (workspaceId, workerId, name) => services.workspaceStore.renameWorker(workspaceId, workerId, name),
|
|
85
87
|
deleteWorker: workerMutations.deleteWorker,
|
|
86
88
|
recordUserInput: services.teamOps.recordUserInput,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const getCodexHome: (pattern?: string, platform?: NodeJS.Platform) => string;
|
|
2
2
|
export declare const readCodexSessionFirstLine: (filePath: string, maxBytes?: number) => string | null;
|
|
3
|
+
export declare const getCodexSessionExistence: (cwd: string, sessionId: string, pattern?: string, platform?: NodeJS.Platform, codexHome?: string) => boolean | undefined;
|
|
3
4
|
export declare const hasCodexSession: (cwd: string, sessionId: string, pattern?: string, platform?: NodeJS.Platform, codexHome?: string) => boolean;
|
|
4
5
|
export declare const snapshotCodexSessionIds: (cwd: string, codexHome?: string, platform?: NodeJS.Platform) => Set<string>;
|
|
5
6
|
export declare const captureCodexSessionId: (cwd: string, knownSessionIds: Set<string>, onCapture: (sessionId: string) => void, timeoutMs?: number, intervalMs?: number, codexHome?: string) => Promise<void>;
|