@rk0429/agentic-relay 0.12.1 → 0.12.3
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/dist/relay.mjs +131 -8
- package/package.json +1 -1
package/dist/relay.mjs
CHANGED
|
@@ -46,6 +46,129 @@ var init_logger = __esm({
|
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
// src/mcp-server/deferred-cleanup-task-store.ts
|
|
50
|
+
import { isTerminal } from "@modelcontextprotocol/sdk/experimental/tasks/interfaces.js";
|
|
51
|
+
import { randomBytes } from "crypto";
|
|
52
|
+
var DeferredCleanupTaskStore;
|
|
53
|
+
var init_deferred_cleanup_task_store = __esm({
|
|
54
|
+
"src/mcp-server/deferred-cleanup-task-store.ts"() {
|
|
55
|
+
"use strict";
|
|
56
|
+
DeferredCleanupTaskStore = class {
|
|
57
|
+
tasks = /* @__PURE__ */ new Map();
|
|
58
|
+
cleanupTimers = /* @__PURE__ */ new Map();
|
|
59
|
+
generateTaskId() {
|
|
60
|
+
return randomBytes(16).toString("hex");
|
|
61
|
+
}
|
|
62
|
+
async createTask(taskParams, requestId, request, _sessionId) {
|
|
63
|
+
const taskId = this.generateTaskId();
|
|
64
|
+
if (this.tasks.has(taskId)) {
|
|
65
|
+
throw new Error(`Task with ID ${taskId} already exists`);
|
|
66
|
+
}
|
|
67
|
+
const actualTtl = taskParams.ttl ?? null;
|
|
68
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
69
|
+
const task = {
|
|
70
|
+
taskId,
|
|
71
|
+
status: "working",
|
|
72
|
+
ttl: actualTtl,
|
|
73
|
+
createdAt,
|
|
74
|
+
lastUpdatedAt: createdAt,
|
|
75
|
+
pollInterval: taskParams.pollInterval ?? 1e3
|
|
76
|
+
};
|
|
77
|
+
this.tasks.set(taskId, { task, request, requestId });
|
|
78
|
+
return { ...task };
|
|
79
|
+
}
|
|
80
|
+
async getTask(taskId, _sessionId) {
|
|
81
|
+
const stored = this.tasks.get(taskId);
|
|
82
|
+
return stored ? { ...stored.task } : null;
|
|
83
|
+
}
|
|
84
|
+
async storeTaskResult(taskId, status, result, _sessionId) {
|
|
85
|
+
const stored = this.tasks.get(taskId);
|
|
86
|
+
if (!stored) {
|
|
87
|
+
throw new Error(`Task with ID ${taskId} not found`);
|
|
88
|
+
}
|
|
89
|
+
if (isTerminal(stored.task.status)) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Cannot store result for task ${taskId} in terminal status '${stored.task.status}'. Task results can only be stored once.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
stored.result = result;
|
|
95
|
+
stored.task.status = status;
|
|
96
|
+
stored.task.lastUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
97
|
+
this.scheduleCleanup(taskId, stored.task.ttl);
|
|
98
|
+
}
|
|
99
|
+
async getTaskResult(taskId, _sessionId) {
|
|
100
|
+
const stored = this.tasks.get(taskId);
|
|
101
|
+
if (!stored) {
|
|
102
|
+
throw new Error(`Task with ID ${taskId} not found`);
|
|
103
|
+
}
|
|
104
|
+
if (!stored.result) {
|
|
105
|
+
throw new Error(`Task ${taskId} has no result stored`);
|
|
106
|
+
}
|
|
107
|
+
return stored.result;
|
|
108
|
+
}
|
|
109
|
+
async updateTaskStatus(taskId, status, statusMessage, _sessionId) {
|
|
110
|
+
const stored = this.tasks.get(taskId);
|
|
111
|
+
if (!stored) {
|
|
112
|
+
throw new Error(`Task with ID ${taskId} not found`);
|
|
113
|
+
}
|
|
114
|
+
if (isTerminal(stored.task.status)) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`Cannot update task ${taskId} from terminal status '${stored.task.status}'.`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
stored.task.status = status;
|
|
120
|
+
if (statusMessage) {
|
|
121
|
+
stored.task.statusMessage = statusMessage;
|
|
122
|
+
}
|
|
123
|
+
stored.task.lastUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
124
|
+
if (isTerminal(status)) {
|
|
125
|
+
this.scheduleCleanup(taskId, stored.task.ttl);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async listTasks(cursor, _sessionId) {
|
|
129
|
+
const PAGE_SIZE = 10;
|
|
130
|
+
const allTaskIds = Array.from(this.tasks.keys());
|
|
131
|
+
let startIndex = 0;
|
|
132
|
+
if (cursor) {
|
|
133
|
+
const cursorIndex = allTaskIds.indexOf(cursor);
|
|
134
|
+
if (cursorIndex >= 0) {
|
|
135
|
+
startIndex = cursorIndex + 1;
|
|
136
|
+
} else {
|
|
137
|
+
throw new Error(`Invalid cursor: ${cursor}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const pageTaskIds = allTaskIds.slice(startIndex, startIndex + PAGE_SIZE);
|
|
141
|
+
const tasks = pageTaskIds.map((id) => {
|
|
142
|
+
const stored = this.tasks.get(id);
|
|
143
|
+
return { ...stored.task };
|
|
144
|
+
});
|
|
145
|
+
const nextCursor = startIndex + PAGE_SIZE < allTaskIds.length ? pageTaskIds[pageTaskIds.length - 1] : void 0;
|
|
146
|
+
return { tasks, nextCursor };
|
|
147
|
+
}
|
|
148
|
+
/** Cleanup all timers (for testing or graceful shutdown) */
|
|
149
|
+
cleanup() {
|
|
150
|
+
for (const timer of this.cleanupTimers.values()) {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
}
|
|
153
|
+
this.cleanupTimers.clear();
|
|
154
|
+
this.tasks.clear();
|
|
155
|
+
}
|
|
156
|
+
scheduleCleanup(taskId, ttl) {
|
|
157
|
+
if (!ttl) return;
|
|
158
|
+
const existingTimer = this.cleanupTimers.get(taskId);
|
|
159
|
+
if (existingTimer) {
|
|
160
|
+
clearTimeout(existingTimer);
|
|
161
|
+
}
|
|
162
|
+
const timer = setTimeout(() => {
|
|
163
|
+
this.tasks.delete(taskId);
|
|
164
|
+
this.cleanupTimers.delete(taskId);
|
|
165
|
+
}, ttl);
|
|
166
|
+
this.cleanupTimers.set(taskId, timer);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
49
172
|
// src/mcp-server/recursion-guard.ts
|
|
50
173
|
import { createHash } from "crypto";
|
|
51
174
|
var RecursionGuard;
|
|
@@ -56,7 +179,7 @@ var init_recursion_guard = __esm({
|
|
|
56
179
|
constructor(config = {
|
|
57
180
|
maxDepth: 5,
|
|
58
181
|
maxCallsPerSession: 50,
|
|
59
|
-
timeoutSec:
|
|
182
|
+
timeoutSec: 86400
|
|
60
183
|
}) {
|
|
61
184
|
this.config = config;
|
|
62
185
|
}
|
|
@@ -1158,13 +1281,12 @@ __export(server_exports, {
|
|
|
1158
1281
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1159
1282
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1160
1283
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
1161
|
-
import { InMemoryTaskStore } from "@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js";
|
|
1162
1284
|
import { InMemoryTaskMessageQueue } from "@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js";
|
|
1163
1285
|
import { createServer } from "http";
|
|
1164
1286
|
import { randomUUID } from "crypto";
|
|
1165
1287
|
import { z as z5 } from "zod";
|
|
1166
1288
|
function createMcpServerOptions() {
|
|
1167
|
-
const taskStore = new
|
|
1289
|
+
const taskStore = new DeferredCleanupTaskStore();
|
|
1168
1290
|
return {
|
|
1169
1291
|
capabilities: { tasks: { requests: { tools: { call: {} } } } },
|
|
1170
1292
|
taskStore,
|
|
@@ -1176,6 +1298,7 @@ var spawnAgentsParallelInputShape, MAX_CHILD_HTTP_SESSIONS, RelayMCPServer;
|
|
|
1176
1298
|
var init_server = __esm({
|
|
1177
1299
|
"src/mcp-server/server.ts"() {
|
|
1178
1300
|
"use strict";
|
|
1301
|
+
init_deferred_cleanup_task_store();
|
|
1179
1302
|
init_recursion_guard();
|
|
1180
1303
|
init_spawn_agent();
|
|
1181
1304
|
init_spawn_agents_parallel();
|
|
@@ -1201,7 +1324,7 @@ var init_server = __esm({
|
|
|
1201
1324
|
this.guard = new RecursionGuard(guardConfig);
|
|
1202
1325
|
this.backendSelector = new BackendSelector();
|
|
1203
1326
|
this.server = new McpServer(
|
|
1204
|
-
{ name: "agentic-relay", version: "0.12.
|
|
1327
|
+
{ name: "agentic-relay", version: "0.12.3" },
|
|
1205
1328
|
createMcpServerOptions()
|
|
1206
1329
|
);
|
|
1207
1330
|
this.registerTools(this.server);
|
|
@@ -1565,7 +1688,7 @@ var init_server = __esm({
|
|
|
1565
1688
|
sessionIdGenerator: () => randomUUID()
|
|
1566
1689
|
});
|
|
1567
1690
|
const server = new McpServer(
|
|
1568
|
-
{ name: "agentic-relay", version: "0.12.
|
|
1691
|
+
{ name: "agentic-relay", version: "0.12.3" },
|
|
1569
1692
|
createMcpServerOptions()
|
|
1570
1693
|
);
|
|
1571
1694
|
this.registerTools(server);
|
|
@@ -4343,7 +4466,7 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
|
|
|
4343
4466
|
guardConfig = {
|
|
4344
4467
|
maxDepth: config.mcpServerMode.maxDepth ?? 5,
|
|
4345
4468
|
maxCallsPerSession: config.mcpServerMode.maxCallsPerSession ?? 20,
|
|
4346
|
-
timeoutSec: config.mcpServerMode.timeoutSec ??
|
|
4469
|
+
timeoutSec: config.mcpServerMode.timeoutSec ?? 86400
|
|
4347
4470
|
};
|
|
4348
4471
|
}
|
|
4349
4472
|
} catch {
|
|
@@ -4517,7 +4640,7 @@ function createVersionCommand(registry2) {
|
|
|
4517
4640
|
description: "Show relay and backend versions"
|
|
4518
4641
|
},
|
|
4519
4642
|
async run() {
|
|
4520
|
-
const relayVersion = "0.12.
|
|
4643
|
+
const relayVersion = "0.12.3";
|
|
4521
4644
|
console.log(`agentic-relay v${relayVersion}`);
|
|
4522
4645
|
console.log("");
|
|
4523
4646
|
console.log("Backends:");
|
|
@@ -4867,7 +4990,7 @@ void configManager.getConfig().then((config) => {
|
|
|
4867
4990
|
var main = defineCommand10({
|
|
4868
4991
|
meta: {
|
|
4869
4992
|
name: "relay",
|
|
4870
|
-
version: "0.12.
|
|
4993
|
+
version: "0.12.3",
|
|
4871
4994
|
description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
|
|
4872
4995
|
},
|
|
4873
4996
|
subCommands: {
|
package/package.json
CHANGED