codex-relay 1.0.6 → 1.1.0
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/api-schema2.js +1 -0
- package/dist/src.js +89 -12
- package/package.json +2 -2
- package/src/api-schema.ts +2 -0
package/dist/api-schema2.js
CHANGED
|
@@ -689,6 +689,7 @@ const apiPaths = {
|
|
|
689
689
|
workspaceTerminalSession: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}`,
|
|
690
690
|
workspaceTerminalInput: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/input`,
|
|
691
691
|
workspaceTerminalOutput: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output`,
|
|
692
|
+
workspaceTerminalOutputStream: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output/stream`,
|
|
692
693
|
workspaceTerminalResize: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/resize`,
|
|
693
694
|
imageAttachments: "/v1/attachments/images",
|
|
694
695
|
imageAttachment: (attachmentId) => `/v1/attachments/images/${encodeURIComponent(attachmentId)}`,
|
package/dist/src.js
CHANGED
|
@@ -1183,14 +1183,60 @@ function createApp(options = {}) {
|
|
|
1183
1183
|
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
1184
1184
|
if (!session) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("workspace_terminal_not_found", "Terminal session was not found."), 404);
|
|
1185
1185
|
const since = Number(c.req.query("since") ?? "0");
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1186
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, workspaceTerminalOutputResponse(session, since));
|
|
1187
|
+
});
|
|
1188
|
+
app.get("/v1/workspace/terminal/sessions/:sessionId/output/stream", async (c) => {
|
|
1189
|
+
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
1190
|
+
if (!session) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("workspace_terminal_not_found", "Terminal session was not found."), 404);
|
|
1191
|
+
const since = Number(c.req.query("since") ?? "0");
|
|
1192
|
+
const encoder = new TextEncoder();
|
|
1193
|
+
const secureSession = getSecureSessionForRequest(c, options.pairing, secureSessionsByTokenHash);
|
|
1194
|
+
let streamController;
|
|
1195
|
+
let closed = false;
|
|
1196
|
+
let stopHeartbeat;
|
|
1197
|
+
let unsubscribe = () => {};
|
|
1198
|
+
const closeStream = () => {
|
|
1199
|
+
if (closed) return;
|
|
1200
|
+
closed = true;
|
|
1201
|
+
if (stopHeartbeat) {
|
|
1202
|
+
clearInterval(stopHeartbeat);
|
|
1203
|
+
stopHeartbeat = void 0;
|
|
1204
|
+
}
|
|
1205
|
+
unsubscribe();
|
|
1206
|
+
if (streamController) {
|
|
1207
|
+
activeStreamControllers.delete(streamController);
|
|
1208
|
+
closeSseController(streamController);
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
const send = (response) => {
|
|
1212
|
+
if (closed || !streamController) return;
|
|
1213
|
+
if (!sendTerminalOutputSse(streamController, encoder, secureSession, response)) {
|
|
1214
|
+
closeStream();
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
if (response.exitedAt) closeStream();
|
|
1218
|
+
};
|
|
1219
|
+
const stream = new ReadableStream({
|
|
1220
|
+
start(controller) {
|
|
1221
|
+
streamController = controller;
|
|
1222
|
+
activeStreamControllers.add(controller);
|
|
1223
|
+
send(workspaceTerminalOutputResponse(session, since));
|
|
1224
|
+
if (session.exitedAt) return;
|
|
1225
|
+
unsubscribe = subscribeWorkspaceTerminalOutput(session, send);
|
|
1226
|
+
stopHeartbeat = setInterval(() => {
|
|
1227
|
+
if (!closed && streamController) enqueueSseChunk(streamController, encoder.encode(": keep-alive\n\n"));
|
|
1228
|
+
}, 3e4);
|
|
1229
|
+
},
|
|
1230
|
+
cancel() {
|
|
1231
|
+
closeStream();
|
|
1232
|
+
}
|
|
1192
1233
|
});
|
|
1193
|
-
return
|
|
1234
|
+
return new Response(stream, { headers: {
|
|
1235
|
+
"cache-control": "no-cache, no-transform",
|
|
1236
|
+
connection: "keep-alive",
|
|
1237
|
+
"content-type": "text/event-stream",
|
|
1238
|
+
"x-accel-buffering": "no"
|
|
1239
|
+
} });
|
|
1194
1240
|
});
|
|
1195
1241
|
app.post("/v1/workspace/terminal/sessions/:sessionId/input", async (c) => {
|
|
1196
1242
|
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
@@ -1199,7 +1245,7 @@ function createApp(options = {}) {
|
|
|
1199
1245
|
if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
|
|
1200
1246
|
if (session.exitedAt) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("workspace_terminal_closed", "Terminal session is closed."), 409);
|
|
1201
1247
|
session.child.write(parsed.data.data);
|
|
1202
|
-
return
|
|
1248
|
+
return new Response(null, { status: 204 });
|
|
1203
1249
|
});
|
|
1204
1250
|
app.post("/v1/workspace/terminal/sessions/:sessionId/resize", async (c) => {
|
|
1205
1251
|
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
@@ -1209,7 +1255,7 @@ function createApp(options = {}) {
|
|
|
1209
1255
|
session.cols = parsed.data.cols;
|
|
1210
1256
|
session.rows = parsed.data.rows;
|
|
1211
1257
|
if (!session.exitedAt) session.child.resize(parsed.data.cols, parsed.data.rows);
|
|
1212
|
-
return
|
|
1258
|
+
return new Response(null, { status: 204 });
|
|
1213
1259
|
});
|
|
1214
1260
|
app.delete("/v1/workspace/terminal/sessions/:sessionId", async (c) => {
|
|
1215
1261
|
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
@@ -1217,7 +1263,7 @@ function createApp(options = {}) {
|
|
|
1217
1263
|
closeWorkspaceTerminalSession(session);
|
|
1218
1264
|
workspaceTerminalSessions.delete(session.sessionId);
|
|
1219
1265
|
}
|
|
1220
|
-
return
|
|
1266
|
+
return new Response(null, { status: 204 });
|
|
1221
1267
|
});
|
|
1222
1268
|
app.get(apiPaths.models, async (c) => {
|
|
1223
1269
|
try {
|
|
@@ -3585,6 +3631,13 @@ function sendSse(controller, encoder, secureSession, event) {
|
|
|
3585
3631
|
threadId
|
|
3586
3632
|
});
|
|
3587
3633
|
}
|
|
3634
|
+
function sendTerminalOutputSse(controller, encoder, secureSession, response) {
|
|
3635
|
+
const parsed = WorkspaceTerminalOutputResponseSchema.parse(response);
|
|
3636
|
+
const data = secureSession ? EncryptedPayloadSchema.parse(encryptForMobile(secureSession.session, JSON.stringify(parsed))) : parsed;
|
|
3637
|
+
if (secureSession) secureSession.persist().catch(() => void 0);
|
|
3638
|
+
if (!enqueueSseChunk(controller, encoder.encode("event: output\n"))) return false;
|
|
3639
|
+
return enqueueSseChunk(controller, encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
|
|
3640
|
+
}
|
|
3588
3641
|
function threadIdFromStreamEvent(event) {
|
|
3589
3642
|
if ("threadId" in event && typeof event.threadId === "string") return event.threadId;
|
|
3590
3643
|
if ("thread" in event && event.thread) return event.thread.id;
|
|
@@ -5303,20 +5356,27 @@ function createWorkspaceTerminalSession(input) {
|
|
|
5303
5356
|
seq: 0,
|
|
5304
5357
|
sessionId,
|
|
5305
5358
|
startedAt,
|
|
5359
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
5306
5360
|
workspacePath: input.cwd
|
|
5307
5361
|
};
|
|
5308
5362
|
const appendOutput = (data) => {
|
|
5309
|
-
|
|
5363
|
+
const chunk = {
|
|
5310
5364
|
data,
|
|
5311
5365
|
seq: session.seq
|
|
5312
|
-
}
|
|
5366
|
+
};
|
|
5367
|
+
session.output.push(chunk);
|
|
5313
5368
|
session.seq += 1;
|
|
5314
5369
|
if (session.output.length > maxWorkspaceTerminalOutputChunks) session.output.splice(0, session.output.length - maxWorkspaceTerminalOutputChunks);
|
|
5370
|
+
notifyWorkspaceTerminalOutput(session, {
|
|
5371
|
+
chunks: [chunk],
|
|
5372
|
+
nextSeq: session.seq
|
|
5373
|
+
});
|
|
5315
5374
|
};
|
|
5316
5375
|
child.onData(appendOutput);
|
|
5317
5376
|
child.onExit(({ exitCode }) => {
|
|
5318
5377
|
session.exitCode = exitCode;
|
|
5319
5378
|
session.exitedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5379
|
+
notifyWorkspaceTerminalOutput(session, workspaceTerminalOutputResponse(session, session.seq));
|
|
5320
5380
|
});
|
|
5321
5381
|
return session;
|
|
5322
5382
|
}
|
|
@@ -5324,6 +5384,23 @@ function closeWorkspaceTerminalSession(session) {
|
|
|
5324
5384
|
if (session.exitedAt) return;
|
|
5325
5385
|
session.child.kill();
|
|
5326
5386
|
}
|
|
5387
|
+
function workspaceTerminalOutputResponse(session, since) {
|
|
5388
|
+
return WorkspaceTerminalOutputResponseSchema.parse({
|
|
5389
|
+
chunks: session.output.filter((chunk) => chunk.seq >= since),
|
|
5390
|
+
exitCode: session.exitCode,
|
|
5391
|
+
exitedAt: session.exitedAt,
|
|
5392
|
+
nextSeq: session.seq
|
|
5393
|
+
});
|
|
5394
|
+
}
|
|
5395
|
+
function subscribeWorkspaceTerminalOutput(session, subscriber) {
|
|
5396
|
+
session.subscribers.add(subscriber);
|
|
5397
|
+
return () => {
|
|
5398
|
+
session.subscribers.delete(subscriber);
|
|
5399
|
+
};
|
|
5400
|
+
}
|
|
5401
|
+
function notifyWorkspaceTerminalOutput(session, response) {
|
|
5402
|
+
for (const subscriber of session.subscribers) subscriber(response);
|
|
5403
|
+
}
|
|
5327
5404
|
async function listWorkspaceFiles(workspacePath, query, directory) {
|
|
5328
5405
|
const normalizedQuery = query.toLowerCase();
|
|
5329
5406
|
const isIgnored = await workspaceIgnoreMatcher(workspacePath);
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-relay",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Local Codex Relay CLI bridge for the Codex Relay mobile app.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/
|
|
8
|
+
"url": "git+https://github.com/gronxb/codex-relay.git",
|
|
9
9
|
"directory": "packages/codex-relay"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
package/src/api-schema.ts
CHANGED
|
@@ -976,6 +976,8 @@ export const apiPaths = {
|
|
|
976
976
|
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/input`,
|
|
977
977
|
workspaceTerminalOutput: (sessionId: string) =>
|
|
978
978
|
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output`,
|
|
979
|
+
workspaceTerminalOutputStream: (sessionId: string) =>
|
|
980
|
+
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output/stream`,
|
|
979
981
|
workspaceTerminalResize: (sessionId: string) =>
|
|
980
982
|
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/resize`,
|
|
981
983
|
imageAttachments: "/v1/attachments/images",
|