@hermespilot/link 0.4.5 → 0.4.6
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.
|
@@ -2080,6 +2080,14 @@ async function ensureHermesApiServerConfig(profileName = "default", configPath =
|
|
|
2080
2080
|
}
|
|
2081
2081
|
return ensureHermesApiServerConfigUnlocked(profileName, configPath);
|
|
2082
2082
|
}
|
|
2083
|
+
async function repairHermesApiServerConfig(profileName = "default", configPath = resolveHermesConfigPath(profileName)) {
|
|
2084
|
+
if (profileName !== "default") {
|
|
2085
|
+
return withProfileApiServerPortAssignmentLock(
|
|
2086
|
+
() => repairHermesApiServerConfigUnlocked(profileName, configPath)
|
|
2087
|
+
);
|
|
2088
|
+
}
|
|
2089
|
+
return repairHermesApiServerConfigUnlocked(profileName, configPath);
|
|
2090
|
+
}
|
|
2083
2091
|
async function ensureHermesApiServerConfigUnlocked(profileName = "default", configPath = resolveHermesConfigPath(profileName)) {
|
|
2084
2092
|
const existingRaw = await readFile2(configPath, "utf8").catch(
|
|
2085
2093
|
(error) => {
|
|
@@ -2096,47 +2104,60 @@ async function ensureHermesApiServerConfigUnlocked(profileName = "default", conf
|
|
|
2096
2104
|
const extra = ensureRecord(apiServer, "extra");
|
|
2097
2105
|
const configOnly = readApiServerConfig(apiServer);
|
|
2098
2106
|
const envOverrides = await readHermesApiServerEnvOverrides(profileName);
|
|
2099
|
-
const
|
|
2100
|
-
const
|
|
2101
|
-
const
|
|
2102
|
-
const
|
|
2103
|
-
const
|
|
2107
|
+
const configKey = configOnly.key?.trim() ? configOnly.key : null;
|
|
2108
|
+
const envKey = envOverrides.key?.trim() ? envOverrides.key : null;
|
|
2109
|
+
const configHost = configOnly.host?.trim() ? configOnly.host : null;
|
|
2110
|
+
const envHost = envOverrides.host?.trim() ? envOverrides.host : null;
|
|
2111
|
+
const configPort = readApiServerPort(configOnly.port);
|
|
2112
|
+
const envPort = readApiServerPort(envOverrides.port);
|
|
2113
|
+
const desiredHost = configHost ?? envHost ?? DEFAULT_HERMES_API_SERVER_HOST;
|
|
2114
|
+
const desiredPort = await resolveDesiredApiServerPort({
|
|
2115
|
+
profileName,
|
|
2116
|
+
configPort,
|
|
2117
|
+
envPort
|
|
2118
|
+
});
|
|
2119
|
+
const desiredKey = configKey ?? envKey ?? randomBytes(32).toString("base64url");
|
|
2104
2120
|
let changed = false;
|
|
2105
2121
|
let enabledAdded = false;
|
|
2106
2122
|
let hostAdded = false;
|
|
2107
2123
|
let portAdded = false;
|
|
2108
|
-
|
|
2109
|
-
if (!beforeEnabled) {
|
|
2124
|
+
if (apiServer.enabled !== true) {
|
|
2110
2125
|
apiServer.enabled = true;
|
|
2111
2126
|
enabledAdded = true;
|
|
2112
2127
|
changed = true;
|
|
2113
2128
|
}
|
|
2114
|
-
if (
|
|
2115
|
-
extra.host =
|
|
2116
|
-
hostAdded =
|
|
2129
|
+
if (configHost !== desiredHost) {
|
|
2130
|
+
extra.host = desiredHost;
|
|
2131
|
+
hostAdded = !configHost;
|
|
2117
2132
|
changed = true;
|
|
2118
2133
|
}
|
|
2119
|
-
if (
|
|
2120
|
-
|
|
2121
|
-
extra.port = assignedPort;
|
|
2122
|
-
portAdded = true;
|
|
2123
|
-
changed = true;
|
|
2124
|
-
} else if (!beforePort) {
|
|
2125
|
-
assignedPort = DEFAULT_HERMES_API_SERVER_PORT;
|
|
2126
|
-
extra.port = assignedPort;
|
|
2134
|
+
if (configPort !== desiredPort) {
|
|
2135
|
+
extra.port = desiredPort;
|
|
2127
2136
|
portAdded = true;
|
|
2128
2137
|
changed = true;
|
|
2129
2138
|
}
|
|
2130
|
-
if (
|
|
2131
|
-
extra.key =
|
|
2139
|
+
if (configKey !== desiredKey) {
|
|
2140
|
+
extra.key = desiredKey;
|
|
2132
2141
|
changed = true;
|
|
2133
2142
|
}
|
|
2134
|
-
|
|
2143
|
+
const desiredApiServer = readApiServerConfig(apiServer, true);
|
|
2144
|
+
const backupPath = changed && existingRaw ? `${configPath}.bak.${Date.now()}` : null;
|
|
2145
|
+
if (backupPath && existingRaw !== null) {
|
|
2146
|
+
await atomicWriteFilePreservingMetadata(backupPath, existingRaw, {
|
|
2147
|
+
metadataSourcePath: configPath
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
if (changed) {
|
|
2151
|
+
document.contents = document.createNode(config);
|
|
2152
|
+
await atomicWriteFilePreservingMetadata(configPath, document.toString());
|
|
2153
|
+
}
|
|
2154
|
+
const envChanged = await writeHermesApiServerEnv(profileName, desiredApiServer);
|
|
2155
|
+
if (!changed && !envChanged) {
|
|
2135
2156
|
return {
|
|
2136
2157
|
configPath,
|
|
2137
2158
|
apiServer: applyEnvOverrides(
|
|
2138
2159
|
readApiServerConfig(apiServer, true),
|
|
2139
|
-
|
|
2160
|
+
await readHermesApiServerEnvOverrides(profileName),
|
|
2140
2161
|
true
|
|
2141
2162
|
),
|
|
2142
2163
|
changed: false,
|
|
@@ -2148,36 +2169,79 @@ async function ensureHermesApiServerConfigUnlocked(profileName = "default", conf
|
|
|
2148
2169
|
notice: null
|
|
2149
2170
|
};
|
|
2150
2171
|
}
|
|
2151
|
-
const backupPath = existingRaw ? `${configPath}.bak.${Date.now()}` : null;
|
|
2152
|
-
if (backupPath && existingRaw !== null) {
|
|
2153
|
-
await atomicWriteFilePreservingMetadata(backupPath, existingRaw, {
|
|
2154
|
-
metadataSourcePath: configPath
|
|
2155
|
-
});
|
|
2156
|
-
}
|
|
2157
|
-
document.contents = document.createNode(config);
|
|
2158
|
-
await atomicWriteFilePreservingMetadata(configPath, document.toString());
|
|
2159
2172
|
return {
|
|
2160
2173
|
configPath,
|
|
2161
2174
|
apiServer: applyEnvOverrides(
|
|
2162
2175
|
readApiServerConfig(apiServer, true),
|
|
2163
|
-
|
|
2176
|
+
await readHermesApiServerEnvOverrides(profileName),
|
|
2164
2177
|
true
|
|
2165
2178
|
),
|
|
2166
2179
|
changed: true,
|
|
2167
|
-
keyAdded: !
|
|
2180
|
+
keyAdded: !configKey,
|
|
2168
2181
|
enabledAdded,
|
|
2169
2182
|
hostAdded,
|
|
2170
2183
|
portAdded,
|
|
2171
2184
|
backupPath,
|
|
2172
2185
|
notice: buildNotice({
|
|
2173
|
-
keyAdded: !
|
|
2186
|
+
keyAdded: !configKey,
|
|
2174
2187
|
enabledAdded,
|
|
2175
2188
|
hostAdded,
|
|
2176
2189
|
portAdded,
|
|
2177
|
-
port:
|
|
2190
|
+
port: desiredPort
|
|
2178
2191
|
})
|
|
2179
2192
|
};
|
|
2180
2193
|
}
|
|
2194
|
+
async function repairHermesApiServerConfigUnlocked(profileName = "default", configPath = resolveHermesConfigPath(profileName)) {
|
|
2195
|
+
const existingRaw = await readFile2(configPath, "utf8").catch(
|
|
2196
|
+
(error) => {
|
|
2197
|
+
if (isNodeError3(error, "ENOENT")) {
|
|
2198
|
+
return null;
|
|
2199
|
+
}
|
|
2200
|
+
throw error;
|
|
2201
|
+
}
|
|
2202
|
+
);
|
|
2203
|
+
const document = existingRaw ? YAML.parseDocument(existingRaw) : new YAML.Document({});
|
|
2204
|
+
const config = toRecord(document.toJSON());
|
|
2205
|
+
const platforms = ensureRecord(config, "platforms");
|
|
2206
|
+
const apiServer = ensureRecord(platforms, "api_server");
|
|
2207
|
+
const extra = ensureRecord(apiServer, "extra");
|
|
2208
|
+
const previous = applyEnvOverrides(
|
|
2209
|
+
readApiServerConfig(apiServer, true),
|
|
2210
|
+
await readHermesApiServerEnvOverrides(profileName),
|
|
2211
|
+
true
|
|
2212
|
+
);
|
|
2213
|
+
const freshPort = await nextProfileApiServerPort(profileName);
|
|
2214
|
+
const freshKey = randomBytes(32).toString("base64url");
|
|
2215
|
+
apiServer.enabled = true;
|
|
2216
|
+
extra.host = DEFAULT_HERMES_API_SERVER_HOST;
|
|
2217
|
+
extra.port = freshPort;
|
|
2218
|
+
extra.key = freshKey;
|
|
2219
|
+
const backupPath = existingRaw ? `${configPath}.bak.${Date.now()}` : null;
|
|
2220
|
+
if (backupPath && existingRaw !== null) {
|
|
2221
|
+
await atomicWriteFilePreservingMetadata(backupPath, existingRaw, {
|
|
2222
|
+
metadataSourcePath: configPath
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
document.contents = document.createNode(config);
|
|
2226
|
+
await atomicWriteFilePreservingMetadata(configPath, document.toString());
|
|
2227
|
+
const apiServerConfig = readApiServerConfig(apiServer, true);
|
|
2228
|
+
await writeHermesApiServerEnv(profileName, apiServerConfig, { force: true });
|
|
2229
|
+
return {
|
|
2230
|
+
configPath,
|
|
2231
|
+
apiServer: applyEnvOverrides(
|
|
2232
|
+
apiServerConfig,
|
|
2233
|
+
await readHermesApiServerEnvOverrides(profileName),
|
|
2234
|
+
true
|
|
2235
|
+
),
|
|
2236
|
+
changed: true,
|
|
2237
|
+
keyAdded: !previous.key,
|
|
2238
|
+
enabledAdded: previous.enabled !== true,
|
|
2239
|
+
hostAdded: previous.host !== DEFAULT_HERMES_API_SERVER_HOST,
|
|
2240
|
+
portAdded: previous.port !== freshPort,
|
|
2241
|
+
backupPath,
|
|
2242
|
+
notice: "\u5DF2\u4E3A Hermes API Server \u91CD\u65B0\u5206\u914D\u672C\u673A\u7AEF\u53E3\u5E76\u8F6E\u6362 key\uFF0C\u7528\u4E8E\u4FEE\u590D\u65E7 Gateway \u6216 key \u4E0D\u4E00\u81F4\u5BFC\u81F4\u7684 401\u3002"
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2181
2245
|
async function readHermesConfigDocument(configPath) {
|
|
2182
2246
|
const existingRaw = await readFile2(configPath, "utf8").catch(
|
|
2183
2247
|
(error) => {
|
|
@@ -3511,6 +3575,21 @@ function shouldAssignDedicatedProfileApiServerPort(profileName, configuredPort)
|
|
|
3511
3575
|
}
|
|
3512
3576
|
return configuredPort === void 0 || configuredPort === DEFAULT_HERMES_API_SERVER_PORT;
|
|
3513
3577
|
}
|
|
3578
|
+
function readApiServerPort(value) {
|
|
3579
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
3580
|
+
}
|
|
3581
|
+
async function resolveDesiredApiServerPort(input) {
|
|
3582
|
+
if (shouldAssignDedicatedProfileApiServerPort(
|
|
3583
|
+
input.profileName,
|
|
3584
|
+
input.configPort ?? void 0
|
|
3585
|
+
)) {
|
|
3586
|
+
if (input.profileName !== "default" && input.envPort !== null && input.envPort !== DEFAULT_HERMES_API_SERVER_PORT) {
|
|
3587
|
+
return input.envPort;
|
|
3588
|
+
}
|
|
3589
|
+
return nextProfileApiServerPort(input.profileName);
|
|
3590
|
+
}
|
|
3591
|
+
return input.configPort ?? input.envPort ?? DEFAULT_HERMES_API_SERVER_PORT;
|
|
3592
|
+
}
|
|
3514
3593
|
async function nextProfileApiServerPort(profileName) {
|
|
3515
3594
|
const usedPorts = await readConfiguredApiServerPorts(profileName);
|
|
3516
3595
|
for (let port = PROFILE_API_SERVER_PORT_START; port <= PROFILE_API_SERVER_PORT_END; port += 1) {
|
|
@@ -3670,14 +3749,82 @@ async function writeHermesEnvValue(profileName, key, value) {
|
|
|
3670
3749
|
}
|
|
3671
3750
|
await atomicWriteFilePreservingMetadata(envPath, nextRaw);
|
|
3672
3751
|
}
|
|
3752
|
+
async function writeHermesApiServerEnv(profileName, config, options = {}) {
|
|
3753
|
+
const envPath = path3.join(resolveHermesProfileDir(profileName), ".env");
|
|
3754
|
+
const existingRaw = await readFile2(envPath, "utf8").catch(
|
|
3755
|
+
(error) => {
|
|
3756
|
+
if (isNodeError3(error, "ENOENT")) {
|
|
3757
|
+
return null;
|
|
3758
|
+
}
|
|
3759
|
+
throw error;
|
|
3760
|
+
}
|
|
3761
|
+
);
|
|
3762
|
+
if (existingRaw === null && profileName === "default" && !options.force) {
|
|
3763
|
+
return false;
|
|
3764
|
+
}
|
|
3765
|
+
return writeHermesEnvValues(
|
|
3766
|
+
profileName,
|
|
3767
|
+
[
|
|
3768
|
+
["API_SERVER_ENABLED", config.enabled === false ? "false" : "true"],
|
|
3769
|
+
["API_SERVER_HOST", config.host ?? DEFAULT_HERMES_API_SERVER_HOST],
|
|
3770
|
+
["API_SERVER_PORT", String(config.port ?? DEFAULT_HERMES_API_SERVER_PORT)],
|
|
3771
|
+
["API_SERVER_KEY", config.key ?? ""]
|
|
3772
|
+
],
|
|
3773
|
+
existingRaw ?? ""
|
|
3774
|
+
);
|
|
3775
|
+
}
|
|
3776
|
+
async function writeHermesEnvValues(profileName, values, existingRaw) {
|
|
3777
|
+
const envPath = path3.join(resolveHermesProfileDir(profileName), ".env");
|
|
3778
|
+
const raw = existingRaw ?? await readFile2(envPath, "utf8").catch((error) => {
|
|
3779
|
+
if (isNodeError3(error, "ENOENT")) {
|
|
3780
|
+
return "";
|
|
3781
|
+
}
|
|
3782
|
+
throw error;
|
|
3783
|
+
});
|
|
3784
|
+
const lines = raw ? raw.split(/\r?\n/u) : [];
|
|
3785
|
+
const remaining = new Map(values);
|
|
3786
|
+
const nextLines = lines.map((line) => {
|
|
3787
|
+
const trimmed = line.trim();
|
|
3788
|
+
for (const [key, value] of remaining) {
|
|
3789
|
+
const keyPattern = new RegExp(
|
|
3790
|
+
`^(?:export\\s+)?${escapeRegExp(key)}=`,
|
|
3791
|
+
"u"
|
|
3792
|
+
);
|
|
3793
|
+
if (keyPattern.test(trimmed)) {
|
|
3794
|
+
remaining.delete(key);
|
|
3795
|
+
return `${key}=${formatEnvValue(value)}`;
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
return line;
|
|
3799
|
+
});
|
|
3800
|
+
if (remaining.size > 0 && nextLines.length > 0 && nextLines.at(-1) !== "") {
|
|
3801
|
+
nextLines.push("");
|
|
3802
|
+
}
|
|
3803
|
+
for (const [key, value] of remaining) {
|
|
3804
|
+
nextLines.push(`${key}=${formatEnvValue(value)}`);
|
|
3805
|
+
}
|
|
3806
|
+
const nextRaw = nextLines.join("\n").replace(/\n*$/u, "\n");
|
|
3807
|
+
if (nextRaw === raw) {
|
|
3808
|
+
return false;
|
|
3809
|
+
}
|
|
3810
|
+
if (raw) {
|
|
3811
|
+
await atomicWriteFilePreservingMetadata(
|
|
3812
|
+
`${envPath}.bak.${Date.now()}`,
|
|
3813
|
+
raw,
|
|
3814
|
+
{ metadataSourcePath: envPath }
|
|
3815
|
+
);
|
|
3816
|
+
}
|
|
3817
|
+
await atomicWriteFilePreservingMetadata(envPath, nextRaw);
|
|
3818
|
+
return true;
|
|
3819
|
+
}
|
|
3673
3820
|
function applyEnvOverrides(config, env, withDefaults) {
|
|
3674
|
-
const host =
|
|
3675
|
-
const port =
|
|
3821
|
+
const host = env.host ?? config.host;
|
|
3822
|
+
const port = env.port ?? config.port;
|
|
3676
3823
|
return {
|
|
3677
|
-
enabled:
|
|
3824
|
+
enabled: env.enabled ?? config.enabled,
|
|
3678
3825
|
host: withDefaults ? host ?? DEFAULT_HERMES_API_SERVER_HOST : host,
|
|
3679
3826
|
port: withDefaults ? port ?? DEFAULT_HERMES_API_SERVER_PORT : port,
|
|
3680
|
-
key:
|
|
3827
|
+
key: env.key ?? config.key
|
|
3681
3828
|
};
|
|
3682
3829
|
}
|
|
3683
3830
|
function parseEnvBoolean(value) {
|
|
@@ -3985,7 +4132,7 @@ import os2 from "os";
|
|
|
3985
4132
|
import path5 from "path";
|
|
3986
4133
|
|
|
3987
4134
|
// src/constants.ts
|
|
3988
|
-
var LINK_VERSION = "0.4.
|
|
4135
|
+
var LINK_VERSION = "0.4.6";
|
|
3989
4136
|
var LINK_COMMAND = "hermeslink";
|
|
3990
4137
|
var LINK_DEFAULT_PORT = 52379;
|
|
3991
4138
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -4548,6 +4695,47 @@ async function ensureHermesApiServerAvailable(options = {}) {
|
|
|
4548
4695
|
});
|
|
4549
4696
|
return { available: true, configResult, started: true, start, health };
|
|
4550
4697
|
}
|
|
4698
|
+
if (health.authInvalid) {
|
|
4699
|
+
void options.logger?.warn("gateway_api_server_auth_repair_requested", {
|
|
4700
|
+
profile: profileName,
|
|
4701
|
+
port: configResult.apiServer.port ?? null,
|
|
4702
|
+
issue: health.issue ?? "auth_invalid"
|
|
4703
|
+
});
|
|
4704
|
+
const repairedConfigResult = await repairHermesApiServerConfig(profileName);
|
|
4705
|
+
const repairedStart = await startHermesGatewayOnce(
|
|
4706
|
+
options.paths ?? resolveRuntimePaths(),
|
|
4707
|
+
profileName,
|
|
4708
|
+
options.logger
|
|
4709
|
+
);
|
|
4710
|
+
health = await waitForHermesApiHealth(
|
|
4711
|
+
repairedConfigResult.apiServer,
|
|
4712
|
+
fetcher,
|
|
4713
|
+
options.timeoutMs ?? DEFAULT_START_TIMEOUT_MS
|
|
4714
|
+
);
|
|
4715
|
+
if (health.healthy) {
|
|
4716
|
+
void options.logger?.info("gateway_api_server_auth_repair_succeeded", {
|
|
4717
|
+
profile: profileName,
|
|
4718
|
+
pid: repairedStart.pid,
|
|
4719
|
+
port: repairedConfigResult.apiServer.port ?? null,
|
|
4720
|
+
log_path: repairedStart.logPath,
|
|
4721
|
+
hermes_version: repairedStart.version?.version ?? null
|
|
4722
|
+
});
|
|
4723
|
+
return {
|
|
4724
|
+
available: true,
|
|
4725
|
+
configResult: repairedConfigResult,
|
|
4726
|
+
started: true,
|
|
4727
|
+
start: repairedStart,
|
|
4728
|
+
health
|
|
4729
|
+
};
|
|
4730
|
+
}
|
|
4731
|
+
void options.logger?.error("gateway_api_server_auth_repair_failed", {
|
|
4732
|
+
profile: profileName,
|
|
4733
|
+
pid: repairedStart.pid,
|
|
4734
|
+
port: repairedConfigResult.apiServer.port ?? null,
|
|
4735
|
+
log_path: repairedStart.logPath,
|
|
4736
|
+
issue: health.issue ?? "unknown"
|
|
4737
|
+
});
|
|
4738
|
+
}
|
|
4551
4739
|
const logHint = await readRecentGatewayLogHint(start.logPath);
|
|
4552
4740
|
void options.logger?.error("gateway_auto_start_failed", {
|
|
4553
4741
|
profile: profileName,
|
|
@@ -4638,12 +4826,9 @@ async function readHermesVersion(options = {}) {
|
|
|
4638
4826
|
}
|
|
4639
4827
|
async function execHermesVersion(hermesBin, logger) {
|
|
4640
4828
|
const failures = [];
|
|
4641
|
-
for (const args of [["version"], ["
|
|
4829
|
+
for (const args of [["--version"], ["version"]]) {
|
|
4642
4830
|
try {
|
|
4643
|
-
return await
|
|
4644
|
-
timeout: 5e3,
|
|
4645
|
-
windowsHide: true
|
|
4646
|
-
});
|
|
4831
|
+
return await spawnHermesVersionCommand(hermesBin, args, 5e3);
|
|
4647
4832
|
} catch (error) {
|
|
4648
4833
|
const failure = describeVersionCommandFailure(hermesBin, args, error);
|
|
4649
4834
|
failures.push(failure);
|
|
@@ -4659,6 +4844,85 @@ async function execHermesVersion(hermesBin, logger) {
|
|
|
4659
4844
|
});
|
|
4660
4845
|
throw new Error(summary);
|
|
4661
4846
|
}
|
|
4847
|
+
async function spawnHermesVersionCommand(hermesBin, args, timeoutMs) {
|
|
4848
|
+
return await new Promise((resolve, reject) => {
|
|
4849
|
+
const child = spawn(hermesBin, args, {
|
|
4850
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4851
|
+
windowsHide: true
|
|
4852
|
+
});
|
|
4853
|
+
let stdout = "";
|
|
4854
|
+
let stderr = "";
|
|
4855
|
+
let settled = false;
|
|
4856
|
+
const timer = setTimeout(() => {
|
|
4857
|
+
finish(() => {
|
|
4858
|
+
reject(
|
|
4859
|
+
createVersionCommandError(
|
|
4860
|
+
`${hermesBin} ${args.join(" ")} timed out after ${timeoutMs}ms`,
|
|
4861
|
+
{ stdout, stderr, killed: true }
|
|
4862
|
+
)
|
|
4863
|
+
);
|
|
4864
|
+
}, true);
|
|
4865
|
+
}, timeoutMs);
|
|
4866
|
+
const finish = (callback, kill = false) => {
|
|
4867
|
+
if (settled) {
|
|
4868
|
+
return;
|
|
4869
|
+
}
|
|
4870
|
+
settled = true;
|
|
4871
|
+
clearTimeout(timer);
|
|
4872
|
+
if (kill && child.pid && !child.killed) {
|
|
4873
|
+
child.kill();
|
|
4874
|
+
}
|
|
4875
|
+
callback();
|
|
4876
|
+
};
|
|
4877
|
+
const resolveIfVersionPrinted = () => {
|
|
4878
|
+
if (parseHermesVersion(stdout)) {
|
|
4879
|
+
finish(() => resolve({ stdout: `${stdout}
|
|
4880
|
+
${stderr}`.trim() }), true);
|
|
4881
|
+
}
|
|
4882
|
+
};
|
|
4883
|
+
child.stdout?.on("data", (chunk) => {
|
|
4884
|
+
stdout += chunk.toString();
|
|
4885
|
+
resolveIfVersionPrinted();
|
|
4886
|
+
});
|
|
4887
|
+
child.stderr?.on("data", (chunk) => {
|
|
4888
|
+
stderr += chunk.toString();
|
|
4889
|
+
});
|
|
4890
|
+
child.once("error", (error) => {
|
|
4891
|
+
finish(() => {
|
|
4892
|
+
reject(
|
|
4893
|
+
createVersionCommandError(error.message, {
|
|
4894
|
+
stdout,
|
|
4895
|
+
stderr,
|
|
4896
|
+
cause: error
|
|
4897
|
+
})
|
|
4898
|
+
);
|
|
4899
|
+
});
|
|
4900
|
+
});
|
|
4901
|
+
child.once("close", (code, signal) => {
|
|
4902
|
+
finish(() => {
|
|
4903
|
+
const raw = `${stdout}
|
|
4904
|
+
${stderr}`.trim();
|
|
4905
|
+
const version = parseHermesVersion(raw);
|
|
4906
|
+
if (code === 0 && (raw || version)) {
|
|
4907
|
+
resolve({ stdout: raw });
|
|
4908
|
+
return;
|
|
4909
|
+
}
|
|
4910
|
+
reject(
|
|
4911
|
+
createVersionCommandError(
|
|
4912
|
+
`${hermesBin} ${args.join(" ")} exited with code ${code ?? "null"}`,
|
|
4913
|
+
{
|
|
4914
|
+
stdout,
|
|
4915
|
+
stderr,
|
|
4916
|
+
code,
|
|
4917
|
+
signal,
|
|
4918
|
+
killed: child.killed
|
|
4919
|
+
}
|
|
4920
|
+
)
|
|
4921
|
+
);
|
|
4922
|
+
});
|
|
4923
|
+
});
|
|
4924
|
+
});
|
|
4925
|
+
}
|
|
4662
4926
|
function assertHermesRunsApiSupported(version, status) {
|
|
4663
4927
|
if (status !== 404) {
|
|
4664
4928
|
return;
|
|
@@ -4916,11 +5180,9 @@ async function readHermesApiServerHealth(config, fetcher = fetch) {
|
|
|
4916
5180
|
detailed: record
|
|
4917
5181
|
};
|
|
4918
5182
|
}
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
return authIssue;
|
|
4923
|
-
}
|
|
5183
|
+
const authIssue = await probeHermesApiServerAuth(resolvedConfig, fetcher);
|
|
5184
|
+
if (authIssue) {
|
|
5185
|
+
return authIssue;
|
|
4924
5186
|
}
|
|
4925
5187
|
return { healthy: true };
|
|
4926
5188
|
}
|
|
@@ -4937,9 +5199,6 @@ async function readHermesApiServerHealth(config, fetcher = fetch) {
|
|
|
4937
5199
|
};
|
|
4938
5200
|
}
|
|
4939
5201
|
async function probeHermesApiServerAuth(config, fetcher) {
|
|
4940
|
-
if (!config.key) {
|
|
4941
|
-
return null;
|
|
4942
|
-
}
|
|
4943
5202
|
const response = await fetchWithTimeout(
|
|
4944
5203
|
`http://127.0.0.1:${config.port}/v1/models`,
|
|
4945
5204
|
{
|
|
@@ -5150,6 +5409,21 @@ async function probeHermesVersion(hermesBin, options) {
|
|
|
5150
5409
|
}
|
|
5151
5410
|
}
|
|
5152
5411
|
}
|
|
5412
|
+
function createVersionCommandError(message, details) {
|
|
5413
|
+
const error = new Error(message, { cause: details.cause });
|
|
5414
|
+
error.stdout = details.stdout;
|
|
5415
|
+
error.stderr = details.stderr;
|
|
5416
|
+
if (details.code !== void 0) {
|
|
5417
|
+
error.code = details.code;
|
|
5418
|
+
}
|
|
5419
|
+
if (details.signal !== void 0) {
|
|
5420
|
+
error.signal = details.signal;
|
|
5421
|
+
}
|
|
5422
|
+
if (details.killed !== void 0) {
|
|
5423
|
+
error.killed = details.killed;
|
|
5424
|
+
}
|
|
5425
|
+
return error;
|
|
5426
|
+
}
|
|
5153
5427
|
function describeVersionCommandFailure(hermesBin, args, error) {
|
|
5154
5428
|
const message = error instanceof Error ? error.message : String(error);
|
|
5155
5429
|
const details = readExecErrorDetails(error, message);
|
|
@@ -11745,6 +12019,46 @@ async function callHermesApi(path26, init, options) {
|
|
|
11745
12019
|
startedAt,
|
|
11746
12020
|
response
|
|
11747
12021
|
);
|
|
12022
|
+
if (response.status !== 401) {
|
|
12023
|
+
return response;
|
|
12024
|
+
}
|
|
12025
|
+
void options.logger?.warn("hermes_api_request_repairing_after_401", {
|
|
12026
|
+
method,
|
|
12027
|
+
path: path26,
|
|
12028
|
+
profile: options.profileName ?? "default",
|
|
12029
|
+
port: config.port ?? null,
|
|
12030
|
+
duration_ms: Date.now() - startedAt
|
|
12031
|
+
});
|
|
12032
|
+
const profileName = options.profileName ?? "default";
|
|
12033
|
+
const repairedConfig = await repairHermesApiServerConfig(profileName);
|
|
12034
|
+
const repairedAvailability = await ensureHermesApiServerAvailable({
|
|
12035
|
+
fetchImpl: options.fetchImpl,
|
|
12036
|
+
forceRestart: true,
|
|
12037
|
+
logger: options.logger,
|
|
12038
|
+
profileName
|
|
12039
|
+
});
|
|
12040
|
+
config = repairedAvailability.configResult.apiServer ?? repairedConfig.apiServer;
|
|
12041
|
+
try {
|
|
12042
|
+
response = await request();
|
|
12043
|
+
} catch (error) {
|
|
12044
|
+
logHermesApiError(
|
|
12045
|
+
options.logger,
|
|
12046
|
+
method,
|
|
12047
|
+
path26,
|
|
12048
|
+
options.profileName,
|
|
12049
|
+
startedAt,
|
|
12050
|
+
error
|
|
12051
|
+
);
|
|
12052
|
+
throw error;
|
|
12053
|
+
}
|
|
12054
|
+
logHermesApiResponse(
|
|
12055
|
+
options.logger,
|
|
12056
|
+
method,
|
|
12057
|
+
path26,
|
|
12058
|
+
options.profileName,
|
|
12059
|
+
startedAt,
|
|
12060
|
+
response
|
|
12061
|
+
);
|
|
11748
12062
|
return response;
|
|
11749
12063
|
}
|
|
11750
12064
|
async function fetchHermesApi(fetcher, config, path26, init, options) {
|
|
@@ -16025,11 +16339,15 @@ function createHttpErrorMiddleware(logger) {
|
|
|
16025
16339
|
}
|
|
16026
16340
|
|
|
16027
16341
|
// src/hermes/profiles.ts
|
|
16028
|
-
import {
|
|
16342
|
+
import { execFile as execFile4 } from "child_process";
|
|
16343
|
+
import { readdir as readdir9, readFile as readFile12, rename as rename3, stat as stat12 } from "fs/promises";
|
|
16029
16344
|
import path18 from "path";
|
|
16345
|
+
import { promisify as promisify4 } from "util";
|
|
16030
16346
|
import YAML2 from "yaml";
|
|
16031
16347
|
var DEFAULT_PROFILE = "default";
|
|
16032
16348
|
var PROFILE_NAME_PATTERN4 = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
16349
|
+
var PROFILE_DELETE_TIMEOUT_MS = 3e4;
|
|
16350
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
16033
16351
|
async function listHermesProfiles(paths = resolveRuntimePaths()) {
|
|
16034
16352
|
const profiles = /* @__PURE__ */ new Map();
|
|
16035
16353
|
profiles.set(DEFAULT_PROFILE, await profileInfo(DEFAULT_PROFILE, paths));
|
|
@@ -16101,12 +16419,7 @@ async function updateHermesProfileMetadata(name, metadata, paths = resolveRuntim
|
|
|
16101
16419
|
async function deleteHermesProfile(name, paths = resolveRuntimePaths()) {
|
|
16102
16420
|
assertMutableProfile(name);
|
|
16103
16421
|
const profile = await profileInfo(name, paths);
|
|
16104
|
-
const exists = await
|
|
16105
|
-
if (isNodeError14(error, "ENOENT")) {
|
|
16106
|
-
return false;
|
|
16107
|
-
}
|
|
16108
|
-
throw error;
|
|
16109
|
-
});
|
|
16422
|
+
const exists = await pathExists(profile.path);
|
|
16110
16423
|
if (!exists) {
|
|
16111
16424
|
throw new LinkHttpError(
|
|
16112
16425
|
404,
|
|
@@ -16114,7 +16427,14 @@ async function deleteHermesProfile(name, paths = resolveRuntimePaths()) {
|
|
|
16114
16427
|
`Profile "${name}" does not exist`
|
|
16115
16428
|
);
|
|
16116
16429
|
}
|
|
16117
|
-
await
|
|
16430
|
+
await deleteHermesProfileWithCli(name);
|
|
16431
|
+
if (await pathExists(profile.path)) {
|
|
16432
|
+
throw new LinkHttpError(
|
|
16433
|
+
502,
|
|
16434
|
+
"hermes_profile_delete_incomplete",
|
|
16435
|
+
`Hermes CLI reported success, but Profile "${name}" still exists at ${profile.path}`
|
|
16436
|
+
);
|
|
16437
|
+
}
|
|
16118
16438
|
await deleteProfileIdentity(paths, {
|
|
16119
16439
|
profileName: profile.name,
|
|
16120
16440
|
profileUid: profile.uid
|
|
@@ -16170,6 +16490,52 @@ function assertProfileName(name) {
|
|
|
16170
16490
|
throw new LinkHttpError(400, "invalid_profile_name", "invalid profile name");
|
|
16171
16491
|
}
|
|
16172
16492
|
}
|
|
16493
|
+
async function pathExists(targetPath) {
|
|
16494
|
+
return await stat12(targetPath).then(() => true).catch((error) => {
|
|
16495
|
+
if (isNodeError14(error, "ENOENT")) {
|
|
16496
|
+
return false;
|
|
16497
|
+
}
|
|
16498
|
+
throw error;
|
|
16499
|
+
});
|
|
16500
|
+
}
|
|
16501
|
+
async function deleteHermesProfileWithCli(name) {
|
|
16502
|
+
try {
|
|
16503
|
+
await execFileAsync4(resolveHermesBin(), ["profile", "delete", name, "--yes"], {
|
|
16504
|
+
timeout: PROFILE_DELETE_TIMEOUT_MS,
|
|
16505
|
+
windowsHide: true
|
|
16506
|
+
});
|
|
16507
|
+
} catch (error) {
|
|
16508
|
+
throw new LinkHttpError(
|
|
16509
|
+
502,
|
|
16510
|
+
"hermes_profile_delete_failed",
|
|
16511
|
+
`Hermes CLI could not delete Profile "${name}": ${formatExecError(error)}`
|
|
16512
|
+
);
|
|
16513
|
+
}
|
|
16514
|
+
}
|
|
16515
|
+
function formatExecError(error) {
|
|
16516
|
+
if (!(error instanceof Error)) {
|
|
16517
|
+
return String(error);
|
|
16518
|
+
}
|
|
16519
|
+
const output = readExecErrorOutput2(error);
|
|
16520
|
+
return output ? `${error.message}
|
|
16521
|
+
${output}` : error.message;
|
|
16522
|
+
}
|
|
16523
|
+
function readExecErrorOutput2(error) {
|
|
16524
|
+
const parts = [];
|
|
16525
|
+
if ("stdout" in error && error.stdout != null) {
|
|
16526
|
+
const stdout = String(error.stdout).trim();
|
|
16527
|
+
if (stdout) {
|
|
16528
|
+
parts.push(stdout);
|
|
16529
|
+
}
|
|
16530
|
+
}
|
|
16531
|
+
if ("stderr" in error && error.stderr != null) {
|
|
16532
|
+
const stderr = String(error.stderr).trim();
|
|
16533
|
+
if (stderr) {
|
|
16534
|
+
parts.push(stderr);
|
|
16535
|
+
}
|
|
16536
|
+
}
|
|
16537
|
+
return parts.join("\n");
|
|
16538
|
+
}
|
|
16173
16539
|
function isNodeError14(error, code) {
|
|
16174
16540
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
16175
16541
|
}
|
|
@@ -16883,7 +17249,7 @@ import {
|
|
|
16883
17249
|
cp,
|
|
16884
17250
|
mkdir as mkdir10,
|
|
16885
17251
|
readFile as readFile13,
|
|
16886
|
-
rm as
|
|
17252
|
+
rm as rm6,
|
|
16887
17253
|
stat as stat13
|
|
16888
17254
|
} from "fs/promises";
|
|
16889
17255
|
import path19 from "path";
|
|
@@ -17184,7 +17550,7 @@ async function generateProfileName(displayName, paths) {
|
|
|
17184
17550
|
for (let attempt = 0; attempt < 100; attempt += 1) {
|
|
17185
17551
|
const suffix = randomSuffix(attempt);
|
|
17186
17552
|
const candidate = `${base}-${suffix}`.slice(0, 64).replace(/[-_]+$/u, "");
|
|
17187
|
-
if (!existing.has(candidate) && !await
|
|
17553
|
+
if (!existing.has(candidate) && !await pathExists2(resolveHermesProfileDir(candidate))) {
|
|
17188
17554
|
return candidate;
|
|
17189
17555
|
}
|
|
17190
17556
|
}
|
|
@@ -17210,7 +17576,7 @@ function randomSuffix(attempt) {
|
|
|
17210
17576
|
}
|
|
17211
17577
|
async function applyProfileCreationPostSteps(input) {
|
|
17212
17578
|
const profilePath = resolveHermesProfileDir(input.profileName);
|
|
17213
|
-
if (!await
|
|
17579
|
+
if (!await pathExists2(profilePath)) {
|
|
17214
17580
|
await ensureDirectoryWithInheritedMetadata(profilePath, 448);
|
|
17215
17581
|
}
|
|
17216
17582
|
if (input.sourceProfile && input.copyScopes.length > 0) {
|
|
@@ -17376,10 +17742,10 @@ async function writeEnvValues(profileName, values) {
|
|
|
17376
17742
|
async function copySkills(sourceProfile, targetProfile) {
|
|
17377
17743
|
const sourceSkills = path19.join(resolveHermesProfileDir(sourceProfile), "skills");
|
|
17378
17744
|
const targetSkills = path19.join(resolveHermesProfileDir(targetProfile), "skills");
|
|
17379
|
-
if (!await
|
|
17745
|
+
if (!await pathExists2(sourceSkills)) {
|
|
17380
17746
|
return;
|
|
17381
17747
|
}
|
|
17382
|
-
await
|
|
17748
|
+
await rm6(targetSkills, { recursive: true, force: true });
|
|
17383
17749
|
await cp(sourceSkills, targetSkills, {
|
|
17384
17750
|
recursive: true,
|
|
17385
17751
|
force: true,
|
|
@@ -17427,7 +17793,7 @@ async function failProfileCreation(input) {
|
|
|
17427
17793
|
await input.writer.write(`
|
|
17428
17794
|
Rolling back ${input.rollbackProfileName}...
|
|
17429
17795
|
`);
|
|
17430
|
-
await
|
|
17796
|
+
await rm6(resolveHermesProfileDir(input.rollbackProfileName), {
|
|
17431
17797
|
recursive: true,
|
|
17432
17798
|
force: true
|
|
17433
17799
|
}).catch(() => void 0);
|
|
@@ -17478,14 +17844,14 @@ function profileCreationLogPath(paths) {
|
|
|
17478
17844
|
async function clearProfileCreationLogFiles(paths) {
|
|
17479
17845
|
const primary = profileCreationLogPath(paths);
|
|
17480
17846
|
await Promise.all([
|
|
17481
|
-
|
|
17847
|
+
rm6(primary, { force: true }).catch(() => void 0),
|
|
17482
17848
|
...Array.from(
|
|
17483
17849
|
{ length: PROFILE_CREATE_LOG_MAX_FILES },
|
|
17484
|
-
(_, index) =>
|
|
17850
|
+
(_, index) => rm6(`${primary}.${index + 1}`, { force: true }).catch(() => void 0)
|
|
17485
17851
|
)
|
|
17486
17852
|
]);
|
|
17487
17853
|
}
|
|
17488
|
-
async function
|
|
17854
|
+
async function pathExists2(targetPath) {
|
|
17489
17855
|
return await stat13(targetPath).then(() => true).catch((error) => {
|
|
17490
17856
|
if (isNodeError15(error, "ENOENT")) {
|
|
17491
17857
|
return false;
|
|
@@ -20337,7 +20703,7 @@ function readModelList(payload) {
|
|
|
20337
20703
|
// src/hermes/updates.ts
|
|
20338
20704
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
20339
20705
|
import { spawn as spawn3 } from "child_process";
|
|
20340
|
-
import { mkdir as mkdir11, readFile as readFile16, rm as
|
|
20706
|
+
import { mkdir as mkdir11, readFile as readFile16, rm as rm7 } from "fs/promises";
|
|
20341
20707
|
import path22 from "path";
|
|
20342
20708
|
var SERVER_HERMES_RELEASES_LATEST_PATH = "/api/v1/hermes-agent/releases/latest";
|
|
20343
20709
|
var RELEASE_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
@@ -20627,10 +20993,10 @@ function updateLogPath(paths) {
|
|
|
20627
20993
|
async function clearUpdateLogFiles(paths) {
|
|
20628
20994
|
const primary = updateLogPath(paths);
|
|
20629
20995
|
await Promise.all([
|
|
20630
|
-
|
|
20996
|
+
rm7(primary, { force: true }).catch(() => void 0),
|
|
20631
20997
|
...Array.from(
|
|
20632
20998
|
{ length: UPDATE_LOG_MAX_FILES },
|
|
20633
|
-
(_, index) =>
|
|
20999
|
+
(_, index) => rm7(`${primary}.${index + 1}`, { force: true }).catch(() => void 0)
|
|
20634
21000
|
)
|
|
20635
21001
|
]);
|
|
20636
21002
|
}
|
|
@@ -20722,17 +21088,17 @@ function readString17(payload, key) {
|
|
|
20722
21088
|
// src/link/updates.ts
|
|
20723
21089
|
import { spawn as spawn5 } from "child_process";
|
|
20724
21090
|
import { EventEmitter as EventEmitter4 } from "events";
|
|
20725
|
-
import { mkdir as mkdir14, readFile as readFile18, rm as
|
|
21091
|
+
import { mkdir as mkdir14, readFile as readFile18, rm as rm10 } from "fs/promises";
|
|
20726
21092
|
import path24 from "path";
|
|
20727
21093
|
|
|
20728
21094
|
// src/daemon/process.ts
|
|
20729
21095
|
import { spawn as spawn4 } from "child_process";
|
|
20730
|
-
import { mkdir as mkdir13, readFile as readFile17, rm as
|
|
21096
|
+
import { mkdir as mkdir13, readFile as readFile17, rm as rm9 } from "fs/promises";
|
|
20731
21097
|
import path23 from "path";
|
|
20732
21098
|
|
|
20733
21099
|
// src/daemon/service.ts
|
|
20734
21100
|
import { createServer } from "http";
|
|
20735
|
-
import { mkdir as mkdir12, rm as
|
|
21101
|
+
import { mkdir as mkdir12, rm as rm8, writeFile as writeFile3 } from "fs/promises";
|
|
20736
21102
|
|
|
20737
21103
|
// src/relay/control-client.ts
|
|
20738
21104
|
import WebSocket from "ws";
|
|
@@ -21845,7 +22211,7 @@ async function startLinkService(options = {}) {
|
|
|
21845
22211
|
await logger.info("service_stopped");
|
|
21846
22212
|
await logger.flush();
|
|
21847
22213
|
if (options.writePidFile) {
|
|
21848
|
-
await
|
|
22214
|
+
await rm8(pidFilePath(paths), { force: true }).catch(() => void 0);
|
|
21849
22215
|
}
|
|
21850
22216
|
}
|
|
21851
22217
|
};
|
|
@@ -22037,7 +22403,7 @@ async function stopDaemonProcess(paths = resolveRuntimePaths()) {
|
|
|
22037
22403
|
try {
|
|
22038
22404
|
process.kill(status.pid, "SIGTERM");
|
|
22039
22405
|
} catch {
|
|
22040
|
-
await
|
|
22406
|
+
await rm9(pidFilePath(paths), { force: true }).catch(() => void 0);
|
|
22041
22407
|
return await getDaemonStatus(paths);
|
|
22042
22408
|
}
|
|
22043
22409
|
for (let index = 0; index < 20; index += 1) {
|
|
@@ -22059,7 +22425,7 @@ async function stopDaemonProcess(paths = resolveRuntimePaths()) {
|
|
|
22059
22425
|
}
|
|
22060
22426
|
}
|
|
22061
22427
|
if (!isProcessAlive3(status.pid) || !await pidBackedServiceIsReachable(paths)) {
|
|
22062
|
-
await
|
|
22428
|
+
await rm9(pidFilePath(paths), { force: true }).catch(() => void 0);
|
|
22063
22429
|
}
|
|
22064
22430
|
return await getDaemonStatus(paths);
|
|
22065
22431
|
}
|
|
@@ -22067,7 +22433,7 @@ async function getDaemonStatus(paths = resolveRuntimePaths()) {
|
|
|
22067
22433
|
const pidFile = pidFilePath(paths);
|
|
22068
22434
|
const pid = await readPid(pidFile);
|
|
22069
22435
|
if (pid && !isProcessAlive3(pid)) {
|
|
22070
|
-
await
|
|
22436
|
+
await rm9(pidFile, { force: true }).catch(() => void 0);
|
|
22071
22437
|
return {
|
|
22072
22438
|
running: false,
|
|
22073
22439
|
pid: null,
|
|
@@ -22522,10 +22888,10 @@ function updateLogPath2(paths) {
|
|
|
22522
22888
|
async function clearUpdateLogFiles2(paths) {
|
|
22523
22889
|
const primary = updateLogPath2(paths);
|
|
22524
22890
|
await Promise.all([
|
|
22525
|
-
|
|
22891
|
+
rm10(primary, { force: true }).catch(() => void 0),
|
|
22526
22892
|
...Array.from(
|
|
22527
22893
|
{ length: UPDATE_LOG_MAX_FILES2 },
|
|
22528
|
-
(_, index) =>
|
|
22894
|
+
(_, index) => rm10(`${primary}.${index + 1}`, { force: true }).catch(() => void 0)
|
|
22529
22895
|
)
|
|
22530
22896
|
]);
|
|
22531
22897
|
}
|
|
@@ -22582,7 +22948,7 @@ function readString18(payload, key) {
|
|
|
22582
22948
|
|
|
22583
22949
|
// src/pairing/pairing.ts
|
|
22584
22950
|
import path25 from "path";
|
|
22585
|
-
import { rm as
|
|
22951
|
+
import { rm as rm11 } from "fs/promises";
|
|
22586
22952
|
|
|
22587
22953
|
// src/relay/bootstrap.ts
|
|
22588
22954
|
var RelayNetworkError = class extends Error {
|
|
@@ -22844,7 +23210,7 @@ async function readPairingClaim(sessionId, paths = resolveRuntimePaths()) {
|
|
|
22844
23210
|
};
|
|
22845
23211
|
}
|
|
22846
23212
|
async function clearPairingClaim(sessionId, paths = resolveRuntimePaths()) {
|
|
22847
|
-
await
|
|
23213
|
+
await rm11(pairingClaimPath(sessionId, paths), { force: true }).catch(() => void 0);
|
|
22848
23214
|
}
|
|
22849
23215
|
async function claimPairing(input) {
|
|
22850
23216
|
const paths = input.paths ?? resolveRuntimePaths();
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED