var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// src/openclaw-compat.ts
var openclaw_compat_exports = {};
__export(openclaw_compat_exports, {
  onAgentEvent: () => onAgentEvent,
  onSessionTranscriptUpdate: () => onSessionTranscriptUpdate,
  requestHeartbeatNow: () => requestHeartbeatNow
});
async function requestHeartbeatNow(opts) {
  if (_heartbeatFn === null) {
    try {
      const mod = await import("openclaw/dist/plugin-sdk/infra/heartbeat-wake.js");
      _heartbeatFn = mod.requestHeartbeatNow ?? mod.default?.requestHeartbeatNow ?? false;
    } catch {
      _heartbeatFn = false;
    }
  }
  if (typeof _heartbeatFn === "function") {
    try {
      await _heartbeatFn(opts);
      return true;
    } catch {
      return false;
    }
  }
  return false;
}
async function onAgentEvent(callback) {
  if (_agentEventFn === null) {
    try {
      const mod = await import("openclaw/dist/plugin-sdk/infra/agent-events.js");
      _agentEventFn = mod.onAgentEvent ?? mod.default?.onAgentEvent ?? false;
    } catch {
      _agentEventFn = false;
    }
  }
  if (typeof _agentEventFn === "function") {
    try {
      return _agentEventFn(callback);
    } catch {
      return () => {
      };
    }
  }
  return () => {
  };
}
async function onSessionTranscriptUpdate(callback) {
  if (_transcriptFn === null) {
    try {
      const mod = await import("openclaw/dist/plugin-sdk/sessions/transcript-events.js");
      _transcriptFn = mod.onSessionTranscriptUpdate ?? mod.default?.onSessionTranscriptUpdate ?? false;
    } catch {
      _transcriptFn = false;
    }
  }
  if (typeof _transcriptFn === "function") {
    try {
      return _transcriptFn(callback);
    } catch {
      return () => {
      };
    }
  }
  return () => {
  };
}
var _heartbeatFn, _agentEventFn, _transcriptFn;
var init_openclaw_compat = __esm({
  "src/openclaw-compat.ts"() {
    "use strict";
    _heartbeatFn = null;
    _agentEventFn = null;
    _transcriptFn = null;
  }
});

// src/openclaw-entry.ts
import { resolve } from "node:path";
import { randomBytes } from "node:crypto";

// src/account-config.ts
var DEFAULT_API_URL = "https://api.agentvault.chat";
var DEFAULT_HTTP_PORT = 18790;
function listAccountIds(cfg) {
  const av = cfg?.channels?.agentvault;
  if (!av) return [];
  if (av.accounts && typeof av.accounts === "object") {
    return Object.keys(av.accounts);
  }
  return av.dataDir ? ["default"] : [];
}
function resolveAccount(cfg, accountId) {
  const av = cfg?.channels?.agentvault ?? {};
  const id = accountId ?? "default";
  if (av.accounts && typeof av.accounts === "object") {
    const acct = av.accounts[id];
    if (!acct) {
      return {
        accountId: id,
        dataDir: "",
        apiUrl: av.apiUrl ?? DEFAULT_API_URL,
        agentName: id,
        httpPort: DEFAULT_HTTP_PORT,
        configured: false
      };
    }
    let httpPort = acct.httpPort;
    if (httpPort == null) {
      const keys = Object.keys(av.accounts);
      const index = keys.indexOf(id);
      httpPort = DEFAULT_HTTP_PORT + (index >= 0 ? index : 0);
    }
    return {
      accountId: id,
      dataDir: acct.dataDir ?? "",
      apiUrl: acct.apiUrl ?? av.apiUrl ?? DEFAULT_API_URL,
      agentName: acct.agentName ?? id,
      httpPort,
      configured: Boolean(acct.dataDir)
    };
  }
  return {
    accountId: id,
    dataDir: av.dataDir ?? "~/.openclaw/agentvault",
    apiUrl: av.apiUrl ?? DEFAULT_API_URL,
    agentName: av.agentName ?? "OpenClaw Agent",
    httpPort: av.httpPort ?? DEFAULT_HTTP_PORT,
    configured: Boolean(av.dataDir)
  };
}

// src/fetch-interceptor.ts
import { AsyncLocalStorage } from "node:async_hooks";
import diagnosticsChannel from "node:diagnostics_channel";
var traceStore = new AsyncLocalStorage();
var DEFAULT_SKIP_PATTERNS = [
  /^https?:\/\/localhost(:\d+)?/,
  /^https?:\/\/127\.0\.0\.1(:\d+)?/,
  /\.agentvault\.chat/,
  /\.agentvault\.dev/,
  /\.clerk\./
];
var installed = false;
var originalFetch;
var inflightRequests = /* @__PURE__ */ new WeakMap();
var unsubCreate;
var unsubHeaders;
var unsubError;
function shouldSkip(url, extraPatterns) {
  const allPatterns = [...DEFAULT_SKIP_PATTERNS, ...extraPatterns];
  return allPatterns.some((p) => p.test(url));
}
function extractUrl(origin, path) {
  return `${origin}${path}`;
}
function installFetchInterceptor(opts) {
  if (installed) return;
  installed = true;
  const skipPatterns = [
    ...DEFAULT_SKIP_PATTERNS,
    ...opts.skipPatterns ?? []
  ];
  try {
    const createChannel = diagnosticsChannel.channel("undici:request:create");
    const headersChannel = diagnosticsChannel.channel("undici:request:headers");
    const errorChannel = diagnosticsChannel.channel("undici:request:error");
    const onRequestCreate = (message) => {
      try {
        const msg = message;
        const req = msg.request;
        if (!req) return;
        const origin = String(req.origin ?? "");
        const path = String(req.path ?? "/");
        const url = extractUrl(origin, path);
        if (shouldSkip(url, skipPatterns)) return;
        inflightRequests.set(req, {
          url,
          method: String(req.method ?? "GET").toUpperCase(),
          startTime: Date.now()
        });
      } catch {
      }
    };
    const onRequestHeaders = (message) => {
      try {
        const msg = message;
        const tracked = inflightRequests.get(msg.request);
        if (!tracked) return;
        inflightRequests.delete(msg.request);
        const latencyMs = Date.now() - tracked.startTime;
        const ctx = traceStore.getStore();
        opts.onHttpCall({
          method: tracked.method,
          url: tracked.url,
          statusCode: msg.response?.statusCode ?? 0,
          latencyMs,
          traceId: ctx?.traceId,
          parentSpanId: ctx?.parentSpanId
        });
      } catch {
      }
    };
    const onRequestError = (message) => {
      try {
        const msg = message;
        const tracked = inflightRequests.get(msg.request);
        if (!tracked) return;
        inflightRequests.delete(msg.request);
        const latencyMs = Date.now() - tracked.startTime;
        const ctx = traceStore.getStore();
        opts.onHttpCall({
          method: tracked.method,
          url: tracked.url,
          statusCode: 0,
          latencyMs,
          traceId: ctx?.traceId,
          parentSpanId: ctx?.parentSpanId
        });
      } catch {
      }
    };
    createChannel.subscribe(onRequestCreate);
    headersChannel.subscribe(onRequestHeaders);
    errorChannel.subscribe(onRequestError);
    unsubCreate = () => createChannel.unsubscribe(onRequestCreate);
    unsubHeaders = () => headersChannel.unsubscribe(onRequestHeaders);
    unsubError = () => errorChannel.unsubscribe(onRequestError);
  } catch {
  }
  originalFetch = globalThis.fetch;
  const savedOriginal = originalFetch;
  globalThis.fetch = async (input, init) => {
    const url = input instanceof Request ? input.url : input instanceof URL ? input.href : String(input);
    if (shouldSkip(url, skipPatterns)) {
      return savedOriginal(input, init);
    }
    const method = input instanceof Request ? input.method : init?.method ?? "GET";
    const ctx = traceStore.getStore();
    const start = Date.now();
    try {
      const response = await savedOriginal(input, init);
      const latencyMs = Date.now() - start;
      try {
        opts.onHttpCall({
          method,
          url,
          statusCode: response.status,
          latencyMs,
          traceId: ctx?.traceId,
          parentSpanId: ctx?.parentSpanId
        });
      } catch {
      }
      return response;
    } catch (err) {
      const latencyMs = Date.now() - start;
      try {
        opts.onHttpCall({
          method,
          url,
          statusCode: 0,
          latencyMs,
          traceId: ctx?.traceId,
          parentSpanId: ctx?.parentSpanId
        });
      } catch {
      }
      throw err;
    }
  };
}
function runWithTraceContext(ctx, fn) {
  return traceStore.run(ctx, fn);
}

// src/http-handlers.ts
async function handleSendRequest(parsed, channel) {
  const text = parsed.text;
  if (!text || typeof text !== "string") {
    return { status: 400, body: { ok: false, error: "Missing 'text' field" } };
  }
  try {
    if (parsed.hub_address && typeof parsed.hub_address === "string") {
      await channel.sendToAgent(parsed.hub_address, text);
    } else if (parsed.room_id && typeof parsed.room_id === "string") {
      await channel.sendToRoom(parsed.room_id, text, {
        messageType: parsed.message_type,
        priority: parsed.priority,
        metadata: parsed.metadata
      });
    } else if (parsed.file_path && typeof parsed.file_path === "string") {
      await channel.sendWithAttachment(text, parsed.file_path, {
        topicId: parsed.topicId
      });
    } else {
      await channel.send(text, {
        topicId: parsed.topicId,
        messageType: parsed.message_type,
        metadata: parsed.metadata
      });
    }
    return { status: 200, body: { ok: true } };
  } catch (err) {
    return { status: 500, body: { ok: false, error: String(err) } };
  }
}
async function handleActionRequest(parsed, channel) {
  if (!parsed.action || typeof parsed.action !== "string") {
    return { status: 400, body: { ok: false, error: "Missing 'action' field" } };
  }
  try {
    const confirmation = {
      action: parsed.action,
      status: parsed.status ?? "completed",
      decisionId: parsed.decision_id,
      detail: parsed.detail,
      estimated_cost: parsed.estimated_cost
    };
    if (parsed.room_id && typeof parsed.room_id === "string") {
      await channel.sendActionConfirmationToRoom(parsed.room_id, confirmation);
    } else {
      await channel.sendActionConfirmation(confirmation);
    }
    return { status: 200, body: { ok: true } };
  } catch (err) {
    return { status: 500, body: { ok: false, error: String(err) } };
  }
}
async function handleDecisionRequest(parsed, channel) {
  const title = parsed.title;
  if (!title || typeof title !== "string") {
    return { status: 400, body: { ok: false, error: "Missing 'title' field" } };
  }
  const options = parsed.options;
  if (!Array.isArray(options) || options.length < 2) {
    return { status: 400, body: { ok: false, error: "'options' must be an array with at least 2 items" } };
  }
  for (const opt of options) {
    if (!opt || typeof opt !== "object" || !opt.option_id || !opt.label) {
      return { status: 400, body: { ok: false, error: "Each option must have 'option_id' and 'label'" } };
    }
  }
  try {
    const decision_id = await channel.sendDecisionRequest({
      title,
      description: parsed.description,
      options,
      context_refs: parsed.context_refs,
      deadline: parsed.deadline,
      auto_action: parsed.auto_action
    });
    return { status: 200, body: { ok: true, decision_id } };
  } catch (err) {
    return { status: 500, body: { ok: false, error: String(err) } };
  }
}
function handleStatusRequest(channel) {
  return {
    status: 200,
    body: {
      ok: true,
      state: channel.state,
      deviceId: channel.deviceId ?? void 0,
      sessions: channel.sessionCount
    }
  };
}

// src/openclaw-entry.ts
init_openclaw_compat();
var _ocRuntime = null;
var _channels = /* @__PURE__ */ new Map();
var _messageQueue = [];
var isUsingManagedRoutes = false;
function _setRuntime(rt) {
  _ocRuntime = rt;
  if (_messageQueue.length > 0) {
    const pending = _messageQueue.splice(0);
    for (const fn of pending) {
      fn().catch(() => {
      });
    }
  }
}
function _parseMentions(text) {
  const mentions = [];
  const re = /@(\w[\w]*)/gi;
  let match;
  while ((match = re.exec(text)) !== null) {
    mentions.push(match[1].toLowerCase());
  }
  return mentions;
}
function _shouldProcessRoomMessage(plaintext, agentName, accountId) {
  const mentions = _parseMentions(plaintext);
  if (mentions.length === 0) return true;
  if (mentions.includes("all") || mentions.includes("everyone")) return true;
  const nameLower = agentName.toLowerCase();
  const idLower = accountId.toLowerCase();
  const firstWord = nameLower.split(/[\s(]/)[0];
  return mentions.some(
    (m) => m === nameLower || m === firstWord || m === idLower
  );
}
function _stripMentions(text, agentName, accountId) {
  const nameLower = agentName.toLowerCase();
  const firstWord = nameLower.split(/[\s(]/)[0];
  const idLower = accountId.toLowerCase();
  return text.replace(/@(\w[\w]*)/gi, (full, name) => {
    const lower = name.toLowerCase();
    if (lower === nameLower || lower === firstWord || lower === idLower) {
      return "";
    }
    if (lower === "all" || lower === "everyone") return "";
    return full;
  }).replace(/^\s+/, "").trim();
}
async function handleInbound(params) {
  const { plaintext: rawPlaintext, metadata, channel, account, cfg } = params;
  const isRoomMessage = Boolean(metadata.roomId);
  const isA2AMessage = Boolean(metadata.a2aChannelId);
  if (isRoomMessage) {
    if (!_shouldProcessRoomMessage(rawPlaintext, account.agentName ?? "", account.accountId ?? "")) {
      return;
    }
  }
  const plaintext = isRoomMessage ? _stripMentions(rawPlaintext, account.agentName ?? "", account.accountId ?? "") : rawPlaintext;
  const startTime = Date.now();
  const traceId = randomBytes(16).toString("hex");
  const rootSpanId = randomBytes(8).toString("hex");
  const inferenceSpanId = randomBytes(8).toString("hex");
  const _sendActivity = (spanData) => {
    try {
      channel.sendActivitySpan({ ...spanData, trace_id: traceId, parent_span_id: inferenceSpanId });
    } catch {
    }
  };
  const _instrument = {
    reportLlm: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportLlmCall(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.llm.model": opts.model ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "llm",
        span_name: opts.model ?? "LLM",
        status: opts.status === "error" ? "error" : "ok",
        start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: opts.latencyMs ?? 0,
        attributes: activityAttrs,
        tokens_input: opts.tokensInput,
        tokens_output: opts.tokensOutput
      });
    },
    reportTool: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportToolCall(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.tool.name": opts.toolName ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "tool",
        span_name: opts.toolName ?? "tool",
        status: opts.success === false ? "error" : "ok",
        start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: opts.latencyMs ?? 0,
        attributes: activityAttrs,
        tool_success: opts.success
      });
    },
    reportError: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportError(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.error.type": opts.errorType ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "error",
        span_name: opts.errorType ?? "error",
        status: "error",
        start_time: (/* @__PURE__ */ new Date()).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: 0,
        attributes: activityAttrs,
        error_type: opts.errorType,
        error_message: opts.errorMessage
      });
    },
    reportHttp: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportHttpCall(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.http.method": opts.method ?? "", "ai.agent.http.url": opts.url ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "http",
        span_name: (() => {
          try {
            return new URL(opts.url).hostname;
          } catch {
            return opts.url?.slice(0, 40) ?? "http";
          }
        })(),
        status: (opts.statusCode ?? 200) >= 400 ? "error" : "ok",
        start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: opts.latencyMs ?? 0,
        attributes: activityAttrs,
        http_method: opts.method,
        http_status_code: opts.statusCode,
        http_url: opts.url
      });
    },
    reportAction: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportActionCall(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.action.type": opts.actionType ?? "", "ai.agent.action.target": opts.target ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "action",
        span_name: `${opts.actionType ?? "action"}: ${opts.target ?? ""}`,
        status: opts.success === false ? "error" : "ok",
        start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: opts.latencyMs ?? 0,
        attributes: activityAttrs,
        action_type: opts.actionType,
        action_target: opts.target
      });
    },
    reportNav: (opts) => {
      const enriched = { ...opts, traceId, parentSpanId: inferenceSpanId };
      if (opts.skillName || _instrument.skillName) enriched.skillName = opts.skillName ?? _instrument.skillName;
      try {
        channel.telemetry?.reportNavCall(enriched);
      } catch {
      }
      const activityAttrs = { "ai.agent.nav.to_url": opts.toUrl ?? "" };
      if (enriched.skillName) activityAttrs["ai.agent.skill.name"] = enriched.skillName;
      _sendActivity({
        span_id: randomBytes(8).toString("hex"),
        span_type: "nav",
        span_name: opts.toUrl?.slice(0, 40) ?? "navigate",
        status: opts.status === "error" ? "error" : "ok",
        start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),
        end_time: (/* @__PURE__ */ new Date()).toISOString(),
        duration_ms: opts.latencyMs ?? 0,
        attributes: activityAttrs
      });
    },
    skillName: void 0,
    traceId,
    parentSpanId: inferenceSpanId
  };
  let replyCount = 0;
  let totalReplyChars = 0;
  let firstReplyTime = null;
  const replySpans = [];
  _emitChildSpan(channel, {
    traceId,
    parentSpanId: rootSpanId,
    name: "ai.agent.message.receive",
    startTime,
    endTime: startTime + 1,
    // instant
    attributes: {
      "ai.agent.message.input_chars": plaintext.length,
      "ai.agent.message.type": isA2AMessage ? "a2a" : metadata.roomId ? "room" : "direct"
    },
    status: "ok"
  });
  try {
    channel.sendTyping();
  } catch {
  }
  const core = _ocRuntime;
  const route = core.channel.routing.resolveAgentRoute({
    cfg,
    channel: "agentvault",
    accountId: account.accountId,
    peer: {
      kind: isA2AMessage ? "a2a" : "direct",
      id: isA2AMessage ? `agentvault:a2a:${metadata.fromHubAddress}` : isRoomMessage ? `agentvault:room:${metadata.roomId}` : "agentvault:owner"
    }
  });
  const storePath = core.channel.session.resolveStorePath(cfg?.session?.store, {
    agentId: route.agentId
  });
  const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
  const previousTimestamp = core.channel.session.readSessionUpdatedAt({
    storePath,
    sessionKey: route.sessionKey
  });
  const body = core.channel.reply.formatAgentEnvelope({
    channel: "AgentVault",
    from: isA2AMessage ? `Agent (${metadata.fromHubAddress})` : isRoomMessage ? "Room" : "Owner",
    timestamp: new Date(metadata.timestamp).getTime(),
    previousTimestamp,
    envelope: envelopeOptions,
    body: plaintext
  });
  const attachmentFields = {};
  if (metadata.attachment) {
    attachmentFields.AttachmentPath = metadata.attachment.filePath;
    attachmentFields.AttachmentFilename = metadata.attachment.filename;
    attachmentFields.AttachmentMime = metadata.attachment.mime;
    if (metadata.attachment.base64) {
      attachmentFields.MediaUrl = metadata.attachment.base64;
      attachmentFields.NumMedia = "1";
    }
  }
  const ctxPayload = core.channel.reply.finalizeInboundContext({
    Body: body,
    RawBody: plaintext,
    CommandBody: plaintext,
    From: isA2AMessage ? `a2a:${metadata.fromHubAddress}` : isRoomMessage ? `agentvault:room:${metadata.roomId}` : "agentvault:owner",
    To: `agentvault:agent:${account.accountId}`,
    SessionKey: route.sessionKey,
    AccountId: account.accountId,
    ChatType: isA2AMessage ? "a2a" : isRoomMessage ? "room" : "direct",
    ConversationLabel: isA2AMessage ? `A2A: ${metadata.fromHubAddress}` : isRoomMessage ? "AgentVault Room" : "AgentVault",
    SenderName: isA2AMessage ? metadata.fromHubAddress : isRoomMessage ? "Room" : "Owner",
    SenderId: isA2AMessage ? `a2a:${metadata.fromHubAddress}` : isRoomMessage ? `agentvault:room:${metadata.roomId}` : "agentvault:owner",
    Provider: "agentvault",
    Surface: "agentvault",
    MessageSid: metadata.messageId,
    Timestamp: new Date(metadata.timestamp).getTime(),
    OriginatingChannel: "agentvault",
    OriginatingTo: `agentvault:agent:${account.accountId}`,
    CommandAuthorized: true,
    Instrument: _instrument,
    // OpenClaw ctx convention
    AgentVaultTelemetry: _instrument,
    // AgentVault-specific accessor
    ...attachmentFields
  });
  await core.channel.session.recordInboundSession({
    storePath,
    sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
    ctx: ctxPayload,
    onRecordError: (err) => {
      core.error?.(`[AgentVault] session record failed: ${String(err)}`);
    }
  });
  try {
    await runWithTraceContext(
      { traceId, parentSpanId: inferenceSpanId },
      () => core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
        ctx: ctxPayload,
        cfg,
        dispatcherOptions: {
          deliver: async (payload) => {
            if (payload.kind === "thinking" || payload.kind === "reasoning") return;
            const text = (payload.text ?? "").trim();
            if (!text) return;
            if (/^(Reasoning|Thinking|Let me think|I need to|Let me check):/i.test(text)) return;
            const replyStart = Date.now();
            replyCount++;
            totalReplyChars += text.length;
            if (!firstReplyTime) firstReplyTime = replyStart;
            if (isA2AMessage) {
              await channel.sendToAgent(metadata.fromHubAddress, text, {
                parentSpanId: inferenceSpanId
              });
            } else if (isRoomMessage) {
              await channel.sendToRoom(metadata.roomId, text, {
                metadata: { content_length: text.length }
              });
            } else {
              await channel.send(text, {
                conversationId: metadata.conversationId,
                topicId: metadata.topicId
              });
            }
            const replyEnd = Date.now();
            replySpans.push({ startTime: replyStart, endTime: replyEnd, chars: text.length, index: replyCount });
          },
          onError: (err, info) => {
            core.error?.(`[AgentVault] ${info?.kind ?? "reply"} error: ${String(err)}`);
          }
        },
        replyOptions: {}
      })
    );
    const endTime = Date.now();
    _emitHierarchicalSpans(channel, {
      traceId,
      rootSpanId,
      inferenceSpanId,
      startTime,
      endTime,
      firstReplyTime,
      replySpans,
      inputChars: plaintext.length,
      replyCount,
      totalReplyChars,
      isRoom: isRoomMessage,
      status: "ok"
    });
  } catch (err) {
    const endTime = Date.now();
    _emitHierarchicalSpans(channel, {
      traceId,
      rootSpanId,
      inferenceSpanId,
      startTime,
      endTime,
      firstReplyTime,
      replySpans,
      inputChars: plaintext.length,
      replyCount,
      totalReplyChars,
      isRoom: isRoomMessage,
      status: "error",
      statusMessage: String(err)
    });
    _emitChildSpan(channel, {
      traceId,
      parentSpanId: rootSpanId,
      name: "error",
      startTime: endTime,
      endTime,
      attributes: {
        "ai.agent.error.type": err?.constructor?.name ?? "Error",
        "ai.agent.error.message": String(err)
      },
      status: "error",
      statusMessage: String(err)
    });
    throw err;
  }
}
function _inferSpanType(name) {
  if (name === "error" || name.includes("error")) return "error";
  if (name.startsWith("llm.") || name.includes("inference")) return "llm";
  if (name.startsWith("tool.") || name.includes("tool")) return "tool";
  if (name.startsWith("http.") || name.includes("http")) return "http";
  if (name.startsWith("nav.") || name.includes("nav")) return "nav";
  if (name.startsWith("action.") || name.includes("action")) return "action";
  return "action";
}
function _extractSpanName(name, attrs) {
  if (attrs["ai.agent.llm.model"]) return String(attrs["ai.agent.llm.model"]);
  if (attrs["ai.agent.tool.name"]) return String(attrs["ai.agent.tool.name"]);
  if (attrs["ai.agent.http.url"]) {
    try {
      return new URL(String(attrs["ai.agent.http.url"])).hostname;
    } catch {
    }
    return String(attrs["ai.agent.http.url"]).slice(0, 40);
  }
  if (attrs["ai.agent.action.type"]) return `${attrs["ai.agent.action.type"]}: ${attrs["ai.agent.action.target"] ?? ""}`;
  if (attrs["ai.agent.nav.to_url"]) return String(attrs["ai.agent.nav.to_url"]).slice(0, 40);
  if (attrs["ai.agent.error.type"]) return String(attrs["ai.agent.error.type"]);
  return name;
}
function _emitChildSpan(channel, opts) {
  try {
    const reporter = channel.telemetry;
    if (!reporter) return;
    const spanId = opts.spanId ?? randomBytes(8).toString("hex");
    reporter.reportCustomSpan({
      traceId: opts.traceId,
      spanId,
      parentSpanId: opts.parentSpanId,
      name: opts.name,
      kind: "internal",
      startTime: opts.startTime,
      endTime: opts.endTime,
      attributes: opts.attributes,
      status: {
        code: opts.status === "ok" ? 1 : 2,
        message: opts.statusMessage
      }
    });
    try {
      const spanType = _inferSpanType(opts.name);
      const spanName = _extractSpanName(opts.name, opts.attributes);
      const durationMs = opts.endTime - opts.startTime;
      channel.sendActivitySpan({
        trace_id: opts.traceId,
        span_id: spanId,
        parent_span_id: opts.parentSpanId,
        span_type: spanType,
        span_name: spanName,
        status: opts.status,
        start_time: new Date(opts.startTime).toISOString(),
        end_time: new Date(opts.endTime).toISOString(),
        duration_ms: durationMs,
        attributes: opts.attributes,
        ...spanType === "llm" ? {
          tokens_input: opts.attributes["ai.agent.llm.tokens_input"],
          tokens_output: opts.attributes["ai.agent.llm.tokens_output"]
        } : {},
        ...spanType === "http" ? {
          http_method: opts.attributes["ai.agent.http.method"],
          http_status_code: opts.attributes["ai.agent.http.status_code"],
          http_url: opts.attributes["ai.agent.http.url"]
        } : {},
        ...spanType === "tool" ? {
          tool_success: opts.attributes["ai.agent.tool.success"]
        } : {},
        ...spanType === "error" ? {
          error_type: opts.attributes["ai.agent.error.type"],
          error_message: opts.attributes["ai.agent.error.message"]
        } : {}
      });
    } catch {
    }
  } catch {
  }
}
function _emitHierarchicalSpans(channel, opts) {
  try {
    const reporter = channel.telemetry;
    if (!reporter) return;
    const inferenceEnd = opts.firstReplyTime ?? opts.endTime;
    _emitChildSpan(channel, {
      traceId: opts.traceId,
      parentSpanId: opts.rootSpanId,
      spanId: opts.inferenceSpanId,
      name: "ai.agent.inference",
      startTime: opts.startTime + 1,
      // just after receive
      endTime: inferenceEnd,
      attributes: {
        "ai.agent.inference.latency_ms": inferenceEnd - opts.startTime,
        "ai.agent.message.input_chars": opts.inputChars
      },
      status: opts.status,
      statusMessage: opts.status === "error" ? opts.statusMessage : void 0
    });
    for (const reply of opts.replySpans) {
      _emitChildSpan(channel, {
        traceId: opts.traceId,
        parentSpanId: opts.rootSpanId,
        name: "ai.agent.reply",
        startTime: reply.startTime,
        endTime: reply.endTime,
        attributes: {
          "ai.agent.reply.index": reply.index,
          "ai.agent.reply.chars": reply.chars
        },
        status: "ok"
      });
    }
    reporter.reportCustomSpan({
      traceId: opts.traceId,
      spanId: opts.rootSpanId,
      name: "ai.agent.message",
      kind: "server",
      startTime: opts.startTime,
      endTime: opts.endTime,
      attributes: {
        "ai.agent.message.input_chars": opts.inputChars,
        "ai.agent.message.reply_count": opts.replyCount,
        "ai.agent.message.reply_chars": opts.totalReplyChars,
        "ai.agent.message.latency_ms": opts.endTime - opts.startTime,
        "ai.agent.message.type": opts.isRoom ? "room" : "direct"
      },
      status: {
        code: opts.status === "ok" ? 1 : 2,
        message: opts.statusMessage
      }
    });
  } catch {
  }
}
var agentVaultPlugin = {
  id: "agentvault",
  meta: {
    id: "agentvault",
    label: "AgentVault",
    selectionLabel: "AgentVault (E2E Encrypted)",
    docsPath: "https://agentvault.chat/docs",
    blurb: "Zero-knowledge, end-to-end encrypted messaging between owners and their AI agents.",
    aliases: ["av", "agent-vault"]
  },
  capabilities: { chatTypes: ["direct", "room"] },
  config: { listAccountIds, resolveAccount },
  gateway: {
    /** Health probe for `openclaw channels status --probe` */
    probe: async (ctx) => {
      const accountId = ctx?.accountId ?? "default";
      const ch = _channels.get(accountId);
      if (!ch) return { ok: false, status: "disconnected", error: "Channel not started" };
      const state = ch.state;
      return {
        ok: state === "ready",
        status: state,
        deviceId: ch.deviceId ?? void 0,
        sessions: ch.sessionCount
      };
    },
    /** Status for `openclaw health --json` per-channel summary */
    status: (ctx) => {
      const accountId = ctx?.accountId ?? "default";
      const ch = _channels.get(accountId);
      if (!ch) return { connected: false, status: "not_started" };
      return {
        connected: ch.state === "ready",
        status: ch.state,
        deviceId: ch.deviceId ?? void 0,
        sessions: ch.sessionCount,
        encrypted: true
      };
    },
    startAccount: async (ctx) => {
      const { account, cfg, log, abortSignal } = ctx;
      const _log = typeof log === "function" ? log : log?.info?.bind(log);
      if (!account.configured) {
        throw new Error(
          "AgentVault channel not configured. Run: npx @agentvault/agentvault setup --token=av_tok_...\nThen restart OpenClaw."
        );
      }
      const dataDir = resolve(account.dataDir.replace(/^~/, process.env.HOME ?? "~"));
      _log?.(`[AgentVault] starting (dataDir=${dataDir})`);
      await new Promise((resolve2, reject) => {
        let channel;
        const onAbort = async () => {
          await channel?.stop();
          _channels.delete(account.accountId);
          resolve2();
        };
        abortSignal?.addEventListener("abort", () => void onAbort());
        import("./index.js").then(({ SecureChannel }) => {
          channel = new SecureChannel({
            inviteToken: "",
            dataDir,
            apiUrl: account.apiUrl,
            agentName: account.agentName,
            onMessage: async (plaintext, metadata) => {
              if (!_ocRuntime) {
                _log?.("[AgentVault] runtime not ready, queuing message");
                _messageQueue.push(async () => {
                  await handleInbound({ plaintext, metadata, channel, account, cfg });
                });
                return;
              }
              try {
                await handleInbound({ plaintext, metadata, channel, account, cfg });
              } catch (err) {
                _log?.(`[AgentVault] inbound error: ${String(err)}`);
              }
            },
            onA2AMessage: async (msg) => {
              const a2aMetadata = {
                a2aChannelId: msg.channelId,
                fromHubAddress: msg.fromHubAddress,
                conversationId: msg.conversationId,
                timestamp: msg.timestamp,
                parentSpanId: msg.parentSpanId,
                messageId: `a2a:${msg.channelId}:${Date.now()}`
              };
              if (!_ocRuntime) {
                _log?.("[AgentVault] runtime not ready, queuing A2A message");
                _messageQueue.push(async () => {
                  await handleInbound({ plaintext: msg.text, metadata: a2aMetadata, channel, account, cfg });
                });
                return;
              }
              try {
                await handleInbound({ plaintext: msg.text, metadata: a2aMetadata, channel, account, cfg });
              } catch (err) {
                _log?.(`[AgentVault] A2A inbound error: ${String(err)}`);
              }
            },
            onStateChange: (state) => {
              _log?.(`[AgentVault] \u2192 ${state}`);
              if (state === "error") reject(new Error("AgentVault channel permanent error"));
            }
          });
          _channels.set(account.accountId, channel);
          channel.on("error", (err) => {
            _log?.(`[AgentVault] channel error (non-fatal): ${String(err)}`);
          });
          const httpPort = account.httpPort ?? 18790;
          channel.on("ready", () => {
            channel.startHttpServer(httpPort);
            _log?.(`[AgentVault] HTTP send server listening on http://127.0.0.1:${httpPort}`);
            if (isUsingManagedRoutes) {
              _log?.(`[AgentVault] OpenClaw managed routes also registered`);
            }
          });
          channel.start().catch(reject);
        }).catch(reject);
      });
      return { stop: async () => {
      } };
    }
  },
  outbound: {
    deliveryMode: "direct",
    // Register valid send targets so OpenClaw's `message` tool can route
    // proactive (agent-initiated) sends — not just replies to inbound messages.
    targets: [
      {
        id: "owner",
        label: "AgentVault Owner",
        accountId: "default"
      },
      {
        id: "default",
        label: "AgentVault Owner (default)",
        accountId: "default"
      }
    ],
    sendText: async ({ to, text, accountId }) => {
      const resolvedId = accountId ?? "default";
      const ch = _channels.get(resolvedId);
      if (!ch) return { ok: false, error: "AgentVault channel not connected" };
      try {
        const wasReady = ch.state === "ready";
        if (to.startsWith("a2a:")) {
          const hubAddress = to.slice(4);
          await ch.sendToAgent(hubAddress, text);
        } else {
          await ch.send(text);
        }
        return { ok: true, queued: !wasReady };
      } catch (err) {
        return { ok: false, error: String(err) };
      }
    },
    sendMedia: async ({ to, text, mediaUrl, accountId }) => {
      const resolvedId = accountId ?? "default";
      const ch = _channels.get(resolvedId);
      if (!ch) return { ok: false, error: "AgentVault channel not connected" };
      try {
        const message = text ? `${text}
${mediaUrl}` : mediaUrl;
        const wasReady = ch.state === "ready";
        if (to.startsWith("a2a:")) {
          await ch.sendToAgent(to.slice(4), message);
        } else {
          await ch.send(message);
        }
        return { ok: true, queued: !wasReady };
      } catch (err) {
        return { ok: false, error: String(err) };
      }
    },
    /** Rich payload delivery — OpenClaw v2026.3.2+ calls this for structured messages. */
    sendPayload: async (ctx) => {
      const { payload, accountId } = ctx;
      const resolvedId = accountId ?? "default";
      const ch = _channels.get(resolvedId);
      if (!ch) return { ok: false, error: "AgentVault channel not connected" };
      try {
        if (payload.isReasoning) return { ok: true };
        requestHeartbeatNow({ reason: "outbound-payload" }).catch(() => {
        });
        const text = (payload.text ?? "").trim();
        if (!text && !payload.mediaUrls?.length) return { ok: true };
        const _send = async (msg) => {
          const target = ctx.to;
          if (target && typeof target === "string" && target.startsWith("a2a:")) {
            await ch.sendToAgent(target.slice(4), msg);
          } else {
            await ch.send(msg);
          }
        };
        if (text) {
          await _send(text);
        }
        if (payload.mediaUrls?.length) {
          for (const url of payload.mediaUrls) {
            await _send(url);
          }
        }
        if (payload.suggestedActions?.length) {
          const actionsText = payload.suggestedActions.map((a) => `- ${a.label}: ${a.action}`).join("\n");
          await _send(`Suggested actions:
${actionsText}`);
        }
        return { ok: true };
      } catch (err) {
        return { ok: false, error: String(err) };
      }
    }
  }
};
var openclaw_entry_default = {
  id: "agentvault",
  name: "AgentVault",
  description: "End-to-end encrypted, zero-knowledge messaging between AI agent owners and their agents.",
  register(api) {
    _setRuntime(api.runtime);
    installFetchInterceptor({
      onHttpCall: (report) => {
        const ch = _channels.values().next().value;
        if (!ch) return;
        if (ch.telemetry) {
          try {
            ch.telemetry.reportHttpCall({
              method: report.method,
              url: report.url,
              statusCode: report.statusCode,
              latencyMs: report.latencyMs,
              ...report.traceId ? { traceId: report.traceId } : {},
              ...report.parentSpanId ? { parentSpanId: report.parentSpanId } : {}
            });
          } catch {
          }
        }
        try {
          const hostname = (() => {
            try {
              return new URL(report.url).hostname;
            } catch {
              return report.url.slice(0, 40);
            }
          })();
          ch.sendActivitySpan({
            trace_id: report.traceId ?? "",
            parent_span_id: report.parentSpanId ?? "",
            span_id: randomBytes(8).toString("hex"),
            span_type: "http",
            span_name: hostname,
            status: report.statusCode >= 400 || report.statusCode === 0 ? "error" : "ok",
            start_time: new Date(Date.now() - report.latencyMs).toISOString(),
            end_time: (/* @__PURE__ */ new Date()).toISOString(),
            duration_ms: report.latencyMs,
            attributes: {
              "ai.agent.http.method": report.method,
              "ai.agent.http.url": report.url
            },
            http_method: report.method,
            http_status_code: report.statusCode,
            http_url: report.url
          });
        } catch {
        }
      }
    });
    api.registerChannel({ plugin: agentVaultPlugin });
    if (typeof api.registerHttpRoute === "function") {
      try {
        api.registerHttpRoute({
          path: "/agentvault/send",
          method: "POST",
          handler: async (req) => {
            const ch = _channels.values().next().value;
            if (!ch) return { status: 503, body: { ok: false, error: "Channel not started" } };
            const parsed = typeof req.body === "string" ? JSON.parse(req.body) : req.body;
            const result = await handleSendRequest(parsed, ch);
            return { status: result.status, body: result.body };
          }
        });
        api.registerHttpRoute({
          path: "/agentvault/action",
          method: "POST",
          handler: async (req) => {
            const ch = _channels.values().next().value;
            if (!ch) return { status: 503, body: { ok: false, error: "Channel not started" } };
            const parsed = typeof req.body === "string" ? JSON.parse(req.body) : req.body;
            const result = await handleActionRequest(parsed, ch);
            return { status: result.status, body: result.body };
          }
        });
        api.registerHttpRoute({
          path: "/agentvault/decision",
          method: "POST",
          handler: async (req) => {
            const ch = _channels.values().next().value;
            if (!ch) return { status: 503, body: { ok: false, error: "Channel not started" } };
            const parsed = typeof req.body === "string" ? JSON.parse(req.body) : req.body;
            const result = await handleDecisionRequest(parsed, ch);
            return { status: result.status, body: result.body };
          }
        });
        api.registerHttpRoute({
          path: "/agentvault/status",
          method: "GET",
          handler: async () => {
            const ch = _channels.values().next().value;
            if (!ch) return { status: 503, body: { ok: false, error: "Channel not started" } };
            const result = handleStatusRequest(ch);
            return { status: result.status, body: result.body };
          }
        });
        isUsingManagedRoutes = true;
      } catch {
      }
    }
    if (typeof api.on === "function") {
      api.on("message_sent", async (event) => {
        try {
          const ch = _channels.values().next().value;
          if (!ch?.telemetry) return;
          ch.telemetry.reportCustomSpan({
            traceId: randomBytes(16).toString("hex"),
            spanId: randomBytes(8).toString("hex"),
            name: "agentvault.message.delivered",
            kind: "internal",
            startTime: event.timestamp,
            endTime: event.timestamp + 1,
            attributes: {
              "agentvault.message.id": event.messageId,
              "agentvault.delivery.status": event.deliveryStatus,
              "agentvault.channel.id": event.channelId
            },
            status: { code: event.deliveryStatus === "failed" ? 2 : 1 }
          });
        } catch {
        }
      });
      api.on("session_start", async (event) => {
        try {
          const ch = _channels.values().next().value;
          if (!ch?.telemetry) return;
          ch.telemetry.reportCustomSpan({
            traceId: randomBytes(16).toString("hex"),
            spanId: randomBytes(8).toString("hex"),
            name: "agentvault.session.start",
            kind: "internal",
            startTime: event.timestamp,
            endTime: event.timestamp + 1,
            attributes: {
              "agentvault.session.key": event.sessionKey,
              "agentvault.agent.id": event.agentId
            },
            status: { code: 1 }
          });
        } catch {
        }
      });
      api.on("session_end", async (event) => {
        try {
          const ch = _channels.values().next().value;
          if (!ch?.telemetry) return;
          ch.telemetry.reportCustomSpan({
            traceId: randomBytes(16).toString("hex"),
            spanId: randomBytes(8).toString("hex"),
            name: "agentvault.session.end",
            kind: "internal",
            startTime: event.timestamp,
            endTime: event.timestamp + 1,
            attributes: {
              "agentvault.session.key": event.sessionKey,
              "agentvault.agent.id": event.agentId,
              ...event.reason ? { "agentvault.session.end_reason": event.reason } : {}
            },
            status: { code: 1 }
          });
        } catch {
        }
      });
    }
    Promise.resolve().then(() => (init_openclaw_compat(), openclaw_compat_exports)).then(async ({ onAgentEvent: onAgentEvent2, onSessionTranscriptUpdate: onSessionTranscriptUpdate2 }) => {
      onAgentEvent2((event) => {
        try {
          const ch = _channels.values().next().value;
          if (!ch?.telemetry) return;
          ch.telemetry.reportCustomSpan({
            traceId: randomBytes(16).toString("hex"),
            spanId: randomBytes(8).toString("hex"),
            name: `ai.agent.event.${event.type}`,
            kind: "internal",
            startTime: event.timestamp,
            endTime: event.timestamp + 1,
            attributes: {
              "ai.agent.event.type": event.type,
              "ai.agent.id": event.agentId,
              ...event.data ? Object.fromEntries(
                Object.entries(event.data).map(([k, v]) => [`ai.agent.event.${k}`, String(v)])
              ) : {}
            },
            status: { code: 1 }
          });
        } catch {
        }
      }).catch(() => {
      });
      onSessionTranscriptUpdate2((update) => {
        try {
          const ch = _channels.values().next().value;
          if (!ch?.telemetry) return;
          ch.telemetry.reportCustomSpan({
            traceId: randomBytes(16).toString("hex"),
            spanId: randomBytes(8).toString("hex"),
            name: "ai.agent.transcript.update",
            kind: "internal",
            startTime: update.timestamp,
            endTime: update.timestamp + 1,
            attributes: {
              "agentvault.session.key": update.sessionKey,
              "ai.agent.transcript.role": update.role ?? "unknown",
              "ai.agent.transcript.delta_chars": update.delta.length
            },
            status: { code: 1 }
          });
        } catch {
        }
      }).catch(() => {
      });
    }).catch(() => {
    });
    try {
      api.registerTool?.({
        name: "agentvault_status",
        description: "Check the AgentVault encrypted channel status, connection state, and session count.",
        parameters: {
          type: "object",
          properties: {
            accountId: {
              type: "string",
              description: "Account ID to check (default: 'default')"
            }
          }
        },
        execute: async (_id, params) => {
          const id = params.accountId ?? "default";
          const ch = _channels.get(id);
          if (!ch) {
            return { content: [{ type: "text", text: JSON.stringify({ connected: false, error: "Channel not started" }) }] };
          }
          return {
            content: [{
              type: "text",
              text: JSON.stringify({
                connected: ch.state === "ready",
                state: ch.state,
                deviceId: ch.deviceId,
                sessions: ch.sessionCount,
                encrypted: true
              })
            }]
          };
        }
      }, { optional: true });
    } catch {
    }
    try {
      api.registerCommand?.({
        name: "agentvault",
        description: "Show AgentVault encrypted channel status",
        handler: () => {
          const statuses = [];
          if (_channels.size === 0) {
            statuses.push("AgentVault: no active channels");
          } else {
            for (const [id, ch] of _channels) {
              statuses.push(`AgentVault [${id}]: ${ch.state} | sessions: ${ch.sessionCount} | encrypted: yes`);
            }
          }
          return { text: statuses.join("\n") };
        }
      });
    } catch {
    }
  }
};
export {
  _parseMentions,
  _shouldProcessRoomMessage,
  _stripMentions,
  openclaw_entry_default as default,
  isUsingManagedRoutes
};
//# sourceMappingURL=openclaw-entry.js.map
