@tt-a1i/hive 1.2.0 → 1.3.4
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 +119 -14
- package/README.en.md +63 -8
- package/README.md +37 -6
- package/assets/hive-team-view.png +0 -0
- package/dist/src/cli/hive-update.d.ts +15 -0
- package/dist/src/cli/hive-update.js +81 -0
- package/dist/src/cli/hive.js +21 -5
- package/dist/src/cli/team.d.ts +6 -0
- package/dist/src/cli/team.js +48 -0
- package/dist/src/server/agent-launch-cache.js +25 -6
- package/dist/src/server/agent-manager.d.ts +2 -2
- package/dist/src/server/agent-run-store.d.ts +1 -1
- package/dist/src/server/agent-runtime-contract.d.ts +3 -0
- package/dist/src/server/agent-runtime.js +3 -0
- package/dist/src/server/agent-startup-instructions.js +1 -1
- package/dist/src/server/agent-stdin-dispatcher.d.ts +4 -0
- package/dist/src/server/agent-stdin-dispatcher.js +12 -0
- package/dist/src/server/app.js +12 -1
- package/dist/src/server/dispatch-ledger-store.d.ts +22 -1
- package/dist/src/server/dispatch-ledger-store.js +34 -3
- package/dist/src/server/hive-team-guidance.js +3 -1
- package/dist/src/server/open-target-commands.js +0 -17
- package/dist/src/server/package-version.d.ts +15 -0
- package/dist/src/server/package-version.js +15 -0
- package/dist/src/server/route-types.d.ts +7 -0
- package/dist/src/server/routes-dispatches.js +4 -2
- package/dist/src/server/routes-runtime.js +1 -0
- package/dist/src/server/routes-team.js +22 -0
- package/dist/src/server/runtime-store-helpers.d.ts +2 -1
- package/dist/src/server/runtime-store-helpers.js +14 -4
- package/dist/src/server/runtime-store.d.ts +5 -8
- package/dist/src/server/runtime-store.js +1 -0
- package/dist/src/server/tasks-websocket-server.d.ts +2 -1
- package/dist/src/server/tasks-websocket-server.js +18 -2
- package/dist/src/server/team-authz.d.ts +1 -1
- package/dist/src/server/team-authz.js +1 -1
- package/dist/src/server/team-operations.d.ts +16 -1
- package/dist/src/server/team-operations.js +28 -1
- package/dist/src/server/terminal-input-profile.d.ts +10 -0
- package/dist/src/server/terminal-input-profile.js +15 -0
- package/dist/src/server/terminal-stream-hub.js +10 -2
- package/dist/src/server/terminal-ws-server.d.ts +2 -1
- package/dist/src/server/terminal-ws-server.js +2 -2
- package/dist/src/server/version-service.js +4 -1
- package/dist/src/server/workspace-shell-runtime.d.ts +2 -1
- package/dist/src/server/workspace-shell-runtime.js +37 -10
- package/dist/src/server/workspace-store-contract.d.ts +1 -0
- package/dist/src/server/workspace-store-mutations.d.ts +1 -0
- package/dist/src/server/workspace-store-mutations.js +1 -0
- package/dist/src/server/workspace-store.js +2 -1
- package/dist/src/shared/open-targets.d.ts +1 -1
- package/dist/src/shared/open-targets.js +9 -16
- package/package.json +2 -2
- package/web/dist/assets/AddWorkerDialog-D6-K1wJm.js +1 -0
- package/web/dist/assets/AddWorkspaceDialog-Du0lndJ0.js +1 -0
- package/web/dist/assets/FirstRunWizard-B8k7S5De.js +1 -0
- package/web/dist/assets/WorkerModal-B3XhIvAX.js +1 -0
- package/web/dist/assets/WorkspaceTaskDrawer-CjEoLJvS.js +1 -0
- package/web/dist/assets/chevron-right-BvbSCniy.js +1 -0
- package/web/dist/assets/finder-C4Jmsb0B.png +0 -0
- package/web/dist/assets/ghostty-D-Js4rdm.png +0 -0
- package/web/dist/assets/index-DB5fHAMI.js +81 -0
- package/web/dist/assets/index-Sbdu6Se0.css +1 -0
- package/web/dist/assets/zed-C5BQT8X3.png +0 -0
- package/web/dist/icons/apple-touch-icon-180.png +0 -0
- package/web/dist/icons/icon-192.png +0 -0
- package/web/dist/icons/icon-32.png +0 -0
- package/web/dist/icons/icon-512-maskable.png +0 -0
- package/web/dist/icons/icon-512.png +0 -0
- package/web/dist/index.html +11 -3
- package/web/dist/manifest.webmanifest +60 -0
- package/web/dist/screenshots/wide-overview.png +0 -0
- package/web/dist/sw.js +99 -0
- package/web/dist/assets/index-BgXxFsKj.css +0 -1
- package/web/dist/assets/index-VeKhgpe_.js +0 -66
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export const createAgentLaunchCache = (store) => {
|
|
2
2
|
const launchConfigs = new Map();
|
|
3
3
|
const workspaceByAgentId = new Map();
|
|
4
|
+
const missingLaunchConfigs = new Set();
|
|
4
5
|
const cacheKey = (workspaceId, agentId) => `${workspaceId}:${agentId}`;
|
|
5
6
|
const load = () => {
|
|
7
|
+
launchConfigs.clear();
|
|
8
|
+
workspaceByAgentId.clear();
|
|
6
9
|
for (const row of store.listLaunchConfigs()) {
|
|
7
10
|
launchConfigs.set(cacheKey(row.workspaceId, row.agentId), row.config);
|
|
8
11
|
workspaceByAgentId.set(row.agentId, row.workspaceId);
|
|
@@ -11,21 +14,33 @@ export const createAgentLaunchCache = (store) => {
|
|
|
11
14
|
load();
|
|
12
15
|
return {
|
|
13
16
|
get(workspaceId, agentId) {
|
|
14
|
-
const
|
|
17
|
+
const key = cacheKey(workspaceId, agentId);
|
|
18
|
+
const config = launchConfigs.get(key);
|
|
15
19
|
if (config)
|
|
16
20
|
return config;
|
|
21
|
+
if (missingLaunchConfigs.has(key)) {
|
|
22
|
+
throw new Error(`Agent launch config not found: ${agentId}`);
|
|
23
|
+
}
|
|
17
24
|
load();
|
|
18
|
-
const reloadedConfig = launchConfigs.get(
|
|
25
|
+
const reloadedConfig = launchConfigs.get(key);
|
|
19
26
|
if (reloadedConfig)
|
|
20
27
|
return reloadedConfig;
|
|
28
|
+
missingLaunchConfigs.add(key);
|
|
21
29
|
throw new Error(`Agent launch config not found: ${agentId}`);
|
|
22
30
|
},
|
|
23
31
|
peek(workspaceId, agentId) {
|
|
24
|
-
const
|
|
32
|
+
const key = cacheKey(workspaceId, agentId);
|
|
33
|
+
const config = launchConfigs.get(key);
|
|
25
34
|
if (config)
|
|
26
35
|
return config;
|
|
36
|
+
if (missingLaunchConfigs.has(key))
|
|
37
|
+
return undefined;
|
|
27
38
|
load();
|
|
28
|
-
|
|
39
|
+
const reloadedConfig = launchConfigs.get(key);
|
|
40
|
+
if (reloadedConfig)
|
|
41
|
+
return reloadedConfig;
|
|
42
|
+
missingLaunchConfigs.add(key);
|
|
43
|
+
return undefined;
|
|
29
44
|
},
|
|
30
45
|
getWorkspaceId(agentId) {
|
|
31
46
|
return workspaceByAgentId.get(agentId);
|
|
@@ -41,12 +56,16 @@ export const createAgentLaunchCache = (store) => {
|
|
|
41
56
|
sessionIdCapture: input.sessionIdCapture ?? null,
|
|
42
57
|
};
|
|
43
58
|
store.saveLaunchConfig(workspaceId, agentId, normalized);
|
|
44
|
-
|
|
59
|
+
const key = cacheKey(workspaceId, agentId);
|
|
60
|
+
launchConfigs.set(key, normalized);
|
|
61
|
+
missingLaunchConfigs.delete(key);
|
|
45
62
|
workspaceByAgentId.set(agentId, workspaceId);
|
|
46
63
|
},
|
|
47
64
|
remove(workspaceId, agentId) {
|
|
48
65
|
store.deleteLaunchConfig(workspaceId, agentId);
|
|
49
|
-
|
|
66
|
+
const key = cacheKey(workspaceId, agentId);
|
|
67
|
+
launchConfigs.delete(key);
|
|
68
|
+
missingLaunchConfigs.add(key);
|
|
50
69
|
workspaceByAgentId.delete(agentId);
|
|
51
70
|
},
|
|
52
71
|
setWorkspaceId(agentId, workspaceId) {
|
|
@@ -27,7 +27,7 @@ interface AgentRunRecord extends AgentRunSnapshot {
|
|
|
27
27
|
resize: (cols: number, rows: number) => void;
|
|
28
28
|
resume: () => void;
|
|
29
29
|
stop: () => void;
|
|
30
|
-
write: (
|
|
30
|
+
write: (input: Buffer | string) => void;
|
|
31
31
|
};
|
|
32
32
|
onExit?: (event: {
|
|
33
33
|
runId: string;
|
|
@@ -40,7 +40,7 @@ interface AgentManager {
|
|
|
40
40
|
resizeRun: (runId: string, cols: number, rows: number) => void;
|
|
41
41
|
resumeRun: (runId: string) => void;
|
|
42
42
|
startAgent: (input: StartAgentInput) => Promise<AgentRunSnapshot>;
|
|
43
|
-
writeInput: (runId: string,
|
|
43
|
+
writeInput: (runId: string, input: Buffer | string) => void;
|
|
44
44
|
getRun: (runId: string) => AgentRunSnapshot;
|
|
45
45
|
removeRun: (runId: string) => void;
|
|
46
46
|
stopRun: (runId: string) => void;
|
|
@@ -27,7 +27,7 @@ export declare const createAgentRunStore: (db: Database) => {
|
|
|
27
27
|
runId: string;
|
|
28
28
|
agentId: string;
|
|
29
29
|
pid: number | null;
|
|
30
|
-
status: "
|
|
30
|
+
status: "error" | "starting" | "running" | "exited";
|
|
31
31
|
exitCode: number | null;
|
|
32
32
|
startedAt: number;
|
|
33
33
|
endedAt: number | null;
|
|
@@ -29,6 +29,9 @@ export interface AgentRuntime {
|
|
|
29
29
|
requireActiveRun?: boolean;
|
|
30
30
|
}) => void;
|
|
31
31
|
writeSendPrompt: (workspaceId: string, workerId: string, dispatchId: string, fromAgentName: string, workerDescription: string, text: string) => void;
|
|
32
|
+
writeCancelPrompt: (workspaceId: string, workerId: string, dispatchId: string, reason: string, input?: {
|
|
33
|
+
requireActiveRun?: boolean;
|
|
34
|
+
}) => void;
|
|
32
35
|
writeUserInputPrompt: (workspaceId: string, text: string) => void;
|
|
33
36
|
}
|
|
34
37
|
export type { StartAgentOptions };
|
|
@@ -115,6 +115,9 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
115
115
|
writeSendPrompt(workspaceId, workerId, dispatchId, fromAgentName, workerDescription, text) {
|
|
116
116
|
stdinDispatcher.writeSendPrompt(workspaceId, workerId, dispatchId, fromAgentName, workerDescription, text);
|
|
117
117
|
},
|
|
118
|
+
writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input = {}) {
|
|
119
|
+
stdinDispatcher.writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input);
|
|
120
|
+
},
|
|
118
121
|
writeUserInputPrompt(workspaceId, text) {
|
|
119
122
|
stdinDispatcher.writeUserInputPrompt(workspaceId, text);
|
|
120
123
|
},
|
|
@@ -15,7 +15,7 @@ export const buildAgentStartupInstructions = ({ agent, workspace, }) => {
|
|
|
15
15
|
'',
|
|
16
16
|
];
|
|
17
17
|
if (agent.role === 'orchestrator') {
|
|
18
|
-
lines.push('你的职责:', '- 直接响应 user,澄清需求并拆解任务', `- 维护 ${TASKS_RELATIVE_PATH}`, '- 按 worker 名称派单,并根据汇报推进下一步', '', '可用 team 命令:', '- team list', '- team send <worker-name> "<task>"', '', '派单时必须使用 worker name,不要使用 worker id。', '', 'Hive worker 派单规则:', ...getHiveTeamRules(agent));
|
|
18
|
+
lines.push('你的职责:', '- 直接响应 user,澄清需求并拆解任务', `- 维护 ${TASKS_RELATIVE_PATH}`, '- 按 worker 名称派单,并根据汇报推进下一步', '', '可用 team 命令:', '- team list', '- team send <worker-name> "<task>"', '- team cancel --dispatch <id> "<reason>"', '', '派单时必须使用 worker name,不要使用 worker id。', '取消未完成派单时必须使用 dispatch id。', '', 'Hive worker 派单规则:', ...getHiveTeamRules(agent));
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
lines.push('可用 team 命令:', '- team report "<完整汇报>" [--dispatch <id>] [--artifact <path>] 完成/失败/阻塞汇报', '- team report --stdin [--dispatch <id>] [--artifact <path>] 同上,从 stdin 读正文(适合多行/含引号/特殊字符)', '- team status "<当前状态>" [--artifact <path>] 中段进度/待命/接入状态', '- team status --stdin [--artifact <path>] 同上,从 stdin 读正文', '- team list 查看 workspace 内的 worker(含状态)', '- team --help 仅查命令用法;**不是**汇报手段', '', '语法要点:', '- 正文是第一个 positional argument,flag 顺序任意:`team report "结论" --dispatch X` 和 `team report --dispatch X "结论"` 都成立。', "- 长正文(多行 / 含引号 / shell 特殊字符 / heredoc)一律走 `--stdin`,并用 *quoted* heredoc(`<<'EOF'`)防止 shell 展开 $vars / 反引号 / 命令替换:", " 例:`team report --stdin --dispatch <id> <<'EOF'`", ' `... 长报告(含 $VAR、`backtick`、"引号" 都按字面量保留)...`', ' `EOF`', '- CLI 报错会同时打印 USAGE,可直接对照修正参数。', '', '完成任务后必须执行 `team report "<结论>"`。', '失败、阻塞或部分完成也用 `team report "<当前状态与原因>"` 汇报。', '没有进行中的任务时,用 `team status "<当前状态>"` 汇报接入、待命或阻塞状态。', '不要调用 team send;worker 之间不能直接派单。', '', 'Hive worker 边界:', ...getHiveTeamRules(agent));
|
|
@@ -13,6 +13,7 @@ export declare const buildOrchestratorReportPayload: (workerName: string, text:
|
|
|
13
13
|
export declare const buildOrchestratorStatusPayload: (workerName: string, text: string, artifacts: string[]) => string;
|
|
14
14
|
export declare const buildOrchestratorUserInputPayload: (text: string) => string;
|
|
15
15
|
export declare const buildWorkerDispatchPayload: (fromAgentName: string, workerDescription: string, dispatchId: string, text: string) => string;
|
|
16
|
+
export declare const buildWorkerCancelPayload: (dispatchId: string, reason: string) => string;
|
|
16
17
|
export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, }: AgentStdinDispatcherInput) => {
|
|
17
18
|
writeReportPrompt(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
18
19
|
requireActiveRun?: boolean;
|
|
@@ -21,6 +22,9 @@ export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfi
|
|
|
21
22
|
requireActiveRun?: boolean;
|
|
22
23
|
}): void;
|
|
23
24
|
writeSendPrompt(workspaceId: string, workerId: string, dispatchId: string, fromAgentName: string, workerDescription: string, text: string): void;
|
|
25
|
+
writeCancelPrompt(workspaceId: string, workerId: string, dispatchId: string, reason: string, input?: {
|
|
26
|
+
requireActiveRun?: boolean;
|
|
27
|
+
}): void;
|
|
24
28
|
writeUserInputPrompt(workspaceId: string, text: string): void;
|
|
25
29
|
};
|
|
26
30
|
export {};
|
|
@@ -33,6 +33,15 @@ export const buildWorkerDispatchPayload = (fromAgentName, workerDescription, dis
|
|
|
33
33
|
buildWorkerReminderTail(dispatchId),
|
|
34
34
|
'',
|
|
35
35
|
].join('\n');
|
|
36
|
+
export const buildWorkerCancelPayload = (dispatchId, reason) => [
|
|
37
|
+
`[Hive 系统消息:dispatch ${dispatchId} 已取消]`,
|
|
38
|
+
'',
|
|
39
|
+
'请停止执行这条派单,不要再为它调用 team report。',
|
|
40
|
+
'',
|
|
41
|
+
'取消原因:',
|
|
42
|
+
reason,
|
|
43
|
+
'',
|
|
44
|
+
].join('\n');
|
|
36
45
|
export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, }) => {
|
|
37
46
|
const writeToActiveAgentRun = (workspaceId, agentId, text, input = {}) => {
|
|
38
47
|
const run = registry
|
|
@@ -72,6 +81,9 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
72
81
|
writeSendPrompt(workspaceId, workerId, dispatchId, fromAgentName, workerDescription, text) {
|
|
73
82
|
writeToActiveAgentRun(workspaceId, workerId, buildWorkerDispatchPayload(fromAgentName, workerDescription, dispatchId, text), { requireActiveRun: true });
|
|
74
83
|
},
|
|
84
|
+
writeCancelPrompt(workspaceId, workerId, dispatchId, reason, input = {}) {
|
|
85
|
+
writeToActiveAgentRun(workspaceId, workerId, buildWorkerCancelPayload(dispatchId, reason), input);
|
|
86
|
+
},
|
|
75
87
|
writeUserInputPrompt(workspaceId, text) {
|
|
76
88
|
writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorUserInputPayload(text));
|
|
77
89
|
},
|
package/dist/src/server/app.js
CHANGED
|
@@ -54,6 +54,14 @@ const CONTENT_TYPES = {
|
|
|
54
54
|
'.webp': 'image/webp',
|
|
55
55
|
'.woff2': 'font/woff2',
|
|
56
56
|
};
|
|
57
|
+
// PWA boot files must bypass HTTP caching: `sw.js` because the browser does its
|
|
58
|
+
// own byte-diff update check, and the manifest because Chrome consults it on
|
|
59
|
+
// every install/uninstall transition. Without these, SW updates can stall on a
|
|
60
|
+
// stale cached copy and the install prompt won't reflect a renamed app.
|
|
61
|
+
const PWA_BOOT_CACHE_CONTROL = {
|
|
62
|
+
'/manifest.webmanifest': 'max-age=0, must-revalidate',
|
|
63
|
+
'/sw.js': 'no-store',
|
|
64
|
+
};
|
|
57
65
|
const sendStatic = async (response, staticDir, pathname, request) => {
|
|
58
66
|
if (request.method !== 'GET' && request.method !== 'HEAD')
|
|
59
67
|
return false;
|
|
@@ -63,6 +71,9 @@ const sendStatic = async (response, staticDir, pathname, request) => {
|
|
|
63
71
|
try {
|
|
64
72
|
const content = await readFile(filePath);
|
|
65
73
|
response.setHeader('content-type', CONTENT_TYPES[extname(filePath)] ?? 'application/octet-stream');
|
|
74
|
+
const cacheControl = PWA_BOOT_CACHE_CONTROL[pathname];
|
|
75
|
+
if (cacheControl !== undefined)
|
|
76
|
+
response.setHeader('cache-control', cacheControl);
|
|
66
77
|
response.statusCode = 200;
|
|
67
78
|
response.end(request.method === 'HEAD' ? undefined : content);
|
|
68
79
|
return true;
|
|
@@ -118,6 +129,6 @@ export const createApp = ({ store, pickFolderService = pickFolder, openWorkspace
|
|
|
118
129
|
sendJson(response, 500, { error: message });
|
|
119
130
|
}
|
|
120
131
|
});
|
|
121
|
-
createTerminalWebSocketServer(server, store);
|
|
132
|
+
createTerminalWebSocketServer(server, store, tasksFileService);
|
|
122
133
|
return { server, store };
|
|
123
134
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Database } from 'better-sqlite3';
|
|
2
|
-
export type DispatchStatus = 'queued' | 'submitted' | 'reported';
|
|
2
|
+
export type DispatchStatus = 'queued' | 'submitted' | 'reported' | 'cancelled';
|
|
3
3
|
export interface DispatchRecord {
|
|
4
4
|
artifacts: string[];
|
|
5
5
|
createdAt: number;
|
|
@@ -28,6 +28,11 @@ interface ReportDispatchInput {
|
|
|
28
28
|
toAgentId: string;
|
|
29
29
|
workspaceId: string;
|
|
30
30
|
}
|
|
31
|
+
interface CancelDispatchInput {
|
|
32
|
+
dispatchId: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
workspaceId: string;
|
|
35
|
+
}
|
|
31
36
|
export interface ListDispatchesOptions {
|
|
32
37
|
limit?: number;
|
|
33
38
|
offset?: number;
|
|
@@ -39,12 +44,28 @@ export declare const createDispatchLedgerStore: (db: Database) => {
|
|
|
39
44
|
deleteWorkerDispatches: (workspaceId: string, workerId: string) => void;
|
|
40
45
|
deleteWorkspaceDispatches: (workspaceId: string) => void;
|
|
41
46
|
findOpenDispatch: (workspaceId: string, toAgentId: string, dispatchId?: string) => DispatchRecord | undefined;
|
|
47
|
+
findOpenDispatchById: (workspaceId: string, dispatchId: string) => DispatchRecord | undefined;
|
|
42
48
|
listOpenDispatchKinds: () => Array<{
|
|
43
49
|
type: "send";
|
|
44
50
|
worker_id: string;
|
|
45
51
|
workspace_id: string;
|
|
46
52
|
}>;
|
|
47
53
|
listWorkspaceDispatches: (workspaceId: string, options?: ListDispatchesOptions) => DispatchRecord[];
|
|
54
|
+
markCancelled: (input: CancelDispatchInput) => {
|
|
55
|
+
reportedAt: number;
|
|
56
|
+
reportText: string;
|
|
57
|
+
status: "cancelled";
|
|
58
|
+
artifacts: string[];
|
|
59
|
+
createdAt: number;
|
|
60
|
+
deliveredAt: number | null;
|
|
61
|
+
fromAgentId: string | null;
|
|
62
|
+
id: string;
|
|
63
|
+
sequence: number | null;
|
|
64
|
+
submittedAt: number | null;
|
|
65
|
+
text: string;
|
|
66
|
+
toAgentId: string;
|
|
67
|
+
workspaceId: string;
|
|
68
|
+
} | undefined;
|
|
48
69
|
markReportedByWorker: (input: ReportDispatchInput) => {
|
|
49
70
|
artifacts: string[];
|
|
50
71
|
reportedAt: number;
|
|
@@ -77,7 +77,7 @@ export const createDispatchLedgerStore = (db) => {
|
|
|
77
77
|
WHERE id = ?
|
|
78
78
|
AND workspace_id = ?
|
|
79
79
|
AND to_agent_id = ?
|
|
80
|
-
AND status
|
|
80
|
+
AND status IN ('queued', 'submitted')
|
|
81
81
|
LIMIT 1`)
|
|
82
82
|
.get(dispatchId, workspaceId, toAgentId);
|
|
83
83
|
return row ? toRecord(row) : undefined;
|
|
@@ -87,12 +87,23 @@ export const createDispatchLedgerStore = (db) => {
|
|
|
87
87
|
FROM dispatches
|
|
88
88
|
WHERE workspace_id = ?
|
|
89
89
|
AND to_agent_id = ?
|
|
90
|
-
AND status
|
|
90
|
+
AND status IN ('queued', 'submitted')
|
|
91
91
|
ORDER BY sequence ASC
|
|
92
92
|
LIMIT 1`)
|
|
93
93
|
.get(workspaceId, toAgentId);
|
|
94
94
|
return row ? toRecord(row) : undefined;
|
|
95
95
|
};
|
|
96
|
+
const findOpenDispatchById = (workspaceId, dispatchId) => {
|
|
97
|
+
const row = db
|
|
98
|
+
.prepare(`SELECT *
|
|
99
|
+
FROM dispatches
|
|
100
|
+
WHERE id = ?
|
|
101
|
+
AND workspace_id = ?
|
|
102
|
+
AND status IN ('queued', 'submitted')
|
|
103
|
+
LIMIT 1`)
|
|
104
|
+
.get(dispatchId, workspaceId);
|
|
105
|
+
return row ? toRecord(row) : undefined;
|
|
106
|
+
};
|
|
96
107
|
const markReportedByWorker = (input) => {
|
|
97
108
|
const dispatch = findOpenDispatch(input.workspaceId, input.toAgentId, input.dispatchId);
|
|
98
109
|
if (!dispatch) {
|
|
@@ -113,6 +124,24 @@ export const createDispatchLedgerStore = (db) => {
|
|
|
113
124
|
status: 'reported',
|
|
114
125
|
};
|
|
115
126
|
};
|
|
127
|
+
const markCancelled = (input) => {
|
|
128
|
+
const dispatch = findOpenDispatchById(input.workspaceId, input.dispatchId);
|
|
129
|
+
if (!dispatch) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
const cancelledAt = Date.now();
|
|
133
|
+
db.prepare(`UPDATE dispatches
|
|
134
|
+
SET status = ?,
|
|
135
|
+
reported_at = ?,
|
|
136
|
+
report_text = ?
|
|
137
|
+
WHERE id = ?`).run('cancelled', cancelledAt, input.reason, dispatch.id);
|
|
138
|
+
return {
|
|
139
|
+
...dispatch,
|
|
140
|
+
reportedAt: cancelledAt,
|
|
141
|
+
reportText: input.reason,
|
|
142
|
+
status: 'cancelled',
|
|
143
|
+
};
|
|
144
|
+
};
|
|
116
145
|
const listWorkspaceDispatches = (workspaceId, options = {}) => {
|
|
117
146
|
const offset = options.offset ?? 0;
|
|
118
147
|
const limit = options.limit ?? 100;
|
|
@@ -138,7 +167,7 @@ export const createDispatchLedgerStore = (db) => {
|
|
|
138
167
|
return db
|
|
139
168
|
.prepare(`SELECT workspace_id, to_agent_id AS worker_id, 'send' AS type
|
|
140
169
|
FROM dispatches
|
|
141
|
-
WHERE status
|
|
170
|
+
WHERE status IN ('queued', 'submitted')
|
|
142
171
|
ORDER BY sequence ASC`)
|
|
143
172
|
.all();
|
|
144
173
|
};
|
|
@@ -154,8 +183,10 @@ export const createDispatchLedgerStore = (db) => {
|
|
|
154
183
|
deleteWorkerDispatches,
|
|
155
184
|
deleteWorkspaceDispatches,
|
|
156
185
|
findOpenDispatch,
|
|
186
|
+
findOpenDispatchById,
|
|
157
187
|
listOpenDispatchKinds,
|
|
158
188
|
listWorkspaceDispatches,
|
|
189
|
+
markCancelled,
|
|
159
190
|
markReportedByWorker,
|
|
160
191
|
markSubmitted,
|
|
161
192
|
};
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* abstract identity restatement.
|
|
15
15
|
*/
|
|
16
16
|
export const ORCHESTRATOR_REMINDER_TAIL = '<hive-system-reminder>\n' +
|
|
17
|
-
'You are the Hive Orchestrator. Reply by either: (a) `team send "<worker-name>" "<task>"` to dispatch follow-up work to a Hive worker, or (
|
|
17
|
+
'You are the Hive Orchestrator. Reply by either: (a) `team send "<worker-name>" "<task>"` to dispatch follow-up work to a Hive worker, (b) `team cancel --dispatch <id> "<reason>"` to cancel an obsolete dispatch, or (c) plain text to the user. Never call your CLI\'s built-in subagent tools (Task / Explore / etc.) — they bypass Hive and will not appear in the UI.\n' +
|
|
18
18
|
'</hive-system-reminder>';
|
|
19
19
|
/**
|
|
20
20
|
* Tail reminder appended to dispatches sent TO a worker. Reinforces the
|
|
@@ -31,6 +31,7 @@ const ORCHESTRATOR_RULES = [
|
|
|
31
31
|
'普通、低风险、几分钟内能直接完成的小任务可以自己做;不要为了形式感派 worker。需要并行、长时间执行、独立 review/test、专门角色,或 user 明确要求 worker/成员处理时,再用 `team send`。',
|
|
32
32
|
'如果只有一个可用 worker,直接用 `team send <worker-name> "<task>"` 派给它;不要把选择题丢回给 user。',
|
|
33
33
|
'当 user 要你“让 worker ...”时,必须用 `team send <worker-name> "<task>"` 派给 Hive worker。',
|
|
34
|
+
'方向变更或 user 明确取消某个未完成派单时,使用 `team cancel --dispatch <id> "<reason>"` 显式关闭旧 dispatch;不要只用自然语言说“取消”。',
|
|
34
35
|
'不要使用你所在 CLI 的内置 subagent / 子代理工具(如 Task / Explore 等)来代替 Hive worker;它们不会出现在 Hive UI,也不会更新 Hive 调度状态。',
|
|
35
36
|
'`team list` 返回的 `last_pty_line` 是该 worker PTY 终端的最后一行原始输出(含任意 stdout / help / 控制序列噪声),**不是** worker 的正式汇报。正式汇报只来自 stdin 注入的 `[Hive 系统消息:来自 @<name> 的汇报]` 或 `[Hive 系统消息:来自 @<name> 的状态更新]`——只把这两种来源当作 reply。',
|
|
36
37
|
];
|
|
@@ -74,6 +75,7 @@ export const buildProtocolDoc = () => [
|
|
|
74
75
|
'',
|
|
75
76
|
'- `team list` — show workspace members and their status',
|
|
76
77
|
'- `team send "<worker-name>" "<task>"` — dispatch to a worker by name (never id)',
|
|
78
|
+
'- `team cancel --dispatch <id> "<reason>"` — cancel an obsolete open dispatch',
|
|
77
79
|
'',
|
|
78
80
|
'## `team` CLI — worker',
|
|
79
81
|
'',
|
|
@@ -20,23 +20,10 @@ const macAttempts = (targetId, path) => {
|
|
|
20
20
|
return [{ command: 'open', args: ['-a', 'Visual Studio Code - Insiders', path] }];
|
|
21
21
|
case 'cursor':
|
|
22
22
|
return [{ command: 'open', args: ['-a', 'Cursor', path] }];
|
|
23
|
-
case 'windsurf':
|
|
24
|
-
return [{ command: 'open', args: ['-a', 'Windsurf', path] }];
|
|
25
23
|
case 'terminal':
|
|
26
24
|
return [{ command: 'open', args: ['-a', 'Terminal', path] }];
|
|
27
|
-
case 'iterm2':
|
|
28
|
-
// Bundle name has always been `iTerm.app` even after the iTerm2 rename;
|
|
29
|
-
// the `iTerm2` fallback in earlier ports is cargo-cult.
|
|
30
|
-
return [{ command: 'open', args: ['-a', 'iTerm', path] }];
|
|
31
25
|
case 'ghostty':
|
|
32
26
|
return [{ command: 'open', args: ['-a', 'Ghostty', path] }];
|
|
33
|
-
case 'intellijidea':
|
|
34
|
-
// 2025.3 unified the editions, but installs predating that still ship
|
|
35
|
-
// `IntelliJ IDEA CE.app` — retry once on the CE bundle.
|
|
36
|
-
return [
|
|
37
|
-
{ command: 'open', args: ['-a', 'IntelliJ IDEA', path] },
|
|
38
|
-
{ command: 'open', args: ['-a', 'IntelliJ IDEA CE', path] },
|
|
39
|
-
];
|
|
40
27
|
case 'zed':
|
|
41
28
|
return [{ command: 'open', args: ['-a', 'Zed', path] }];
|
|
42
29
|
}
|
|
@@ -51,8 +38,6 @@ const linuxAttempts = (targetId, path) => {
|
|
|
51
38
|
return [{ command: 'code-insiders', args: [path] }];
|
|
52
39
|
case 'cursor':
|
|
53
40
|
return [{ command: 'cursor', args: [path] }];
|
|
54
|
-
case 'windsurf':
|
|
55
|
-
return [{ command: 'windsurf', args: [path] }];
|
|
56
41
|
case 'zed':
|
|
57
42
|
return [{ command: 'zed', args: [path] }];
|
|
58
43
|
default:
|
|
@@ -69,8 +54,6 @@ const windowsAttempts = (targetId, path) => {
|
|
|
69
54
|
return [{ command: 'code-insiders', args: [path] }];
|
|
70
55
|
case 'cursor':
|
|
71
56
|
return [{ command: 'cursor', args: [path] }];
|
|
72
|
-
case 'windsurf':
|
|
73
|
-
return [{ command: 'windsurf', args: [path] }];
|
|
74
57
|
case 'zed':
|
|
75
58
|
return [{ command: 'zed', args: [path] }];
|
|
76
59
|
default:
|
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
export declare const PACKAGE_NAME = "@tt-a1i/hive";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical argv for the upgrade command. Sharing one source between the
|
|
4
|
+
* server's install hint (`version-service.ts`) and the CLI upgrade path
|
|
5
|
+
* (`hive-update.ts`) keeps the two from drifting if the package name ever
|
|
6
|
+
* moves.
|
|
7
|
+
*/
|
|
8
|
+
export declare const INSTALL_COMMAND_ARGS: readonly ["install", "-g", "@tt-a1i/hive@latest"];
|
|
9
|
+
export declare const INSTALL_COMMAND_DISPLAY: string;
|
|
10
|
+
/**
|
|
11
|
+
* Windows ships npm as `npm.cmd` (a batch shim); Node's `child_process.spawn`
|
|
12
|
+
* will not resolve `.cmd` without `shell: true` or an explicit suffix, so the
|
|
13
|
+
* default `'npm'` produces ENOENT on Windows. Use this helper any time you
|
|
14
|
+
* spawn npm directly.
|
|
15
|
+
*/
|
|
16
|
+
export declare const getNpmCommand: (platform?: NodeJS.Platform) => string;
|
|
2
17
|
export declare const readPackageVersion: () => string;
|
|
@@ -2,6 +2,21 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
export const PACKAGE_NAME = '@tt-a1i/hive';
|
|
5
|
+
/**
|
|
6
|
+
* Canonical argv for the upgrade command. Sharing one source between the
|
|
7
|
+
* server's install hint (`version-service.ts`) and the CLI upgrade path
|
|
8
|
+
* (`hive-update.ts`) keeps the two from drifting if the package name ever
|
|
9
|
+
* moves.
|
|
10
|
+
*/
|
|
11
|
+
export const INSTALL_COMMAND_ARGS = ['install', '-g', `${PACKAGE_NAME}@latest`];
|
|
12
|
+
export const INSTALL_COMMAND_DISPLAY = `npm ${INSTALL_COMMAND_ARGS.join(' ')}`;
|
|
13
|
+
/**
|
|
14
|
+
* Windows ships npm as `npm.cmd` (a batch shim); Node's `child_process.spawn`
|
|
15
|
+
* will not resolve `.cmd` without `shell: true` or an explicit suffix, so the
|
|
16
|
+
* default `'npm'` produces ENOENT on Windows. Use this helper any time you
|
|
17
|
+
* spawn npm directly.
|
|
18
|
+
*/
|
|
19
|
+
export const getNpmCommand = (platform = process.platform) => platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
5
20
|
export const readPackageVersion = () => {
|
|
6
21
|
let dir = dirname(fileURLToPath(import.meta.url));
|
|
7
22
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
@@ -22,6 +22,13 @@ export interface ReportTaskBody {
|
|
|
22
22
|
status?: string;
|
|
23
23
|
artifacts?: unknown[];
|
|
24
24
|
}
|
|
25
|
+
export interface CancelTaskBody {
|
|
26
|
+
dispatch_id?: string;
|
|
27
|
+
project_id: string;
|
|
28
|
+
from_agent_id: string;
|
|
29
|
+
token?: string;
|
|
30
|
+
reason?: string;
|
|
31
|
+
}
|
|
25
32
|
export interface CreateWorkspaceBody {
|
|
26
33
|
path: string;
|
|
27
34
|
name: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { serializeDispatchRecord } from './dispatch-ledger-serializer.js';
|
|
2
2
|
import { getRequiredParam, route, sendJson } from './route-helpers.js';
|
|
3
3
|
import { requireUiTokenFromRequest } from './ui-auth-helpers.js';
|
|
4
|
-
const DISPATCH_STATUSES = new Set(['queued', 'submitted', 'reported']);
|
|
4
|
+
const DISPATCH_STATUSES = new Set(['queued', 'submitted', 'reported', 'cancelled']);
|
|
5
5
|
const MAX_DISPATCH_LIMIT = 100;
|
|
6
6
|
const MAX_DISPATCH_OFFSET = 100_000;
|
|
7
7
|
const readBoundedInt = (response, value, name, fallback, max) => {
|
|
@@ -33,7 +33,9 @@ export const dispatchRoutes = [
|
|
|
33
33
|
}
|
|
34
34
|
const state = url.searchParams.get('state');
|
|
35
35
|
if (state !== null && !isDispatchStatus(state)) {
|
|
36
|
-
sendJson(response, 400, {
|
|
36
|
+
sendJson(response, 400, {
|
|
37
|
+
error: 'state must be queued, submitted, reported, or cancelled',
|
|
38
|
+
});
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
41
|
const limit = readBoundedInt(response, url.searchParams.get('limit'), 'limit', MAX_DISPATCH_LIMIT, MAX_DISPATCH_LIMIT);
|
|
@@ -25,6 +25,7 @@ export const runtimeRoutes = [
|
|
|
25
25
|
agent_name: summary?.agent_name ?? 'Shell',
|
|
26
26
|
run_id: run.runId,
|
|
27
27
|
status: run.status,
|
|
28
|
+
terminal_input_profile: summary?.terminal_input_profile ?? 'default',
|
|
28
29
|
});
|
|
29
30
|
}),
|
|
30
31
|
route('DELETE', '/api/workspaces/:workspaceId/shell/:runId', ({ params, request, response, store }) => {
|
|
@@ -29,6 +29,28 @@ export const teamRoutes = [
|
|
|
29
29
|
});
|
|
30
30
|
sendJson(response, 202, { dispatch_id: dispatch.id, ok: true });
|
|
31
31
|
}),
|
|
32
|
+
route('POST', '/api/team/cancel', async ({ request, response, store }) => {
|
|
33
|
+
const body = await readJsonBody(request);
|
|
34
|
+
const projectId = requireNonEmptyString(body.project_id, 'project_id');
|
|
35
|
+
const fromAgentId = requireNonEmptyString(body.from_agent_id, 'from_agent_id');
|
|
36
|
+
const dispatchId = requireNonEmptyString(body.dispatch_id, 'dispatch_id');
|
|
37
|
+
const reason = requireNonEmptyString(body.reason, 'reason');
|
|
38
|
+
const agent = authenticateCliAgent({
|
|
39
|
+
fromAgentId,
|
|
40
|
+
getAgent: store.getAgent,
|
|
41
|
+
token: body.token,
|
|
42
|
+
validateToken: store.validateAgentToken,
|
|
43
|
+
workspaceId: projectId,
|
|
44
|
+
});
|
|
45
|
+
requireCommandForRole(agent, 'cancel');
|
|
46
|
+
const result = store.cancelTask(projectId, dispatchId, { fromAgentId, reason });
|
|
47
|
+
sendJson(response, 202, {
|
|
48
|
+
dispatch_id: result.dispatch?.id ?? null,
|
|
49
|
+
forward_error: result.forwardError,
|
|
50
|
+
forwarded: result.forwarded,
|
|
51
|
+
ok: true,
|
|
52
|
+
});
|
|
53
|
+
}),
|
|
32
54
|
route('POST', '/api/team/report', async ({ request, response, store }) => {
|
|
33
55
|
const body = await readJsonBody(request);
|
|
34
56
|
const projectId = requireNonEmptyString(body.project_id, 'project_id');
|
|
@@ -52,6 +52,7 @@ export declare const createRuntimeStoreLifecycle: ({ agentManager, services, }:
|
|
|
52
52
|
agent_name: string;
|
|
53
53
|
run_id: string;
|
|
54
54
|
status: import("./agent-manager.js").RunStatus;
|
|
55
|
+
terminal_input_profile: import("./terminal-input-profile.js").TerminalInputProfile;
|
|
55
56
|
}[];
|
|
56
57
|
startAgent: (workspaceId: string, agentId: string, input: {
|
|
57
58
|
hivePort: string;
|
|
@@ -74,7 +75,7 @@ export declare const createRuntimeStoreLifecycle: ({ agentManager, services, }:
|
|
|
74
75
|
})[]>;
|
|
75
76
|
registerTasksListener: (listener: (workspaceId: string, content: string) => void) => () => void;
|
|
76
77
|
startWorkspaceWatch: (workspaceId: string) => Promise<void>;
|
|
77
|
-
writeRunInput: (runId: string,
|
|
78
|
+
writeRunInput: (runId: string, input: Buffer | string) => void;
|
|
78
79
|
pauseTerminalRun: (runId: string) => void;
|
|
79
80
|
resizeTerminalRun: (runId: string, cols: number, rows: number) => void;
|
|
80
81
|
resumeTerminalRun: (runId: string) => void;
|
|
@@ -10,6 +10,7 @@ import { createSettingsStore } from './settings-store.js';
|
|
|
10
10
|
import { createTasksFileService } from './tasks-file.js';
|
|
11
11
|
import { createTasksFileWatcher } from './tasks-file-watcher.js';
|
|
12
12
|
import { createTeamOperations } from './team-operations.js';
|
|
13
|
+
import { resolveTerminalInputProfile } from './terminal-input-profile.js';
|
|
13
14
|
import { createUiAuth } from './ui-auth.js';
|
|
14
15
|
import { createWorkerOutputTracker } from './worker-output-tracker.js';
|
|
15
16
|
import { createWorkspaceShellRuntime } from './workspace-shell-runtime.js';
|
|
@@ -63,7 +64,9 @@ export const createRuntimeStoreServices = (options = {}) => {
|
|
|
63
64
|
deleteDispatch: dispatchLedgerStore.deleteDispatch,
|
|
64
65
|
deleteMessage: messageLogStore.deleteMessage,
|
|
65
66
|
findOpenDispatch: dispatchLedgerStore.findOpenDispatch,
|
|
67
|
+
findOpenDispatchById: dispatchLedgerStore.findOpenDispatchById,
|
|
66
68
|
insertMessage: messageLogStore.insertMessage,
|
|
69
|
+
markDispatchCancelled: dispatchLedgerStore.markCancelled,
|
|
67
70
|
markDispatchReportedByWorker: dispatchLedgerStore.markReportedByWorker,
|
|
68
71
|
markDispatchSubmitted: dispatchLedgerStore.markSubmitted,
|
|
69
72
|
workspaceStore,
|
|
@@ -167,8 +170,15 @@ export const createRuntimeStoreLifecycle = ({ agentManager, services, }) => {
|
|
|
167
170
|
const run = services.agentRuntime.getActiveRunByAgentId(workspaceId, agent.id);
|
|
168
171
|
if (!run)
|
|
169
172
|
return [];
|
|
173
|
+
const launchConfig = services.agentRuntime.peekAgentLaunchConfig(workspaceId, agent.id);
|
|
170
174
|
return [
|
|
171
|
-
{
|
|
175
|
+
{
|
|
176
|
+
agent_id: agent.id,
|
|
177
|
+
agent_name: agent.name,
|
|
178
|
+
run_id: run.runId,
|
|
179
|
+
status: run.status,
|
|
180
|
+
terminal_input_profile: resolveTerminalInputProfile(launchConfig),
|
|
181
|
+
},
|
|
172
182
|
];
|
|
173
183
|
}),
|
|
174
184
|
...services.shellRuntime.listTerminalRuns(workspaceId),
|
|
@@ -186,14 +196,14 @@ export const createRuntimeStoreLifecycle = ({ agentManager, services, }) => {
|
|
|
186
196
|
const workspace = services.workspaceStore.getWorkspaceSnapshot(workspaceId);
|
|
187
197
|
await services.tasksFileWatcher.start(workspaceId, workspace.summary.path);
|
|
188
198
|
},
|
|
189
|
-
writeRunInput: (runId,
|
|
199
|
+
writeRunInput: (runId, input) => {
|
|
190
200
|
if (!agentManager)
|
|
191
201
|
throw new Error('Agent manager is required for PTY stdin writes');
|
|
192
202
|
if (services.shellRuntime.hasRun(runId)) {
|
|
193
|
-
services.shellRuntime.writeInput(runId,
|
|
203
|
+
services.shellRuntime.writeInput(runId, input);
|
|
194
204
|
return;
|
|
195
205
|
}
|
|
196
|
-
agentManager.writeInput(runId,
|
|
206
|
+
agentManager.writeInput(runId, input);
|
|
197
207
|
},
|
|
198
208
|
pauseTerminalRun: (runId) => {
|
|
199
209
|
if (services.shellRuntime.hasRun(runId))
|
|
@@ -6,7 +6,8 @@ import type { DispatchRecord, ListDispatchesOptions } from './dispatch-ledger-st
|
|
|
6
6
|
import type { RecoveryMessage } from './message-log-store.js';
|
|
7
7
|
import type { PtyOutputBus } from './pty-output-bus.js';
|
|
8
8
|
import type { SettingsStore } from './settings-store.js';
|
|
9
|
-
import type { DispatchTaskInput, ReportTaskInput, ReportTaskResult, StatusTaskInput } from './team-operations.js';
|
|
9
|
+
import type { CancelTaskInput, DispatchTaskInput, ReportTaskInput, ReportTaskResult, StatusTaskInput } from './team-operations.js';
|
|
10
|
+
import type { TerminalRunSummary } from './terminal-input-profile.js';
|
|
10
11
|
import type { WorkerInput, WorkspaceRecord } from './workspace-store.js';
|
|
11
12
|
interface RuntimeStore {
|
|
12
13
|
close: () => Promise<void>;
|
|
@@ -21,6 +22,7 @@ interface RuntimeStore {
|
|
|
21
22
|
dispatchTaskByWorkerName: (workspaceId: string, workerName: string, text: string, input?: DispatchTaskInput) => Promise<DispatchRecord>;
|
|
22
23
|
reportTask: (workspaceId: string, workerId: string, input?: ReportTaskInput) => ReportTaskResult;
|
|
23
24
|
statusTask: (workspaceId: string, workerId: string, input?: StatusTaskInput) => ReportTaskResult;
|
|
25
|
+
cancelTask: (workspaceId: string, dispatchId: string, input: CancelTaskInput) => ReportTaskResult;
|
|
24
26
|
listDispatches: (workspaceId: string, options?: ListDispatchesOptions) => DispatchRecord[];
|
|
25
27
|
listWorkers: (workspaceId: string) => TeamListItem[];
|
|
26
28
|
getLastPtyLineForAgent: (workspaceId: string, agentId: string) => string | null;
|
|
@@ -28,12 +30,7 @@ interface RuntimeStore {
|
|
|
28
30
|
getWorker: (workspaceId: string, workerId: string) => AgentSummary;
|
|
29
31
|
getAgent: (workspaceId: string, agentId: string) => AgentSummary;
|
|
30
32
|
getPtyOutputBus: () => PtyOutputBus;
|
|
31
|
-
listTerminalRuns: (workspaceId: string) =>
|
|
32
|
-
agent_id: string;
|
|
33
|
-
agent_name: string;
|
|
34
|
-
run_id: string;
|
|
35
|
-
status: string;
|
|
36
|
-
}>;
|
|
33
|
+
listTerminalRuns: (workspaceId: string) => TerminalRunSummary[];
|
|
37
34
|
closeWorkspaceShell: (workspaceId: string, runId: string) => boolean;
|
|
38
35
|
startWorkspaceShell: (workspaceId: string) => Promise<LiveAgentRun>;
|
|
39
36
|
configureAgentLaunch: (workspaceId: string, agentId: string, input: AgentLaunchConfigInput) => void;
|
|
@@ -57,7 +54,7 @@ interface RuntimeStore {
|
|
|
57
54
|
resizeAgentRun: (runId: string, cols: number, rows: number) => void;
|
|
58
55
|
resumeTerminalRun: (runId: string) => void;
|
|
59
56
|
settings: SettingsStore;
|
|
60
|
-
writeRunInput: (runId: string,
|
|
57
|
+
writeRunInput: (runId: string, input: Buffer | string) => void;
|
|
61
58
|
getUiToken: () => string;
|
|
62
59
|
stopAgentRun: (runId: string) => void;
|
|
63
60
|
validateAgentToken: (agentId: string, token: string | undefined) => boolean;
|
|
@@ -48,6 +48,7 @@ export const createRuntimeStore = (options = {}) => {
|
|
|
48
48
|
});
|
|
49
49
|
},
|
|
50
50
|
recordUserInput: services.teamOps.recordUserInput,
|
|
51
|
+
cancelTask: services.teamOps.cancelTask,
|
|
51
52
|
dispatchTask: services.teamOps.dispatchTask,
|
|
52
53
|
dispatchTaskByWorkerName: services.teamOps.dispatchTaskByWorkerName,
|
|
53
54
|
reportTask: services.teamOps.reportTask,
|