#!/usr/bin/env node "use strict"; const crypto = require("node:crypto"); const fs = require("node:fs"); async function main() { const args = parseArgs(process.argv.slice(2)); const requestToken = process.env.LAKE_LAMP_REQUEST_TOKEN || readTrim(process.env.LAKE_LAMP_REQUEST_TOKEN_FILE || ""); const baseUrl = String(args.url).replace(/\/$/, ""); const endpoint = requestToken ? "/api/workorders" : "/api/public/workorders"; const body = { system_entry: "光湖语言人格系统当前实例", origin_software: args.software || "未声明软件", origin_model: args.model || "未声明模型", origin_instance: args.instance || "当前实例", persona_id: args.persona, persona_name: args.name || args.persona, target: args.target, scope: args.scope, action: args.action, description: args.description || "", resource: args.resource || "", }; if (requestToken) { const qqId = process.env.GUANGHU_OWNER_QQ_ID || ""; if (!/^\d{5,12}$/.test(qqId)) throw new Error("GUANGHU_OWNER_QQ_ID must be provided transiently for private request mode"); const email = `${qqId}@qq.com`; body.recipient_fingerprint = crypto.createHash("sha256").update(email.toLowerCase()).digest("hex"); } const headers = { "content-type": "application/json" }; if (requestToken) headers.authorization = `Bearer ${requestToken}`; const response = await fetch(`${baseUrl}${endpoint}`, { method: "POST", headers, body: JSON.stringify(body), }); const payload = await response.json(); if (!response.ok) throw new Error(payload.error || `request failed (${response.status})`); process.stdout.write(`${JSON.stringify(payload)}\n`); } function parseArgs(argv) { const result = {}; for (let i = 0; i < argv.length; i += 2) result[String(argv[i]).replace(/^--/, "")] = argv[i + 1]; for (const key of ["url", "persona", "target", "scope", "action"]) if (!result[key]) throw new Error(`--${key} is required`); return result; } function readTrim(file) { return file && fs.existsSync(file) ? fs.readFileSync(file, "utf8").trim() : ""; } main().catch(error => { process.stderr.write(`lake-lamp request failed: ${error.message}\n`); process.exit(1); });