UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

194 lines (191 loc) 7.56 kB
import "./paths-B4BZAPZh.js"; import { B as theme, O as danger } from "./utils-CP9YLh6M.js"; import "./registry-B-j4DRfe.js"; import { f as defaultRuntime } from "./subsystem-BCQGGxdd.js"; import "./exec-DYqRzFbo.js"; import "./agent-scope-BnZW9Gh2.js"; import { kt as ensureAuthProfileStore, l as normalizeProviderId } from "./model-selection-CqaTAlhy.js"; import "./github-copilot-token-D2zp6kMZ.js"; import "./boolean-BsqeuxE6.js"; import "./env-VriqyjXT.js"; import "./message-channel-Bena1Tzd.js"; import "./config-PQiujvsf.js"; import "./manifest-registry-4k4vkhPS.js"; import "./client-BdSkEtCd.js"; import "./call-BCz_8mqq.js"; import "./pairing-token-B-_eiWlR.js"; import { t as formatDocsLink } from "./links-BVCMOGeE.js"; import "./progress-CaVMHLaE.js"; import { n as callGatewayFromCli, t as addGatewayClientOptions } from "./gateway-rpc-BM7hekCw.js"; import path from "node:path"; import fs from "node:fs/promises"; //#region src/agents/pi-auth-json.ts async function readAuthJson(filePath) { try { const raw = await fs.readFile(filePath, "utf8"); const parsed = JSON.parse(raw); if (!parsed || typeof parsed !== "object") return {}; return parsed; } catch { return {}; } } /** * Convert an OpenClaw auth-profiles credential to pi-coding-agent auth.json format. * Returns null if the credential cannot be converted. */ function convertCredential(cred) { if (cred.type === "api_key") { const key = typeof cred.key === "string" ? cred.key.trim() : ""; if (!key) return null; return { type: "api_key", key }; } if (cred.type === "token") { const token = typeof cred.token === "string" ? cred.token.trim() : ""; if (!token) return null; const expires = typeof cred.expires === "number" ? cred.expires : NaN; if (Number.isFinite(expires) && expires > 0 && Date.now() >= expires) return null; return { type: "api_key", key: token }; } if (cred.type === "oauth") { const accessRaw = cred.access; const refreshRaw = cred.refresh; const expiresRaw = cred.expires; const access = typeof accessRaw === "string" ? accessRaw.trim() : ""; const refresh = typeof refreshRaw === "string" ? refreshRaw.trim() : ""; const expires = typeof expiresRaw === "number" ? expiresRaw : NaN; if (!access || !refresh || !Number.isFinite(expires) || expires <= 0) return null; return { type: "oauth", access, refresh, expires }; } return null; } /** * Check if two auth.json credentials are equivalent. */ function credentialsEqual(a, b) { if (!a || typeof a !== "object") return false; if (a.type !== b.type) return false; if (a.type === "api_key" && b.type === "api_key") return a.key === b.key; if (a.type === "oauth" && b.type === "oauth") return a.access === b.access && a.refresh === b.refresh && a.expires === b.expires; return false; } /** * pi-coding-agent's ModelRegistry/AuthStorage expects credentials in auth.json. * * OpenClaw stores credentials in auth-profiles.json instead. This helper * bridges all credentials into agentDir/auth.json so pi-coding-agent can * (a) consider providers authenticated and (b) include built-in models in its * registry/catalog output. * * Syncs all credential types: api_key, token (as api_key), and oauth. */ async function ensurePiAuthJsonFromAuthProfiles(agentDir) { const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false }); const authPath = path.join(agentDir, "auth.json"); const providerCredentials = /* @__PURE__ */ new Map(); for (const [, cred] of Object.entries(store.profiles)) { const provider = normalizeProviderId(String(cred.provider ?? "")).trim(); if (!provider || providerCredentials.has(provider)) continue; const converted = convertCredential(cred); if (converted) providerCredentials.set(provider, converted); } if (providerCredentials.size === 0) return { wrote: false, authPath }; const existing = await readAuthJson(authPath); let changed = false; for (const [provider, cred] of providerCredentials) if (!credentialsEqual(existing[provider], cred)) { existing[provider] = cred; changed = true; } if (!changed) return { wrote: false, authPath }; await fs.mkdir(agentDir, { recursive: true, mode: 448 }); await fs.writeFile(authPath, `${JSON.stringify(existing, null, 2)}\n`, { mode: 384 }); return { wrote: true, authPath }; } //#endregion //#region src/cli/system-cli.ts const normalizeWakeMode = (raw) => { const mode = typeof raw === "string" ? raw.trim() : ""; if (!mode) return "next-heartbeat"; if (mode === "now" || mode === "next-heartbeat") return mode; throw new Error("--mode must be now or next-heartbeat"); }; function registerSystemCli(program) { const system = program.command("system").description("System tools (events, heartbeat, presence)").addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/system", "docs.openclaw.ai/cli/system")}\n`); addGatewayClientOptions(system.command("event").description("Enqueue a system event and optionally trigger a heartbeat").requiredOption("--text <text>", "System event text").option("--mode <mode>", "Wake mode (now|next-heartbeat)", "next-heartbeat").option("--json", "Output JSON", false)).action(async (opts) => { try { const text = typeof opts.text === "string" ? opts.text.trim() : ""; if (!text) throw new Error("--text is required"); const result = await callGatewayFromCli("wake", opts, { mode: normalizeWakeMode(opts.mode), text }, { expectFinal: false }); if (opts.json) defaultRuntime.log(JSON.stringify(result, null, 2)); else defaultRuntime.log("ok"); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); const heartbeat = system.command("heartbeat").description("Heartbeat controls"); addGatewayClientOptions(heartbeat.command("last").description("Show the last heartbeat event").option("--json", "Output JSON", false)).action(async (opts) => { try { const result = await callGatewayFromCli("last-heartbeat", opts, void 0, { expectFinal: false }); defaultRuntime.log(JSON.stringify(result, null, 2)); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); addGatewayClientOptions(heartbeat.command("enable").description("Enable heartbeats").option("--json", "Output JSON", false)).action(async (opts) => { try { const result = await callGatewayFromCli("set-heartbeats", opts, { enabled: true }, { expectFinal: false }); defaultRuntime.log(JSON.stringify(result, null, 2)); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); addGatewayClientOptions(heartbeat.command("disable").description("Disable heartbeats").option("--json", "Output JSON", false)).action(async (opts) => { try { const result = await callGatewayFromCli("set-heartbeats", opts, { enabled: false }, { expectFinal: false }); defaultRuntime.log(JSON.stringify(result, null, 2)); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); addGatewayClientOptions(system.command("presence").description("List system presence entries").option("--json", "Output JSON", false)).action(async (opts) => { try { const result = await callGatewayFromCli("system-presence", opts, void 0, { expectFinal: false }); defaultRuntime.log(JSON.stringify(result, null, 2)); } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); } }); } //#endregion export { registerSystemCli, ensurePiAuthJsonFromAuthProfiles as t };