@gguf/claw
Version:
Multi-channel AI gateway with extensible messaging integrations
453 lines (451 loc) • 16.7 kB
JavaScript
import "./paths-B4BZAPZh.js";
import "./utils-CP9YLh6M.js";
import "./thinking-EAliFiVK.js";
import { E as resolveGatewaySessionStoreTarget, Lt as resolveOutboundTarget, T as pruneLegacyStoreKeys, ft as requestHeartbeatNow, jt as agentCommand, pr as enqueueSystemEvent, w as loadSessionEntry, zt as createOutboundSendDeps } from "./reply-BylFHBd4.js";
import { u as normalizeMainKey } from "./session-key-CZ6OwgSB.js";
import "./registry-B-j4DRfe.js";
import { f as defaultRuntime } from "./subsystem-BCQGGxdd.js";
import "./exec-DYqRzFbo.js";
import { d as resolveSessionAgentId } from "./agent-scope-BnZW9Gh2.js";
import "./model-selection-CqaTAlhy.js";
import "./github-copilot-token-D2zp6kMZ.js";
import "./boolean-BsqeuxE6.js";
import "./env-VriqyjXT.js";
import "./message-channel-Bena1Tzd.js";
import "./send-CsyONLnQ.js";
import { i as loadConfig } from "./config-PQiujvsf.js";
import "./manifest-registry-4k4vkhPS.js";
import "./runner-U04aiHHC.js";
import "./image-DxEpBZim.js";
import "./models-config-B459BnCS.js";
import "./pi-model-discovery-4uUnLc3n.js";
import "./pi-embedded-helpers-BdscQhyS.js";
import "./sandbox-UAzvS0V6.js";
import "./image-ops-CI1VknD1.js";
import "./common-a25M2Kvi.js";
import "./chrome-Dd5zBIFu.js";
import "./tailscale-C3JsBEiY.js";
import "./auth-DZSWPd8D.js";
import "./server-context-DAWsUNUs.js";
import "./frontmatter-6HZ0_y2V.js";
import "./skills-CLmzWt48.js";
import "./routes-DIQa_0pt.js";
import "./redact-B7Mjvk0c.js";
import "./errors-kfGqPQ4b.js";
import "./fs-safe-_OpKPuZA.js";
import "./paths-D1WZUYry.js";
import "./ssrf-6f5m2MMA.js";
import "./store-DSGYY-H9.js";
import "./ports-DwDxX6cS.js";
import "./trash-DLzIf__E.js";
import { u as updateSessionStore } from "./sessions-Z1BZU3xh.js";
import "./dock-7F-MiPtF.js";
import "./normalize-Ci8UyR3Z.js";
import "./accounts-Bj1dJ-fd.js";
import "./accounts-DOl1Wkxo.js";
import "./accounts-t6R5_PzC.js";
import "./bindings-Dja1z-h8.js";
import "./logging-xYH6GmRT.js";
import "./send-uu2Jc-Js.js";
import { r as normalizeChannelId } from "./plugins-CKbXkuXd.js";
import "./paths-C2NfoGZE.js";
import "./tool-display-Bx4M6uNT.js";
import "./fetch-guard-C1sYsWgl.js";
import "./api-key-rotation-CpGefdGL.js";
import "./local-roots-DiDvXIIo.js";
import "./sqlite-JcMMx8Z5.js";
import "./model-catalog-CIixTnGt.js";
import "./tokens-D4lZk7-h.js";
import "./with-timeout-DijiQjw6.js";
import { t as deliverOutboundPayloads } from "./deliver-DgvS3uCz.js";
import "./diagnostic-UUwku4RV.js";
import "./diagnostic-session-state-ByqoIyGn.js";
import "./send-DbwyyQAv.js";
import "./model-VbWjwqaW.js";
import "./reply-prefix-DAK7-zK4.js";
import "./memory-cli-DxmtLhh_.js";
import "./manager-C0teWocQ.js";
import "./retry-rUEdE6zT.js";
import "./chunk-CMylpCPi.js";
import "./markdown-tables-B9VGUdDc.js";
import "./ir-24qCLTKH.js";
import "./render-CXDO_kgw.js";
import "./commands-registry-bb_U-3FM.js";
import "./client-BdSkEtCd.js";
import "./call-BCz_8mqq.js";
import "./pairing-token-B-_eiWlR.js";
import "./channel-activity-DynIQUB_.js";
import "./fetch-Bu5zBCce.js";
import "./tables-C70h_80U.js";
import "./send-CAfFUUkm.js";
import "./pairing-store-T5DpOfoL.js";
import "./proxy-BiOWrea2.js";
import "./links-BVCMOGeE.js";
import "./cli-utils-CX1oQ81G.js";
import "./help-format-dbk2xW0E.js";
import "./progress-CaVMHLaE.js";
import "./resolve-route-2TU_aaLs.js";
import "./replies-NhrZJ3yf.js";
import "./skill-commands-N8Sho46-.js";
import "./workspace-dirs-CE3CxabZ.js";
import "./pi-tools.policy-DTy1DnPK.js";
import "./outbound-attachment-CntoLTI_.js";
import "./delivery-queue-CxDDEWQg.js";
import "./session-cost-usage-BlUDaylg.js";
import "./send-4LoRaltQ.js";
import "./onboard-helpers-DbjfBSMX.js";
import "./prompt-style-VqCNjBi8.js";
import "./pairing-labels-DaESq9ML.js";
import "./exec-approvals-q0C8VDMT.js";
import "./nodes-screen-5fMfTT2n.js";
import "./control-service-BoO2TGOx.js";
import "./stagger-B6VQyn1F.js";
import "./channel-selection-DuDSoVSC.js";
import { c as parseMessageWithAttachments, l as formatForLog, r as registerApnsToken, s as normalizeRpcAttachmentsToChatAttachments } from "./push-apns-DAgh5PMd.js";
import { randomUUID } from "node:crypto";
//#region src/gateway/server-node-events.ts
const MAX_EXEC_EVENT_OUTPUT_CHARS = 180;
const VOICE_TRANSCRIPT_DEDUPE_WINDOW_MS = 1500;
const MAX_RECENT_VOICE_TRANSCRIPTS = 200;
const recentVoiceTranscripts = /* @__PURE__ */ new Map();
function normalizeNonEmptyString(value) {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
function normalizeFiniteInteger(value) {
return typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : null;
}
function resolveVoiceTranscriptFingerprint(obj, text) {
const eventId = normalizeNonEmptyString(obj.eventId) ?? normalizeNonEmptyString(obj.providerEventId) ?? normalizeNonEmptyString(obj.transcriptId);
if (eventId) return `event:${eventId}`;
const callId = normalizeNonEmptyString(obj.providerCallId) ?? normalizeNonEmptyString(obj.callId);
const sequence = normalizeFiniteInteger(obj.sequence) ?? normalizeFiniteInteger(obj.seq);
if (callId && sequence !== null) return `call-seq:${callId}:${sequence}`;
const eventTimestamp = normalizeFiniteInteger(obj.timestamp) ?? normalizeFiniteInteger(obj.ts) ?? normalizeFiniteInteger(obj.eventTimestamp);
if (callId && eventTimestamp !== null) return `call-ts:${callId}:${eventTimestamp}`;
if (eventTimestamp !== null) return `timestamp:${eventTimestamp}|text:${text}`;
return `text:${text}`;
}
function shouldDropDuplicateVoiceTranscript(params) {
const previous = recentVoiceTranscripts.get(params.sessionKey);
if (previous && previous.fingerprint === params.fingerprint && params.now - previous.ts <= VOICE_TRANSCRIPT_DEDUPE_WINDOW_MS) return true;
recentVoiceTranscripts.set(params.sessionKey, {
fingerprint: params.fingerprint,
ts: params.now
});
if (recentVoiceTranscripts.size > MAX_RECENT_VOICE_TRANSCRIPTS) {
const cutoff = params.now - VOICE_TRANSCRIPT_DEDUPE_WINDOW_MS * 2;
for (const [key, value] of recentVoiceTranscripts) {
if (value.ts < cutoff) recentVoiceTranscripts.delete(key);
if (recentVoiceTranscripts.size <= MAX_RECENT_VOICE_TRANSCRIPTS) break;
}
while (recentVoiceTranscripts.size > MAX_RECENT_VOICE_TRANSCRIPTS) {
const oldestKey = recentVoiceTranscripts.keys().next().value;
if (oldestKey === void 0) break;
recentVoiceTranscripts.delete(oldestKey);
}
}
return false;
}
function compactExecEventOutput(raw) {
const normalized = raw.replace(/\s+/g, " ").trim();
if (!normalized) return "";
if (normalized.length <= MAX_EXEC_EVENT_OUTPUT_CHARS) return normalized;
const safe = Math.max(1, MAX_EXEC_EVENT_OUTPUT_CHARS - 1);
return `${normalized.slice(0, safe)}…`;
}
async function touchSessionStore(params) {
const { storePath } = params;
if (!storePath) return;
await updateSessionStore(storePath, (store) => {
const target = resolveGatewaySessionStoreTarget({
cfg: params.cfg,
key: params.sessionKey,
store
});
pruneLegacyStoreKeys({
store,
canonicalKey: target.canonicalKey,
candidates: target.storeKeys
});
store[params.canonicalKey] = {
sessionId: params.sessionId,
updatedAt: params.now,
thinkingLevel: params.entry?.thinkingLevel,
verboseLevel: params.entry?.verboseLevel,
reasoningLevel: params.entry?.reasoningLevel,
systemSent: params.entry?.systemSent,
sendPolicy: params.entry?.sendPolicy,
lastChannel: params.entry?.lastChannel,
lastTo: params.entry?.lastTo
};
});
}
function queueSessionStoreTouch(params) {
touchSessionStore({
cfg: params.cfg,
sessionKey: params.sessionKey,
storePath: params.storePath,
canonicalKey: params.canonicalKey,
entry: params.entry,
sessionId: params.sessionId,
now: params.now
}).catch((err) => {
params.ctx.logGateway.warn("voice session-store update failed: " + formatForLog(err));
});
}
function parseSessionKeyFromPayloadJSON(payloadJSON) {
let payload;
try {
payload = JSON.parse(payloadJSON);
} catch {
return null;
}
if (typeof payload !== "object" || payload === null) return null;
const obj = payload;
const sessionKey = typeof obj.sessionKey === "string" ? obj.sessionKey.trim() : "";
return sessionKey.length > 0 ? sessionKey : null;
}
async function sendReceiptAck(params) {
const resolved = resolveOutboundTarget({
channel: params.channel,
to: params.to,
cfg: params.cfg,
mode: "explicit"
});
if (!resolved.ok) throw new Error(String(resolved.error));
const agentId = resolveSessionAgentId({
sessionKey: params.sessionKey,
config: params.cfg
});
await deliverOutboundPayloads({
cfg: params.cfg,
channel: params.channel,
to: resolved.to,
payloads: [{ text: params.text }],
agentId,
bestEffort: true,
deps: createOutboundSendDeps(params.deps)
});
}
const handleNodeEvent = async (ctx, nodeId, evt) => {
switch (evt.event) {
case "voice.transcript": {
if (!evt.payloadJSON) return;
let payload;
try {
payload = JSON.parse(evt.payloadJSON);
} catch {
return;
}
const obj = typeof payload === "object" && payload !== null ? payload : {};
const text = typeof obj.text === "string" ? obj.text.trim() : "";
if (!text) return;
if (text.length > 2e4) return;
const sessionKeyRaw = typeof obj.sessionKey === "string" ? obj.sessionKey.trim() : "";
const cfg = loadConfig();
const rawMainKey = normalizeMainKey(cfg.session?.mainKey);
const sessionKey = sessionKeyRaw.length > 0 ? sessionKeyRaw : rawMainKey;
const { storePath, entry, canonicalKey } = loadSessionEntry(sessionKey);
const now = Date.now();
if (shouldDropDuplicateVoiceTranscript({
sessionKey: canonicalKey,
fingerprint: resolveVoiceTranscriptFingerprint(obj, text),
now
})) return;
const sessionId = entry?.sessionId ?? randomUUID();
queueSessionStoreTouch({
ctx,
cfg,
sessionKey,
storePath,
canonicalKey,
entry,
sessionId,
now
});
ctx.addChatRun(sessionId, {
sessionKey: canonicalKey,
clientRunId: `voice-${randomUUID()}`
});
agentCommand({
message: text,
sessionId,
sessionKey: canonicalKey,
thinking: "low",
deliver: false,
messageChannel: "node",
inputProvenance: {
kind: "external_user",
sourceChannel: "voice",
sourceTool: "gateway.voice.transcript"
}
}, defaultRuntime, ctx.deps).catch((err) => {
ctx.logGateway.warn(`agent failed node=${nodeId}: ${formatForLog(err)}`);
});
return;
}
case "agent.request": {
if (!evt.payloadJSON) return;
let link = null;
try {
link = JSON.parse(evt.payloadJSON);
} catch {
return;
}
let message = (link?.message ?? "").trim();
const normalizedAttachments = normalizeRpcAttachmentsToChatAttachments(link?.attachments ?? void 0);
let images = [];
if (normalizedAttachments.length > 0) try {
const parsed = await parseMessageWithAttachments(message, normalizedAttachments, {
maxBytes: 5e6,
log: ctx.logGateway
});
message = parsed.message.trim();
images = parsed.images;
} catch {
return;
}
if (!message) return;
if (message.length > 2e4) return;
let channel = normalizeChannelId(typeof link?.channel === "string" ? link.channel.trim() : "") ?? void 0;
let to = typeof link?.to === "string" && link.to.trim() ? link.to.trim() : void 0;
const deliverRequested = Boolean(link?.deliver);
const wantsReceipt = Boolean(link?.receipt);
const receiptText = (typeof link?.receiptText === "string" ? link.receiptText.trim() : "") || "Just received your iOS share + request, working on it.";
const sessionKeyRaw = (link?.sessionKey ?? "").trim();
const sessionKey = sessionKeyRaw.length > 0 ? sessionKeyRaw : `node-${nodeId}`;
const cfg = loadConfig();
const { storePath, entry, canonicalKey } = loadSessionEntry(sessionKey);
const now = Date.now();
const sessionId = entry?.sessionId ?? randomUUID();
await touchSessionStore({
cfg,
sessionKey,
storePath,
canonicalKey,
entry,
sessionId,
now
});
if (deliverRequested && (!channel || !to)) {
const entryChannel = typeof entry?.lastChannel === "string" ? normalizeChannelId(entry.lastChannel) : void 0;
const entryTo = typeof entry?.lastTo === "string" ? entry.lastTo.trim() : "";
if (!channel && entryChannel) channel = entryChannel;
if (!to && entryTo) to = entryTo;
}
const deliver = deliverRequested && Boolean(channel && to);
const deliveryChannel = deliver ? channel : void 0;
const deliveryTo = deliver ? to : void 0;
if (deliverRequested && !deliver) ctx.logGateway.warn(`agent delivery disabled node=${nodeId}: missing session delivery route (channel=${channel ?? "-"} to=${to ?? "-"})`);
if (wantsReceipt && deliveryChannel && deliveryTo) sendReceiptAck({
cfg,
deps: ctx.deps,
sessionKey: canonicalKey,
channel: deliveryChannel,
to: deliveryTo,
text: receiptText
}).catch((err) => {
ctx.logGateway.warn(`agent receipt failed node=${nodeId}: ${formatForLog(err)}`);
});
else if (wantsReceipt) ctx.logGateway.warn(`agent receipt skipped node=${nodeId}: missing delivery route (channel=${deliveryChannel ?? "-"} to=${deliveryTo ?? "-"})`);
agentCommand({
message,
images,
sessionId,
sessionKey: canonicalKey,
thinking: link?.thinking ?? void 0,
deliver,
to: deliveryTo,
channel: deliveryChannel,
timeout: typeof link?.timeoutSeconds === "number" ? link.timeoutSeconds.toString() : void 0,
messageChannel: "node"
}, defaultRuntime, ctx.deps).catch((err) => {
ctx.logGateway.warn(`agent failed node=${nodeId}: ${formatForLog(err)}`);
});
return;
}
case "chat.subscribe": {
if (!evt.payloadJSON) return;
const sessionKey = parseSessionKeyFromPayloadJSON(evt.payloadJSON);
if (!sessionKey) return;
ctx.nodeSubscribe(nodeId, sessionKey);
return;
}
case "chat.unsubscribe": {
if (!evt.payloadJSON) return;
const sessionKey = parseSessionKeyFromPayloadJSON(evt.payloadJSON);
if (!sessionKey) return;
ctx.nodeUnsubscribe(nodeId, sessionKey);
return;
}
case "exec.started":
case "exec.finished":
case "exec.denied": {
if (!evt.payloadJSON) return;
let payload;
try {
payload = JSON.parse(evt.payloadJSON);
} catch {
return;
}
const obj = typeof payload === "object" && payload !== null ? payload : {};
const sessionKey = typeof obj.sessionKey === "string" ? obj.sessionKey.trim() : `node-${nodeId}`;
if (!sessionKey) return;
const runId = typeof obj.runId === "string" ? obj.runId.trim() : "";
const command = typeof obj.command === "string" ? obj.command.trim() : "";
const exitCode = typeof obj.exitCode === "number" && Number.isFinite(obj.exitCode) ? obj.exitCode : void 0;
const timedOut = obj.timedOut === true;
const output = typeof obj.output === "string" ? obj.output.trim() : "";
const reason = typeof obj.reason === "string" ? obj.reason.trim() : "";
let text = "";
if (evt.event === "exec.started") {
text = `Exec started (node=${nodeId}${runId ? ` id=${runId}` : ""})`;
if (command) text += `: ${command}`;
} else if (evt.event === "exec.finished") {
const exitLabel = timedOut ? "timeout" : `code ${exitCode ?? "?"}`;
const compactOutput = compactExecEventOutput(output);
if (!(timedOut || exitCode !== 0 || compactOutput.length > 0)) return;
text = `Exec finished (node=${nodeId}${runId ? ` id=${runId}` : ""}, ${exitLabel})`;
if (compactOutput) text += `\n${compactOutput}`;
} else {
text = `Exec denied (node=${nodeId}${runId ? ` id=${runId}` : ""}${reason ? `, ${reason}` : ""})`;
if (command) text += `: ${command}`;
}
enqueueSystemEvent(text, {
sessionKey,
contextKey: runId ? `exec:${runId}` : "exec"
});
requestHeartbeatNow({ reason: "exec-event" });
return;
}
case "push.apns.register": {
if (!evt.payloadJSON) return;
let payload;
try {
payload = JSON.parse(evt.payloadJSON);
} catch {
return;
}
const obj = typeof payload === "object" && payload !== null ? payload : {};
const token = typeof obj.token === "string" ? obj.token : "";
const topic = typeof obj.topic === "string" ? obj.topic : "";
const environment = obj.environment;
try {
await registerApnsToken({
nodeId,
token,
topic,
environment
});
} catch (err) {
ctx.logGateway.warn(`push apns register failed node=${nodeId}: ${formatForLog(err)}`);
}
return;
}
default: return;
}
};
//#endregion
export { handleNodeEvent };