@wiimdy/openfunderse 1.1.4 → 1.1.5
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
CHANGED
|
@@ -22,6 +22,9 @@ set -a; source .env.strategy; set +a
|
|
|
22
22
|
set -a; source .env.participant; set +a
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
By default, `install` and `bot-init` also sync env keys into OpenClaw config (`~/.openclaw/openclaw.json > env.vars`).
|
|
26
|
+
Disable this with `--no-sync-openclaw-env`.
|
|
27
|
+
|
|
25
28
|
## Where Files Are Stored
|
|
26
29
|
|
|
27
30
|
- In OpenClaw, skills are installed under `~/.openclaw/workspace/skills`.
|
package/bin/openfunderse.mjs
CHANGED
|
@@ -71,8 +71,10 @@ function printUsage() {
|
|
|
71
71
|
Usage:
|
|
72
72
|
openfunderse list
|
|
73
73
|
openfunderse bot-init [--role <strategy|participant>] [--skill-name <name>] [--env-path <path>] [--wallet-dir <dir>] [--wallet-name <name>] [--force] [--yes]
|
|
74
|
+
[--no-sync-openclaw-env]
|
|
74
75
|
openfunderse install <pack-name> [--dest <skills-dir>] [--codex-home <dir>] [--force] [--with-runtime]
|
|
75
76
|
[--no-init-env] [--env-path <path>] [--env-profile <strategy|participant|all>]
|
|
77
|
+
[--no-sync-openclaw-env]
|
|
76
78
|
[--runtime-package <name>] [--runtime-dir <dir>] [--runtime-manager <npm|pnpm|yarn|bun>]
|
|
77
79
|
|
|
78
80
|
Examples:
|
|
@@ -105,6 +107,7 @@ function parseArgs(argv) {
|
|
|
105
107
|
skillName: "",
|
|
106
108
|
walletDir: "",
|
|
107
109
|
walletName: "",
|
|
110
|
+
syncOpenclawEnv: true,
|
|
108
111
|
yes: false
|
|
109
112
|
};
|
|
110
113
|
const positionals = [];
|
|
@@ -137,6 +140,14 @@ function parseArgs(argv) {
|
|
|
137
140
|
options.withRuntime = true;
|
|
138
141
|
continue;
|
|
139
142
|
}
|
|
143
|
+
if (token === "--sync-openclaw-env") {
|
|
144
|
+
options.syncOpenclawEnv = true;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (token === "--no-sync-openclaw-env") {
|
|
148
|
+
options.syncOpenclawEnv = false;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
140
151
|
if (token === "--init-env") {
|
|
141
152
|
options.initEnv = true;
|
|
142
153
|
options.initEnvExplicit = true;
|
|
@@ -317,6 +328,11 @@ function runtimeEnvExamplePath(runtimeDir, runtimePackage) {
|
|
|
317
328
|
return path.join(runtimeDir, "node_modules", ...runtimePackage.split("/"), ".env.example");
|
|
318
329
|
}
|
|
319
330
|
|
|
331
|
+
function openclawConfigPath(codexHome) {
|
|
332
|
+
const resolvedCodexHome = path.resolve(codexHome);
|
|
333
|
+
return path.join(path.dirname(resolvedCodexHome), "openclaw.json");
|
|
334
|
+
}
|
|
335
|
+
|
|
320
336
|
function defaultEnvFileNameForProfile(profile) {
|
|
321
337
|
if (profile === "strategy") {
|
|
322
338
|
return ".env.strategy";
|
|
@@ -411,6 +427,86 @@ function readAssignedEnvValue(content, key) {
|
|
|
411
427
|
return "";
|
|
412
428
|
}
|
|
413
429
|
|
|
430
|
+
function parseEnvAssignments(content) {
|
|
431
|
+
const result = {};
|
|
432
|
+
const lines = String(content || "").replace(/^\uFEFF/, "").split(/\r?\n/);
|
|
433
|
+
for (const rawLine of lines) {
|
|
434
|
+
const line = rawLine.trim();
|
|
435
|
+
if (!line || line.startsWith("#")) continue;
|
|
436
|
+
const match = line.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
437
|
+
if (!match) continue;
|
|
438
|
+
const key = match[1];
|
|
439
|
+
let value = (match[2] || "").trim();
|
|
440
|
+
if (
|
|
441
|
+
((value.startsWith("\"") && value.endsWith("\"")) ||
|
|
442
|
+
(value.startsWith("'") && value.endsWith("'"))) &&
|
|
443
|
+
value.length >= 2
|
|
444
|
+
) {
|
|
445
|
+
value = value.slice(1, -1);
|
|
446
|
+
}
|
|
447
|
+
result[key] = value;
|
|
448
|
+
}
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
async function syncOpenclawEnvVarsFromFile(envFile, codexHome) {
|
|
453
|
+
const configPath = openclawConfigPath(codexHome);
|
|
454
|
+
if (!existsSync(configPath)) {
|
|
455
|
+
return {
|
|
456
|
+
synced: false,
|
|
457
|
+
reason: "openclaw-config-not-found",
|
|
458
|
+
configPath,
|
|
459
|
+
envFile,
|
|
460
|
+
writtenKeys: []
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const envContent = await readFile(envFile, "utf8");
|
|
465
|
+
const assignments = parseEnvAssignments(envContent);
|
|
466
|
+
const keys = Object.keys(assignments);
|
|
467
|
+
if (keys.length === 0) {
|
|
468
|
+
return {
|
|
469
|
+
synced: false,
|
|
470
|
+
reason: "empty-env-file",
|
|
471
|
+
configPath,
|
|
472
|
+
envFile,
|
|
473
|
+
writtenKeys: []
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const rawConfig = await readFile(configPath, "utf8");
|
|
478
|
+
const parsedConfig = JSON.parse(rawConfig);
|
|
479
|
+
if (!parsedConfig || typeof parsedConfig !== "object" || Array.isArray(parsedConfig)) {
|
|
480
|
+
throw new Error(`invalid openclaw config json object: ${configPath}`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const nextConfig = { ...parsedConfig };
|
|
484
|
+
const envSection =
|
|
485
|
+
nextConfig.env && typeof nextConfig.env === "object" && !Array.isArray(nextConfig.env)
|
|
486
|
+
? { ...nextConfig.env }
|
|
487
|
+
: {};
|
|
488
|
+
const varsSection =
|
|
489
|
+
envSection.vars && typeof envSection.vars === "object" && !Array.isArray(envSection.vars)
|
|
490
|
+
? { ...envSection.vars }
|
|
491
|
+
: {};
|
|
492
|
+
|
|
493
|
+
for (const [key, value] of Object.entries(assignments)) {
|
|
494
|
+
varsSection[key] = value;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
envSection.vars = varsSection;
|
|
498
|
+
nextConfig.env = envSection;
|
|
499
|
+
await writeFile(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`);
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
synced: true,
|
|
503
|
+
reason: "ok",
|
|
504
|
+
configPath,
|
|
505
|
+
envFile,
|
|
506
|
+
writtenKeys: keys
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
414
510
|
function isPlaceholderEnvValue(value) {
|
|
415
511
|
const normalized = (value || "").trim();
|
|
416
512
|
if (!normalized) return true;
|
|
@@ -596,11 +692,27 @@ async function runBotInit(options) {
|
|
|
596
692
|
await mkdir(path.dirname(envFile), { recursive: true });
|
|
597
693
|
await writeFile(envFile, nextEnvContent);
|
|
598
694
|
await chmod(envFile, 0o600);
|
|
695
|
+
let syncMeta = null;
|
|
696
|
+
if (options.syncOpenclawEnv) {
|
|
697
|
+
const codexHome = options.codexHome ? path.resolve(options.codexHome) : defaultCodexHome();
|
|
698
|
+
syncMeta = await syncOpenclawEnvVarsFromFile(envFile, codexHome);
|
|
699
|
+
}
|
|
599
700
|
const sourceCommand = `set -a; source ${shellQuote(envFile)}; set +a`;
|
|
600
701
|
|
|
601
702
|
console.log(`Initialized ${role} bot wallet for Monad testnet (${DEFAULT_MONAD_CHAIN_ID}).`);
|
|
602
703
|
console.log(`Address: ${wallet.address}`);
|
|
603
704
|
console.log(`Env file updated: ${envFile}`);
|
|
705
|
+
if (syncMeta) {
|
|
706
|
+
if (syncMeta.synced) {
|
|
707
|
+
console.log(
|
|
708
|
+
`Synced env vars to OpenClaw config: ${syncMeta.configPath} (${syncMeta.writtenKeys.length} keys)`
|
|
709
|
+
);
|
|
710
|
+
} else {
|
|
711
|
+
console.log(
|
|
712
|
+
`Skipped OpenClaw env sync (${syncMeta.reason}): ${syncMeta.configPath}`
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
604
716
|
console.log(`Wallet backup (keep secret): ${walletFiles.walletPath}`);
|
|
605
717
|
console.log(`Private key backup (keep secret): ${walletFiles.privateKeyPath}`);
|
|
606
718
|
console.log(`Load env now: ${sourceCommand}`);
|
|
@@ -776,6 +888,10 @@ async function installPack(packName, options) {
|
|
|
776
888
|
};
|
|
777
889
|
envScaffoldMeta = await writeEnvScaffold(envOptions);
|
|
778
890
|
}
|
|
891
|
+
let openclawSyncMeta = null;
|
|
892
|
+
if (envScaffoldMeta && options.syncOpenclawEnv) {
|
|
893
|
+
openclawSyncMeta = await syncOpenclawEnvVarsFromFile(envScaffoldMeta.envFile, codexHome);
|
|
894
|
+
}
|
|
779
895
|
|
|
780
896
|
console.log(`Installed pack: ${packName}`);
|
|
781
897
|
console.log(`Skills root: ${skillsRoot}`);
|
|
@@ -796,6 +912,17 @@ async function installPack(packName, options) {
|
|
|
796
912
|
);
|
|
797
913
|
}
|
|
798
914
|
}
|
|
915
|
+
if (openclawSyncMeta) {
|
|
916
|
+
if (openclawSyncMeta.synced) {
|
|
917
|
+
console.log(
|
|
918
|
+
`Synced env vars to OpenClaw config: ${openclawSyncMeta.configPath} (${openclawSyncMeta.writtenKeys.length} keys)`
|
|
919
|
+
);
|
|
920
|
+
} else {
|
|
921
|
+
console.log(
|
|
922
|
+
`Skipped OpenClaw env sync (${openclawSyncMeta.reason}): ${openclawSyncMeta.configPath}`
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
799
926
|
console.log("Restart Codex to pick up new skills.");
|
|
800
927
|
}
|
|
801
928
|
|
package/package.json
CHANGED
|
@@ -51,6 +51,10 @@ npx @wiimdy/openfunderse@latest bot-init \
|
|
|
51
51
|
set -a; source .env.participant; set +a
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
OpenClaw note:
|
|
55
|
+
- `install` / `bot-init` sync env keys into `~/.openclaw/openclaw.json` (`env.vars`) by default.
|
|
56
|
+
- Use `--no-sync-openclaw-env` if you want file-only behavior.
|
|
57
|
+
|
|
54
58
|
Note:
|
|
55
59
|
- The scaffold includes a temporary public key placeholder by default.
|
|
56
60
|
- Always run `bot-init` before funding or running production actions.
|
|
@@ -73,6 +73,10 @@ npx @wiimdy/openfunderse@latest bot-init \
|
|
|
73
73
|
set -a; source .env.strategy; set +a
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
OpenClaw note:
|
|
77
|
+
- `install` / `bot-init` sync env keys into `~/.openclaw/openclaw.json` (`env.vars`) by default.
|
|
78
|
+
- Use `--no-sync-openclaw-env` if you want file-only behavior.
|
|
79
|
+
|
|
76
80
|
Note:
|
|
77
81
|
- The scaffold includes a temporary public key placeholder by default.
|
|
78
82
|
- Always run `bot-init` before funding or running production actions.
|