@rk0429/agentic-relay 2.0.6 → 2.0.7
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 +186 -50
- package/package.json +1 -1
package/dist/relay.mjs
CHANGED
|
@@ -332,7 +332,7 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } fr
|
|
|
332
332
|
import { join as join6 } from "path";
|
|
333
333
|
import { homedir as homedir5 } from "os";
|
|
334
334
|
import { nanoid as nanoid2 } from "nanoid";
|
|
335
|
-
function
|
|
335
|
+
function getRelayHome3() {
|
|
336
336
|
return process.env["RELAY_HOME"] ?? join6(homedir5(), ".relay");
|
|
337
337
|
}
|
|
338
338
|
function isValidEventType(type) {
|
|
@@ -347,7 +347,7 @@ var init_agent_event_store = __esm({
|
|
|
347
347
|
maxEvents: 1e3,
|
|
348
348
|
ttlMs: 36e5,
|
|
349
349
|
backend: "jsonl",
|
|
350
|
-
sessionDir: join6(
|
|
350
|
+
sessionDir: join6(getRelayHome3(), "sessions"),
|
|
351
351
|
eventsFileName: "events.jsonl"
|
|
352
352
|
};
|
|
353
353
|
AgentEventStore = class {
|
|
@@ -8442,7 +8442,7 @@ var init_server = __esm({
|
|
|
8442
8442
|
this.agentEventStore
|
|
8443
8443
|
);
|
|
8444
8444
|
this.server = new McpServer(
|
|
8445
|
-
{ name: "agentic-relay", version: "2.0.
|
|
8445
|
+
{ name: "agentic-relay", version: "2.0.7" },
|
|
8446
8446
|
createMcpServerOptions()
|
|
8447
8447
|
);
|
|
8448
8448
|
this.registerTools(this.server);
|
|
@@ -8956,7 +8956,7 @@ var init_server = __esm({
|
|
|
8956
8956
|
sessionIdGenerator: () => randomUUID()
|
|
8957
8957
|
});
|
|
8958
8958
|
const server = new McpServer(
|
|
8959
|
-
{ name: "agentic-relay", version: "2.0.
|
|
8959
|
+
{ name: "agentic-relay", version: "2.0.7" },
|
|
8960
8960
|
createMcpServerOptions()
|
|
8961
8961
|
);
|
|
8962
8962
|
this.registerTools(server, childRelayContext);
|
|
@@ -10969,7 +10969,7 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
10969
10969
|
|
|
10970
10970
|
// src/adapters/codex-adapter.ts
|
|
10971
10971
|
init_logger();
|
|
10972
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
10972
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, mkdtemp, copyFile } from "fs/promises";
|
|
10973
10973
|
import { homedir as homedir2 } from "os";
|
|
10974
10974
|
import { join as join2, dirname as dirname2 } from "path";
|
|
10975
10975
|
async function loadCodexSDK() {
|
|
@@ -11066,6 +11066,12 @@ function toTOMLString(value) {
|
|
|
11066
11066
|
function toTOMLStringArray(values) {
|
|
11067
11067
|
return `[${values.map(toTOMLString).join(", ")}]`;
|
|
11068
11068
|
}
|
|
11069
|
+
function toTOMLInlineTable(values) {
|
|
11070
|
+
return `{ ${Object.entries(values).map(([key, value]) => `${toTOMLString(key)} = ${toTOMLString(value)}`).join(", ")} }`;
|
|
11071
|
+
}
|
|
11072
|
+
function toTOMLTableKey(key) {
|
|
11073
|
+
return /^[A-Za-z0-9_-]+$/.test(key) ? key : toTOMLString(key);
|
|
11074
|
+
}
|
|
11069
11075
|
function generateMcpServersTOML(servers) {
|
|
11070
11076
|
const parts = [];
|
|
11071
11077
|
for (const server of servers) {
|
|
@@ -11079,11 +11085,88 @@ function generateMcpServersTOML(servers) {
|
|
|
11079
11085
|
}
|
|
11080
11086
|
return parts.join("\n");
|
|
11081
11087
|
}
|
|
11088
|
+
function generateChildMcpServersTOML(servers) {
|
|
11089
|
+
const parts = [];
|
|
11090
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
11091
|
+
parts.push(`[mcp_servers.${toTOMLTableKey(name)}]`);
|
|
11092
|
+
if ("url" in server) {
|
|
11093
|
+
parts.push(`url = ${toTOMLString(server.url)}`);
|
|
11094
|
+
if (server.headers && Object.keys(server.headers).length > 0) {
|
|
11095
|
+
parts.push(`headers = ${toTOMLInlineTable(server.headers)}`);
|
|
11096
|
+
}
|
|
11097
|
+
} else {
|
|
11098
|
+
parts.push(`command = ${toTOMLString(server.command)}`);
|
|
11099
|
+
if (server.args && server.args.length > 0) {
|
|
11100
|
+
parts.push(`args = ${toTOMLStringArray(server.args)}`);
|
|
11101
|
+
}
|
|
11102
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
11103
|
+
parts.push(`env = ${toTOMLInlineTable(server.env)}`);
|
|
11104
|
+
}
|
|
11105
|
+
}
|
|
11106
|
+
parts.push("");
|
|
11107
|
+
}
|
|
11108
|
+
return parts.join("\n");
|
|
11109
|
+
}
|
|
11110
|
+
function rewriteCodexConfigWithMcpServers(existingContent, mcpServers) {
|
|
11111
|
+
const parsed = parseTOMLMcpServers(existingContent);
|
|
11112
|
+
const preamble = parsed.preambleLines.join("\n").replace(/\n+$/, "");
|
|
11113
|
+
const mcpSection = generateChildMcpServersTOML(mcpServers);
|
|
11114
|
+
const postamble = parsed.postambleLines.join("\n").replace(/^\n+/, "");
|
|
11115
|
+
const parts = [];
|
|
11116
|
+
if (preamble) parts.push(preamble);
|
|
11117
|
+
if (mcpSection) parts.push(mcpSection);
|
|
11118
|
+
if (postamble) parts.push(postamble);
|
|
11119
|
+
let output = parts.join("\n\n");
|
|
11120
|
+
if (!output.endsWith("\n")) output += "\n";
|
|
11121
|
+
return output;
|
|
11122
|
+
}
|
|
11123
|
+
function getRelayHome() {
|
|
11124
|
+
return process.env["RELAY_HOME"] ?? join2(homedir2(), ".relay");
|
|
11125
|
+
}
|
|
11126
|
+
function encodeNativeSessionId(threadId, codexHome) {
|
|
11127
|
+
if (!codexHome) {
|
|
11128
|
+
return threadId;
|
|
11129
|
+
}
|
|
11130
|
+
return `${threadId}@@${Buffer.from(codexHome, "utf8").toString("base64url")}`;
|
|
11131
|
+
}
|
|
11132
|
+
function decodeNativeSessionId(nativeSessionId) {
|
|
11133
|
+
const separatorIndex = nativeSessionId.lastIndexOf("@@");
|
|
11134
|
+
if (separatorIndex === -1) {
|
|
11135
|
+
return { threadId: nativeSessionId };
|
|
11136
|
+
}
|
|
11137
|
+
const threadId = nativeSessionId.slice(0, separatorIndex);
|
|
11138
|
+
const encodedHome = nativeSessionId.slice(separatorIndex + 2);
|
|
11139
|
+
try {
|
|
11140
|
+
const codexHome = Buffer.from(encodedHome, "base64url").toString("utf8");
|
|
11141
|
+
return { threadId, codexHome };
|
|
11142
|
+
} catch {
|
|
11143
|
+
return { threadId: nativeSessionId };
|
|
11144
|
+
}
|
|
11145
|
+
}
|
|
11146
|
+
function isFileNotFoundError(error) {
|
|
11147
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
11148
|
+
}
|
|
11149
|
+
async function copyIfExists(from, to) {
|
|
11150
|
+
try {
|
|
11151
|
+
await copyFile(from, to);
|
|
11152
|
+
} catch (error) {
|
|
11153
|
+
if (isFileNotFoundError(error)) {
|
|
11154
|
+
return;
|
|
11155
|
+
}
|
|
11156
|
+
throw error;
|
|
11157
|
+
}
|
|
11158
|
+
}
|
|
11082
11159
|
var CodexAdapter = class extends BaseAdapter {
|
|
11083
11160
|
id = "codex";
|
|
11084
11161
|
command = "codex";
|
|
11162
|
+
getCodexHomePath() {
|
|
11163
|
+
return join2(homedir2(), ".codex");
|
|
11164
|
+
}
|
|
11165
|
+
getIsolatedCodexHomesPath() {
|
|
11166
|
+
return join2(getRelayHome(), "codex-homes");
|
|
11167
|
+
}
|
|
11085
11168
|
getConfigPath() {
|
|
11086
|
-
return join2(
|
|
11169
|
+
return join2(this.getCodexHomePath(), "config.toml");
|
|
11087
11170
|
}
|
|
11088
11171
|
async checkAuthStatus() {
|
|
11089
11172
|
const result = await this.processManager.execute(this.command, [
|
|
@@ -11096,46 +11179,74 @@ var CodexAdapter = class extends BaseAdapter {
|
|
|
11096
11179
|
...!authenticated ? { message: "codex authentication not configured" } : {}
|
|
11097
11180
|
};
|
|
11098
11181
|
}
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
const
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11182
|
+
async prepareIsolatedCodexHome(mcpServers) {
|
|
11183
|
+
const codexHomesDir = this.getIsolatedCodexHomesPath();
|
|
11184
|
+
await mkdir2(codexHomesDir, { recursive: true });
|
|
11185
|
+
const isolatedCodexHome = await mkdtemp(join2(codexHomesDir, "codex-"));
|
|
11186
|
+
const realCodexHome = this.getCodexHomePath();
|
|
11187
|
+
await copyIfExists(
|
|
11188
|
+
join2(realCodexHome, "auth.json"),
|
|
11189
|
+
join2(isolatedCodexHome, "auth.json")
|
|
11190
|
+
);
|
|
11191
|
+
await copyIfExists(
|
|
11192
|
+
join2(realCodexHome, "version.json"),
|
|
11193
|
+
join2(isolatedCodexHome, "version.json")
|
|
11194
|
+
);
|
|
11195
|
+
await copyIfExists(
|
|
11196
|
+
join2(realCodexHome, "internal_storage.json"),
|
|
11197
|
+
join2(isolatedCodexHome, "internal_storage.json")
|
|
11198
|
+
);
|
|
11199
|
+
await copyIfExists(
|
|
11200
|
+
join2(realCodexHome, ".codex-global-state.json"),
|
|
11201
|
+
join2(isolatedCodexHome, ".codex-global-state.json")
|
|
11202
|
+
);
|
|
11203
|
+
let existingConfig = "";
|
|
11204
|
+
try {
|
|
11205
|
+
existingConfig = await readFile2(this.getConfigPath(), "utf-8");
|
|
11206
|
+
} catch (error) {
|
|
11207
|
+
if (!isFileNotFoundError(error)) {
|
|
11208
|
+
throw error;
|
|
11116
11209
|
}
|
|
11117
11210
|
}
|
|
11118
|
-
|
|
11211
|
+
const isolatedConfig = rewriteCodexConfigWithMcpServers(
|
|
11212
|
+
existingConfig,
|
|
11213
|
+
mcpServers
|
|
11214
|
+
);
|
|
11215
|
+
await writeFile2(join2(isolatedCodexHome, "config.toml"), isolatedConfig, {
|
|
11216
|
+
mode: 384
|
|
11217
|
+
});
|
|
11218
|
+
return isolatedCodexHome;
|
|
11119
11219
|
}
|
|
11120
|
-
buildCodexOptions(flags) {
|
|
11220
|
+
async buildCodexOptions(flags) {
|
|
11121
11221
|
const options = {};
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11222
|
+
let env;
|
|
11223
|
+
let isolatedCodexHome;
|
|
11224
|
+
const ensureEnv = () => {
|
|
11225
|
+
if (!env) {
|
|
11226
|
+
env = {};
|
|
11227
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
11228
|
+
if (value !== void 0) {
|
|
11229
|
+
env[key] = value;
|
|
11230
|
+
}
|
|
11127
11231
|
}
|
|
11128
11232
|
}
|
|
11129
|
-
env
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11233
|
+
return env;
|
|
11234
|
+
};
|
|
11235
|
+
if (flags.mcpContext) {
|
|
11236
|
+
const resolvedEnv = ensureEnv();
|
|
11237
|
+
resolvedEnv.RELAY_TRACE_ID = flags.mcpContext.traceId;
|
|
11238
|
+
resolvedEnv.RELAY_PARENT_SESSION_ID = flags.mcpContext.parentSessionId;
|
|
11239
|
+
resolvedEnv.RELAY_DEPTH = String(flags.mcpContext.depth);
|
|
11133
11240
|
}
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11241
|
+
if (flags.mcpServers && Object.keys(flags.mcpServers).length > 0) {
|
|
11242
|
+
const resolvedEnv = ensureEnv();
|
|
11243
|
+
isolatedCodexHome = await this.prepareIsolatedCodexHome(flags.mcpServers);
|
|
11244
|
+
resolvedEnv.CODEX_HOME = isolatedCodexHome;
|
|
11245
|
+
}
|
|
11246
|
+
if (env) {
|
|
11247
|
+
options.env = env;
|
|
11137
11248
|
}
|
|
11138
|
-
return options;
|
|
11249
|
+
return { options, isolatedCodexHome };
|
|
11139
11250
|
}
|
|
11140
11251
|
mapFlags(flags) {
|
|
11141
11252
|
const args = mapCommonToNative("codex", flags);
|
|
@@ -11189,7 +11300,8 @@ ${prompt}`;
|
|
|
11189
11300
|
);
|
|
11190
11301
|
try {
|
|
11191
11302
|
const { Codex } = await loadCodexSDK();
|
|
11192
|
-
const
|
|
11303
|
+
const { options, isolatedCodexHome } = await this.buildCodexOptions(flags);
|
|
11304
|
+
const codex = new Codex(options);
|
|
11193
11305
|
const thread = codex.startThread({
|
|
11194
11306
|
...flags.model ? { model: flags.model } : {},
|
|
11195
11307
|
workingDirectory: process.cwd(),
|
|
@@ -11200,7 +11312,12 @@ ${prompt}`;
|
|
|
11200
11312
|
exitCode: 0,
|
|
11201
11313
|
stdout: result.finalResponse,
|
|
11202
11314
|
stderr: "",
|
|
11203
|
-
...thread.id ? {
|
|
11315
|
+
...thread.id ? {
|
|
11316
|
+
nativeSessionId: encodeNativeSessionId(
|
|
11317
|
+
thread.id,
|
|
11318
|
+
isolatedCodexHome
|
|
11319
|
+
)
|
|
11320
|
+
} : {}
|
|
11204
11321
|
};
|
|
11205
11322
|
} catch (error) {
|
|
11206
11323
|
return {
|
|
@@ -11221,7 +11338,8 @@ ${prompt}`;
|
|
|
11221
11338
|
);
|
|
11222
11339
|
try {
|
|
11223
11340
|
const { Codex } = await loadCodexSDK();
|
|
11224
|
-
const
|
|
11341
|
+
const { options, isolatedCodexHome } = await this.buildCodexOptions(flags);
|
|
11342
|
+
const codex = new Codex(options);
|
|
11225
11343
|
const thread = codex.startThread({
|
|
11226
11344
|
...flags.model ? { model: flags.model } : {},
|
|
11227
11345
|
workingDirectory: process.cwd(),
|
|
@@ -11282,14 +11400,20 @@ ${prompt}`;
|
|
|
11282
11400
|
yield {
|
|
11283
11401
|
type: "done",
|
|
11284
11402
|
result: { exitCode: 0, stdout: finalResponse, stderr: "" },
|
|
11285
|
-
nativeSessionId: threadId
|
|
11403
|
+
nativeSessionId: threadId || thread.id ? encodeNativeSessionId(
|
|
11404
|
+
threadId ?? thread.id ?? "",
|
|
11405
|
+
isolatedCodexHome
|
|
11406
|
+
) : void 0
|
|
11286
11407
|
};
|
|
11287
11408
|
} else if (event.type === "turn.failed") {
|
|
11288
11409
|
const errorMessage = event.error.message ?? "Turn failed";
|
|
11289
11410
|
yield {
|
|
11290
11411
|
type: "done",
|
|
11291
11412
|
result: { exitCode: 1, stdout: "", stderr: errorMessage },
|
|
11292
|
-
nativeSessionId: threadId
|
|
11413
|
+
nativeSessionId: threadId || thread.id ? encodeNativeSessionId(
|
|
11414
|
+
threadId ?? thread.id ?? "",
|
|
11415
|
+
isolatedCodexHome
|
|
11416
|
+
) : void 0
|
|
11293
11417
|
};
|
|
11294
11418
|
} else if (event.type === "error") {
|
|
11295
11419
|
yield {
|
|
@@ -11310,8 +11434,20 @@ ${prompt}`;
|
|
|
11310
11434
|
async continueSession(nativeSessionId, prompt) {
|
|
11311
11435
|
try {
|
|
11312
11436
|
const { Codex } = await loadCodexSDK();
|
|
11313
|
-
const
|
|
11314
|
-
const
|
|
11437
|
+
const { threadId, codexHome } = decodeNativeSessionId(nativeSessionId);
|
|
11438
|
+
const codex = new Codex(
|
|
11439
|
+
codexHome ? {
|
|
11440
|
+
env: {
|
|
11441
|
+
...Object.fromEntries(
|
|
11442
|
+
Object.entries(process.env).filter(
|
|
11443
|
+
([, value]) => value !== void 0
|
|
11444
|
+
)
|
|
11445
|
+
),
|
|
11446
|
+
CODEX_HOME: codexHome
|
|
11447
|
+
}
|
|
11448
|
+
} : {}
|
|
11449
|
+
);
|
|
11450
|
+
const thread = codex.resumeThread(threadId, {
|
|
11315
11451
|
workingDirectory: process.cwd(),
|
|
11316
11452
|
approvalPolicy: "never"
|
|
11317
11453
|
});
|
|
@@ -11650,7 +11786,7 @@ import { readFile as readFile4, writeFile as writeFile4, readdir, mkdir as mkdir
|
|
|
11650
11786
|
import { join as join4 } from "path";
|
|
11651
11787
|
import { homedir as homedir4 } from "os";
|
|
11652
11788
|
import { nanoid } from "nanoid";
|
|
11653
|
-
function
|
|
11789
|
+
function getRelayHome2() {
|
|
11654
11790
|
return process.env["RELAY_HOME"] ?? join4(homedir4(), ".relay");
|
|
11655
11791
|
}
|
|
11656
11792
|
function getSessionsDir(relayHome2) {
|
|
@@ -11690,7 +11826,7 @@ var SessionManager = class _SessionManager {
|
|
|
11690
11826
|
]);
|
|
11691
11827
|
sessionsDir;
|
|
11692
11828
|
constructor(sessionsDir) {
|
|
11693
|
-
this.sessionsDir = sessionsDir ?? getSessionsDir(
|
|
11829
|
+
this.sessionsDir = sessionsDir ?? getSessionsDir(getRelayHome2());
|
|
11694
11830
|
}
|
|
11695
11831
|
getSessionsDir() {
|
|
11696
11832
|
return this.sessionsDir;
|
|
@@ -13433,7 +13569,7 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
|
|
|
13433
13569
|
responseOutputDir,
|
|
13434
13570
|
relayConfig
|
|
13435
13571
|
);
|
|
13436
|
-
await server.start({ transport, port, currentVersion: "2.0.
|
|
13572
|
+
await server.start({ transport, port, currentVersion: "2.0.7" });
|
|
13437
13573
|
}
|
|
13438
13574
|
})
|
|
13439
13575
|
},
|
|
@@ -13593,7 +13729,7 @@ function createVersionCommand(registry2) {
|
|
|
13593
13729
|
description: "Show relay and backend versions"
|
|
13594
13730
|
},
|
|
13595
13731
|
async run() {
|
|
13596
|
-
const relayVersion = "2.0.
|
|
13732
|
+
const relayVersion = "2.0.7";
|
|
13597
13733
|
console.log(`agentic-relay v${relayVersion}`);
|
|
13598
13734
|
console.log("");
|
|
13599
13735
|
console.log("Backends:");
|
|
@@ -13990,7 +14126,7 @@ var subCommandNames = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "upd
|
|
|
13990
14126
|
var main = defineCommand11({
|
|
13991
14127
|
meta: {
|
|
13992
14128
|
name: "relay",
|
|
13993
|
-
version: "2.0.
|
|
14129
|
+
version: "2.0.7",
|
|
13994
14130
|
description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
|
|
13995
14131
|
},
|
|
13996
14132
|
args: {
|
package/package.json
CHANGED