@dev-anywhere/proxy 0.1.0 → 0.1.2
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 +21 -13
- package/dist/chunk-CDKXSDAV.js +36 -0
- package/dist/chunk-CDKXSDAV.js.map +1 -0
- package/dist/{chunk-QWPI6YON.js → chunk-DFLQ3TFT.js} +137 -40
- package/dist/chunk-DFLQ3TFT.js.map +1 -0
- package/dist/{chunk-JPJMOVQ5.js → chunk-QXOARRC2.js} +2 -2
- package/dist/{chunk-WXWH6L7J.js → chunk-TG7JPHE5.js} +2 -2
- package/dist/index.js +46 -18
- package/dist/index.js.map +1 -1
- package/dist/serve.js +181 -127
- package/dist/serve.js.map +1 -1
- package/dist/session-worker.js +2 -2
- package/dist/{terminal-ZPPKNAL4.js → terminal-GIU6MXOR.js} +14 -6
- package/dist/terminal-GIU6MXOR.js.map +1 -0
- package/package.json +3 -3
- package/dist/chunk-7PXDRNLY.js +0 -34
- package/dist/chunk-7PXDRNLY.js.map +0 -1
- package/dist/chunk-QWPI6YON.js.map +0 -1
- package/dist/terminal-ZPPKNAL4.js.map +0 -1
- /package/dist/{chunk-JPJMOVQ5.js.map → chunk-QXOARRC2.js.map} +0 -0
- /package/dist/{chunk-WXWH6L7J.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,11 +40,13 @@ 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";
|
|
@@ -620,31 +625,20 @@ function parsePort(value, source) {
|
|
|
620
625
|
}
|
|
621
626
|
return port;
|
|
622
627
|
}
|
|
623
|
-
function
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
const envName = requestedEnv ?? fromFile.defaultEnv ?? "local";
|
|
632
|
-
const config = fromFile.envs[envName];
|
|
633
|
-
if (!config) {
|
|
634
|
-
const available = Object.keys(fromFile.envs).sort();
|
|
635
|
-
throw new Error(
|
|
636
|
-
`Unknown config env "${envName}". Available envs: ${available.length > 0 ? available.join(", ") : "(none)"}`
|
|
637
|
-
);
|
|
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".`);
|
|
638
634
|
}
|
|
639
|
-
return
|
|
640
|
-
envName,
|
|
641
|
-
envNameSource: requestedEnv ? "cli" : fromFile.defaultEnv ? "file" : "default",
|
|
642
|
-
config
|
|
643
|
-
};
|
|
635
|
+
return value;
|
|
644
636
|
}
|
|
645
637
|
function readConfigFile() {
|
|
646
|
-
if (!existsSync3(CONFIG_PATH))
|
|
647
|
-
|
|
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")));
|
|
648
642
|
}
|
|
649
643
|
function agentCliField(provider) {
|
|
650
644
|
return provider === "claude" ? "claudeBin" : "codexBin";
|
|
@@ -669,68 +663,71 @@ function uniqueAbsolutePaths(paths) {
|
|
|
669
663
|
}
|
|
670
664
|
return result;
|
|
671
665
|
}
|
|
672
|
-
function
|
|
673
|
-
const
|
|
674
|
-
|
|
675
|
-
|
|
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
|
+
}
|
|
676
685
|
return {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
686
|
+
relayName,
|
|
687
|
+
relayNameSource: requestedRelayName?.trim() ? "cli" : "profile",
|
|
688
|
+
relay
|
|
680
689
|
};
|
|
681
690
|
}
|
|
682
691
|
function loadConfig(options) {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
serviceLogger.warn(
|
|
689
|
-
{ path: CONFIG_PATH, err: err instanceof Error ? err.message : String(err) },
|
|
690
|
-
"Failed to parse config file, falling back to env-only"
|
|
691
|
-
);
|
|
692
|
-
}
|
|
693
|
-
} else {
|
|
694
|
-
serviceLogger.debug({ path: CONFIG_PATH }, "Config file not found, using env-only");
|
|
695
|
-
}
|
|
696
|
-
const resolved = resolveFileConfig(fromFile, options?.envName);
|
|
697
|
-
const hookPortFromFile = resolved.config.hookPort ?? fromFile.hookPort;
|
|
698
|
-
const claudeBinFromFile = resolved.config.claudeBin ?? fromFile.claudeBin;
|
|
699
|
-
const codexBinFromFile = resolved.config.codexBin ?? fromFile.codexBin;
|
|
700
|
-
const claudeBinHistory = [
|
|
701
|
-
...resolved.config.claudeBinHistory ?? [],
|
|
702
|
-
...fromFile.claudeBinHistory ?? []
|
|
703
|
-
];
|
|
704
|
-
const codexBinHistory = [
|
|
705
|
-
...resolved.config.codexBinHistory ?? [],
|
|
706
|
-
...fromFile.codexBinHistory ?? []
|
|
707
|
-
];
|
|
708
|
-
const claudeBin = process.env.CLAUDE_BIN ?? claudeBinFromFile;
|
|
709
|
-
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;
|
|
710
697
|
const config = {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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),
|
|
715
703
|
claudeBin,
|
|
716
704
|
codexBin,
|
|
717
705
|
agentCliSuggestions: {
|
|
718
|
-
claude: uniqueAbsolutePaths([
|
|
719
|
-
|
|
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
|
+
])
|
|
720
716
|
},
|
|
721
717
|
sources: {
|
|
722
|
-
|
|
723
|
-
relayUrl: process.env.RELAY_URL ? "env" : resolved.
|
|
724
|
-
relayToken: process.env.RELAY_PROXY_TOKEN ? "env" : resolved.
|
|
725
|
-
hookPort: process.env.DEV_ANYWHERE_HOOK_PORT ? "env" :
|
|
726
|
-
claudeBin: process.env.CLAUDE_BIN ? "env" :
|
|
727
|
-
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"
|
|
728
724
|
}
|
|
729
725
|
};
|
|
730
726
|
serviceLogger.info(
|
|
731
727
|
{
|
|
732
|
-
|
|
733
|
-
|
|
728
|
+
profile: config.profileName,
|
|
729
|
+
relayName: config.relayName,
|
|
730
|
+
relayNameSource: config.sources.relayName,
|
|
734
731
|
relayUrl: config.relayUrl ?? "(unset)",
|
|
735
732
|
relayUrlSource: config.sources.relayUrl,
|
|
736
733
|
relayTokenSource: config.sources.relayToken,
|
|
@@ -750,20 +747,20 @@ function buildProviderEnv(config, baseEnv = process.env) {
|
|
|
750
747
|
...config.codexBin ? { CODEX_BIN: config.codexBin } : {}
|
|
751
748
|
};
|
|
752
749
|
}
|
|
753
|
-
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) {
|
|
754
761
|
const normalized = validateAgentCliPath(path);
|
|
755
762
|
const fromFile = readConfigFile();
|
|
756
|
-
|
|
757
|
-
if (fromFile.envs) {
|
|
758
|
-
const envName = resolved.envName ?? options?.envName ?? fromFile.defaultEnv ?? "local";
|
|
759
|
-
fromFile.envs[envName] = updateAgentCliPathInEnvConfig(
|
|
760
|
-
fromFile.envs[envName] ?? {},
|
|
761
|
-
provider,
|
|
762
|
-
normalized
|
|
763
|
-
);
|
|
764
|
-
} else {
|
|
765
|
-
Object.assign(fromFile, updateAgentCliPathInEnvConfig(fromFile, provider, normalized));
|
|
766
|
-
}
|
|
763
|
+
fromFile.agentCli = updateAgentCliConfig(fromFile.agentCli ?? {}, provider, normalized);
|
|
767
764
|
mkdirSync3(dirname3(CONFIG_PATH), { recursive: true });
|
|
768
765
|
writeFileSync3(CONFIG_PATH, `${JSON.stringify(fromFile, null, 2)}
|
|
769
766
|
`, "utf-8");
|
|
@@ -2063,7 +2060,7 @@ function terminateSessionByOwnership(deps, sessionId) {
|
|
|
2063
2060
|
}
|
|
2064
2061
|
|
|
2065
2062
|
// src/serve/clipboard-image-upload.ts
|
|
2066
|
-
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
2063
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
2067
2064
|
import { isAbsolute as isAbsolute3, join as join5, relative, resolve } from "path";
|
|
2068
2065
|
import { nanoid as nanoid3 } from "nanoid";
|
|
2069
2066
|
var MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
@@ -2096,15 +2093,50 @@ function decodeBase64Image(dataBase64) {
|
|
|
2096
2093
|
}
|
|
2097
2094
|
return buffer;
|
|
2098
2095
|
}
|
|
2099
|
-
function
|
|
2100
|
-
const root = resolve(
|
|
2101
|
-
const uploadDir = resolve(root,
|
|
2096
|
+
function resolveChildDir(rootPath, ...segments) {
|
|
2097
|
+
const root = resolve(rootPath);
|
|
2098
|
+
const uploadDir = resolve(root, ...segments);
|
|
2102
2099
|
const relativePath = relative(root, uploadDir);
|
|
2103
2100
|
if (!relativePath || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
|
|
2104
2101
|
throw new Error("\u4F1A\u8BDD\u8DEF\u5F84\u65E0\u6548");
|
|
2105
2102
|
}
|
|
2106
2103
|
return uploadDir;
|
|
2107
2104
|
}
|
|
2105
|
+
function resolveSessionClipboardDir(dataDir, sessionId) {
|
|
2106
|
+
return resolveChildDir(dataDir, sessionId, "clipboard");
|
|
2107
|
+
}
|
|
2108
|
+
function normalizeGitignoreLine(line) {
|
|
2109
|
+
return line.trim().replace(/^\/+/, "").replace(/\/+$/, "");
|
|
2110
|
+
}
|
|
2111
|
+
function ensureProjectClipboardIgnored(cwd) {
|
|
2112
|
+
const gitignorePath = join5(cwd, ".gitignore");
|
|
2113
|
+
if (!existsSync5(gitignorePath)) return;
|
|
2114
|
+
try {
|
|
2115
|
+
const current = readFileSync5(gitignorePath, "utf-8");
|
|
2116
|
+
const alreadyIgnored = current.split(/\r?\n/).some((line) => normalizeGitignoreLine(line) === ".dev-anywhere");
|
|
2117
|
+
if (alreadyIgnored) return;
|
|
2118
|
+
const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
2119
|
+
writeFileSync4(gitignorePath, `${current}${separator}.dev-anywhere/
|
|
2120
|
+
`);
|
|
2121
|
+
} catch {
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
function trySaveProjectClipboardImage(options) {
|
|
2125
|
+
if (!options.cwd) return null;
|
|
2126
|
+
try {
|
|
2127
|
+
const cwd = resolve(options.cwd);
|
|
2128
|
+
if (!statSync(cwd).isDirectory()) return null;
|
|
2129
|
+
const clipboardRoot = resolve(cwd, ".dev-anywhere", "clipboard");
|
|
2130
|
+
const uploadDir = resolveChildDir(clipboardRoot, options.sessionId);
|
|
2131
|
+
const path = join5(uploadDir, options.fileName);
|
|
2132
|
+
mkdirSync4(uploadDir, { recursive: true });
|
|
2133
|
+
writeFileSync4(path, options.buffer, { mode: 384 });
|
|
2134
|
+
ensureProjectClipboardIgnored(cwd);
|
|
2135
|
+
return { success: true, path: relative(cwd, path) };
|
|
2136
|
+
} catch {
|
|
2137
|
+
return null;
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2108
2140
|
function saveClipboardImageUpload(request, options = {}) {
|
|
2109
2141
|
const extension = IMAGE_EXTENSIONS.get(request.mimeType);
|
|
2110
2142
|
if (!extension) {
|
|
@@ -2116,12 +2148,19 @@ function saveClipboardImageUpload(request, options = {}) {
|
|
|
2116
2148
|
};
|
|
2117
2149
|
}
|
|
2118
2150
|
try {
|
|
2119
|
-
const dataDir = options.dataDir ?? DATA_DIR;
|
|
2120
|
-
const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
|
|
2121
2151
|
const buffer = decodeBase64Image(request.dataBase64);
|
|
2122
2152
|
const now = options.now ?? Date.now;
|
|
2123
2153
|
const suffix = options.randomSuffix?.() ?? nanoid3(6);
|
|
2124
2154
|
const fileName = `pasted-${formatTimestamp(now())}-${suffix}.${extension}`;
|
|
2155
|
+
const projectResult = trySaveProjectClipboardImage({
|
|
2156
|
+
cwd: options.cwd,
|
|
2157
|
+
sessionId: request.sessionId,
|
|
2158
|
+
fileName,
|
|
2159
|
+
buffer
|
|
2160
|
+
});
|
|
2161
|
+
if (projectResult) return projectResult;
|
|
2162
|
+
const dataDir = options.dataDir ?? DATA_DIR;
|
|
2163
|
+
const uploadDir = resolveSessionClipboardDir(dataDir, request.sessionId);
|
|
2125
2164
|
const path = join5(uploadDir, fileName);
|
|
2126
2165
|
mkdirSync4(uploadDir, { recursive: true });
|
|
2127
2166
|
writeFileSync4(path, buffer, { mode: 384 });
|
|
@@ -2229,12 +2268,17 @@ var RelayInputHandlers = class {
|
|
|
2229
2268
|
serviceLogger.warn({ sessionId }, "Clipboard image upload rejected: session not found");
|
|
2230
2269
|
return;
|
|
2231
2270
|
}
|
|
2232
|
-
const result = saveClipboardImageUpload(
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2271
|
+
const result = saveClipboardImageUpload(
|
|
2272
|
+
{
|
|
2273
|
+
sessionId,
|
|
2274
|
+
mimeType: typeof msg.mimeType === "string" ? msg.mimeType : "",
|
|
2275
|
+
dataBase64: typeof msg.dataBase64 === "string" ? msg.dataBase64 : "",
|
|
2276
|
+
fileName: typeof msg.fileName === "string" ? msg.fileName : void 0
|
|
2277
|
+
},
|
|
2278
|
+
{
|
|
2279
|
+
cwd: session.cwd
|
|
2280
|
+
}
|
|
2281
|
+
);
|
|
2238
2282
|
this.deps.relayConnection.sendRaw(
|
|
2239
2283
|
JSON.stringify({
|
|
2240
2284
|
type: "clipboard_image_upload_response",
|
|
@@ -2444,14 +2488,14 @@ var RelayPermissionHandlers = class {
|
|
|
2444
2488
|
|
|
2445
2489
|
// src/serve/relay-resource-handlers.ts
|
|
2446
2490
|
import { homedir as homedir4 } from "os";
|
|
2447
|
-
import { accessSync, constants, statSync } from "fs";
|
|
2491
|
+
import { accessSync, constants, statSync as statSync2 } from "fs";
|
|
2448
2492
|
function errorMessage(err) {
|
|
2449
2493
|
return err instanceof Error ? err.message : String(err);
|
|
2450
2494
|
}
|
|
2451
2495
|
function validateExecutablePath(path) {
|
|
2452
2496
|
const normalized = path.trim();
|
|
2453
2497
|
if (!normalized.startsWith("/")) throw new Error("CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
|
|
2454
|
-
const stat2 =
|
|
2498
|
+
const stat2 = statSync2(normalized);
|
|
2455
2499
|
if (!stat2.isFile()) throw new Error("CLI \u8DEF\u5F84\u4E0D\u662F\u53EF\u6267\u884C\u6587\u4EF6");
|
|
2456
2500
|
accessSync(normalized, constants.X_OK);
|
|
2457
2501
|
return normalized;
|
|
@@ -2491,7 +2535,7 @@ var RelayResourceHandlers = class {
|
|
|
2491
2535
|
}
|
|
2492
2536
|
try {
|
|
2493
2537
|
const path = validateExecutablePath(rawPath ?? "");
|
|
2494
|
-
saveAgentCliPath(provider, path
|
|
2538
|
+
saveAgentCliPath(provider, path);
|
|
2495
2539
|
this.deps.setAgentCliPath(provider, path);
|
|
2496
2540
|
const agentCli = detectAgentCliStatus(this.deps.getProviderEnv(), {
|
|
2497
2541
|
suggestions: this.deps.getAgentCliSuggestions()
|
|
@@ -2560,7 +2604,7 @@ var RelayResourceHandlers = class {
|
|
|
2560
2604
|
};
|
|
2561
2605
|
|
|
2562
2606
|
// src/serve/relay-session-create-handler.ts
|
|
2563
|
-
import { rmSync, statSync as
|
|
2607
|
+
import { rmSync, statSync as statSync3 } from "fs";
|
|
2564
2608
|
import { isAbsolute as isAbsolute4 } from "path";
|
|
2565
2609
|
import { nanoid as nanoid4 } from "nanoid";
|
|
2566
2610
|
|
|
@@ -2855,7 +2899,7 @@ function validateSessionCwd(cwd) {
|
|
|
2855
2899
|
return { message: "\u5DE5\u4F5C\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84", code: ControlErrorCode.INVALID_PATH };
|
|
2856
2900
|
}
|
|
2857
2901
|
try {
|
|
2858
|
-
const stat2 =
|
|
2902
|
+
const stat2 = statSync3(trimmed);
|
|
2859
2903
|
return stat2.isDirectory() ? null : { message: "\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u662F\u76EE\u5F55", code: ControlErrorCode.PATH_NOT_DIRECTORY };
|
|
2860
2904
|
} catch (err) {
|
|
2861
2905
|
return {
|
|
@@ -3110,7 +3154,6 @@ var RelayRouter = class {
|
|
|
3110
3154
|
relaySend: deps.relaySend,
|
|
3111
3155
|
controlHandlers: deps.controlHandlers,
|
|
3112
3156
|
sessionManager: deps.sessionManager,
|
|
3113
|
-
envName: deps.envName,
|
|
3114
3157
|
getProviderEnv: deps.getProviderEnv,
|
|
3115
3158
|
getAgentCliSuggestions: deps.getAgentCliSuggestions,
|
|
3116
3159
|
setAgentCliPath: deps.setAgentCliPath
|
|
@@ -3652,7 +3695,7 @@ function touchSessionActivity(sessionManager, relay, sessionId, now = Date.now()
|
|
|
3652
3695
|
|
|
3653
3696
|
// src/serve/service-files.ts
|
|
3654
3697
|
import { execSync } from "child_process";
|
|
3655
|
-
import { existsSync as
|
|
3698
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
3656
3699
|
import { hostname } from "os";
|
|
3657
3700
|
import { connect as connect2 } from "net";
|
|
3658
3701
|
function tryConnectSocket(sockPath) {
|
|
@@ -3671,7 +3714,7 @@ function isProcessAlive(pid) {
|
|
|
3671
3714
|
}
|
|
3672
3715
|
}
|
|
3673
3716
|
async function cleanupStaleResources() {
|
|
3674
|
-
if (
|
|
3717
|
+
if (existsSync6(SOCK_PATH)) {
|
|
3675
3718
|
const existing = await tryConnectSocket(SOCK_PATH);
|
|
3676
3719
|
if (existing) {
|
|
3677
3720
|
existing.destroy();
|
|
@@ -3683,8 +3726,8 @@ async function cleanupStaleResources() {
|
|
|
3683
3726
|
unlinkSync2(SOCK_PATH);
|
|
3684
3727
|
serviceLogger.info("Removed stale socket file");
|
|
3685
3728
|
}
|
|
3686
|
-
if (
|
|
3687
|
-
const pidStr =
|
|
3729
|
+
if (existsSync6(PID_PATH)) {
|
|
3730
|
+
const pidStr = readFileSync6(PID_PATH, "utf-8").trim();
|
|
3688
3731
|
const pid = parseInt(pidStr, 10);
|
|
3689
3732
|
if (!isNaN(pid) && isProcessAlive(pid)) {
|
|
3690
3733
|
const msg = `Another service is already running with PID ${pid}`;
|
|
@@ -3696,8 +3739,13 @@ async function cleanupStaleResources() {
|
|
|
3696
3739
|
serviceLogger.info("Removed stale PID file");
|
|
3697
3740
|
}
|
|
3698
3741
|
}
|
|
3742
|
+
function formatProxyNameForProfile(baseName, profileName = PROFILE_NAME) {
|
|
3743
|
+
return profileName === DEFAULT_PROXY_PROFILE ? baseName : `${baseName} (${profileName})`;
|
|
3744
|
+
}
|
|
3699
3745
|
function getProxyName() {
|
|
3700
|
-
|
|
3746
|
+
const explicitName = process.env.DEV_ANYWHERE_PROXY_NAME?.trim();
|
|
3747
|
+
if (explicitName) return explicitName;
|
|
3748
|
+
return formatProxyNameForProfile(getComputerName() || hostname());
|
|
3701
3749
|
}
|
|
3702
3750
|
function getComputerName() {
|
|
3703
3751
|
try {
|
|
@@ -4054,7 +4102,7 @@ function handleTerminalConnection(socket, deps) {
|
|
|
4054
4102
|
|
|
4055
4103
|
// src/serve/hook-registry.ts
|
|
4056
4104
|
import { createHash, randomBytes } from "crypto";
|
|
4057
|
-
import { existsSync as
|
|
4105
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
4058
4106
|
import { dirname as dirname4 } from "path";
|
|
4059
4107
|
import { z } from "zod";
|
|
4060
4108
|
var PersistedHookSessionBindingSchema = z.object({
|
|
@@ -4115,10 +4163,10 @@ var HookRegistry = class {
|
|
|
4115
4163
|
}
|
|
4116
4164
|
}
|
|
4117
4165
|
load() {
|
|
4118
|
-
if (!this.persistPath || !
|
|
4166
|
+
if (!this.persistPath || !existsSync7(this.persistPath)) return;
|
|
4119
4167
|
try {
|
|
4120
4168
|
const parsed = PersistedHookRegistrySchema.parse(
|
|
4121
|
-
JSON.parse(
|
|
4169
|
+
JSON.parse(readFileSync7(this.persistPath, "utf8"))
|
|
4122
4170
|
);
|
|
4123
4171
|
this.bindingsBySession.clear();
|
|
4124
4172
|
for (const binding of parsed.bindings) {
|
|
@@ -4434,24 +4482,25 @@ function parseServiceOptions(argv) {
|
|
|
4434
4482
|
const options = {};
|
|
4435
4483
|
for (let i = 0; i < argv.length; i++) {
|
|
4436
4484
|
const arg = argv[i];
|
|
4437
|
-
if (arg === "--
|
|
4438
|
-
const
|
|
4439
|
-
if (!
|
|
4440
|
-
throw new Error("Missing value for --
|
|
4485
|
+
if (arg === "--relay") {
|
|
4486
|
+
const relayName = argv[i + 1];
|
|
4487
|
+
if (!relayName || relayName.startsWith("-")) {
|
|
4488
|
+
throw new Error("Missing value for --relay");
|
|
4441
4489
|
}
|
|
4442
|
-
options.
|
|
4490
|
+
options.relayName = relayName;
|
|
4443
4491
|
i++;
|
|
4444
4492
|
continue;
|
|
4445
4493
|
}
|
|
4446
|
-
if (arg.startsWith("--
|
|
4447
|
-
const
|
|
4448
|
-
if (!
|
|
4449
|
-
options.
|
|
4494
|
+
if (arg.startsWith("--relay=")) {
|
|
4495
|
+
const relayName = arg.slice("--relay=".length);
|
|
4496
|
+
if (!relayName) throw new Error("Missing value for --relay");
|
|
4497
|
+
options.relayName = relayName;
|
|
4450
4498
|
}
|
|
4451
4499
|
}
|
|
4452
4500
|
return options;
|
|
4453
4501
|
}
|
|
4454
4502
|
async function startService(options) {
|
|
4503
|
+
ensureProfileWorkspace();
|
|
4455
4504
|
await cleanupStaleResources();
|
|
4456
4505
|
try {
|
|
4457
4506
|
unlinkSync3(STOPPED_PATH);
|
|
@@ -4479,7 +4528,7 @@ async function startService(options) {
|
|
|
4479
4528
|
sessionManager.startReaper();
|
|
4480
4529
|
const terminalSockets = /* @__PURE__ */ new Map();
|
|
4481
4530
|
const proxyName = getProxyName();
|
|
4482
|
-
let proxyConfig = loadConfig({
|
|
4531
|
+
let proxyConfig = loadConfig({ relayName: options?.relayName });
|
|
4483
4532
|
const getProviderEnv = () => buildProviderEnv(proxyConfig, process.env);
|
|
4484
4533
|
const getAgentCliSuggestions = () => proxyConfig.agentCliSuggestions;
|
|
4485
4534
|
const setAgentCliPath = (provider, path) => {
|
|
@@ -4501,8 +4550,9 @@ async function startService(options) {
|
|
|
4501
4550
|
const relayUrl = options?.relayUrl ?? proxyConfig.relayUrl;
|
|
4502
4551
|
const relayToken = proxyConfig.relayToken;
|
|
4503
4552
|
const statusConfig = {
|
|
4504
|
-
|
|
4505
|
-
|
|
4553
|
+
profile: PROFILE_NAME,
|
|
4554
|
+
relayName: proxyConfig.relayName,
|
|
4555
|
+
relayNameSource: proxyConfig.sources.relayName,
|
|
4506
4556
|
relayUrl,
|
|
4507
4557
|
relayUrlSource: proxyConfig.sources.relayUrl,
|
|
4508
4558
|
relayTokenSource: proxyConfig.sources.relayToken,
|
|
@@ -4510,12 +4560,16 @@ async function startService(options) {
|
|
|
4510
4560
|
hookPortSource: proxyConfig.sources.hookPort
|
|
4511
4561
|
};
|
|
4512
4562
|
if (!relayUrl) {
|
|
4513
|
-
const msg =
|
|
4563
|
+
const msg = `Relay URL is required. Set relays.${proxyConfig.relayName}.url in ~/.dev-anywhere/config.json or pass --relay <name>.`;
|
|
4514
4564
|
serviceLogger.error(msg);
|
|
4515
4565
|
console.error(msg);
|
|
4516
4566
|
process.exit(1);
|
|
4517
4567
|
}
|
|
4518
|
-
const relayConnection = new RelayConnection(relayUrl, {
|
|
4568
|
+
const relayConnection = new RelayConnection(relayUrl, {
|
|
4569
|
+
name: proxyName,
|
|
4570
|
+
token: relayToken,
|
|
4571
|
+
proxyIdPath: PROXY_ID_PATH
|
|
4572
|
+
});
|
|
4519
4573
|
const relaySend = (data) => relayConnection.sendRaw(data);
|
|
4520
4574
|
const controlHandlers = createControlMessageHandlers(relaySend, sessionManager);
|
|
4521
4575
|
const observerChangeState = (sessionId, next) => changeSessionState(sessionManager, relayConnection, sessionId, next);
|
|
@@ -4577,7 +4631,8 @@ async function startService(options) {
|
|
|
4577
4631
|
relayConnection.connect();
|
|
4578
4632
|
serviceLogger.info(
|
|
4579
4633
|
{
|
|
4580
|
-
|
|
4634
|
+
relayName: proxyConfig.relayName,
|
|
4635
|
+
profile: PROFILE_NAME,
|
|
4581
4636
|
relayUrl,
|
|
4582
4637
|
proxyName,
|
|
4583
4638
|
tokenSet: !!relayToken,
|
|
@@ -4601,7 +4656,6 @@ async function startService(options) {
|
|
|
4601
4656
|
permissionBroker,
|
|
4602
4657
|
hookEventRouter: hookRuntime.hookEventRouter,
|
|
4603
4658
|
agentStatusRegistry,
|
|
4604
|
-
envName: proxyConfig.envName,
|
|
4605
4659
|
getProviderEnv,
|
|
4606
4660
|
getAgentCliSuggestions,
|
|
4607
4661
|
setAgentCliPath
|