replicas-engine 0.1.850 → 0.1.852
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/README.md +11 -0
- package/dist/src/{asp-host-DP3MWORN.js → asp-host-BTHMIOWF.js} +4 -4
- package/dist/src/{chunk-RLNQ34YJ.js → chunk-FCGE52IS.js} +2 -2
- package/dist/src/{chunk-3F6JSA2B.js → chunk-HPMBSWPV.js} +5 -5
- package/dist/src/{chunk-Q42GPHHD.js → chunk-ICQTYE55.js} +59 -4
- package/dist/src/{chunk-JA23HN6S.js → chunk-JQDFBEAW.js} +10 -3
- package/dist/src/{chunk-2QWUV5HZ.js → chunk-KCTWAJQL.js} +1 -1
- package/dist/src/{chunk-EDKHMP3M.js → chunk-WABXMCX5.js} +2 -2
- package/dist/src/{chunk-CGN7NMUB.js → chunk-XZ56DHQ7.js} +1 -1
- package/dist/src/command-protection-hook.js +3 -3
- package/dist/src/deepseek-command-protection-plugin.js +4 -4
- package/dist/src/headless-agent.js +2 -2
- package/dist/src/index.js +133 -126
- package/dist/src/post-tool-pr-hook.js +2 -2
- package/dist/src/relay-mcp.js +75 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,17 @@ Chats:
|
|
|
33
33
|
- `POST /chats/:chatId/messages`
|
|
34
34
|
- `POST /chats/:chatId/interrupt`
|
|
35
35
|
|
|
36
|
+
Relay subagents:
|
|
37
|
+
|
|
38
|
+
- `GET /chats/:parentChatId/subagents`
|
|
39
|
+
- `POST /chats/:parentChatId/subagents`
|
|
40
|
+
- `POST /chats/:parentChatId/subagents/:subagentId/messages`
|
|
41
|
+
- `GET /chats/:parentChatId/subagents/:subagentId`
|
|
42
|
+
- `GET /chats/:parentChatId/subagents/:subagentId/wait?timeoutMinutes=<minutes>` (SSE)
|
|
43
|
+
- `DELETE /chats/:parentChatId/subagents/:subagentId`
|
|
44
|
+
|
|
45
|
+
The `subagent_relay` MCP server exposes child work through `spawn_agent`, `message_agent`, `get_agent`, and `wait_agent`. Spawn and message calls wait by default; set `blocking: false` to return the child chat ID immediately, then use `get_agent` or `wait_agent` later. A wait timeout returns `status: "working"` with `timedOut: true` without interrupting the child; completed work returns `status: "completed"` and its response.
|
|
46
|
+
|
|
36
47
|
Canvas:
|
|
37
48
|
|
|
38
49
|
- `GET /canvas`
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
getCodexAspHost,
|
|
6
6
|
restartCodexAspHost,
|
|
7
7
|
restartCodexAspHostIfRunning
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-HPMBSWPV.js";
|
|
9
|
+
import "./chunk-KCTWAJQL.js";
|
|
10
|
+
import "./chunk-WABXMCX5.js";
|
|
11
11
|
import "./chunk-UZSNFLDQ.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-ICQTYE55.js";
|
|
13
13
|
import "./chunk-VEQXQN22.js";
|
|
14
14
|
export {
|
|
15
15
|
getCodexAspHost,
|
|
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
monolithRequest
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KCTWAJQL.js";
|
|
7
7
|
import {
|
|
8
8
|
extractCommandProtectionCommandText,
|
|
9
9
|
findGitCommitSignals,
|
|
10
10
|
findPrMergeSignals
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ICQTYE55.js";
|
|
12
12
|
|
|
13
13
|
// src/services/command-protection-service.ts
|
|
14
14
|
var DEFAULT_COMMAND_PROTECTION_BLOCK_MESSAGE = "Blocked by Replicas command protection.";
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
ENGINE_ENV,
|
|
6
6
|
monolithRequest,
|
|
7
7
|
setAgentCredentialSnapshot
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KCTWAJQL.js";
|
|
9
9
|
import {
|
|
10
10
|
AppServerProcess,
|
|
11
11
|
SUBPROCESS_MAX_BUFFER,
|
|
12
12
|
buildCodexAgentEnv,
|
|
13
13
|
execFileAsync
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WABXMCX5.js";
|
|
15
15
|
import {
|
|
16
16
|
isRecord
|
|
17
17
|
} from "./chunk-UZSNFLDQ.js";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
createSuccessResult,
|
|
24
24
|
listOpenAICompatibleModels,
|
|
25
25
|
resolveOpenAICompatibleModelsUrl
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-ICQTYE55.js";
|
|
27
27
|
|
|
28
28
|
// src/managers/codex-token-manager.ts
|
|
29
29
|
import { promises as fs } from "fs";
|
|
@@ -244,7 +244,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
|
|
|
244
244
|
await this.applyCredentialUpdate(++this.credentialGeneration, async () => {
|
|
245
245
|
await this.applyCredentialsResponse(data);
|
|
246
246
|
if (data.scope) setAgentCredentialSnapshot("codex", { method: data.type, scope: data.scope, revision: data.revision });
|
|
247
|
-
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-
|
|
247
|
+
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-BTHMIOWF.js");
|
|
248
248
|
await restartCodexAspHostIfRunning2();
|
|
249
249
|
});
|
|
250
250
|
await this.start(true);
|
|
@@ -264,7 +264,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
|
|
|
264
264
|
await this.applyCredentialUpdate(generation, async () => {
|
|
265
265
|
await this.applyCredentialsResponse(data);
|
|
266
266
|
if (restartOnChange && CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index])) {
|
|
267
|
-
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-
|
|
267
|
+
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-BTHMIOWF.js");
|
|
268
268
|
await restartCodexAspHostIfRunning2();
|
|
269
269
|
}
|
|
270
270
|
if (data.scope) {
|
|
@@ -992,14 +992,21 @@ var spawnRelaySubagentRequestSchema = z3.object({
|
|
|
992
992
|
).default("all"),
|
|
993
993
|
model: z3.string().min(1).optional(),
|
|
994
994
|
thinkingLevel: z3.enum(VALID_THINKING_LEVELS).optional(),
|
|
995
|
-
title: z3.string().min(1).optional()
|
|
996
|
-
timeoutMinutes: z3.number().positive().max(1440).optional()
|
|
995
|
+
title: z3.string().min(1).optional()
|
|
997
996
|
});
|
|
998
997
|
var messageRelaySubagentRequestSchema = z3.object({
|
|
999
998
|
message: z3.string().min(1),
|
|
1000
999
|
model: z3.string().min(1).optional(),
|
|
1001
|
-
thinkingLevel: z3.enum(VALID_THINKING_LEVELS).optional()
|
|
1002
|
-
|
|
1000
|
+
thinkingLevel: z3.enum(VALID_THINKING_LEVELS).optional()
|
|
1001
|
+
});
|
|
1002
|
+
var waitRelaySubagentRequestSchema = z3.object({
|
|
1003
|
+
timeoutMinutes: z3.coerce.number().positive().max(1440).optional()
|
|
1004
|
+
});
|
|
1005
|
+
var relaySubagentResponseSchema = z3.object({
|
|
1006
|
+
chatId: z3.string().uuid(),
|
|
1007
|
+
status: z3.enum(["working", "completed"]),
|
|
1008
|
+
response: z3.string().optional(),
|
|
1009
|
+
timedOut: z3.literal(true).optional()
|
|
1003
1010
|
});
|
|
1004
1011
|
var sendChatMessageRequestSchema = z3.object({
|
|
1005
1012
|
messageId: z3.string().min(1).optional(),
|
|
@@ -1506,6 +1513,9 @@ function gitIdentityConfigCommands(identity, scope = "global") {
|
|
|
1506
1513
|
];
|
|
1507
1514
|
}
|
|
1508
1515
|
|
|
1516
|
+
// ../shared/src/relay.ts
|
|
1517
|
+
var RELAY_MCP_SERVER_NAME = "subagent_relay";
|
|
1518
|
+
|
|
1509
1519
|
// ../shared/src/headless-agent.ts
|
|
1510
1520
|
import { z as z4 } from "zod";
|
|
1511
1521
|
var headlessAgentRequestBaseSchema = z4.object({
|
|
@@ -1552,6 +1562,47 @@ var headlessFilesystemAgentResultSchema = z4.object({
|
|
|
1552
1562
|
// ../shared/src/engine/environment.ts
|
|
1553
1563
|
var DESKTOP_STREAM_PORT = 6080;
|
|
1554
1564
|
|
|
1565
|
+
// ../shared/src/sse.ts
|
|
1566
|
+
function parseSseChunk(chunk) {
|
|
1567
|
+
let data = "";
|
|
1568
|
+
let id = null;
|
|
1569
|
+
for (const line of chunk.split("\n")) {
|
|
1570
|
+
if (line.startsWith("data: ")) {
|
|
1571
|
+
data += line.slice(6);
|
|
1572
|
+
} else if (line.startsWith("id: ")) {
|
|
1573
|
+
id = line.slice(4);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
if (!data) return null;
|
|
1577
|
+
try {
|
|
1578
|
+
return { event: JSON.parse(data), id };
|
|
1579
|
+
} catch {
|
|
1580
|
+
return null;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
async function readSseStream(body, onEvent, shouldContinue = () => true) {
|
|
1584
|
+
const reader = body.getReader();
|
|
1585
|
+
const decoder2 = new TextDecoder();
|
|
1586
|
+
let buffer = "";
|
|
1587
|
+
try {
|
|
1588
|
+
while (shouldContinue()) {
|
|
1589
|
+
const { done, value } = await reader.read();
|
|
1590
|
+
if (done) break;
|
|
1591
|
+
buffer += decoder2.decode(value, { stream: true });
|
|
1592
|
+
const chunks = buffer.split("\n\n");
|
|
1593
|
+
buffer = chunks.pop() ?? "";
|
|
1594
|
+
for (const chunk of chunks) {
|
|
1595
|
+
if (!shouldContinue()) break;
|
|
1596
|
+
const parsed = parseSseChunk(chunk);
|
|
1597
|
+
if (!parsed) continue;
|
|
1598
|
+
await onEvent(parsed.event, parsed.id);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
} finally {
|
|
1602
|
+
await reader.cancel().catch(() => void 0);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1555
1606
|
// ../shared/src/json.ts
|
|
1556
1607
|
function safeJsonParse(str, fallback) {
|
|
1557
1608
|
try {
|
|
@@ -7935,6 +7986,8 @@ export {
|
|
|
7935
7986
|
createChatRequestSchema,
|
|
7936
7987
|
spawnRelaySubagentRequestSchema,
|
|
7937
7988
|
messageRelaySubagentRequestSchema,
|
|
7989
|
+
waitRelaySubagentRequestSchema,
|
|
7990
|
+
relaySubagentResponseSchema,
|
|
7938
7991
|
sendChatMessageRequestSchema,
|
|
7939
7992
|
isChatMessageSender,
|
|
7940
7993
|
normalizeCodexAspTranscriptStatus,
|
|
@@ -8019,6 +8072,7 @@ export {
|
|
|
8019
8072
|
REPLICAS_CONFIG_FILENAMES,
|
|
8020
8073
|
parseReplicasConfigString,
|
|
8021
8074
|
createUuidFromHex,
|
|
8075
|
+
RELAY_MCP_SERVER_NAME,
|
|
8022
8076
|
headlessAgentRequestSchema,
|
|
8023
8077
|
isAuthenticationErrorText,
|
|
8024
8078
|
isClaudeAuthErrorText,
|
|
@@ -8047,5 +8101,6 @@ export {
|
|
|
8047
8101
|
getChatTranscriptHistorySize,
|
|
8048
8102
|
createChatTranscriptPages,
|
|
8049
8103
|
parseChatTranscriptArtifact,
|
|
8104
|
+
readSseStream,
|
|
8050
8105
|
isSkillRegistryManifest
|
|
8051
8106
|
};
|
|
@@ -7,8 +7,15 @@ import { existsSync } from "fs";
|
|
|
7
7
|
import { dirname, join } from "path";
|
|
8
8
|
import { fileURLToPath } from "url";
|
|
9
9
|
import { createRequire } from "module";
|
|
10
|
-
var
|
|
11
|
-
|
|
10
|
+
var RELAY_MCP_TOOLS = {
|
|
11
|
+
getProviders: "get_providers",
|
|
12
|
+
spawnAgent: "spawn_agent",
|
|
13
|
+
getAgent: "get_agent",
|
|
14
|
+
waitAgent: "wait_agent",
|
|
15
|
+
messageAgent: "message_agent",
|
|
16
|
+
deleteAgent: "delete_agent"
|
|
17
|
+
};
|
|
18
|
+
var RELAY_MCP_TOOL_NAMES = Object.values(RELAY_MCP_TOOLS);
|
|
12
19
|
var RELAY_MCP_TOOL_TIMEOUT_MS = 24 * 60 * 60 * 1e3 + 6e4;
|
|
13
20
|
function relayMcpProcessConfig(parentChatId) {
|
|
14
21
|
const directory = dirname(fileURLToPath(import.meta.url));
|
|
@@ -38,7 +45,7 @@ function relayCodexMcpConfig(parentChatId) {
|
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
export {
|
|
41
|
-
|
|
48
|
+
RELAY_MCP_TOOLS,
|
|
42
49
|
RELAY_MCP_TOOL_NAMES,
|
|
43
50
|
RELAY_MCP_TOOL_TIMEOUT_MS,
|
|
44
51
|
relayMcpProcessConfig,
|
|
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
|
|
|
4
4
|
import {
|
|
5
5
|
HOOK_EXEC_MAX_BUFFER_BYTES,
|
|
6
6
|
isVersionBelow
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ICQTYE55.js";
|
|
8
8
|
|
|
9
9
|
// src/utils/codex-agent-env.ts
|
|
10
10
|
function buildCodexAgentEnv(source = process.env) {
|
|
@@ -241,7 +241,7 @@ var DEFAULT_CODEX_ARGS = [
|
|
|
241
241
|
var MIN_CODEX_CLI_VERSION = "0.153.3";
|
|
242
242
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
243
243
|
var codexCliVersionEnsured = null;
|
|
244
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
244
|
+
var ENGINE_PACKAGE_VERSION = "0.1.852";
|
|
245
245
|
var INITIALIZE_METHOD = "initialize";
|
|
246
246
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
247
247
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
shouldRefreshPullRequests
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ICQTYE55.js";
|
|
7
7
|
|
|
8
8
|
// src/services/post-tool-pr-notifier.ts
|
|
9
9
|
async function notifyPostToolUse(toolName, toolInput) {
|
|
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
evaluateCommandProtection
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-FCGE52IS.js";
|
|
7
|
+
import "./chunk-KCTWAJQL.js";
|
|
8
8
|
import {
|
|
9
9
|
isRecord
|
|
10
10
|
} from "./chunk-UZSNFLDQ.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-ICQTYE55.js";
|
|
12
12
|
import "./chunk-VEQXQN22.js";
|
|
13
13
|
|
|
14
14
|
// src/command-protection-hook.ts
|
|
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
evaluateCommandProtection
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FCGE52IS.js";
|
|
7
7
|
import {
|
|
8
8
|
notifyPostToolUse
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-XZ56DHQ7.js";
|
|
10
|
+
import "./chunk-KCTWAJQL.js";
|
|
11
11
|
import "./chunk-UZSNFLDQ.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-ICQTYE55.js";
|
|
13
13
|
import "./chunk-VEQXQN22.js";
|
|
14
14
|
|
|
15
15
|
// src/deepseek-command-protection-plugin.ts
|
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
AppServerProcess,
|
|
10
10
|
buildCodexAgentEnv
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WABXMCX5.js";
|
|
12
12
|
import {
|
|
13
13
|
AGENT,
|
|
14
14
|
getMemoryOutputSafetyViolation,
|
|
15
15
|
headlessAgentRequestSchema
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ICQTYE55.js";
|
|
17
17
|
import "./chunk-VEQXQN22.js";
|
|
18
18
|
|
|
19
19
|
// src/headless-agent.ts
|
package/dist/src/index.js
CHANGED
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
evaluateCommandProtection,
|
|
92
92
|
extractToolCommand,
|
|
93
93
|
reportCommandProtectionBlock
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-FCGE52IS.js";
|
|
95
95
|
import {
|
|
96
96
|
ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
|
|
97
97
|
AGENT_MESSAGE_DELTA_METHOD,
|
|
@@ -115,12 +115,12 @@ import {
|
|
|
115
115
|
recoverCompletedTurn
|
|
116
116
|
} from "./chunk-FLDA7BX3.js";
|
|
117
117
|
import {
|
|
118
|
-
|
|
118
|
+
RELAY_MCP_TOOLS,
|
|
119
119
|
RELAY_MCP_TOOL_NAMES,
|
|
120
120
|
RELAY_MCP_TOOL_TIMEOUT_MS,
|
|
121
121
|
relayCodexMcpConfig,
|
|
122
122
|
relayMcpProcessConfig
|
|
123
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-JQDFBEAW.js";
|
|
124
124
|
import {
|
|
125
125
|
BaseRefreshManager,
|
|
126
126
|
CodexAspAuthMethodChangedError,
|
|
@@ -132,20 +132,20 @@ import {
|
|
|
132
132
|
recordCredentialFallback,
|
|
133
133
|
recordExhaustedCredential,
|
|
134
134
|
restartCodexAspHost
|
|
135
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-HPMBSWPV.js";
|
|
136
136
|
import {
|
|
137
137
|
ENGINE_ENV,
|
|
138
138
|
IS_WARMING_MODE,
|
|
139
139
|
monolithRequest,
|
|
140
140
|
monolithService,
|
|
141
141
|
setAgentCredentialSnapshot
|
|
142
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-KCTWAJQL.js";
|
|
143
143
|
import {
|
|
144
144
|
AspClient,
|
|
145
145
|
SUBPROCESS_MAX_BUFFER,
|
|
146
146
|
execAsync,
|
|
147
147
|
execFileAsync
|
|
148
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-WABXMCX5.js";
|
|
149
149
|
import {
|
|
150
150
|
isRecord as isRecord2
|
|
151
151
|
} from "./chunk-UZSNFLDQ.js";
|
|
@@ -223,6 +223,7 @@ import {
|
|
|
223
223
|
OPENCODE_GO_BASE_URL,
|
|
224
224
|
OPENCODE_GO_PROVIDER,
|
|
225
225
|
QUEUED_MESSAGE_REMOVED_EVENT_TYPE,
|
|
226
|
+
RELAY_MCP_SERVER_NAME,
|
|
226
227
|
REMOVED_MESSAGE_IDS_PAYLOAD_KEY,
|
|
227
228
|
REPLICAS_CONFIG_FILENAMES,
|
|
228
229
|
SANDBOX_PATHS,
|
|
@@ -355,9 +356,10 @@ import {
|
|
|
355
356
|
shouldRefreshPullRequests,
|
|
356
357
|
spawnRelaySubagentRequestSchema,
|
|
357
358
|
stripAgentDiagnosticErrors,
|
|
359
|
+
waitRelaySubagentRequestSchema,
|
|
358
360
|
withTimeout,
|
|
359
361
|
workspaceCredentialProviderSchema
|
|
360
|
-
} from "./chunk-
|
|
362
|
+
} from "./chunk-ICQTYE55.js";
|
|
361
363
|
import {
|
|
362
364
|
__commonJS,
|
|
363
365
|
__export,
|
|
@@ -59912,9 +59914,9 @@ Go straight to the point. Lead with outcomes and decisions, keep updates concise
|
|
|
59912
59914
|
|
|
59913
59915
|
Your primary constraint is context. Work directly when the task is small, tightly coupled to context you already hold, or cheaper to complete than explain. Delegate independent work that would consume substantial context, including broad investigation, multi-file implementation, iterative debugging, test-and-fix loops, and unbiased review or verification. Do not delegate trivial work or work whose full context would cost more to transfer than doing it yourself.
|
|
59914
59916
|
|
|
59915
|
-
Use the \`${RELAY_MCP_SERVER_NAME}\` MCP server exclusively for delegation; never use terminal commands or the base harness's native agent-spawning, delegation, or collaboration tools. It exposes
|
|
59917
|
+
Use the \`${RELAY_MCP_SERVER_NAME}\` MCP server exclusively for delegation; never use terminal commands or the base harness's native agent-spawning, delegation, or collaboration tools. It exposes ${RELAY_MCP_TOOL_NAMES.map((name) => `\`${name}\``).join(", ")}; your harness may show them with an MCP server prefix. In Pi, call them through the \`mcp\` gateway for the \`${RELAY_MCP_SERVER_NAME}\` server if direct tools are not yet visible. Check \`${RELAY_MCP_TOOLS.getProviders}\` before the first delegation instead of guessing. Spawning and messaging block by default; use \`blocking: false\` only when you intend to continue independently, then inspect or join the child with \`${RELAY_MCP_TOOLS.getAgent}\` or \`${RELAY_MCP_TOOLS.waitAgent}\`.
|
|
59916
59918
|
|
|
59917
|
-
Choose how much parent context each child inherits with
|
|
59919
|
+
Choose how much parent context each child inherits with \`${RELAY_MCP_TOOLS.spawnAgent}.fork_turns\`:
|
|
59918
59920
|
|
|
59919
59921
|
- \`"all"\` (default): inherit the conversation as an extension of yourself when the task depends on prior decisions and constraints.
|
|
59920
59922
|
- \`"none"\`: start with only the task prompt to reduce input tokens or get an independent assessment without your prior reasoning. Include all necessary requirements, paths, constraints, and evidence in the prompt; the child cannot infer omitted context.
|
|
@@ -61627,7 +61629,6 @@ var LAST_MESSAGE_PREVIEW_MAX = 200;
|
|
|
61627
61629
|
var MAX_ACCEPTED_SEND_RESPONSES = 50;
|
|
61628
61630
|
var MAX_REMOVED_MESSAGE_IDS = 6e3;
|
|
61629
61631
|
var RELAY_SUBAGENT_POLL_INTERVAL_MS = 2e3;
|
|
61630
|
-
var DEFAULT_RELAY_SUBAGENT_TIMEOUT_MS = 6e5;
|
|
61631
61632
|
async function resolveRelayBaseProvider(provider, requested) {
|
|
61632
61633
|
if (provider !== "relay") return null;
|
|
61633
61634
|
return requested ?? (await monolithService.getRelayConfig())?.baseProvider ?? (!ENGINE_ENV.REPLICAS_WORKSPACE_ID ? DEFAULT_RELAY_BASE_PROVIDER : null);
|
|
@@ -61845,7 +61846,7 @@ var ChatService = class {
|
|
|
61845
61846
|
});
|
|
61846
61847
|
throw error;
|
|
61847
61848
|
}
|
|
61848
|
-
return this.
|
|
61849
|
+
return this.getRelaySubagent(parentChatId, chat.id);
|
|
61849
61850
|
}
|
|
61850
61851
|
async getRelaySubagentProviders(parentChatId) {
|
|
61851
61852
|
const parent = this.requireChat(parentChatId);
|
|
@@ -61861,7 +61862,17 @@ var ChatService = class {
|
|
|
61861
61862
|
...request.model ? { model: request.model } : {},
|
|
61862
61863
|
...request.thinkingLevel ? { thinkingLevel: request.thinkingLevel } : {}
|
|
61863
61864
|
});
|
|
61864
|
-
return this.
|
|
61865
|
+
return this.getRelaySubagent(parentChatId, chatId);
|
|
61866
|
+
}
|
|
61867
|
+
async getRelaySubagent(parentChatId, chatId) {
|
|
61868
|
+
const chat = this.requireRelayChild(parentChatId, chatId);
|
|
61869
|
+
if (hasActiveChatTurn(chat)) return { chatId, status: "working" };
|
|
61870
|
+
const history = await chat.provider.getHistory();
|
|
61871
|
+
return {
|
|
61872
|
+
chatId,
|
|
61873
|
+
status: "completed",
|
|
61874
|
+
response: extractFinalResponse(history, getChatExecutionProvider(chat.persisted)) ?? "[No response from subagent]"
|
|
61875
|
+
};
|
|
61865
61876
|
}
|
|
61866
61877
|
async deleteRelaySubagent(parentChatId, chatId) {
|
|
61867
61878
|
this.requireRelayChild(parentChatId, chatId);
|
|
@@ -61874,24 +61885,19 @@ var ChatService = class {
|
|
|
61874
61885
|
if (child.persisted.parentChatId !== parentChatId) throw new Error("Chat is not a child of this Relay chat");
|
|
61875
61886
|
return child;
|
|
61876
61887
|
}
|
|
61877
|
-
async waitForRelaySubagent(chatId, timeoutMinutes) {
|
|
61878
|
-
const timeoutMs = timeoutMinutes ? timeoutMinutes * 6e4 :
|
|
61888
|
+
async waitForRelaySubagent(parentChatId, chatId, timeoutMinutes, signal) {
|
|
61889
|
+
const timeoutMs = timeoutMinutes ? timeoutMinutes * 6e4 : null;
|
|
61879
61890
|
const startedAt = Date.now();
|
|
61880
61891
|
while (true) {
|
|
61881
|
-
|
|
61882
|
-
|
|
61883
|
-
|
|
61884
|
-
|
|
61885
|
-
|
|
61886
|
-
|
|
61887
|
-
|
|
61888
|
-
|
|
61889
|
-
|
|
61890
|
-
if (remainingMs <= 0) {
|
|
61891
|
-
await this.interrupt(chatId);
|
|
61892
|
-
throw new Error(`Subagent chat ${chatId} timed out after ${timeoutMs}ms`);
|
|
61893
|
-
}
|
|
61894
|
-
await new Promise((resolve7) => setTimeout(resolve7, Math.min(RELAY_SUBAGENT_POLL_INTERVAL_MS, remainingMs)));
|
|
61892
|
+
if (signal?.aborted) throw new Error("Relay wait was cancelled");
|
|
61893
|
+
const result = await this.getRelaySubagent(parentChatId, chatId);
|
|
61894
|
+
if (result.status === "completed") return result;
|
|
61895
|
+
const remainingMs = timeoutMs === null ? null : timeoutMs - (Date.now() - startedAt);
|
|
61896
|
+
if (remainingMs !== null && remainingMs <= 0) return { ...result, timedOut: true };
|
|
61897
|
+
await new Promise((resolve7) => setTimeout(
|
|
61898
|
+
resolve7,
|
|
61899
|
+
remainingMs === null ? RELAY_SUBAGENT_POLL_INTERVAL_MS : Math.min(RELAY_SUBAGENT_POLL_INTERVAL_MS, remainingMs)
|
|
61900
|
+
));
|
|
61895
61901
|
}
|
|
61896
61902
|
}
|
|
61897
61903
|
async sendMessage(chatId, request) {
|
|
@@ -63919,6 +63925,47 @@ var updateTextFileSchema = (maxLength) => z6.object({
|
|
|
63919
63925
|
function jsonError(message, details) {
|
|
63920
63926
|
return { error: message, details };
|
|
63921
63927
|
}
|
|
63928
|
+
function createJsonEventStream(run, onError) {
|
|
63929
|
+
const encoder2 = new TextEncoder();
|
|
63930
|
+
const stream = new ReadableStream({
|
|
63931
|
+
start(controller) {
|
|
63932
|
+
let closed = false;
|
|
63933
|
+
const enqueue = (chunk) => {
|
|
63934
|
+
if (closed) return false;
|
|
63935
|
+
try {
|
|
63936
|
+
controller.enqueue(encoder2.encode(chunk));
|
|
63937
|
+
return true;
|
|
63938
|
+
} catch {
|
|
63939
|
+
closed = true;
|
|
63940
|
+
return false;
|
|
63941
|
+
}
|
|
63942
|
+
};
|
|
63943
|
+
const send = (data, event) => {
|
|
63944
|
+
enqueue(`${event ? `event: ${event}
|
|
63945
|
+
` : ""}data: ${JSON.stringify(data)}
|
|
63946
|
+
|
|
63947
|
+
`);
|
|
63948
|
+
};
|
|
63949
|
+
const heartbeat = setInterval(() => {
|
|
63950
|
+
if (!enqueue(": ping\n\n")) clearInterval(heartbeat);
|
|
63951
|
+
}, 15e3);
|
|
63952
|
+
enqueue(": connected\n\n");
|
|
63953
|
+
run(send).catch((error) => {
|
|
63954
|
+
const failure = onError(error);
|
|
63955
|
+
send(failure.data, failure.event);
|
|
63956
|
+
}).finally(() => {
|
|
63957
|
+
clearInterval(heartbeat);
|
|
63958
|
+
if (!closed) {
|
|
63959
|
+
closed = true;
|
|
63960
|
+
controller.close();
|
|
63961
|
+
}
|
|
63962
|
+
});
|
|
63963
|
+
}
|
|
63964
|
+
});
|
|
63965
|
+
return new Response(stream, {
|
|
63966
|
+
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
|
|
63967
|
+
});
|
|
63968
|
+
}
|
|
63922
63969
|
function createV1Routes(deps) {
|
|
63923
63970
|
const app2 = new Hono();
|
|
63924
63971
|
app2.post("/pull-requests/check", async (c) => {
|
|
@@ -64054,6 +64101,42 @@ function createV1Routes(deps) {
|
|
|
64054
64101
|
), 400);
|
|
64055
64102
|
}
|
|
64056
64103
|
});
|
|
64104
|
+
app2.get("/chats/:chatId/subagents/:subagentId", async (c) => {
|
|
64105
|
+
try {
|
|
64106
|
+
return c.json(await deps.chatService.getRelaySubagent(
|
|
64107
|
+
c.req.param("chatId"),
|
|
64108
|
+
c.req.param("subagentId")
|
|
64109
|
+
));
|
|
64110
|
+
} catch (error) {
|
|
64111
|
+
return c.json(jsonError(
|
|
64112
|
+
"Failed to load Relay subagent",
|
|
64113
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
64114
|
+
), 400);
|
|
64115
|
+
}
|
|
64116
|
+
});
|
|
64117
|
+
app2.get("/chats/:chatId/subagents/:subagentId/wait", async (c) => {
|
|
64118
|
+
const parsed = waitRelaySubagentRequestSchema.safeParse(c.req.query());
|
|
64119
|
+
if (!parsed.success) {
|
|
64120
|
+
return c.json(jsonError("Failed to wait for Relay subagent", parsed.error.message), 400);
|
|
64121
|
+
}
|
|
64122
|
+
return createJsonEventStream(
|
|
64123
|
+
async (send) => {
|
|
64124
|
+
send(await deps.chatService.waitForRelaySubagent(
|
|
64125
|
+
c.req.param("chatId"),
|
|
64126
|
+
c.req.param("subagentId"),
|
|
64127
|
+
parsed.data.timeoutMinutes,
|
|
64128
|
+
c.req.raw.signal
|
|
64129
|
+
));
|
|
64130
|
+
},
|
|
64131
|
+
(error) => ({
|
|
64132
|
+
event: "error",
|
|
64133
|
+
data: {
|
|
64134
|
+
error: "Failed to wait for Relay subagent",
|
|
64135
|
+
details: error instanceof Error ? error.message : "Unknown error"
|
|
64136
|
+
}
|
|
64137
|
+
})
|
|
64138
|
+
);
|
|
64139
|
+
});
|
|
64057
64140
|
app2.delete("/chats/:chatId/subagents/:subagentId", async (c) => {
|
|
64058
64141
|
try {
|
|
64059
64142
|
await deps.chatService.deleteRelaySubagent(c.req.param("chatId"), c.req.param("subagentId"));
|
|
@@ -64604,56 +64687,18 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
64604
64687
|
app2.post("/warm-hooks/run/stream", async (c) => {
|
|
64605
64688
|
try {
|
|
64606
64689
|
const body = await c.req.json();
|
|
64607
|
-
|
|
64608
|
-
|
|
64609
|
-
|
|
64610
|
-
|
|
64611
|
-
|
|
64612
|
-
|
|
64613
|
-
|
|
64614
|
-
|
|
64615
|
-
|
|
64616
|
-
|
|
64617
|
-
|
|
64618
|
-
|
|
64619
|
-
}
|
|
64620
|
-
};
|
|
64621
|
-
const heartbeat = setInterval(() => {
|
|
64622
|
-
if (!safeEnqueue(": ping\n\n")) clearInterval(heartbeat);
|
|
64623
|
-
}, 15e3);
|
|
64624
|
-
safeEnqueue(": connected\n\n");
|
|
64625
|
-
runWarmHooksStreaming({
|
|
64626
|
-
globalWarmHook: body.globalWarmHook,
|
|
64627
|
-
environmentWarmHook: body.environmentWarmHook,
|
|
64628
|
-
organizationWarmHook: body.organizationWarmHook,
|
|
64629
|
-
timeoutMs: body.timeoutMs,
|
|
64630
|
-
onEvent: (event) => {
|
|
64631
|
-
safeEnqueue(`data: ${JSON.stringify(event)}
|
|
64632
|
-
|
|
64633
|
-
`);
|
|
64634
|
-
}
|
|
64635
|
-
}).then(() => {
|
|
64636
|
-
clearInterval(heartbeat);
|
|
64637
|
-
if (!closed) {
|
|
64638
|
-
closed = true;
|
|
64639
|
-
controller.close();
|
|
64640
|
-
}
|
|
64641
|
-
}).catch((err) => {
|
|
64642
|
-
const message = err instanceof Error ? err.message : "Unknown error";
|
|
64643
|
-
safeEnqueue(`data: ${JSON.stringify({ type: "error", data: message })}
|
|
64644
|
-
|
|
64645
|
-
`);
|
|
64646
|
-
clearInterval(heartbeat);
|
|
64647
|
-
if (!closed) {
|
|
64648
|
-
closed = true;
|
|
64649
|
-
controller.close();
|
|
64650
|
-
}
|
|
64651
|
-
});
|
|
64652
|
-
}
|
|
64653
|
-
});
|
|
64654
|
-
return new Response(stream, {
|
|
64655
|
-
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
|
|
64656
|
-
});
|
|
64690
|
+
return createJsonEventStream(
|
|
64691
|
+
(send) => runWarmHooksStreaming({
|
|
64692
|
+
globalWarmHook: body.globalWarmHook,
|
|
64693
|
+
environmentWarmHook: body.environmentWarmHook,
|
|
64694
|
+
organizationWarmHook: body.organizationWarmHook,
|
|
64695
|
+
timeoutMs: body.timeoutMs,
|
|
64696
|
+
onEvent: (event) => {
|
|
64697
|
+
send(event);
|
|
64698
|
+
}
|
|
64699
|
+
}),
|
|
64700
|
+
(error) => ({ data: { type: "error", data: error instanceof Error ? error.message : "Unknown error" } })
|
|
64701
|
+
);
|
|
64657
64702
|
} catch (error) {
|
|
64658
64703
|
return c.json(
|
|
64659
64704
|
jsonError("Failed to run warm hooks", error instanceof Error ? error.message : "Unknown error"),
|
|
@@ -64664,54 +64709,16 @@ data: ${JSON.stringify("Terminal session not found")}
|
|
|
64664
64709
|
app2.post("/start-hooks/run/stream", async (c) => {
|
|
64665
64710
|
try {
|
|
64666
64711
|
const body = await c.req.json();
|
|
64667
|
-
|
|
64668
|
-
|
|
64669
|
-
|
|
64670
|
-
|
|
64671
|
-
|
|
64672
|
-
|
|
64673
|
-
|
|
64674
|
-
|
|
64675
|
-
|
|
64676
|
-
|
|
64677
|
-
closed = true;
|
|
64678
|
-
return false;
|
|
64679
|
-
}
|
|
64680
|
-
};
|
|
64681
|
-
const heartbeat = setInterval(() => {
|
|
64682
|
-
if (!safeEnqueue(": ping\n\n")) clearInterval(heartbeat);
|
|
64683
|
-
}, 15e3);
|
|
64684
|
-
safeEnqueue(": connected\n\n");
|
|
64685
|
-
replicasConfigService.runStartHooksStreaming({
|
|
64686
|
-
environmentStartHook: body.environmentStartHook,
|
|
64687
|
-
timeoutMs: body.timeoutMs,
|
|
64688
|
-
onEvent: (event) => {
|
|
64689
|
-
safeEnqueue(`data: ${JSON.stringify(event)}
|
|
64690
|
-
|
|
64691
|
-
`);
|
|
64692
|
-
}
|
|
64693
|
-
}).then(() => {
|
|
64694
|
-
clearInterval(heartbeat);
|
|
64695
|
-
if (!closed) {
|
|
64696
|
-
closed = true;
|
|
64697
|
-
controller.close();
|
|
64698
|
-
}
|
|
64699
|
-
}).catch((err) => {
|
|
64700
|
-
const message = err instanceof Error ? err.message : "Unknown error";
|
|
64701
|
-
safeEnqueue(`data: ${JSON.stringify({ type: "error", data: message })}
|
|
64702
|
-
|
|
64703
|
-
`);
|
|
64704
|
-
clearInterval(heartbeat);
|
|
64705
|
-
if (!closed) {
|
|
64706
|
-
closed = true;
|
|
64707
|
-
controller.close();
|
|
64708
|
-
}
|
|
64709
|
-
});
|
|
64710
|
-
}
|
|
64711
|
-
});
|
|
64712
|
-
return new Response(stream, {
|
|
64713
|
-
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
|
|
64714
|
-
});
|
|
64712
|
+
return createJsonEventStream(
|
|
64713
|
+
(send) => replicasConfigService.runStartHooksStreaming({
|
|
64714
|
+
environmentStartHook: body.environmentStartHook,
|
|
64715
|
+
timeoutMs: body.timeoutMs,
|
|
64716
|
+
onEvent: (event) => {
|
|
64717
|
+
send(event);
|
|
64718
|
+
}
|
|
64719
|
+
}),
|
|
64720
|
+
(error) => ({ data: { type: "error", data: error instanceof Error ? error.message : "Unknown error" } })
|
|
64721
|
+
);
|
|
64715
64722
|
} catch (error) {
|
|
64716
64723
|
return c.json(
|
|
64717
64724
|
jsonError("Failed to run start hooks", error instanceof Error ? error.message : "Unknown error"),
|
|
@@ -3,11 +3,11 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
notifyPostToolUse
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XZ56DHQ7.js";
|
|
7
7
|
import {
|
|
8
8
|
isRecord
|
|
9
9
|
} from "./chunk-UZSNFLDQ.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-ICQTYE55.js";
|
|
11
11
|
import "./chunk-VEQXQN22.js";
|
|
12
12
|
|
|
13
13
|
// src/post-tool-pr-hook.ts
|
package/dist/src/relay-mcp.js
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module';
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
RELAY_MCP_TOOLS
|
|
6
|
+
} from "./chunk-JQDFBEAW.js";
|
|
7
7
|
import {
|
|
8
|
+
RELAY_MCP_SERVER_NAME,
|
|
8
9
|
messageRelaySubagentRequestSchema,
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
readSseStream,
|
|
11
|
+
relaySubagentResponseSchema,
|
|
12
|
+
spawnRelaySubagentRequestSchema,
|
|
13
|
+
waitRelaySubagentRequestSchema
|
|
14
|
+
} from "./chunk-ICQTYE55.js";
|
|
11
15
|
import "./chunk-VEQXQN22.js";
|
|
12
16
|
|
|
13
17
|
// src/relay-mcp.ts
|
|
@@ -39,14 +43,37 @@ async function request(path, method, body) {
|
|
|
39
43
|
if (!response.ok) throw new Error(text || `Relay request failed (${response.status})`);
|
|
40
44
|
return text || JSON.stringify({ success: true });
|
|
41
45
|
}
|
|
46
|
+
async function waitForAgent(chatId, timeoutMinutes) {
|
|
47
|
+
const query = timeoutMinutes ? `?timeoutMinutes=${timeoutMinutes}` : "";
|
|
48
|
+
const response = await fetch(`http://localhost:${enginePort}/chats/${parentChatId}/subagents/${chatId}/wait${query}`, {
|
|
49
|
+
headers: {
|
|
50
|
+
Accept: "text/event-stream",
|
|
51
|
+
"X-Replicas-Engine-Secret": engineSecret
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok || !response.body) throw new Error(await response.text() || `Relay wait failed (${response.status})`);
|
|
55
|
+
let result;
|
|
56
|
+
await readSseStream(response.body, (event) => {
|
|
57
|
+
const parsed = relaySubagentResponseSchema.safeParse(event);
|
|
58
|
+
if (parsed.success) {
|
|
59
|
+
result = JSON.stringify(parsed.data);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const failure = z.object({ error: z.string(), details: z.string().optional() }).safeParse(event);
|
|
63
|
+
if (failure.success) throw new Error(failure.data.details || failure.data.error);
|
|
64
|
+
throw new Error("Relay wait stream returned an invalid response");
|
|
65
|
+
});
|
|
66
|
+
if (!result) throw new Error("Relay wait stream ended without a result");
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
42
69
|
var server = new McpServer({ name: RELAY_MCP_SERVER_NAME, version: "1.0.0" });
|
|
43
|
-
server.registerTool(
|
|
70
|
+
server.registerTool(RELAY_MCP_TOOLS.getProviders, {
|
|
44
71
|
description: "List the agent providers Relay is allowed to use and the configured Relay base provider."
|
|
45
72
|
}, async () => ({
|
|
46
73
|
content: [{ type: "text", text: await request(`/chats/${parentChatId}/subagents`, "GET") }]
|
|
47
74
|
}));
|
|
48
|
-
server.registerTool(
|
|
49
|
-
description: "Spawn a child agent with all, none, or the latest N turns of parent context
|
|
75
|
+
server.registerTool(RELAY_MCP_TOOLS.spawnAgent, {
|
|
76
|
+
description: "Spawn a child agent with all, none, or the latest N turns of parent context. Blocks by default; set blocking to false to return its chat ID immediately.",
|
|
50
77
|
inputSchema: {
|
|
51
78
|
provider: spawnRelaySubagentRequestSchema.shape.provider.describe("Provider returned by get_providers."),
|
|
52
79
|
prompt: spawnRelaySubagentRequestSchema.shape.prompt.describe("The child\u2019s assigned task, scope, and expected result. Include all necessary context when fork_turns is none."),
|
|
@@ -54,43 +81,55 @@ server.registerTool("spawn_agent", {
|
|
|
54
81
|
model: spawnRelaySubagentRequestSchema.shape.model,
|
|
55
82
|
thinking_level: spawnRelaySubagentRequestSchema.shape.thinkingLevel,
|
|
56
83
|
title: spawnRelaySubagentRequestSchema.shape.title,
|
|
57
|
-
|
|
84
|
+
blocking: z.boolean().optional().describe("Wait for the child to finish. Defaults to true."),
|
|
85
|
+
timeout_minutes: waitRelaySubagentRequestSchema.shape.timeoutMinutes.describe("Maximum time to wait without interrupting the child.")
|
|
86
|
+
}
|
|
87
|
+
}, async ({ provider, prompt, fork_turns, model, thinking_level, title, blocking, timeout_minutes }) => {
|
|
88
|
+
const created = await request(`/chats/${parentChatId}/subagents`, "POST", {
|
|
89
|
+
provider,
|
|
90
|
+
prompt,
|
|
91
|
+
forkTurns: fork_turns,
|
|
92
|
+
...model ? { model } : {},
|
|
93
|
+
...thinking_level ? { thinkingLevel: thinking_level } : {},
|
|
94
|
+
...title ? { title } : {}
|
|
95
|
+
});
|
|
96
|
+
const createdAgent = relaySubagentResponseSchema.parse(JSON.parse(created));
|
|
97
|
+
return { content: [{ type: "text", text: blocking === false ? created : await waitForAgent(createdAgent.chatId, timeout_minutes) }] };
|
|
98
|
+
});
|
|
99
|
+
server.registerTool(RELAY_MCP_TOOLS.getAgent, {
|
|
100
|
+
description: "Get the current status and final response, if available, for one of this Relay chat\u2019s child agents.",
|
|
101
|
+
inputSchema: { chat_id: z.string().uuid() }
|
|
102
|
+
}, async ({ chat_id }) => ({
|
|
103
|
+
content: [{ type: "text", text: await request(`/chats/${parentChatId}/subagents/${chat_id}`, "GET") }]
|
|
104
|
+
}));
|
|
105
|
+
server.registerTool(RELAY_MCP_TOOLS.waitAgent, {
|
|
106
|
+
description: "Wait for one of this Relay chat\u2019s child agents to finish over a heartbeat stream. A timeout stops waiting without interrupting the child.",
|
|
107
|
+
inputSchema: {
|
|
108
|
+
chat_id: z.string().uuid(),
|
|
109
|
+
timeout_minutes: waitRelaySubagentRequestSchema.shape.timeoutMinutes
|
|
58
110
|
}
|
|
59
|
-
}, async ({
|
|
60
|
-
content: [{
|
|
61
|
-
type: "text",
|
|
62
|
-
text: await request(`/chats/${parentChatId}/subagents`, "POST", {
|
|
63
|
-
provider,
|
|
64
|
-
prompt,
|
|
65
|
-
forkTurns: fork_turns,
|
|
66
|
-
...model ? { model } : {},
|
|
67
|
-
...thinking_level ? { thinkingLevel: thinking_level } : {},
|
|
68
|
-
...title ? { title } : {},
|
|
69
|
-
...timeout_minutes ? { timeoutMinutes: timeout_minutes } : {}
|
|
70
|
-
})
|
|
71
|
-
}]
|
|
111
|
+
}, async ({ chat_id, timeout_minutes }) => ({
|
|
112
|
+
content: [{ type: "text", text: await waitForAgent(chat_id, timeout_minutes) }]
|
|
72
113
|
}));
|
|
73
|
-
server.registerTool(
|
|
74
|
-
description: "Send a follow-up to one of this Relay chat\u2019s child agents
|
|
114
|
+
server.registerTool(RELAY_MCP_TOOLS.messageAgent, {
|
|
115
|
+
description: "Send a follow-up to one of this Relay chat\u2019s child agents. Blocks by default; set blocking to false to return immediately.",
|
|
75
116
|
inputSchema: {
|
|
76
117
|
chat_id: z.string().uuid(),
|
|
77
118
|
message: messageRelaySubagentRequestSchema.shape.message,
|
|
78
119
|
model: messageRelaySubagentRequestSchema.shape.model,
|
|
79
120
|
thinking_level: messageRelaySubagentRequestSchema.shape.thinkingLevel,
|
|
80
|
-
|
|
121
|
+
blocking: z.boolean().optional().describe("Wait for the child to finish. Defaults to true."),
|
|
122
|
+
timeout_minutes: waitRelaySubagentRequestSchema.shape.timeoutMinutes.describe("Maximum time to wait without interrupting the child.")
|
|
81
123
|
}
|
|
82
|
-
}, async ({ chat_id, message, model, thinking_level, timeout_minutes }) =>
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}]
|
|
92
|
-
}));
|
|
93
|
-
server.registerTool("delete_agent", {
|
|
124
|
+
}, async ({ chat_id, message, model, thinking_level, blocking, timeout_minutes }) => {
|
|
125
|
+
const accepted = await request(`/chats/${parentChatId}/subagents/${chat_id}/messages`, "POST", {
|
|
126
|
+
message,
|
|
127
|
+
...model ? { model } : {},
|
|
128
|
+
...thinking_level ? { thinkingLevel: thinking_level } : {}
|
|
129
|
+
});
|
|
130
|
+
return { content: [{ type: "text", text: blocking === false ? accepted : await waitForAgent(chat_id, timeout_minutes) }] };
|
|
131
|
+
});
|
|
132
|
+
server.registerTool(RELAY_MCP_TOOLS.deleteAgent, {
|
|
94
133
|
description: "Delete one of this Relay chat\u2019s child agents.",
|
|
95
134
|
inputSchema: { chat_id: z.string().uuid() }
|
|
96
135
|
}, async ({ chat_id }) => ({
|