clawconnect-agent 0.2.3 → 0.2.4
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.
|
@@ -5,6 +5,8 @@ export interface HermesApiBootstrapOptions {
|
|
|
5
5
|
fileEnv?: Record<string, string>;
|
|
6
6
|
runHermesCommand?: (args: string[]) => string;
|
|
7
7
|
generateApiKey?: () => string;
|
|
8
|
+
writeEnvValues?: (values: Record<string, string>) => void;
|
|
9
|
+
readBackEnv?: () => Record<string, string>;
|
|
8
10
|
}
|
|
9
11
|
export type HermesApiBootstrapResult = "already-ready" | "configured" | "explicit-local" | "external-api";
|
|
10
12
|
/**
|
|
@@ -16,4 +18,5 @@ export type HermesApiBootstrapResult = "already-ready" | "configured" | "explici
|
|
|
16
18
|
* idempotent and never exposes the generated API key to ClawConnect logs.
|
|
17
19
|
*/
|
|
18
20
|
export declare function ensureHermesApiServer(options?: HermesApiBootstrapOptions): HermesApiBootstrapResult;
|
|
21
|
+
export declare function writeHermesEnvValues(values: Record<string, string>, options?: Pick<HermesApiBootstrapOptions, "env" | "hermesHome">): void;
|
|
19
22
|
export {};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { parseEnvFile } from "../../config/env.js";
|
|
5
|
+
import { setRestrictiveDirPermissions, setRestrictiveFilePermissions } from "../../platform/service-manager-common.js";
|
|
2
6
|
import { resolveHermesApiSettings, readHermesHomeEnv } from "./hermes-runtime-api-settings.js";
|
|
7
|
+
import { resolveHermesHomeDir } from "./hermes-runtime-paths.js";
|
|
3
8
|
import { runHermes } from "./hermes-runtime-process.js";
|
|
4
9
|
/**
|
|
5
10
|
* Make Hermes' local API Server the default ClawConnect transport.
|
|
@@ -28,19 +33,75 @@ export function ensureHermesApiServer(options = {}) {
|
|
|
28
33
|
const run = options.runHermesCommand ?? ((args) => runHermes(args));
|
|
29
34
|
const existingKey = firstNonEmpty(env.CLAWCONNECT_HERMES_API_KEY, fileEnv.CLAWCONNECT_HERMES_API_KEY, env.API_SERVER_KEY, fileEnv.API_SERVER_KEY, settings.apiKey);
|
|
30
35
|
const apiKey = existingKey ?? (options.generateApiKey ?? (() => randomBytes(32).toString("hex")))();
|
|
36
|
+
const values = {
|
|
37
|
+
API_SERVER_ENABLED: "true",
|
|
38
|
+
...(!existingKey ? { API_SERVER_KEY: apiKey } : {}),
|
|
39
|
+
};
|
|
31
40
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
const writeEnvValues = options.writeEnvValues ?? ((nextValues) => {
|
|
42
|
+
writeHermesEnvValues(nextValues, { env, hermesHome: options.hermesHome });
|
|
43
|
+
});
|
|
44
|
+
writeEnvValues(values);
|
|
45
|
+
const verifiedEnv = options.readBackEnv
|
|
46
|
+
? options.readBackEnv()
|
|
47
|
+
: options.writeEnvValues
|
|
48
|
+
? { ...fileEnv, ...values }
|
|
49
|
+
: readHermesHomeEnv({ env, hermesHome: options.hermesHome });
|
|
50
|
+
const verified = resolveHermesApiSettings({ env, fileEnv: verifiedEnv, hermesHome: options.hermesHome });
|
|
51
|
+
if (!isTruthy(verifiedEnv.API_SERVER_ENABLED) || !verified.executionReady) {
|
|
52
|
+
throw new Error("Hermes API environment verification failed");
|
|
35
53
|
}
|
|
36
54
|
run(["gateway", "restart"]);
|
|
37
55
|
}
|
|
38
56
|
catch {
|
|
39
|
-
throw new Error("Failed to enable the Hermes API Server
|
|
40
|
-
+ "
|
|
57
|
+
throw new Error("Failed to enable and verify the Hermes API Server in its .env file. "
|
|
58
|
+
+ "Check the Hermes home permissions, or explicitly set CLAWCONNECT_HERMES_RUNTIME_MODE=local.");
|
|
41
59
|
}
|
|
42
60
|
return "configured";
|
|
43
61
|
}
|
|
62
|
+
export function writeHermesEnvValues(values, options = {}) {
|
|
63
|
+
const env = options.env ?? process.env;
|
|
64
|
+
const hermesHome = options.hermesHome ?? resolveHermesHomeDir({ env });
|
|
65
|
+
const envPath = join(hermesHome, ".env");
|
|
66
|
+
const current = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
|
|
67
|
+
const requested = new Map(Object.entries(values));
|
|
68
|
+
const pending = new Map(requested);
|
|
69
|
+
const written = new Set();
|
|
70
|
+
const lines = current.split(/\r?\n/).map((line) => {
|
|
71
|
+
const match = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/);
|
|
72
|
+
const key = match?.[1];
|
|
73
|
+
if (!key || !requested.has(key))
|
|
74
|
+
return line;
|
|
75
|
+
if (written.has(key))
|
|
76
|
+
return "";
|
|
77
|
+
const value = requested.get(key) ?? "";
|
|
78
|
+
written.add(key);
|
|
79
|
+
pending.delete(key);
|
|
80
|
+
return `${key}=${formatEnvValue(value)}`;
|
|
81
|
+
});
|
|
82
|
+
while (lines.length > 0 && lines[lines.length - 1] === "")
|
|
83
|
+
lines.pop();
|
|
84
|
+
for (const [key, value] of pending) {
|
|
85
|
+
lines.push(`${key}=${formatEnvValue(value)}`);
|
|
86
|
+
}
|
|
87
|
+
const output = `${lines.join("\n")}\n`;
|
|
88
|
+
const tempPath = join(dirname(envPath), `.env.clawconnect-${process.pid}-${randomBytes(6).toString("hex")}.tmp`);
|
|
89
|
+
mkdirSync(hermesHome, { recursive: true });
|
|
90
|
+
setRestrictiveDirPermissions(hermesHome);
|
|
91
|
+
writeFileSync(tempPath, output, "utf8");
|
|
92
|
+
setRestrictiveFilePermissions(tempPath);
|
|
93
|
+
renameSync(tempPath, envPath);
|
|
94
|
+
setRestrictiveFilePermissions(envPath);
|
|
95
|
+
const verified = parseEnvFile(readFileSync(envPath, "utf8"));
|
|
96
|
+
for (const [key, value] of Object.entries(values)) {
|
|
97
|
+
if (verified[key] !== value) {
|
|
98
|
+
throw new Error(`Failed to verify Hermes environment key ${key}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function formatEnvValue(value) {
|
|
103
|
+
return /^[A-Za-z0-9_./:@+-]*$/.test(value) ? value : JSON.stringify(value);
|
|
104
|
+
}
|
|
44
105
|
function firstNonEmpty(...values) {
|
|
45
106
|
for (const value of values) {
|
|
46
107
|
const trimmed = value?.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hermes-api-bootstrap.js","sourceRoot":"","sources":["../../../src/hermes/runtime/hermes-api-bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"hermes-api-bootstrap.js","sourceRoot":"","sources":["../../../src/hermes/runtime/hermes-api-bootstrap.ts"],"names":[],"mappings":"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"}
|