@dev-anywhere/proxy 0.0.6 → 0.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/README.md +3 -2
- package/dist/{chunk-3XXFLKKG.js → chunk-7PXDRNLY.js} +2 -2
- package/dist/{chunk-2XDZRLST.js → chunk-JPJMOVQ5.js} +2 -2
- package/dist/{chunk-VHCL7NVJ.js → chunk-QWPI6YON.js} +17 -2
- package/dist/chunk-QWPI6YON.js.map +1 -0
- package/dist/{chunk-XRTTHTM2.js → chunk-WXWH6L7J.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/serve.js +165 -34
- package/dist/serve.js.map +1 -1
- package/dist/session-worker.js +2 -2
- package/dist/session-worker.js.map +1 -1
- package/dist/{terminal-TVPPZQJW.js → terminal-ZPPKNAL4.js} +4 -4
- package/package.json +4 -4
- package/dist/chunk-VHCL7NVJ.js.map +0 -1
- /package/dist/{chunk-3XXFLKKG.js.map → chunk-7PXDRNLY.js.map} +0 -0
- /package/dist/{chunk-2XDZRLST.js.map → chunk-JPJMOVQ5.js.map} +0 -0
- /package/dist/{chunk-XRTTHTM2.js.map → chunk-WXWH6L7J.js.map} +0 -0
- /package/dist/{terminal-TVPPZQJW.js.map → terminal-ZPPKNAL4.js.map} +0 -0
package/dist/serve.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
KnownContentBlockSchema,
|
|
6
6
|
SeqCounter,
|
|
7
7
|
StreamJsonEventSchema
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JPJMOVQ5.js";
|
|
9
9
|
import {
|
|
10
10
|
createFSM,
|
|
11
11
|
defineFSM,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
serviceLogger,
|
|
15
15
|
shouldReleaseApprovalWait,
|
|
16
16
|
stateAfterApprovalRelease
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-WXWH6L7J.js";
|
|
18
18
|
import {
|
|
19
19
|
spawnScript
|
|
20
20
|
} from "./chunk-ZUWAB67J.js";
|
|
@@ -41,11 +41,11 @@ import {
|
|
|
41
41
|
serializeWorkerMsg,
|
|
42
42
|
sessionPaths,
|
|
43
43
|
tildify
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-QWPI6YON.js";
|
|
45
45
|
|
|
46
46
|
// src/serve.ts
|
|
47
47
|
import { createServer as createServer2 } from "net";
|
|
48
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
48
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync6, chmodSync, rmSync as rmSync2 } from "fs";
|
|
49
49
|
|
|
50
50
|
// src/serve/session-manager.ts
|
|
51
51
|
import { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync } from "fs";
|
|
@@ -183,6 +183,14 @@ var SessionManager = class {
|
|
|
183
183
|
serviceLogger.info({ sessionId: id, from: oldState, to: newState }, "Session state changed");
|
|
184
184
|
return true;
|
|
185
185
|
}
|
|
186
|
+
touchSession(id, now = Date.now(), minIntervalMs = 0) {
|
|
187
|
+
const session = this.sessions.get(id);
|
|
188
|
+
if (!session) return false;
|
|
189
|
+
if (now - session.updatedAt < minIntervalMs) return false;
|
|
190
|
+
session.updatedAt = now;
|
|
191
|
+
this.save();
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
186
194
|
terminateSession(id, context) {
|
|
187
195
|
const session = this.sessions.get(id);
|
|
188
196
|
if (!session) {
|
|
@@ -1078,7 +1086,7 @@ function extractConversationText(msg) {
|
|
|
1078
1086
|
return null;
|
|
1079
1087
|
}
|
|
1080
1088
|
async function extractTitleAndCwd(filePath) {
|
|
1081
|
-
return new Promise((
|
|
1089
|
+
return new Promise((resolve2) => {
|
|
1082
1090
|
const rl = createInterface({
|
|
1083
1091
|
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
1084
1092
|
crlfDelay: Infinity
|
|
@@ -1106,10 +1114,10 @@ async function extractTitleAndCwd(filePath) {
|
|
|
1106
1114
|
}
|
|
1107
1115
|
});
|
|
1108
1116
|
rl.on("close", () => {
|
|
1109
|
-
if (!resolved)
|
|
1110
|
-
else
|
|
1117
|
+
if (!resolved) resolve2({ title, cwd });
|
|
1118
|
+
else resolve2({ title, cwd });
|
|
1111
1119
|
});
|
|
1112
|
-
rl.on("error", () =>
|
|
1120
|
+
rl.on("error", () => resolve2({ title, cwd }));
|
|
1113
1121
|
});
|
|
1114
1122
|
}
|
|
1115
1123
|
async function collectJsonlFiles(root) {
|
|
@@ -1131,7 +1139,7 @@ async function collectJsonlFiles(root) {
|
|
|
1131
1139
|
return files;
|
|
1132
1140
|
}
|
|
1133
1141
|
async function extractCodexTitleAndCwd(filePath) {
|
|
1134
|
-
return new Promise((
|
|
1142
|
+
return new Promise((resolve2) => {
|
|
1135
1143
|
const rl = createInterface({
|
|
1136
1144
|
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
1137
1145
|
crlfDelay: Infinity
|
|
@@ -1155,8 +1163,8 @@ async function extractCodexTitleAndCwd(filePath) {
|
|
|
1155
1163
|
} catch {
|
|
1156
1164
|
}
|
|
1157
1165
|
});
|
|
1158
|
-
rl.on("close", () =>
|
|
1159
|
-
rl.on("error", () =>
|
|
1166
|
+
rl.on("close", () => resolve2({ id, title, cwd }));
|
|
1167
|
+
rl.on("error", () => resolve2({ id, title, cwd }));
|
|
1160
1168
|
});
|
|
1161
1169
|
}
|
|
1162
1170
|
function extractCodexUserText(payload) {
|
|
@@ -1721,16 +1729,16 @@ var WorkerRegistry = class {
|
|
|
1721
1729
|
return workerPid;
|
|
1722
1730
|
}
|
|
1723
1731
|
connect(sessionId, sockPath) {
|
|
1724
|
-
return new Promise((
|
|
1732
|
+
return new Promise((resolve2) => {
|
|
1725
1733
|
const sock = connect(sockPath);
|
|
1726
1734
|
sock.on("connect", () => {
|
|
1727
1735
|
this.sockets.set(sessionId, sock);
|
|
1728
1736
|
createWorkerReader(sock, (msg) => this.handleWorkerMessage(sessionId, msg));
|
|
1729
1737
|
sock.on("close", () => this.onDisconnect(sessionId));
|
|
1730
1738
|
sock.on("error", () => this.onDisconnect(sessionId));
|
|
1731
|
-
|
|
1739
|
+
resolve2(sock);
|
|
1732
1740
|
});
|
|
1733
|
-
sock.on("error", () =>
|
|
1741
|
+
sock.on("error", () => resolve2(null));
|
|
1734
1742
|
});
|
|
1735
1743
|
}
|
|
1736
1744
|
// 枚举 DATA_DIR 下所有 session 目录,尝试连接存活的 worker.sock;失败则清理 stale socket。
|
|
@@ -1856,6 +1864,7 @@ var WorkerRegistry = class {
|
|
|
1856
1864
|
return;
|
|
1857
1865
|
}
|
|
1858
1866
|
const ev = parsed.data;
|
|
1867
|
+
this.deps.touchSessionActivity?.(sessionId);
|
|
1859
1868
|
const isStreamDeltaSession = this.streamDeltaSessions.has(sessionId);
|
|
1860
1869
|
if (ev.type === "stream_event") {
|
|
1861
1870
|
const delta = ContentBlockDeltaSchema.safeParse(ev.event);
|
|
@@ -2053,6 +2062,80 @@ function terminateSessionByOwnership(deps, sessionId) {
|
|
|
2053
2062
|
return { success: false, action: "not_found" };
|
|
2054
2063
|
}
|
|
2055
2064
|
|
|
2065
|
+
// src/serve/clipboard-image-upload.ts
|
|
2066
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
2067
|
+
import { isAbsolute as isAbsolute3, join as join5, relative, resolve } from "path";
|
|
2068
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
2069
|
+
var MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
2070
|
+
var MAX_CLIPBOARD_IMAGE_BASE64_LENGTH = Math.ceil(MAX_CLIPBOARD_IMAGE_BYTES / 3) * 4;
|
|
2071
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
2072
|
+
["image/png", "png"],
|
|
2073
|
+
["image/jpeg", "jpg"],
|
|
2074
|
+
["image/webp", "webp"],
|
|
2075
|
+
["image/gif", "gif"]
|
|
2076
|
+
]);
|
|
2077
|
+
function formatTimestamp(ms) {
|
|
2078
|
+
const [date, time = "000000"] = new Date(ms).toISOString().replace(/\.\d{3}Z$/, "").split("T");
|
|
2079
|
+
return `${date.replace(/-/g, "")}-${time.replace(/:/g, "")}`;
|
|
2080
|
+
}
|
|
2081
|
+
function normalizeBase64(input) {
|
|
2082
|
+
return input.replace(/^data:[^;]+;base64,/i, "").replace(/\s/g, "");
|
|
2083
|
+
}
|
|
2084
|
+
function decodeBase64Image(dataBase64) {
|
|
2085
|
+
const normalized = normalizeBase64(dataBase64);
|
|
2086
|
+
if (normalized.length > MAX_CLIPBOARD_IMAGE_BASE64_LENGTH) {
|
|
2087
|
+
throw new Error("\u56FE\u7247\u8D85\u8FC7 10MB \u9650\u5236");
|
|
2088
|
+
}
|
|
2089
|
+
if (!normalized || !/^[A-Za-z0-9+/]*={0,2}$/.test(normalized)) {
|
|
2090
|
+
throw new Error("\u56FE\u7247\u6570\u636E\u4E0D\u662F\u6709\u6548\u7684 base64");
|
|
2091
|
+
}
|
|
2092
|
+
const buffer = Buffer.from(normalized, "base64");
|
|
2093
|
+
if (buffer.length === 0) throw new Error("\u56FE\u7247\u6570\u636E\u4E3A\u7A7A");
|
|
2094
|
+
if (buffer.length > MAX_CLIPBOARD_IMAGE_BYTES) {
|
|
2095
|
+
throw new Error("\u56FE\u7247\u8D85\u8FC7 10MB \u9650\u5236");
|
|
2096
|
+
}
|
|
2097
|
+
return buffer;
|
|
2098
|
+
}
|
|
2099
|
+
function resolveSessionClipboardDir(dataDir, sessionId) {
|
|
2100
|
+
const root = resolve(dataDir);
|
|
2101
|
+
const uploadDir = resolve(root, sessionId, "clipboard");
|
|
2102
|
+
const relativePath = relative(root, uploadDir);
|
|
2103
|
+
if (!relativePath || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
|
|
2104
|
+
throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
|
|
2105
|
+
}
|
|
2106
|
+
return uploadDir;
|
|
2107
|
+
}
|
|
2108
|
+
function saveClipboardImageUpload(request, options = {}) {
|
|
2109
|
+
const extension = IMAGE_EXTENSIONS.get(request.mimeType);
|
|
2110
|
+
if (!extension) {
|
|
2111
|
+
return {
|
|
2112
|
+
success: false,
|
|
2113
|
+
path: "",
|
|
2114
|
+
error: "\u4E0D\u652F\u6301\u8FD9\u79CD\u56FE\u7247\u683C\u5F0F",
|
|
2115
|
+
errorCode: ControlErrorCode.UNKNOWN
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
try {
|
|
2119
|
+
const dataDir = options.dataDir ?? DATA_DIR;
|
|
2120
|
+
const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
|
|
2121
|
+
const buffer = decodeBase64Image(request.dataBase64);
|
|
2122
|
+
const now = options.now ?? Date.now;
|
|
2123
|
+
const suffix = options.randomSuffix?.() ?? nanoid3(6);
|
|
2124
|
+
const fileName = `pasted-${formatTimestamp(now())}-${suffix}.${extension}`;
|
|
2125
|
+
const path = join5(uploadDir, fileName);
|
|
2126
|
+
mkdirSync4(uploadDir, { recursive: true });
|
|
2127
|
+
writeFileSync4(path, buffer, { mode: 384 });
|
|
2128
|
+
return { success: true, path };
|
|
2129
|
+
} catch (err) {
|
|
2130
|
+
return {
|
|
2131
|
+
success: false,
|
|
2132
|
+
path: "",
|
|
2133
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2134
|
+
errorCode: ControlErrorCode.UNKNOWN
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2056
2139
|
// src/serve/pty-input.ts
|
|
2057
2140
|
function serializeRawPtyInput(sessionId, data) {
|
|
2058
2141
|
return serializeIpc({ type: "pty_input", sessionId, data });
|
|
@@ -2126,6 +2209,42 @@ var RelayInputHandlers = class {
|
|
|
2126
2209
|
ts.write(serializeRawPtyInput(sessionId, data));
|
|
2127
2210
|
serviceLogger.info({ sessionId, bytes: data.length }, "Raw PTY input forwarded");
|
|
2128
2211
|
}
|
|
2212
|
+
onClipboardImageUpload(msg) {
|
|
2213
|
+
const sessionId = msg.sessionId;
|
|
2214
|
+
const requestId = msg.requestId;
|
|
2215
|
+
if (!sessionId) return;
|
|
2216
|
+
const session = this.deps.sessionManager.getSession(sessionId);
|
|
2217
|
+
if (!session) {
|
|
2218
|
+
this.deps.relayConnection.sendRaw(
|
|
2219
|
+
JSON.stringify({
|
|
2220
|
+
type: "clipboard_image_upload_response",
|
|
2221
|
+
requestId,
|
|
2222
|
+
sessionId,
|
|
2223
|
+
success: false,
|
|
2224
|
+
path: "",
|
|
2225
|
+
error: "\u4F1A\u8BDD\u4E0D\u5B58\u5728",
|
|
2226
|
+
errorCode: ControlErrorCode.SESSION_NOT_FOUND
|
|
2227
|
+
})
|
|
2228
|
+
);
|
|
2229
|
+
serviceLogger.warn({ sessionId }, "Clipboard image upload rejected: session not found");
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
const result = saveClipboardImageUpload({
|
|
2233
|
+
sessionId,
|
|
2234
|
+
mimeType: typeof msg.mimeType === "string" ? msg.mimeType : "",
|
|
2235
|
+
dataBase64: typeof msg.dataBase64 === "string" ? msg.dataBase64 : "",
|
|
2236
|
+
fileName: typeof msg.fileName === "string" ? msg.fileName : void 0
|
|
2237
|
+
});
|
|
2238
|
+
this.deps.relayConnection.sendRaw(
|
|
2239
|
+
JSON.stringify({
|
|
2240
|
+
type: "clipboard_image_upload_response",
|
|
2241
|
+
requestId,
|
|
2242
|
+
sessionId,
|
|
2243
|
+
...result
|
|
2244
|
+
})
|
|
2245
|
+
);
|
|
2246
|
+
serviceLogger.info({ sessionId, success: result.success }, "Clipboard image upload handled");
|
|
2247
|
+
}
|
|
2129
2248
|
};
|
|
2130
2249
|
|
|
2131
2250
|
// src/serve/relay-history-handlers.ts
|
|
@@ -2442,8 +2561,8 @@ var RelayResourceHandlers = class {
|
|
|
2442
2561
|
|
|
2443
2562
|
// src/serve/relay-session-create-handler.ts
|
|
2444
2563
|
import { rmSync, statSync as statSync2 } from "fs";
|
|
2445
|
-
import { isAbsolute as
|
|
2446
|
-
import { nanoid as
|
|
2564
|
+
import { isAbsolute as isAbsolute4 } from "path";
|
|
2565
|
+
import { nanoid as nanoid4 } from "nanoid";
|
|
2447
2566
|
|
|
2448
2567
|
// src/serve/hosted-pty-registry.ts
|
|
2449
2568
|
import * as pty from "node-pty";
|
|
@@ -2595,6 +2714,7 @@ var HostedPtyRegistry = class {
|
|
|
2595
2714
|
hosted.lastOutputTime = Date.now();
|
|
2596
2715
|
hosted.outputSeq += 1;
|
|
2597
2716
|
hosted.terminal.write(data);
|
|
2717
|
+
this.deps.touchSessionActivity(sessionId);
|
|
2598
2718
|
this.sendBinary(sessionId, Buffer.from(data, "utf-8"), hosted.outputSeq);
|
|
2599
2719
|
const oscSequences = extractOscSequences(data);
|
|
2600
2720
|
const session = this.deps.sessionManager.getSession(sessionId);
|
|
@@ -2731,7 +2851,7 @@ function validateSessionCwd(cwd) {
|
|
|
2731
2851
|
return { message: "\u8BF7\u8F93\u5165\u5DE5\u4F5C\u76EE\u5F55", code: ControlErrorCode.INVALID_PATH };
|
|
2732
2852
|
}
|
|
2733
2853
|
const trimmed = cwd.trim();
|
|
2734
|
-
if (!
|
|
2854
|
+
if (!isAbsolute4(trimmed)) {
|
|
2735
2855
|
return { message: "\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84", code: ControlErrorCode.INVALID_PATH };
|
|
2736
2856
|
}
|
|
2737
2857
|
try {
|
|
@@ -2790,7 +2910,7 @@ var RelaySessionCreateHandler = class {
|
|
|
2790
2910
|
const resumeSessionId = msg.resumeSessionId;
|
|
2791
2911
|
const streamDelta = msg.streamDelta === true;
|
|
2792
2912
|
const name = tildify(sessionCwd);
|
|
2793
|
-
const pendingId =
|
|
2913
|
+
const pendingId = nanoid4();
|
|
2794
2914
|
const hook = this.deps.createHookContext(pendingId, provider);
|
|
2795
2915
|
const workerPid = this.deps.workerRegistry.spawn(pendingId, {
|
|
2796
2916
|
cwd: sessionCwd,
|
|
@@ -2875,7 +2995,7 @@ var RelaySessionCreateHandler = class {
|
|
|
2875
2995
|
return;
|
|
2876
2996
|
}
|
|
2877
2997
|
const resumeSessionId = msg.resumeSessionId;
|
|
2878
|
-
const pendingId =
|
|
2998
|
+
const pendingId = nanoid4();
|
|
2879
2999
|
const name = tildify(cwd);
|
|
2880
3000
|
const hook = this.deps.createHookContext(pendingId, provider);
|
|
2881
3001
|
try {
|
|
@@ -3042,6 +3162,7 @@ var RelayRouter = class {
|
|
|
3042
3162
|
handlers = {
|
|
3043
3163
|
user_input: (msg) => this.inputHandlers.onUserInput(msg),
|
|
3044
3164
|
remote_input_raw: (msg) => this.inputHandlers.onRemoteInputRaw(msg),
|
|
3165
|
+
clipboard_image_upload: (msg) => this.inputHandlers.onClipboardImageUpload(msg),
|
|
3045
3166
|
tool_approve: (msg) => this.permissionHandlers.onToolApprove(msg),
|
|
3046
3167
|
tool_deny: (msg) => this.permissionHandlers.onToolDeny(msg),
|
|
3047
3168
|
proxy_info_request: (msg) => this.resourceHandlers.onProxyInfoRequest(msg),
|
|
@@ -3232,11 +3353,11 @@ var PermissionBroker = class {
|
|
|
3232
3353
|
message: "Duplicate permission request id."
|
|
3233
3354
|
});
|
|
3234
3355
|
}
|
|
3235
|
-
return new Promise((
|
|
3356
|
+
return new Promise((resolve2) => {
|
|
3236
3357
|
this.pending.set(request.requestId, {
|
|
3237
3358
|
...request,
|
|
3238
3359
|
source: "hook",
|
|
3239
|
-
resolve,
|
|
3360
|
+
resolve: resolve2,
|
|
3240
3361
|
createdAt: Date.now()
|
|
3241
3362
|
});
|
|
3242
3363
|
});
|
|
@@ -3460,6 +3581,7 @@ var AgentStatusRegistry = class {
|
|
|
3460
3581
|
};
|
|
3461
3582
|
|
|
3462
3583
|
// src/serve/session-broadcast.ts
|
|
3584
|
+
var ACTIVITY_STATUS_PUSH_INTERVAL_MS = 15e3;
|
|
3463
3585
|
function toSessionListPayload(s) {
|
|
3464
3586
|
return {
|
|
3465
3587
|
sessionId: s.id,
|
|
@@ -3522,6 +3644,11 @@ function changeSessionState(sessionManager, relay, sessionId, next) {
|
|
|
3522
3644
|
if (changed) pushSessionStatus(relay, sessionManager, sessionId);
|
|
3523
3645
|
return changed;
|
|
3524
3646
|
}
|
|
3647
|
+
function touchSessionActivity(sessionManager, relay, sessionId, now = Date.now()) {
|
|
3648
|
+
const touched = sessionManager.touchSession(sessionId, now, ACTIVITY_STATUS_PUSH_INTERVAL_MS);
|
|
3649
|
+
if (touched) pushSessionStatus(relay, sessionManager, sessionId);
|
|
3650
|
+
return touched;
|
|
3651
|
+
}
|
|
3525
3652
|
|
|
3526
3653
|
// src/serve/service-files.ts
|
|
3527
3654
|
import { execSync } from "child_process";
|
|
@@ -3529,10 +3656,10 @@ import { existsSync as existsSync5, readFileSync as readFileSync5, unlinkSync as
|
|
|
3529
3656
|
import { hostname } from "os";
|
|
3530
3657
|
import { connect as connect2 } from "net";
|
|
3531
3658
|
function tryConnectSocket(sockPath) {
|
|
3532
|
-
return new Promise((
|
|
3659
|
+
return new Promise((resolve2) => {
|
|
3533
3660
|
const s = connect2(sockPath);
|
|
3534
|
-
s.on("connect", () =>
|
|
3535
|
-
s.on("error", () =>
|
|
3661
|
+
s.on("connect", () => resolve2(s));
|
|
3662
|
+
s.on("error", () => resolve2(null));
|
|
3536
3663
|
});
|
|
3537
3664
|
}
|
|
3538
3665
|
function isProcessAlive(pid) {
|
|
@@ -3876,6 +4003,7 @@ function handleTerminalConnection(socket, deps) {
|
|
|
3876
4003
|
},
|
|
3877
4004
|
(sessionId, data, outputSeq) => {
|
|
3878
4005
|
if (!sessionManager.getSession(sessionId)) return;
|
|
4006
|
+
touchSessionActivity(sessionManager, relayConnection, sessionId);
|
|
3879
4007
|
const sessionIdBuf = Buffer.from(sessionId, "utf-8");
|
|
3880
4008
|
const wsFrame = Buffer.alloc(1 + sessionIdBuf.length + 4 + data.length);
|
|
3881
4009
|
wsFrame[0] = sessionIdBuf.length;
|
|
@@ -3926,7 +4054,7 @@ function handleTerminalConnection(socket, deps) {
|
|
|
3926
4054
|
|
|
3927
4055
|
// src/serve/hook-registry.ts
|
|
3928
4056
|
import { createHash, randomBytes } from "crypto";
|
|
3929
|
-
import { existsSync as existsSync6, mkdirSync as
|
|
4057
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
3930
4058
|
import { dirname as dirname4 } from "path";
|
|
3931
4059
|
import { z } from "zod";
|
|
3932
4060
|
var PersistedHookSessionBindingSchema = z.object({
|
|
@@ -4006,9 +4134,9 @@ var HookRegistry = class {
|
|
|
4006
4134
|
save() {
|
|
4007
4135
|
if (!this.persistPath) return;
|
|
4008
4136
|
try {
|
|
4009
|
-
|
|
4137
|
+
mkdirSync5(dirname4(this.persistPath), { recursive: true });
|
|
4010
4138
|
const tmpPath = `${this.persistPath}.${process.pid}.${Date.now()}.tmp`;
|
|
4011
|
-
|
|
4139
|
+
writeFileSync5(
|
|
4012
4140
|
tmpPath,
|
|
4013
4141
|
JSON.stringify(
|
|
4014
4142
|
{
|
|
@@ -4060,7 +4188,7 @@ var HookServer = class {
|
|
|
4060
4188
|
this.writeJson(res, 500, { error: "internal_error" });
|
|
4061
4189
|
});
|
|
4062
4190
|
});
|
|
4063
|
-
return new Promise((
|
|
4191
|
+
return new Promise((resolve2, reject) => {
|
|
4064
4192
|
const onError = (err) => {
|
|
4065
4193
|
this.server?.off("listening", onListening);
|
|
4066
4194
|
reject(err);
|
|
@@ -4068,7 +4196,7 @@ var HookServer = class {
|
|
|
4068
4196
|
const onListening = () => {
|
|
4069
4197
|
this.server?.off("error", onError);
|
|
4070
4198
|
serviceLogger.info({ host: this.host, port: this.options.port }, "Hook server listening");
|
|
4071
|
-
|
|
4199
|
+
resolve2();
|
|
4072
4200
|
};
|
|
4073
4201
|
this.server.once("error", onError);
|
|
4074
4202
|
this.server.once("listening", onListening);
|
|
@@ -4079,8 +4207,8 @@ var HookServer = class {
|
|
|
4079
4207
|
if (!this.server) return Promise.resolve();
|
|
4080
4208
|
const server = this.server;
|
|
4081
4209
|
this.server = null;
|
|
4082
|
-
return new Promise((
|
|
4083
|
-
server.close((err) => err ? reject(err) :
|
|
4210
|
+
return new Promise((resolve2, reject) => {
|
|
4211
|
+
server.close((err) => err ? reject(err) : resolve2());
|
|
4084
4212
|
});
|
|
4085
4213
|
}
|
|
4086
4214
|
getListeningPort() {
|
|
@@ -4194,7 +4322,7 @@ var HookServer = class {
|
|
|
4194
4322
|
this.writeJson(res, 200, payload);
|
|
4195
4323
|
}
|
|
4196
4324
|
readBody(req) {
|
|
4197
|
-
return new Promise((
|
|
4325
|
+
return new Promise((resolve2, reject) => {
|
|
4198
4326
|
let body = "";
|
|
4199
4327
|
let size = 0;
|
|
4200
4328
|
req.setEncoding("utf8");
|
|
@@ -4207,7 +4335,7 @@ var HookServer = class {
|
|
|
4207
4335
|
}
|
|
4208
4336
|
body += chunk;
|
|
4209
4337
|
});
|
|
4210
|
-
req.on("end", () =>
|
|
4338
|
+
req.on("end", () => resolve2(body));
|
|
4211
4339
|
req.on("error", reject);
|
|
4212
4340
|
});
|
|
4213
4341
|
}
|
|
@@ -4391,6 +4519,7 @@ async function startService(options) {
|
|
|
4391
4519
|
const relaySend = (data) => relayConnection.sendRaw(data);
|
|
4392
4520
|
const controlHandlers = createControlMessageHandlers(relaySend, sessionManager);
|
|
4393
4521
|
const observerChangeState = (sessionId, next) => changeSessionState(sessionManager, relayConnection, sessionId, next);
|
|
4522
|
+
const observerTouchActivity = (sessionId) => touchSessionActivity(sessionManager, relayConnection, sessionId);
|
|
4394
4523
|
const emitAgentStatus = (sessionId, phase) => {
|
|
4395
4524
|
const session = sessionManager.getSession(sessionId);
|
|
4396
4525
|
if (!session) return;
|
|
@@ -4421,6 +4550,7 @@ async function startService(options) {
|
|
|
4421
4550
|
permissionBroker,
|
|
4422
4551
|
relayConnection,
|
|
4423
4552
|
jsonObserver,
|
|
4553
|
+
touchSessionActivity: observerTouchActivity,
|
|
4424
4554
|
getProviderEnv
|
|
4425
4555
|
});
|
|
4426
4556
|
const hostedPtyRegistry = new HostedPtyRegistry({
|
|
@@ -4428,6 +4558,7 @@ async function startService(options) {
|
|
|
4428
4558
|
relayConnection,
|
|
4429
4559
|
getProviderEnv,
|
|
4430
4560
|
changeSessionState: observerChangeState,
|
|
4561
|
+
touchSessionActivity: observerTouchActivity,
|
|
4431
4562
|
onTurnComplete: (sessionId) => {
|
|
4432
4563
|
resolveInterruptedApprovals(
|
|
4433
4564
|
permissionBroker,
|
|
@@ -4513,7 +4644,7 @@ async function startService(options) {
|
|
|
4513
4644
|
});
|
|
4514
4645
|
});
|
|
4515
4646
|
server.listen(SOCK_PATH, () => {
|
|
4516
|
-
|
|
4647
|
+
writeFileSync6(PID_PATH, String(process.pid));
|
|
4517
4648
|
chmodSync(SOCK_PATH, 384);
|
|
4518
4649
|
serviceLogger.info({ pid: process.pid, sock: SOCK_PATH }, "Service started");
|
|
4519
4650
|
});
|