@agenthifive/openclaw 0.1.0 → 0.2.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 +16 -13
- package/dist/auto-patch.d.ts +56 -0
- package/dist/auto-patch.d.ts.map +1 -0
- package/dist/auto-patch.js +446 -0
- package/dist/auto-patch.js.map +1 -0
- package/dist/config-discovery.d.ts +41 -0
- package/dist/config-discovery.d.ts.map +1 -0
- package/dist/config-discovery.js +161 -0
- package/dist/config-discovery.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/patch-verify.d.ts +6 -9
- package/dist/patch-verify.d.ts.map +1 -1
- package/dist/patch-verify.js +22 -21
- package/dist/patch-verify.js.map +1 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +19 -12
- package/dist/register.js.map +1 -1
- package/dist/setup-wizard.d.ts +5 -3
- package/dist/setup-wizard.d.ts.map +1 -1
- package/dist/setup-wizard.js +159 -26
- package/dist/setup-wizard.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Or add to your OpenClaw config manually:
|
|
|
37
37
|
|
|
38
38
|
### 2. Setup
|
|
39
39
|
|
|
40
|
-
Run the setup wizard to bootstrap agent auth
|
|
40
|
+
Run the setup wizard to bootstrap agent auth, discover connected services, write config, and apply the credential proxying patch:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
43
|
openclaw setup-vault
|
|
@@ -49,7 +49,13 @@ Or non-interactively:
|
|
|
49
49
|
openclaw setup-vault --base-url https://app.agenthifive.com --bootstrap-secret ah5b_...
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
The wizard
|
|
52
|
+
The wizard automatically:
|
|
53
|
+
- Writes plugin config to `~/.openclaw/openclaw.json`
|
|
54
|
+
- Applies the credential proxying patch to your OpenClaw installation
|
|
55
|
+
|
|
56
|
+
Additional flags:
|
|
57
|
+
- `--config-path <path>` — explicit config file path
|
|
58
|
+
- `--openclaw-dir <path>` — explicit OpenClaw installation directory
|
|
53
59
|
|
|
54
60
|
### 3. Connect Services
|
|
55
61
|
|
|
@@ -82,20 +88,17 @@ Plugin config goes in `plugins.entries.agenthifive.config` in your `openclaw.jso
|
|
|
82
88
|
| `pollTimeoutMs` | number | Approval poll timeout (default: 300000) |
|
|
83
89
|
| `pollIntervalMs` | number | Approval poll interval (default: 3000) |
|
|
84
90
|
|
|
85
|
-
## LLM Credential Proxying
|
|
86
|
-
|
|
87
|
-
To route LLM API calls through the vault (so agents don't need local API keys), apply the included patch:
|
|
91
|
+
## LLM Credential Proxying
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
pnpm patch openclaw
|
|
91
|
-
cd <temp-directory>
|
|
92
|
-
patch -p1 < node_modules/@agenthifive/openclaw/patches/model-auth.patch
|
|
93
|
-
pnpm patch-commit <temp-directory>
|
|
94
|
-
```
|
|
93
|
+
The setup wizard automatically patches OpenClaw's `resolveApiKeyForProvider()` to route LLM API calls through the vault, so agents don't need local API keys.
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
The patch is applied during `openclaw setup-vault` and:
|
|
96
|
+
- Works with both npm installs (`dist/` chunks) and source installs (`src/`)
|
|
97
|
+
- Creates a `.bak` backup of the patched file
|
|
98
|
+
- Is idempotent (safe to run multiple times)
|
|
99
|
+
- Uses dynamic imports — no-op when the plugin is not installed
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
To apply manually (e.g. after an OpenClaw upgrade), re-run the setup wizard or see [`patches/README.md`](patches/README.md).
|
|
99
102
|
|
|
100
103
|
## Programmatic Usage
|
|
101
104
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-patching for OpenClaw's credential resolution.
|
|
3
|
+
*
|
|
4
|
+
* Finds the OpenClaw installation and injects vault credential resolution
|
|
5
|
+
* into resolveApiKeyForProvider(). Supports both source installs (TypeScript)
|
|
6
|
+
* and npm installs (compiled JS chunks with hashed filenames).
|
|
7
|
+
*
|
|
8
|
+
* The patch adds two tiers before local profile resolution:
|
|
9
|
+
* - Tier 0: Proxied providers (vault bearer token used directly)
|
|
10
|
+
* - Tier 0.5: Credential provider chain (query vault before local profiles)
|
|
11
|
+
*/
|
|
12
|
+
export interface OpenClawInstall {
|
|
13
|
+
dir: string;
|
|
14
|
+
kind: "source" | "dist";
|
|
15
|
+
}
|
|
16
|
+
export interface PatchResult {
|
|
17
|
+
applied: boolean;
|
|
18
|
+
alreadyPatched: boolean;
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Locate the OpenClaw installation directory.
|
|
23
|
+
*
|
|
24
|
+
* Strategy (cascading, first match wins):
|
|
25
|
+
* 1. `which`/`where` openclaw → resolve symlink → walk up to package.json
|
|
26
|
+
* 2. `npm root -g` → check for openclaw package
|
|
27
|
+
* 3. Well-known paths (Linux, macOS, Windows)
|
|
28
|
+
* 4. `find` as last resort (Linux/macOS only, with timeout)
|
|
29
|
+
*
|
|
30
|
+
* Returns null if not found — caller should ask the user.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findOpenClawInstallDir(): Promise<OpenClawInstall | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Find all OpenClaw installations (for disambiguation when multiple exist).
|
|
35
|
+
*/
|
|
36
|
+
export declare function findAllOpenClawInstalls(): Promise<OpenClawInstall[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Validate a user-provided OpenClaw installation path.
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateOpenClawDir(dir: string): OpenClawInstall | null;
|
|
41
|
+
/**
|
|
42
|
+
* Find the chunk file containing resolveApiKeyForProvider in dist/.
|
|
43
|
+
*/
|
|
44
|
+
export declare function findDistChunk(distDir: string): string | null;
|
|
45
|
+
export declare function applyDistPatch(openclawDir: string): PatchResult;
|
|
46
|
+
export declare function applySourcePatch(openclawDir: string): PatchResult;
|
|
47
|
+
/**
|
|
48
|
+
* Apply the credential resolution patch to an OpenClaw installation.
|
|
49
|
+
* Automatically detects source vs dist installs.
|
|
50
|
+
*/
|
|
51
|
+
export declare function applyPatch(install: OpenClawInstall): PatchResult;
|
|
52
|
+
/**
|
|
53
|
+
* Check if the credential resolution patch is applied in an OpenClaw installation.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isPatchApplied(install: OpenClawInstall): boolean;
|
|
56
|
+
//# sourceMappingURL=auto-patch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-patch.d.ts","sourceRoot":"","sources":["../src/auto-patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AA+DD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoB9E;AAkKD;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAiB1E;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAIvE;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6B5D;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAqD/D;AAMD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAmFjE;AAMD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAIhE;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAUhE"}
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-patching for OpenClaw's credential resolution.
|
|
3
|
+
*
|
|
4
|
+
* Finds the OpenClaw installation and injects vault credential resolution
|
|
5
|
+
* into resolveApiKeyForProvider(). Supports both source installs (TypeScript)
|
|
6
|
+
* and npm installs (compiled JS chunks with hashed filenames).
|
|
7
|
+
*
|
|
8
|
+
* The patch adds two tiers before local profile resolution:
|
|
9
|
+
* - Tier 0: Proxied providers (vault bearer token used directly)
|
|
10
|
+
* - Tier 0.5: Credential provider chain (query vault before local profiles)
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from "node:child_process";
|
|
13
|
+
import { existsSync, readdirSync, readFileSync, realpathSync, writeFileSync, } from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Marker used to detect if the patch is already applied
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const PATCH_MARKER = "@agenthifive/openclaw/runtime";
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Code injected into compiled dist files
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
const INJECTED_CODE = `
|
|
24
|
+
\t// -- AgentHiFive: Tier 0 + Tier 0.5 vault credential resolution --
|
|
25
|
+
\t// @agenthifive/openclaw/runtime
|
|
26
|
+
\ttry {
|
|
27
|
+
\t\tconst runtime = await import("@agenthifive/openclaw/runtime");
|
|
28
|
+
\t\tif (runtime.isInitialized()) {
|
|
29
|
+
\t\t\tconst proxiedProviders = runtime.getProxiedProviders();
|
|
30
|
+
\t\t\tif (proxiedProviders.includes(provider)) {
|
|
31
|
+
\t\t\t\tconst vaultToken = runtime.getVaultBearerToken();
|
|
32
|
+
\t\t\t\tif (vaultToken) {
|
|
33
|
+
\t\t\t\t\treturn { apiKey: vaultToken, source: "vault:agent-token", mode: "api-key" };
|
|
34
|
+
\t\t\t\t}
|
|
35
|
+
\t\t\t}
|
|
36
|
+
\t\t\tconst vaultResult = await runtime.resolveCredential({
|
|
37
|
+
\t\t\t\tkind: "model_provider",
|
|
38
|
+
\t\t\t\tprovider,
|
|
39
|
+
\t\t\t\tprofileId: preferredProfile,
|
|
40
|
+
\t\t\t});
|
|
41
|
+
\t\t\tif (vaultResult?.apiKey) {
|
|
42
|
+
\t\t\t\treturn {
|
|
43
|
+
\t\t\t\t\tapiKey: vaultResult.apiKey,
|
|
44
|
+
\t\t\t\t\tsource: "credential-provider:vault",
|
|
45
|
+
\t\t\t\t\tmode: vaultResult.mode ?? "api-key",
|
|
46
|
+
\t\t\t\t};
|
|
47
|
+
\t\t\t}
|
|
48
|
+
\t\t}
|
|
49
|
+
\t} catch {
|
|
50
|
+
\t\t// Plugin not installed -- skip vault credential resolution
|
|
51
|
+
\t}
|
|
52
|
+
`;
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Anchor patterns
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
/**
|
|
57
|
+
* Regex matching the store assignment line in resolveApiKeyForProvider.
|
|
58
|
+
* This is stable across upstream versions — it's the first line after
|
|
59
|
+
* the destructuring of params.
|
|
60
|
+
*
|
|
61
|
+
* Upstream dist (2026.3.13):
|
|
62
|
+
* const store = params.store ?? ensureAuthProfileStore(params.agentDir);
|
|
63
|
+
* if (profileId) {
|
|
64
|
+
*/
|
|
65
|
+
const DIST_ANCHOR = /const store\s*=\s*params\.store\s*\?\?\s*ensureAuthProfileStore\(params\.agentDir\);\n/;
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Find OpenClaw installation
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
/**
|
|
70
|
+
* Locate the OpenClaw installation directory.
|
|
71
|
+
*
|
|
72
|
+
* Strategy (cascading, first match wins):
|
|
73
|
+
* 1. `which`/`where` openclaw → resolve symlink → walk up to package.json
|
|
74
|
+
* 2. `npm root -g` → check for openclaw package
|
|
75
|
+
* 3. Well-known paths (Linux, macOS, Windows)
|
|
76
|
+
* 4. `find` as last resort (Linux/macOS only, with timeout)
|
|
77
|
+
*
|
|
78
|
+
* Returns null if not found — caller should ask the user.
|
|
79
|
+
*/
|
|
80
|
+
export async function findOpenClawInstallDir() {
|
|
81
|
+
// Strategy 1: which/where → resolve symlink
|
|
82
|
+
const result = await findViaWhich();
|
|
83
|
+
if (result)
|
|
84
|
+
return result;
|
|
85
|
+
// Strategy 2: npm root -g
|
|
86
|
+
const npmResult = findViaNpmRoot();
|
|
87
|
+
if (npmResult)
|
|
88
|
+
return npmResult;
|
|
89
|
+
// Strategy 3: well-known paths
|
|
90
|
+
const wellKnown = findViaWellKnownPaths();
|
|
91
|
+
if (wellKnown)
|
|
92
|
+
return wellKnown;
|
|
93
|
+
// Strategy 4: find command (Linux/macOS only)
|
|
94
|
+
if (process.platform !== "win32") {
|
|
95
|
+
const found = findViaFind();
|
|
96
|
+
if (found)
|
|
97
|
+
return found;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
function classifyInstall(dir) {
|
|
102
|
+
const hasSrc = existsSync(path.join(dir, "src", "agents", "model-auth.ts"));
|
|
103
|
+
return { dir, kind: hasSrc ? "source" : "dist" };
|
|
104
|
+
}
|
|
105
|
+
function isOpenClawDir(dir) {
|
|
106
|
+
const pkgPath = path.join(dir, "package.json");
|
|
107
|
+
if (!existsSync(pkgPath))
|
|
108
|
+
return false;
|
|
109
|
+
try {
|
|
110
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
111
|
+
return pkg.name === "openclaw";
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function walkUpToPackageRoot(startDir) {
|
|
118
|
+
let dir = startDir;
|
|
119
|
+
for (let i = 0; i < 10; i++) {
|
|
120
|
+
if (isOpenClawDir(dir))
|
|
121
|
+
return dir;
|
|
122
|
+
const parent = path.dirname(dir);
|
|
123
|
+
if (parent === dir)
|
|
124
|
+
break;
|
|
125
|
+
dir = parent;
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
async function findViaWhich() {
|
|
130
|
+
const cmd = process.platform === "win32" ? "where openclaw" : "which openclaw";
|
|
131
|
+
try {
|
|
132
|
+
const bin = execSync(cmd, {
|
|
133
|
+
encoding: "utf-8",
|
|
134
|
+
timeout: 5_000,
|
|
135
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
136
|
+
}).trim();
|
|
137
|
+
if (!bin)
|
|
138
|
+
return null;
|
|
139
|
+
// Resolve symlinks to find the real binary location
|
|
140
|
+
let realBin;
|
|
141
|
+
try {
|
|
142
|
+
realBin = realpathSync(bin);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
realBin = bin;
|
|
146
|
+
}
|
|
147
|
+
// Walk up from binary to find package root
|
|
148
|
+
const root = walkUpToPackageRoot(path.dirname(realBin));
|
|
149
|
+
if (root)
|
|
150
|
+
return classifyInstall(root);
|
|
151
|
+
// Binary might be a wrapper script — check if it references a node_modules path
|
|
152
|
+
try {
|
|
153
|
+
const content = readFileSync(realBin, "utf-8");
|
|
154
|
+
const match = /["']([^"']+openclaw[^"']*)['"]/i.exec(content);
|
|
155
|
+
if (match?.[1]) {
|
|
156
|
+
const candidate = path.resolve(path.dirname(realBin), match[1]);
|
|
157
|
+
const root2 = walkUpToPackageRoot(path.dirname(candidate));
|
|
158
|
+
if (root2)
|
|
159
|
+
return classifyInstall(root2);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Not readable as text
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// which/where failed
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function findViaNpmRoot() {
|
|
172
|
+
try {
|
|
173
|
+
const root = execSync("npm root -g", {
|
|
174
|
+
encoding: "utf-8",
|
|
175
|
+
timeout: 5_000,
|
|
176
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
177
|
+
}).trim();
|
|
178
|
+
if (!root)
|
|
179
|
+
return null;
|
|
180
|
+
const candidate = path.join(root, "openclaw");
|
|
181
|
+
if (isOpenClawDir(candidate))
|
|
182
|
+
return classifyInstall(candidate);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// npm not available or failed
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
function findViaWellKnownPaths() {
|
|
190
|
+
const candidates = [];
|
|
191
|
+
if (process.platform === "win32") {
|
|
192
|
+
const appData = process.env.APPDATA;
|
|
193
|
+
if (appData) {
|
|
194
|
+
candidates.push(path.join(appData, "npm", "node_modules", "openclaw"));
|
|
195
|
+
}
|
|
196
|
+
const localAppData = process.env.LOCALAPPDATA;
|
|
197
|
+
if (localAppData) {
|
|
198
|
+
candidates.push(path.join(localAppData, "pnpm", "global", "5", "node_modules", "openclaw"));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
candidates.push("/usr/lib/node_modules/openclaw", "/usr/local/lib/node_modules/openclaw", path.join(process.env.HOME ?? "", ".local/share/pnpm/global/5/node_modules/openclaw"));
|
|
203
|
+
if (process.platform === "darwin") {
|
|
204
|
+
candidates.push("/opt/homebrew/lib/node_modules/openclaw", "/usr/local/Cellar/node/*/lib/node_modules/openclaw");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
for (const candidate of candidates) {
|
|
208
|
+
if (isOpenClawDir(candidate))
|
|
209
|
+
return classifyInstall(candidate);
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
function findViaFind() {
|
|
214
|
+
// Search common directories for openclaw package.json
|
|
215
|
+
const searchDirs = ["/usr", "/opt", process.env.HOME ?? ""].filter((d) => d && existsSync(d));
|
|
216
|
+
for (const searchDir of searchDirs) {
|
|
217
|
+
try {
|
|
218
|
+
const output = execSync(`find "${searchDir}" -maxdepth 8 -name "package.json" -path "*/openclaw/package.json" 2>/dev/null`, {
|
|
219
|
+
encoding: "utf-8",
|
|
220
|
+
timeout: 10_000,
|
|
221
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
222
|
+
}).trim();
|
|
223
|
+
if (!output)
|
|
224
|
+
continue;
|
|
225
|
+
const matches = output
|
|
226
|
+
.split("\n")
|
|
227
|
+
.filter(Boolean)
|
|
228
|
+
.map((p) => path.dirname(p))
|
|
229
|
+
.filter(isOpenClawDir);
|
|
230
|
+
if (matches.length === 1)
|
|
231
|
+
return classifyInstall(matches[0]);
|
|
232
|
+
if (matches.length > 1) {
|
|
233
|
+
// Multiple installs found — return null so caller can ask the user
|
|
234
|
+
// Store matches for the caller to display
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// find timed out or failed
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Find all OpenClaw installations (for disambiguation when multiple exist).
|
|
246
|
+
*/
|
|
247
|
+
export async function findAllOpenClawInstalls() {
|
|
248
|
+
const results = [];
|
|
249
|
+
const seen = new Set();
|
|
250
|
+
const add = (install) => {
|
|
251
|
+
if (!install)
|
|
252
|
+
return;
|
|
253
|
+
const resolved = path.resolve(install.dir);
|
|
254
|
+
if (seen.has(resolved))
|
|
255
|
+
return;
|
|
256
|
+
seen.add(resolved);
|
|
257
|
+
results.push({ ...install, dir: resolved });
|
|
258
|
+
};
|
|
259
|
+
add(await findViaWhich());
|
|
260
|
+
add(findViaNpmRoot());
|
|
261
|
+
add(findViaWellKnownPaths());
|
|
262
|
+
return results;
|
|
263
|
+
}
|
|
264
|
+
// ---------------------------------------------------------------------------
|
|
265
|
+
// Validate user-provided path
|
|
266
|
+
// ---------------------------------------------------------------------------
|
|
267
|
+
/**
|
|
268
|
+
* Validate a user-provided OpenClaw installation path.
|
|
269
|
+
*/
|
|
270
|
+
export function validateOpenClawDir(dir) {
|
|
271
|
+
const resolved = path.resolve(dir);
|
|
272
|
+
if (!isOpenClawDir(resolved))
|
|
273
|
+
return null;
|
|
274
|
+
return classifyInstall(resolved);
|
|
275
|
+
}
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Apply patch to dist (compiled JS)
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
/**
|
|
280
|
+
* Find the chunk file containing resolveApiKeyForProvider in dist/.
|
|
281
|
+
*/
|
|
282
|
+
export function findDistChunk(distDir) {
|
|
283
|
+
if (!existsSync(distDir))
|
|
284
|
+
return null;
|
|
285
|
+
const files = readdirSync(distDir).filter((f) => f.endsWith(".js"));
|
|
286
|
+
// Primary: look for auth-profiles-*.js (upstream chunk name)
|
|
287
|
+
const authChunk = files.find((f) => f.startsWith("auth-profiles") || f.startsWith("model-auth"));
|
|
288
|
+
if (authChunk) {
|
|
289
|
+
const content = readFileSync(path.join(distDir, authChunk), "utf-8");
|
|
290
|
+
if (content.includes("resolveApiKeyForProvider")) {
|
|
291
|
+
return path.join(distDir, authChunk);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Fallback: search all JS files
|
|
295
|
+
for (const file of files) {
|
|
296
|
+
const filePath = path.join(distDir, file);
|
|
297
|
+
const content = readFileSync(filePath, "utf-8");
|
|
298
|
+
if (content.includes("async function resolveApiKeyForProvider") &&
|
|
299
|
+
content.includes("ensureAuthProfileStore")) {
|
|
300
|
+
return filePath;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
export function applyDistPatch(openclawDir) {
|
|
306
|
+
const distDir = path.join(openclawDir, "dist");
|
|
307
|
+
const chunkPath = findDistChunk(distDir);
|
|
308
|
+
if (!chunkPath) {
|
|
309
|
+
return {
|
|
310
|
+
applied: false,
|
|
311
|
+
alreadyPatched: false,
|
|
312
|
+
message: "Could not find resolveApiKeyForProvider in OpenClaw dist/. " +
|
|
313
|
+
"The OpenClaw version may be incompatible.",
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const source = readFileSync(chunkPath, "utf-8");
|
|
317
|
+
// Already patched?
|
|
318
|
+
if (source.includes(PATCH_MARKER)) {
|
|
319
|
+
return {
|
|
320
|
+
applied: true,
|
|
321
|
+
alreadyPatched: true,
|
|
322
|
+
message: `Already patched: ${path.basename(chunkPath)}`,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
// Find anchor
|
|
326
|
+
const match = DIST_ANCHOR.exec(source);
|
|
327
|
+
if (!match) {
|
|
328
|
+
return {
|
|
329
|
+
applied: false,
|
|
330
|
+
alreadyPatched: false,
|
|
331
|
+
message: `Found ${path.basename(chunkPath)} but could not locate the anchor point. ` +
|
|
332
|
+
"The OpenClaw version may be incompatible.",
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
// Create backup
|
|
336
|
+
const backupPath = chunkPath + ".bak";
|
|
337
|
+
writeFileSync(backupPath, source);
|
|
338
|
+
// Inject code after the anchor line
|
|
339
|
+
const insertPos = match.index + match[0].length;
|
|
340
|
+
const patched = source.slice(0, insertPos) + INJECTED_CODE + source.slice(insertPos);
|
|
341
|
+
writeFileSync(chunkPath, patched);
|
|
342
|
+
return {
|
|
343
|
+
applied: true,
|
|
344
|
+
alreadyPatched: false,
|
|
345
|
+
message: `Patched ${path.basename(chunkPath)} (backup: ${path.basename(backupPath)})`,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
// Apply patch to source install
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
export function applySourcePatch(openclawDir) {
|
|
352
|
+
const targetFile = path.join(openclawDir, "src", "agents", "model-auth.ts");
|
|
353
|
+
if (!existsSync(targetFile)) {
|
|
354
|
+
return {
|
|
355
|
+
applied: false,
|
|
356
|
+
alreadyPatched: false,
|
|
357
|
+
message: "src/agents/model-auth.ts not found",
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const source = readFileSync(targetFile, "utf-8");
|
|
361
|
+
if (source.includes(PATCH_MARKER)) {
|
|
362
|
+
return {
|
|
363
|
+
applied: true,
|
|
364
|
+
alreadyPatched: true,
|
|
365
|
+
message: "Source already patched",
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
// Try using the patch command
|
|
369
|
+
const patchFile = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "patches", "model-auth.patch");
|
|
370
|
+
if (!existsSync(patchFile)) {
|
|
371
|
+
return {
|
|
372
|
+
applied: false,
|
|
373
|
+
alreadyPatched: false,
|
|
374
|
+
message: "patches/model-auth.patch not found in plugin package",
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
execSync(`patch -p1 --forward < "${patchFile}"`, {
|
|
379
|
+
cwd: openclawDir,
|
|
380
|
+
encoding: "utf-8",
|
|
381
|
+
timeout: 10_000,
|
|
382
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
383
|
+
});
|
|
384
|
+
return {
|
|
385
|
+
applied: true,
|
|
386
|
+
alreadyPatched: false,
|
|
387
|
+
message: "Source patch applied via patch -p1",
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
catch (err) {
|
|
391
|
+
// patch command failed — try manual injection as fallback
|
|
392
|
+
const match = DIST_ANCHOR.exec(source);
|
|
393
|
+
if (match) {
|
|
394
|
+
const backupPath = targetFile + ".bak";
|
|
395
|
+
writeFileSync(backupPath, source);
|
|
396
|
+
const insertPos = match.index + match[0].length;
|
|
397
|
+
const patched = source.slice(0, insertPos) +
|
|
398
|
+
"\n" +
|
|
399
|
+
INJECTED_CODE.replace(/\t/g, " ") +
|
|
400
|
+
"\n" +
|
|
401
|
+
source.slice(insertPos);
|
|
402
|
+
writeFileSync(targetFile, patched);
|
|
403
|
+
return {
|
|
404
|
+
applied: true,
|
|
405
|
+
alreadyPatched: false,
|
|
406
|
+
message: `Source patched via text injection (backup: ${path.basename(backupPath)})`,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
applied: false,
|
|
411
|
+
alreadyPatched: false,
|
|
412
|
+
message: `patch command failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// ---------------------------------------------------------------------------
|
|
417
|
+
// Unified apply
|
|
418
|
+
// ---------------------------------------------------------------------------
|
|
419
|
+
/**
|
|
420
|
+
* Apply the credential resolution patch to an OpenClaw installation.
|
|
421
|
+
* Automatically detects source vs dist installs.
|
|
422
|
+
*/
|
|
423
|
+
export function applyPatch(install) {
|
|
424
|
+
return install.kind === "source"
|
|
425
|
+
? applySourcePatch(install.dir)
|
|
426
|
+
: applyDistPatch(install.dir);
|
|
427
|
+
}
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
// Check if patch is applied
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
/**
|
|
432
|
+
* Check if the credential resolution patch is applied in an OpenClaw installation.
|
|
433
|
+
*/
|
|
434
|
+
export function isPatchApplied(install) {
|
|
435
|
+
if (install.kind === "source") {
|
|
436
|
+
const file = path.join(install.dir, "src", "agents", "model-auth.ts");
|
|
437
|
+
if (!existsSync(file))
|
|
438
|
+
return false;
|
|
439
|
+
return readFileSync(file, "utf-8").includes(PATCH_MARKER);
|
|
440
|
+
}
|
|
441
|
+
const chunkPath = findDistChunk(path.join(install.dir, "dist"));
|
|
442
|
+
if (!chunkPath)
|
|
443
|
+
return false;
|
|
444
|
+
return readFileSync(chunkPath, "utf-8").includes(PATCH_MARKER);
|
|
445
|
+
}
|
|
446
|
+
//# sourceMappingURL=auto-patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-patch.js","sourceRoot":"","sources":["../src/auto-patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw config file discovery and merge utilities.
|
|
3
|
+
*
|
|
4
|
+
* Reimplements OpenClaw's config path resolution logic since we can't
|
|
5
|
+
* import from the openclaw package (we're a plugin, not a dependency).
|
|
6
|
+
*
|
|
7
|
+
* Resolution order (matches OpenClaw's src/config/paths.ts):
|
|
8
|
+
* 1. $OPENCLAW_CONFIG_PATH / $CLAWDBOT_CONFIG_PATH (explicit override)
|
|
9
|
+
* 2. $OPENCLAW_STATE_DIR/openclaw.json
|
|
10
|
+
* 3. ~/.openclaw/openclaw.json (preferred)
|
|
11
|
+
* 4. Legacy: ~/.openclaw/clawdbot.json, ~/.clawdbot/, ~/.moltbot/, ~/.moldbot/
|
|
12
|
+
* 5. Return null — caller must ask the user
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Find an existing OpenClaw config file.
|
|
16
|
+
*
|
|
17
|
+
* Returns the absolute path to the first existing config file found,
|
|
18
|
+
* or `null` if no config file exists anywhere. The caller should prompt
|
|
19
|
+
* the user rather than silently creating a default file.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveOpenClawConfigPath(env?: NodeJS.ProcessEnv): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Return the canonical default config path (for prompting the user).
|
|
24
|
+
*/
|
|
25
|
+
export declare function defaultConfigPath(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Read an existing config file. Returns `{}` if the file doesn't exist.
|
|
28
|
+
* Throws on parse errors so the caller can warn the user.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readExistingConfig(configPath: string): Record<string, unknown>;
|
|
31
|
+
/**
|
|
32
|
+
* Deep-merge the AgentHiFive plugin config into an existing OpenClaw config.
|
|
33
|
+
*
|
|
34
|
+
* - Sets `plugins.enabled = true`
|
|
35
|
+
* - Adds `"agenthifive"` to `plugins.allow` (deduped)
|
|
36
|
+
* - Adds `"@agenthifive/openclaw"` to `plugins.load.paths` (deduped)
|
|
37
|
+
* - Replaces `plugins.entries.agenthifive` entirely
|
|
38
|
+
* - Preserves ALL other keys untouched
|
|
39
|
+
*/
|
|
40
|
+
export declare function mergePluginConfig(existing: Record<string, unknown>, pluginBlock: Record<string, unknown>): Record<string, unknown>;
|
|
41
|
+
//# sourceMappingURL=config-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-discovery.d.ts","sourceRoot":"","sources":["../src/config-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiDH;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,IAAI,CAgCf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyCzB"}
|