@dev-anywhere/proxy 0.0.6 → 0.1.1
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 +23 -14
- package/dist/chunk-CDKXSDAV.js +36 -0
- package/dist/chunk-CDKXSDAV.js.map +1 -0
- package/dist/{chunk-VHCL7NVJ.js → chunk-DFLQ3TFT.js} +152 -40
- package/dist/chunk-DFLQ3TFT.js.map +1 -0
- package/dist/{chunk-2XDZRLST.js → chunk-QXOARRC2.js} +2 -2
- package/dist/{chunk-XRTTHTM2.js → chunk-TG7JPHE5.js} +2 -2
- package/dist/index.js +46 -18
- package/dist/index.js.map +1 -1
- package/dist/serve.js +273 -135
- 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-GIU6MXOR.js} +14 -6
- package/dist/terminal-GIU6MXOR.js.map +1 -0
- package/package.json +4 -4
- package/dist/chunk-3XXFLKKG.js +0 -34
- package/dist/chunk-3XXFLKKG.js.map +0 -1
- package/dist/chunk-VHCL7NVJ.js.map +0 -1
- package/dist/terminal-TVPPZQJW.js.map +0 -1
- /package/dist/{chunk-2XDZRLST.js.map → chunk-QXOARRC2.js.map} +0 -0
- /package/dist/{chunk-XRTTHTM2.js.map → chunk-TG7JPHE5.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-QXOARRC2.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-TG7JPHE5.js";
|
|
18
18
|
import {
|
|
19
19
|
spawnScript
|
|
20
20
|
} from "./chunk-ZUWAB67J.js";
|
|
@@ -27,9 +27,12 @@ import {
|
|
|
27
27
|
CONFIG_PATH,
|
|
28
28
|
ControlErrorCode,
|
|
29
29
|
DATA_DIR,
|
|
30
|
+
DEFAULT_PROXY_PROFILE,
|
|
30
31
|
HOOK_REGISTRY_PATH,
|
|
31
32
|
MessageEnvelopeSchema,
|
|
32
33
|
PID_PATH,
|
|
34
|
+
PROFILE_NAME,
|
|
35
|
+
PROXY_ID_PATH,
|
|
33
36
|
SESSIONS_PATH,
|
|
34
37
|
SOCK_PATH,
|
|
35
38
|
STOPPED_PATH,
|
|
@@ -37,15 +40,17 @@ import {
|
|
|
37
40
|
buildMessage,
|
|
38
41
|
createIpcReader,
|
|
39
42
|
createWorkerReader,
|
|
43
|
+
defaultHookPortForProfile,
|
|
44
|
+
ensureProfileWorkspace,
|
|
40
45
|
serializeIpc,
|
|
41
46
|
serializeWorkerMsg,
|
|
42
47
|
sessionPaths,
|
|
43
48
|
tildify
|
|
44
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-DFLQ3TFT.js";
|
|
45
50
|
|
|
46
51
|
// src/serve.ts
|
|
47
52
|
import { createServer as createServer2 } from "net";
|
|
48
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
53
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync6, chmodSync, rmSync as rmSync2 } from "fs";
|
|
49
54
|
|
|
50
55
|
// src/serve/session-manager.ts
|
|
51
56
|
import { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync } from "fs";
|
|
@@ -183,6 +188,14 @@ var SessionManager = class {
|
|
|
183
188
|
serviceLogger.info({ sessionId: id, from: oldState, to: newState }, "Session state changed");
|
|
184
189
|
return true;
|
|
185
190
|
}
|
|
191
|
+
touchSession(id, now = Date.now(), minIntervalMs = 0) {
|
|
192
|
+
const session = this.sessions.get(id);
|
|
193
|
+
if (!session) return false;
|
|
194
|
+
if (now - session.updatedAt < minIntervalMs) return false;
|
|
195
|
+
session.updatedAt = now;
|
|
196
|
+
this.save();
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
186
199
|
terminateSession(id, context) {
|
|
187
200
|
const session = this.sessions.get(id);
|
|
188
201
|
if (!session) {
|
|
@@ -612,31 +625,20 @@ function parsePort(value, source) {
|
|
|
612
625
|
}
|
|
613
626
|
return port;
|
|
614
627
|
}
|
|
615
|
-
function
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
const envName = requestedEnv ?? fromFile.defaultEnv ?? "local";
|
|
624
|
-
const config = fromFile.envs[envName];
|
|
625
|
-
if (!config) {
|
|
626
|
-
const available = Object.keys(fromFile.envs).sort();
|
|
627
|
-
throw new Error(
|
|
628
|
-
`Unknown config env "${envName}". Available envs: ${available.length > 0 ? available.join(", ") : "(none)"}`
|
|
629
|
-
);
|
|
628
|
+
function isRecord(value) {
|
|
629
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
630
|
+
}
|
|
631
|
+
function validateConfigShape(value) {
|
|
632
|
+
if (!isRecord(value) || !isRecord(value.profiles) || !isRecord(value.relays)) {
|
|
633
|
+
throw new Error(`Invalid config shape in ${CONFIG_PATH}: expected "profiles" and "relays".`);
|
|
630
634
|
}
|
|
631
|
-
return
|
|
632
|
-
envName,
|
|
633
|
-
envNameSource: requestedEnv ? "cli" : fromFile.defaultEnv ? "file" : "default",
|
|
634
|
-
config
|
|
635
|
-
};
|
|
635
|
+
return value;
|
|
636
636
|
}
|
|
637
637
|
function readConfigFile() {
|
|
638
|
-
if (!existsSync3(CONFIG_PATH))
|
|
639
|
-
|
|
638
|
+
if (!existsSync3(CONFIG_PATH)) {
|
|
639
|
+
throw new Error(`Dev Anywhere config not found at ${CONFIG_PATH}. Run "dev-anywhere init".`);
|
|
640
|
+
}
|
|
641
|
+
return validateConfigShape(JSON.parse(readFileSync3(CONFIG_PATH, "utf-8")));
|
|
640
642
|
}
|
|
641
643
|
function agentCliField(provider) {
|
|
642
644
|
return provider === "claude" ? "claudeBin" : "codexBin";
|
|
@@ -661,68 +663,71 @@ function uniqueAbsolutePaths(paths) {
|
|
|
661
663
|
}
|
|
662
664
|
return result;
|
|
663
665
|
}
|
|
664
|
-
function
|
|
665
|
-
const
|
|
666
|
-
|
|
667
|
-
|
|
666
|
+
function resolveRelayConfig(fromFile, requestedRelayName) {
|
|
667
|
+
const profile = fromFile.profiles[PROFILE_NAME];
|
|
668
|
+
if (!profile) {
|
|
669
|
+
const available = Object.keys(fromFile.profiles).sort();
|
|
670
|
+
throw new Error(
|
|
671
|
+
`Unknown profile "${PROFILE_NAME}". Available profiles: ${available.length > 0 ? available.join(", ") : "(none)"}`
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
const relayName = requestedRelayName?.trim() || profile.relay?.trim();
|
|
675
|
+
if (!relayName) {
|
|
676
|
+
throw new Error(`Profile "${PROFILE_NAME}" must specify a relay.`);
|
|
677
|
+
}
|
|
678
|
+
const relay = fromFile.relays[relayName];
|
|
679
|
+
if (!relay) {
|
|
680
|
+
const available = Object.keys(fromFile.relays).sort();
|
|
681
|
+
throw new Error(
|
|
682
|
+
`Unknown relay "${relayName}". Available relays: ${available.length > 0 ? available.join(", ") : "(none)"}`
|
|
683
|
+
);
|
|
684
|
+
}
|
|
668
685
|
return {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
686
|
+
relayName,
|
|
687
|
+
relayNameSource: requestedRelayName?.trim() ? "cli" : "profile",
|
|
688
|
+
relay
|
|
672
689
|
};
|
|
673
690
|
}
|
|
674
691
|
function loadConfig(options) {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
serviceLogger.warn(
|
|
681
|
-
{ path: CONFIG_PATH, err: err instanceof Error ? err.message : String(err) },
|
|
682
|
-
"Failed to parse config file, falling back to env-only"
|
|
683
|
-
);
|
|
684
|
-
}
|
|
685
|
-
} else {
|
|
686
|
-
serviceLogger.debug({ path: CONFIG_PATH }, "Config file not found, using env-only");
|
|
687
|
-
}
|
|
688
|
-
const resolved = resolveFileConfig(fromFile, options?.envName);
|
|
689
|
-
const hookPortFromFile = resolved.config.hookPort ?? fromFile.hookPort;
|
|
690
|
-
const claudeBinFromFile = resolved.config.claudeBin ?? fromFile.claudeBin;
|
|
691
|
-
const codexBinFromFile = resolved.config.codexBin ?? fromFile.codexBin;
|
|
692
|
-
const claudeBinHistory = [
|
|
693
|
-
...resolved.config.claudeBinHistory ?? [],
|
|
694
|
-
...fromFile.claudeBinHistory ?? []
|
|
695
|
-
];
|
|
696
|
-
const codexBinHistory = [
|
|
697
|
-
...resolved.config.codexBinHistory ?? [],
|
|
698
|
-
...fromFile.codexBinHistory ?? []
|
|
699
|
-
];
|
|
700
|
-
const claudeBin = process.env.CLAUDE_BIN ?? claudeBinFromFile;
|
|
701
|
-
const codexBin = process.env.CODEX_BIN ?? codexBinFromFile;
|
|
692
|
+
const fromFile = readConfigFile();
|
|
693
|
+
const agentCli = fromFile.agentCli ?? {};
|
|
694
|
+
const resolved = resolveRelayConfig(fromFile, options?.relayName);
|
|
695
|
+
const claudeBin = process.env.CLAUDE_BIN ?? agentCli.claudeBin;
|
|
696
|
+
const codexBin = process.env.CODEX_BIN ?? agentCli.codexBin;
|
|
702
697
|
const config = {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
698
|
+
profileName: PROFILE_NAME,
|
|
699
|
+
relayName: resolved.relayName,
|
|
700
|
+
relayUrl: process.env.RELAY_URL ?? resolved.relay.url,
|
|
701
|
+
relayToken: process.env.RELAY_PROXY_TOKEN ?? resolved.relay.proxyToken,
|
|
702
|
+
hookPort: parsePort(process.env.DEV_ANYWHERE_HOOK_PORT, "DEV_ANYWHERE_HOOK_PORT") ?? defaultHookPortForProfile(PROFILE_NAME),
|
|
707
703
|
claudeBin,
|
|
708
704
|
codexBin,
|
|
709
705
|
agentCliSuggestions: {
|
|
710
|
-
claude: uniqueAbsolutePaths([
|
|
711
|
-
|
|
706
|
+
claude: uniqueAbsolutePaths([
|
|
707
|
+
process.env.CLAUDE_BIN,
|
|
708
|
+
agentCli.claudeBin,
|
|
709
|
+
...agentCli.claudeBinHistory ?? []
|
|
710
|
+
]),
|
|
711
|
+
codex: uniqueAbsolutePaths([
|
|
712
|
+
process.env.CODEX_BIN,
|
|
713
|
+
agentCli.codexBin,
|
|
714
|
+
...agentCli.codexBinHistory ?? []
|
|
715
|
+
])
|
|
712
716
|
},
|
|
713
717
|
sources: {
|
|
714
|
-
|
|
715
|
-
relayUrl: process.env.RELAY_URL ? "env" : resolved.
|
|
716
|
-
relayToken: process.env.RELAY_PROXY_TOKEN ? "env" : resolved.
|
|
717
|
-
hookPort: process.env.DEV_ANYWHERE_HOOK_PORT ? "env" :
|
|
718
|
-
claudeBin: process.env.CLAUDE_BIN ? "env" :
|
|
719
|
-
codexBin: process.env.CODEX_BIN ? "env" :
|
|
718
|
+
relayName: resolved.relayNameSource,
|
|
719
|
+
relayUrl: process.env.RELAY_URL ? "env" : resolved.relay.url ? "file" : "none",
|
|
720
|
+
relayToken: process.env.RELAY_PROXY_TOKEN ? "env" : resolved.relay.proxyToken ? "file" : "none",
|
|
721
|
+
hookPort: process.env.DEV_ANYWHERE_HOOK_PORT ? "env" : "default",
|
|
722
|
+
claudeBin: process.env.CLAUDE_BIN ? "env" : agentCli.claudeBin ? "file" : "none",
|
|
723
|
+
codexBin: process.env.CODEX_BIN ? "env" : agentCli.codexBin ? "file" : "none"
|
|
720
724
|
}
|
|
721
725
|
};
|
|
722
726
|
serviceLogger.info(
|
|
723
727
|
{
|
|
724
|
-
|
|
725
|
-
|
|
728
|
+
profile: config.profileName,
|
|
729
|
+
relayName: config.relayName,
|
|
730
|
+
relayNameSource: config.sources.relayName,
|
|
726
731
|
relayUrl: config.relayUrl ?? "(unset)",
|
|
727
732
|
relayUrlSource: config.sources.relayUrl,
|
|
728
733
|
relayTokenSource: config.sources.relayToken,
|
|
@@ -742,20 +747,20 @@ function buildProviderEnv(config, baseEnv = process.env) {
|
|
|
742
747
|
...config.codexBin ? { CODEX_BIN: config.codexBin } : {}
|
|
743
748
|
};
|
|
744
749
|
}
|
|
745
|
-
function
|
|
750
|
+
function updateAgentCliConfig(config, provider, path) {
|
|
751
|
+
const field = agentCliField(provider);
|
|
752
|
+
const historyField = agentCliHistoryField(provider);
|
|
753
|
+
const history = uniqueAbsolutePaths([path, ...config[historyField] ?? []]).slice(0, 8);
|
|
754
|
+
return {
|
|
755
|
+
...config,
|
|
756
|
+
[field]: path,
|
|
757
|
+
[historyField]: history
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
function saveAgentCliPath(provider, path) {
|
|
746
761
|
const normalized = validateAgentCliPath(path);
|
|
747
762
|
const fromFile = readConfigFile();
|
|
748
|
-
|
|
749
|
-
if (fromFile.envs) {
|
|
750
|
-
const envName = resolved.envName ?? options?.envName ?? fromFile.defaultEnv ?? "local";
|
|
751
|
-
fromFile.envs[envName] = updateAgentCliPathInEnvConfig(
|
|
752
|
-
fromFile.envs[envName] ?? {},
|
|
753
|
-
provider,
|
|
754
|
-
normalized
|
|
755
|
-
);
|
|
756
|
-
} else {
|
|
757
|
-
Object.assign(fromFile, updateAgentCliPathInEnvConfig(fromFile, provider, normalized));
|
|
758
|
-
}
|
|
763
|
+
fromFile.agentCli = updateAgentCliConfig(fromFile.agentCli ?? {}, provider, normalized);
|
|
759
764
|
mkdirSync3(dirname3(CONFIG_PATH), { recursive: true });
|
|
760
765
|
writeFileSync3(CONFIG_PATH, `${JSON.stringify(fromFile, null, 2)}
|
|
761
766
|
`, "utf-8");
|
|
@@ -1078,7 +1083,7 @@ function extractConversationText(msg) {
|
|
|
1078
1083
|
return null;
|
|
1079
1084
|
}
|
|
1080
1085
|
async function extractTitleAndCwd(filePath) {
|
|
1081
|
-
return new Promise((
|
|
1086
|
+
return new Promise((resolve2) => {
|
|
1082
1087
|
const rl = createInterface({
|
|
1083
1088
|
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
1084
1089
|
crlfDelay: Infinity
|
|
@@ -1106,10 +1111,10 @@ async function extractTitleAndCwd(filePath) {
|
|
|
1106
1111
|
}
|
|
1107
1112
|
});
|
|
1108
1113
|
rl.on("close", () => {
|
|
1109
|
-
if (!resolved)
|
|
1110
|
-
else
|
|
1114
|
+
if (!resolved) resolve2({ title, cwd });
|
|
1115
|
+
else resolve2({ title, cwd });
|
|
1111
1116
|
});
|
|
1112
|
-
rl.on("error", () =>
|
|
1117
|
+
rl.on("error", () => resolve2({ title, cwd }));
|
|
1113
1118
|
});
|
|
1114
1119
|
}
|
|
1115
1120
|
async function collectJsonlFiles(root) {
|
|
@@ -1131,7 +1136,7 @@ async function collectJsonlFiles(root) {
|
|
|
1131
1136
|
return files;
|
|
1132
1137
|
}
|
|
1133
1138
|
async function extractCodexTitleAndCwd(filePath) {
|
|
1134
|
-
return new Promise((
|
|
1139
|
+
return new Promise((resolve2) => {
|
|
1135
1140
|
const rl = createInterface({
|
|
1136
1141
|
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
1137
1142
|
crlfDelay: Infinity
|
|
@@ -1155,8 +1160,8 @@ async function extractCodexTitleAndCwd(filePath) {
|
|
|
1155
1160
|
} catch {
|
|
1156
1161
|
}
|
|
1157
1162
|
});
|
|
1158
|
-
rl.on("close", () =>
|
|
1159
|
-
rl.on("error", () =>
|
|
1163
|
+
rl.on("close", () => resolve2({ id, title, cwd }));
|
|
1164
|
+
rl.on("error", () => resolve2({ id, title, cwd }));
|
|
1160
1165
|
});
|
|
1161
1166
|
}
|
|
1162
1167
|
function extractCodexUserText(payload) {
|
|
@@ -1721,16 +1726,16 @@ var WorkerRegistry = class {
|
|
|
1721
1726
|
return workerPid;
|
|
1722
1727
|
}
|
|
1723
1728
|
connect(sessionId, sockPath) {
|
|
1724
|
-
return new Promise((
|
|
1729
|
+
return new Promise((resolve2) => {
|
|
1725
1730
|
const sock = connect(sockPath);
|
|
1726
1731
|
sock.on("connect", () => {
|
|
1727
1732
|
this.sockets.set(sessionId, sock);
|
|
1728
1733
|
createWorkerReader(sock, (msg) => this.handleWorkerMessage(sessionId, msg));
|
|
1729
1734
|
sock.on("close", () => this.onDisconnect(sessionId));
|
|
1730
1735
|
sock.on("error", () => this.onDisconnect(sessionId));
|
|
1731
|
-
|
|
1736
|
+
resolve2(sock);
|
|
1732
1737
|
});
|
|
1733
|
-
sock.on("error", () =>
|
|
1738
|
+
sock.on("error", () => resolve2(null));
|
|
1734
1739
|
});
|
|
1735
1740
|
}
|
|
1736
1741
|
// 枚举 DATA_DIR 下所有 session 目录,尝试连接存活的 worker.sock;失败则清理 stale socket。
|
|
@@ -1856,6 +1861,7 @@ var WorkerRegistry = class {
|
|
|
1856
1861
|
return;
|
|
1857
1862
|
}
|
|
1858
1863
|
const ev = parsed.data;
|
|
1864
|
+
this.deps.touchSessionActivity?.(sessionId);
|
|
1859
1865
|
const isStreamDeltaSession = this.streamDeltaSessions.has(sessionId);
|
|
1860
1866
|
if (ev.type === "stream_event") {
|
|
1861
1867
|
const delta = ContentBlockDeltaSchema.safeParse(ev.event);
|
|
@@ -2053,6 +2059,80 @@ function terminateSessionByOwnership(deps, sessionId) {
|
|
|
2053
2059
|
return { success: false, action: "not_found" };
|
|
2054
2060
|
}
|
|
2055
2061
|
|
|
2062
|
+
// src/serve/clipboard-image-upload.ts
|
|
2063
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
2064
|
+
import { isAbsolute as isAbsolute3, join as join5, relative, resolve } from "path";
|
|
2065
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
2066
|
+
var MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
2067
|
+
var MAX_CLIPBOARD_IMAGE_BASE64_LENGTH = Math.ceil(MAX_CLIPBOARD_IMAGE_BYTES / 3) * 4;
|
|
2068
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
2069
|
+
["image/png", "png"],
|
|
2070
|
+
["image/jpeg", "jpg"],
|
|
2071
|
+
["image/webp", "webp"],
|
|
2072
|
+
["image/gif", "gif"]
|
|
2073
|
+
]);
|
|
2074
|
+
function formatTimestamp(ms) {
|
|
2075
|
+
const [date, time = "000000"] = new Date(ms).toISOString().replace(/\.\d{3}Z$/, "").split("T");
|
|
2076
|
+
return `${date.replace(/-/g, "")}-${time.replace(/:/g, "")}`;
|
|
2077
|
+
}
|
|
2078
|
+
function normalizeBase64(input) {
|
|
2079
|
+
return input.replace(/^data:[^;]+;base64,/i, "").replace(/\s/g, "");
|
|
2080
|
+
}
|
|
2081
|
+
function decodeBase64Image(dataBase64) {
|
|
2082
|
+
const normalized = normalizeBase64(dataBase64);
|
|
2083
|
+
if (normalized.length > MAX_CLIPBOARD_IMAGE_BASE64_LENGTH) {
|
|
2084
|
+
throw new Error("\u56FE\u7247\u8D85\u8FC7 10MB \u9650\u5236");
|
|
2085
|
+
}
|
|
2086
|
+
if (!normalized || !/^[A-Za-z0-9+/]*={0,2}$/.test(normalized)) {
|
|
2087
|
+
throw new Error("\u56FE\u7247\u6570\u636E\u4E0D\u662F\u6709\u6548\u7684 base64");
|
|
2088
|
+
}
|
|
2089
|
+
const buffer = Buffer.from(normalized, "base64");
|
|
2090
|
+
if (buffer.length === 0) throw new Error("\u56FE\u7247\u6570\u636E\u4E3A\u7A7A");
|
|
2091
|
+
if (buffer.length > MAX_CLIPBOARD_IMAGE_BYTES) {
|
|
2092
|
+
throw new Error("\u56FE\u7247\u8D85\u8FC7 10MB \u9650\u5236");
|
|
2093
|
+
}
|
|
2094
|
+
return buffer;
|
|
2095
|
+
}
|
|
2096
|
+
function resolveSessionClipboardDir(dataDir, sessionId) {
|
|
2097
|
+
const root = resolve(dataDir);
|
|
2098
|
+
const uploadDir = resolve(root, sessionId, "clipboard");
|
|
2099
|
+
const relativePath = relative(root, uploadDir);
|
|
2100
|
+
if (!relativePath || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
|
|
2101
|
+
throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
|
|
2102
|
+
}
|
|
2103
|
+
return uploadDir;
|
|
2104
|
+
}
|
|
2105
|
+
function saveClipboardImageUpload(request, options = {}) {
|
|
2106
|
+
const extension = IMAGE_EXTENSIONS.get(request.mimeType);
|
|
2107
|
+
if (!extension) {
|
|
2108
|
+
return {
|
|
2109
|
+
success: false,
|
|
2110
|
+
path: "",
|
|
2111
|
+
error: "\u4E0D\u652F\u6301\u8FD9\u79CD\u56FE\u7247\u683C\u5F0F",
|
|
2112
|
+
errorCode: ControlErrorCode.UNKNOWN
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
try {
|
|
2116
|
+
const dataDir = options.dataDir ?? DATA_DIR;
|
|
2117
|
+
const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
|
|
2118
|
+
const buffer = decodeBase64Image(request.dataBase64);
|
|
2119
|
+
const now = options.now ?? Date.now;
|
|
2120
|
+
const suffix = options.randomSuffix?.() ?? nanoid3(6);
|
|
2121
|
+
const fileName = `pasted-${formatTimestamp(now())}-${suffix}.${extension}`;
|
|
2122
|
+
const path = join5(uploadDir, fileName);
|
|
2123
|
+
mkdirSync4(uploadDir, { recursive: true });
|
|
2124
|
+
writeFileSync4(path, buffer, { mode: 384 });
|
|
2125
|
+
return { success: true, path };
|
|
2126
|
+
} catch (err) {
|
|
2127
|
+
return {
|
|
2128
|
+
success: false,
|
|
2129
|
+
path: "",
|
|
2130
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2131
|
+
errorCode: ControlErrorCode.UNKNOWN
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2056
2136
|
// src/serve/pty-input.ts
|
|
2057
2137
|
function serializeRawPtyInput(sessionId, data) {
|
|
2058
2138
|
return serializeIpc({ type: "pty_input", sessionId, data });
|
|
@@ -2126,6 +2206,42 @@ var RelayInputHandlers = class {
|
|
|
2126
2206
|
ts.write(serializeRawPtyInput(sessionId, data));
|
|
2127
2207
|
serviceLogger.info({ sessionId, bytes: data.length }, "Raw PTY input forwarded");
|
|
2128
2208
|
}
|
|
2209
|
+
onClipboardImageUpload(msg) {
|
|
2210
|
+
const sessionId = msg.sessionId;
|
|
2211
|
+
const requestId = msg.requestId;
|
|
2212
|
+
if (!sessionId) return;
|
|
2213
|
+
const session = this.deps.sessionManager.getSession(sessionId);
|
|
2214
|
+
if (!session) {
|
|
2215
|
+
this.deps.relayConnection.sendRaw(
|
|
2216
|
+
JSON.stringify({
|
|
2217
|
+
type: "clipboard_image_upload_response",
|
|
2218
|
+
requestId,
|
|
2219
|
+
sessionId,
|
|
2220
|
+
success: false,
|
|
2221
|
+
path: "",
|
|
2222
|
+
error: "\u4F1A\u8BDD\u4E0D\u5B58\u5728",
|
|
2223
|
+
errorCode: ControlErrorCode.SESSION_NOT_FOUND
|
|
2224
|
+
})
|
|
2225
|
+
);
|
|
2226
|
+
serviceLogger.warn({ sessionId }, "Clipboard image upload rejected: session not found");
|
|
2227
|
+
return;
|
|
2228
|
+
}
|
|
2229
|
+
const result = saveClipboardImageUpload({
|
|
2230
|
+
sessionId,
|
|
2231
|
+
mimeType: typeof msg.mimeType === "string" ? msg.mimeType : "",
|
|
2232
|
+
dataBase64: typeof msg.dataBase64 === "string" ? msg.dataBase64 : "",
|
|
2233
|
+
fileName: typeof msg.fileName === "string" ? msg.fileName : void 0
|
|
2234
|
+
});
|
|
2235
|
+
this.deps.relayConnection.sendRaw(
|
|
2236
|
+
JSON.stringify({
|
|
2237
|
+
type: "clipboard_image_upload_response",
|
|
2238
|
+
requestId,
|
|
2239
|
+
sessionId,
|
|
2240
|
+
...result
|
|
2241
|
+
})
|
|
2242
|
+
);
|
|
2243
|
+
serviceLogger.info({ sessionId, success: result.success }, "Clipboard image upload handled");
|
|
2244
|
+
}
|
|
2129
2245
|
};
|
|
2130
2246
|
|
|
2131
2247
|
// src/serve/relay-history-handlers.ts
|
|
@@ -2372,7 +2488,7 @@ var RelayResourceHandlers = class {
|
|
|
2372
2488
|
}
|
|
2373
2489
|
try {
|
|
2374
2490
|
const path = validateExecutablePath(rawPath ?? "");
|
|
2375
|
-
saveAgentCliPath(provider, path
|
|
2491
|
+
saveAgentCliPath(provider, path);
|
|
2376
2492
|
this.deps.setAgentCliPath(provider, path);
|
|
2377
2493
|
const agentCli = detectAgentCliStatus(this.deps.getProviderEnv(), {
|
|
2378
2494
|
suggestions: this.deps.getAgentCliSuggestions()
|
|
@@ -2442,8 +2558,8 @@ var RelayResourceHandlers = class {
|
|
|
2442
2558
|
|
|
2443
2559
|
// src/serve/relay-session-create-handler.ts
|
|
2444
2560
|
import { rmSync, statSync as statSync2 } from "fs";
|
|
2445
|
-
import { isAbsolute as
|
|
2446
|
-
import { nanoid as
|
|
2561
|
+
import { isAbsolute as isAbsolute4 } from "path";
|
|
2562
|
+
import { nanoid as nanoid4 } from "nanoid";
|
|
2447
2563
|
|
|
2448
2564
|
// src/serve/hosted-pty-registry.ts
|
|
2449
2565
|
import * as pty from "node-pty";
|
|
@@ -2595,6 +2711,7 @@ var HostedPtyRegistry = class {
|
|
|
2595
2711
|
hosted.lastOutputTime = Date.now();
|
|
2596
2712
|
hosted.outputSeq += 1;
|
|
2597
2713
|
hosted.terminal.write(data);
|
|
2714
|
+
this.deps.touchSessionActivity(sessionId);
|
|
2598
2715
|
this.sendBinary(sessionId, Buffer.from(data, "utf-8"), hosted.outputSeq);
|
|
2599
2716
|
const oscSequences = extractOscSequences(data);
|
|
2600
2717
|
const session = this.deps.sessionManager.getSession(sessionId);
|
|
@@ -2731,7 +2848,7 @@ function validateSessionCwd(cwd) {
|
|
|
2731
2848
|
return { message: "\u8BF7\u8F93\u5165\u5DE5\u4F5C\u76EE\u5F55", code: ControlErrorCode.INVALID_PATH };
|
|
2732
2849
|
}
|
|
2733
2850
|
const trimmed = cwd.trim();
|
|
2734
|
-
if (!
|
|
2851
|
+
if (!isAbsolute4(trimmed)) {
|
|
2735
2852
|
return { message: "\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84", code: ControlErrorCode.INVALID_PATH };
|
|
2736
2853
|
}
|
|
2737
2854
|
try {
|
|
@@ -2790,7 +2907,7 @@ var RelaySessionCreateHandler = class {
|
|
|
2790
2907
|
const resumeSessionId = msg.resumeSessionId;
|
|
2791
2908
|
const streamDelta = msg.streamDelta === true;
|
|
2792
2909
|
const name = tildify(sessionCwd);
|
|
2793
|
-
const pendingId =
|
|
2910
|
+
const pendingId = nanoid4();
|
|
2794
2911
|
const hook = this.deps.createHookContext(pendingId, provider);
|
|
2795
2912
|
const workerPid = this.deps.workerRegistry.spawn(pendingId, {
|
|
2796
2913
|
cwd: sessionCwd,
|
|
@@ -2875,7 +2992,7 @@ var RelaySessionCreateHandler = class {
|
|
|
2875
2992
|
return;
|
|
2876
2993
|
}
|
|
2877
2994
|
const resumeSessionId = msg.resumeSessionId;
|
|
2878
|
-
const pendingId =
|
|
2995
|
+
const pendingId = nanoid4();
|
|
2879
2996
|
const name = tildify(cwd);
|
|
2880
2997
|
const hook = this.deps.createHookContext(pendingId, provider);
|
|
2881
2998
|
try {
|
|
@@ -2990,7 +3107,6 @@ var RelayRouter = class {
|
|
|
2990
3107
|
relaySend: deps.relaySend,
|
|
2991
3108
|
controlHandlers: deps.controlHandlers,
|
|
2992
3109
|
sessionManager: deps.sessionManager,
|
|
2993
|
-
envName: deps.envName,
|
|
2994
3110
|
getProviderEnv: deps.getProviderEnv,
|
|
2995
3111
|
getAgentCliSuggestions: deps.getAgentCliSuggestions,
|
|
2996
3112
|
setAgentCliPath: deps.setAgentCliPath
|
|
@@ -3042,6 +3158,7 @@ var RelayRouter = class {
|
|
|
3042
3158
|
handlers = {
|
|
3043
3159
|
user_input: (msg) => this.inputHandlers.onUserInput(msg),
|
|
3044
3160
|
remote_input_raw: (msg) => this.inputHandlers.onRemoteInputRaw(msg),
|
|
3161
|
+
clipboard_image_upload: (msg) => this.inputHandlers.onClipboardImageUpload(msg),
|
|
3045
3162
|
tool_approve: (msg) => this.permissionHandlers.onToolApprove(msg),
|
|
3046
3163
|
tool_deny: (msg) => this.permissionHandlers.onToolDeny(msg),
|
|
3047
3164
|
proxy_info_request: (msg) => this.resourceHandlers.onProxyInfoRequest(msg),
|
|
@@ -3232,11 +3349,11 @@ var PermissionBroker = class {
|
|
|
3232
3349
|
message: "Duplicate permission request id."
|
|
3233
3350
|
});
|
|
3234
3351
|
}
|
|
3235
|
-
return new Promise((
|
|
3352
|
+
return new Promise((resolve2) => {
|
|
3236
3353
|
this.pending.set(request.requestId, {
|
|
3237
3354
|
...request,
|
|
3238
3355
|
source: "hook",
|
|
3239
|
-
resolve,
|
|
3356
|
+
resolve: resolve2,
|
|
3240
3357
|
createdAt: Date.now()
|
|
3241
3358
|
});
|
|
3242
3359
|
});
|
|
@@ -3460,6 +3577,7 @@ var AgentStatusRegistry = class {
|
|
|
3460
3577
|
};
|
|
3461
3578
|
|
|
3462
3579
|
// src/serve/session-broadcast.ts
|
|
3580
|
+
var ACTIVITY_STATUS_PUSH_INTERVAL_MS = 15e3;
|
|
3463
3581
|
function toSessionListPayload(s) {
|
|
3464
3582
|
return {
|
|
3465
3583
|
sessionId: s.id,
|
|
@@ -3522,6 +3640,11 @@ function changeSessionState(sessionManager, relay, sessionId, next) {
|
|
|
3522
3640
|
if (changed) pushSessionStatus(relay, sessionManager, sessionId);
|
|
3523
3641
|
return changed;
|
|
3524
3642
|
}
|
|
3643
|
+
function touchSessionActivity(sessionManager, relay, sessionId, now = Date.now()) {
|
|
3644
|
+
const touched = sessionManager.touchSession(sessionId, now, ACTIVITY_STATUS_PUSH_INTERVAL_MS);
|
|
3645
|
+
if (touched) pushSessionStatus(relay, sessionManager, sessionId);
|
|
3646
|
+
return touched;
|
|
3647
|
+
}
|
|
3525
3648
|
|
|
3526
3649
|
// src/serve/service-files.ts
|
|
3527
3650
|
import { execSync } from "child_process";
|
|
@@ -3529,10 +3652,10 @@ import { existsSync as existsSync5, readFileSync as readFileSync5, unlinkSync as
|
|
|
3529
3652
|
import { hostname } from "os";
|
|
3530
3653
|
import { connect as connect2 } from "net";
|
|
3531
3654
|
function tryConnectSocket(sockPath) {
|
|
3532
|
-
return new Promise((
|
|
3655
|
+
return new Promise((resolve2) => {
|
|
3533
3656
|
const s = connect2(sockPath);
|
|
3534
|
-
s.on("connect", () =>
|
|
3535
|
-
s.on("error", () =>
|
|
3657
|
+
s.on("connect", () => resolve2(s));
|
|
3658
|
+
s.on("error", () => resolve2(null));
|
|
3536
3659
|
});
|
|
3537
3660
|
}
|
|
3538
3661
|
function isProcessAlive(pid) {
|
|
@@ -3569,8 +3692,13 @@ async function cleanupStaleResources() {
|
|
|
3569
3692
|
serviceLogger.info("Removed stale PID file");
|
|
3570
3693
|
}
|
|
3571
3694
|
}
|
|
3695
|
+
function formatProxyNameForProfile(baseName, profileName = PROFILE_NAME) {
|
|
3696
|
+
return profileName === DEFAULT_PROXY_PROFILE ? baseName : `${baseName} (${profileName})`;
|
|
3697
|
+
}
|
|
3572
3698
|
function getProxyName() {
|
|
3573
|
-
|
|
3699
|
+
const explicitName = process.env.DEV_ANYWHERE_PROXY_NAME?.trim();
|
|
3700
|
+
if (explicitName) return explicitName;
|
|
3701
|
+
return formatProxyNameForProfile(getComputerName() || hostname());
|
|
3574
3702
|
}
|
|
3575
3703
|
function getComputerName() {
|
|
3576
3704
|
try {
|
|
@@ -3876,6 +4004,7 @@ function handleTerminalConnection(socket, deps) {
|
|
|
3876
4004
|
},
|
|
3877
4005
|
(sessionId, data, outputSeq) => {
|
|
3878
4006
|
if (!sessionManager.getSession(sessionId)) return;
|
|
4007
|
+
touchSessionActivity(sessionManager, relayConnection, sessionId);
|
|
3879
4008
|
const sessionIdBuf = Buffer.from(sessionId, "utf-8");
|
|
3880
4009
|
const wsFrame = Buffer.alloc(1 + sessionIdBuf.length + 4 + data.length);
|
|
3881
4010
|
wsFrame[0] = sessionIdBuf.length;
|
|
@@ -3926,7 +4055,7 @@ function handleTerminalConnection(socket, deps) {
|
|
|
3926
4055
|
|
|
3927
4056
|
// src/serve/hook-registry.ts
|
|
3928
4057
|
import { createHash, randomBytes } from "crypto";
|
|
3929
|
-
import { existsSync as existsSync6, mkdirSync as
|
|
4058
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
3930
4059
|
import { dirname as dirname4 } from "path";
|
|
3931
4060
|
import { z } from "zod";
|
|
3932
4061
|
var PersistedHookSessionBindingSchema = z.object({
|
|
@@ -4006,9 +4135,9 @@ var HookRegistry = class {
|
|
|
4006
4135
|
save() {
|
|
4007
4136
|
if (!this.persistPath) return;
|
|
4008
4137
|
try {
|
|
4009
|
-
|
|
4138
|
+
mkdirSync5(dirname4(this.persistPath), { recursive: true });
|
|
4010
4139
|
const tmpPath = `${this.persistPath}.${process.pid}.${Date.now()}.tmp`;
|
|
4011
|
-
|
|
4140
|
+
writeFileSync5(
|
|
4012
4141
|
tmpPath,
|
|
4013
4142
|
JSON.stringify(
|
|
4014
4143
|
{
|
|
@@ -4060,7 +4189,7 @@ var HookServer = class {
|
|
|
4060
4189
|
this.writeJson(res, 500, { error: "internal_error" });
|
|
4061
4190
|
});
|
|
4062
4191
|
});
|
|
4063
|
-
return new Promise((
|
|
4192
|
+
return new Promise((resolve2, reject) => {
|
|
4064
4193
|
const onError = (err) => {
|
|
4065
4194
|
this.server?.off("listening", onListening);
|
|
4066
4195
|
reject(err);
|
|
@@ -4068,7 +4197,7 @@ var HookServer = class {
|
|
|
4068
4197
|
const onListening = () => {
|
|
4069
4198
|
this.server?.off("error", onError);
|
|
4070
4199
|
serviceLogger.info({ host: this.host, port: this.options.port }, "Hook server listening");
|
|
4071
|
-
|
|
4200
|
+
resolve2();
|
|
4072
4201
|
};
|
|
4073
4202
|
this.server.once("error", onError);
|
|
4074
4203
|
this.server.once("listening", onListening);
|
|
@@ -4079,8 +4208,8 @@ var HookServer = class {
|
|
|
4079
4208
|
if (!this.server) return Promise.resolve();
|
|
4080
4209
|
const server = this.server;
|
|
4081
4210
|
this.server = null;
|
|
4082
|
-
return new Promise((
|
|
4083
|
-
server.close((err) => err ? reject(err) :
|
|
4211
|
+
return new Promise((resolve2, reject) => {
|
|
4212
|
+
server.close((err) => err ? reject(err) : resolve2());
|
|
4084
4213
|
});
|
|
4085
4214
|
}
|
|
4086
4215
|
getListeningPort() {
|
|
@@ -4194,7 +4323,7 @@ var HookServer = class {
|
|
|
4194
4323
|
this.writeJson(res, 200, payload);
|
|
4195
4324
|
}
|
|
4196
4325
|
readBody(req) {
|
|
4197
|
-
return new Promise((
|
|
4326
|
+
return new Promise((resolve2, reject) => {
|
|
4198
4327
|
let body = "";
|
|
4199
4328
|
let size = 0;
|
|
4200
4329
|
req.setEncoding("utf8");
|
|
@@ -4207,7 +4336,7 @@ var HookServer = class {
|
|
|
4207
4336
|
}
|
|
4208
4337
|
body += chunk;
|
|
4209
4338
|
});
|
|
4210
|
-
req.on("end", () =>
|
|
4339
|
+
req.on("end", () => resolve2(body));
|
|
4211
4340
|
req.on("error", reject);
|
|
4212
4341
|
});
|
|
4213
4342
|
}
|
|
@@ -4306,24 +4435,25 @@ function parseServiceOptions(argv) {
|
|
|
4306
4435
|
const options = {};
|
|
4307
4436
|
for (let i = 0; i < argv.length; i++) {
|
|
4308
4437
|
const arg = argv[i];
|
|
4309
|
-
if (arg === "--
|
|
4310
|
-
const
|
|
4311
|
-
if (!
|
|
4312
|
-
throw new Error("Missing value for --
|
|
4438
|
+
if (arg === "--relay") {
|
|
4439
|
+
const relayName = argv[i + 1];
|
|
4440
|
+
if (!relayName || relayName.startsWith("-")) {
|
|
4441
|
+
throw new Error("Missing value for --relay");
|
|
4313
4442
|
}
|
|
4314
|
-
options.
|
|
4443
|
+
options.relayName = relayName;
|
|
4315
4444
|
i++;
|
|
4316
4445
|
continue;
|
|
4317
4446
|
}
|
|
4318
|
-
if (arg.startsWith("--
|
|
4319
|
-
const
|
|
4320
|
-
if (!
|
|
4321
|
-
options.
|
|
4447
|
+
if (arg.startsWith("--relay=")) {
|
|
4448
|
+
const relayName = arg.slice("--relay=".length);
|
|
4449
|
+
if (!relayName) throw new Error("Missing value for --relay");
|
|
4450
|
+
options.relayName = relayName;
|
|
4322
4451
|
}
|
|
4323
4452
|
}
|
|
4324
4453
|
return options;
|
|
4325
4454
|
}
|
|
4326
4455
|
async function startService(options) {
|
|
4456
|
+
ensureProfileWorkspace();
|
|
4327
4457
|
await cleanupStaleResources();
|
|
4328
4458
|
try {
|
|
4329
4459
|
unlinkSync3(STOPPED_PATH);
|
|
@@ -4351,7 +4481,7 @@ async function startService(options) {
|
|
|
4351
4481
|
sessionManager.startReaper();
|
|
4352
4482
|
const terminalSockets = /* @__PURE__ */ new Map();
|
|
4353
4483
|
const proxyName = getProxyName();
|
|
4354
|
-
let proxyConfig = loadConfig({
|
|
4484
|
+
let proxyConfig = loadConfig({ relayName: options?.relayName });
|
|
4355
4485
|
const getProviderEnv = () => buildProviderEnv(proxyConfig, process.env);
|
|
4356
4486
|
const getAgentCliSuggestions = () => proxyConfig.agentCliSuggestions;
|
|
4357
4487
|
const setAgentCliPath = (provider, path) => {
|
|
@@ -4373,8 +4503,9 @@ async function startService(options) {
|
|
|
4373
4503
|
const relayUrl = options?.relayUrl ?? proxyConfig.relayUrl;
|
|
4374
4504
|
const relayToken = proxyConfig.relayToken;
|
|
4375
4505
|
const statusConfig = {
|
|
4376
|
-
|
|
4377
|
-
|
|
4506
|
+
profile: PROFILE_NAME,
|
|
4507
|
+
relayName: proxyConfig.relayName,
|
|
4508
|
+
relayNameSource: proxyConfig.sources.relayName,
|
|
4378
4509
|
relayUrl,
|
|
4379
4510
|
relayUrlSource: proxyConfig.sources.relayUrl,
|
|
4380
4511
|
relayTokenSource: proxyConfig.sources.relayToken,
|
|
@@ -4382,15 +4513,20 @@ async function startService(options) {
|
|
|
4382
4513
|
hookPortSource: proxyConfig.sources.hookPort
|
|
4383
4514
|
};
|
|
4384
4515
|
if (!relayUrl) {
|
|
4385
|
-
const msg =
|
|
4516
|
+
const msg = `Relay URL is required. Set relays.${proxyConfig.relayName}.url in ~/.dev-anywhere/config.json or pass --relay <name>.`;
|
|
4386
4517
|
serviceLogger.error(msg);
|
|
4387
4518
|
console.error(msg);
|
|
4388
4519
|
process.exit(1);
|
|
4389
4520
|
}
|
|
4390
|
-
const relayConnection = new RelayConnection(relayUrl, {
|
|
4521
|
+
const relayConnection = new RelayConnection(relayUrl, {
|
|
4522
|
+
name: proxyName,
|
|
4523
|
+
token: relayToken,
|
|
4524
|
+
proxyIdPath: PROXY_ID_PATH
|
|
4525
|
+
});
|
|
4391
4526
|
const relaySend = (data) => relayConnection.sendRaw(data);
|
|
4392
4527
|
const controlHandlers = createControlMessageHandlers(relaySend, sessionManager);
|
|
4393
4528
|
const observerChangeState = (sessionId, next) => changeSessionState(sessionManager, relayConnection, sessionId, next);
|
|
4529
|
+
const observerTouchActivity = (sessionId) => touchSessionActivity(sessionManager, relayConnection, sessionId);
|
|
4394
4530
|
const emitAgentStatus = (sessionId, phase) => {
|
|
4395
4531
|
const session = sessionManager.getSession(sessionId);
|
|
4396
4532
|
if (!session) return;
|
|
@@ -4421,6 +4557,7 @@ async function startService(options) {
|
|
|
4421
4557
|
permissionBroker,
|
|
4422
4558
|
relayConnection,
|
|
4423
4559
|
jsonObserver,
|
|
4560
|
+
touchSessionActivity: observerTouchActivity,
|
|
4424
4561
|
getProviderEnv
|
|
4425
4562
|
});
|
|
4426
4563
|
const hostedPtyRegistry = new HostedPtyRegistry({
|
|
@@ -4428,6 +4565,7 @@ async function startService(options) {
|
|
|
4428
4565
|
relayConnection,
|
|
4429
4566
|
getProviderEnv,
|
|
4430
4567
|
changeSessionState: observerChangeState,
|
|
4568
|
+
touchSessionActivity: observerTouchActivity,
|
|
4431
4569
|
onTurnComplete: (sessionId) => {
|
|
4432
4570
|
resolveInterruptedApprovals(
|
|
4433
4571
|
permissionBroker,
|
|
@@ -4446,7 +4584,8 @@ async function startService(options) {
|
|
|
4446
4584
|
relayConnection.connect();
|
|
4447
4585
|
serviceLogger.info(
|
|
4448
4586
|
{
|
|
4449
|
-
|
|
4587
|
+
relayName: proxyConfig.relayName,
|
|
4588
|
+
profile: PROFILE_NAME,
|
|
4450
4589
|
relayUrl,
|
|
4451
4590
|
proxyName,
|
|
4452
4591
|
tokenSet: !!relayToken,
|
|
@@ -4470,7 +4609,6 @@ async function startService(options) {
|
|
|
4470
4609
|
permissionBroker,
|
|
4471
4610
|
hookEventRouter: hookRuntime.hookEventRouter,
|
|
4472
4611
|
agentStatusRegistry,
|
|
4473
|
-
envName: proxyConfig.envName,
|
|
4474
4612
|
getProviderEnv,
|
|
4475
4613
|
getAgentCliSuggestions,
|
|
4476
4614
|
setAgentCliPath
|
|
@@ -4513,7 +4651,7 @@ async function startService(options) {
|
|
|
4513
4651
|
});
|
|
4514
4652
|
});
|
|
4515
4653
|
server.listen(SOCK_PATH, () => {
|
|
4516
|
-
|
|
4654
|
+
writeFileSync6(PID_PATH, String(process.pid));
|
|
4517
4655
|
chmodSync(SOCK_PATH, 384);
|
|
4518
4656
|
serviceLogger.info({ pid: process.pid, sock: SOCK_PATH }, "Service started");
|
|
4519
4657
|
});
|