@agentvault/agentvault 0.13.8 → 0.13.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"openclaw-entry.d.ts","sourceRoot":"","sources":["../src/openclaw-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,uEAAuE;AACvE,iBAAS,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9C;AAED,qFAAqF;AACrF,iBAAS,yBAAyB,CAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAcT;AAED,sFAAsF;AACtF,iBAAS,cAAc,CACrB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAiBR;AA+mBD,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,cAAc,EAAE,CAAC;;;;;kBAQrD,GAAG;;AAJnB,wBAuDE"}
1
+ {"version":3,"file":"openclaw-entry.d.ts","sourceRoot":"","sources":["../src/openclaw-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,uEAAuE;AACvE,iBAAS,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9C;AAED,qFAAqF;AACrF,iBAAS,yBAAyB,CAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAcT;AAED,sFAAsF;AACtF,iBAAS,cAAc,CACrB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAiBR;AA2oBD,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,cAAc,EAAE,CAAC;;;;;kBAQrD,GAAG;;AAJnB,wBAgHE"}
@@ -696,9 +696,35 @@ var agentVaultPlugin = {
696
696
  blurb: "Zero-knowledge, end-to-end encrypted messaging between owners and their AI agents.",
697
697
  aliases: ["av", "agent-vault"]
698
698
  },
699
- capabilities: { chatTypes: ["direct"] },
699
+ capabilities: { chatTypes: ["direct", "room"] },
700
700
  config: { listAccountIds, resolveAccount },
701
701
  gateway: {
702
+ /** Health probe for `openclaw channels status --probe` */
703
+ probe: async (ctx) => {
704
+ const accountId = ctx?.accountId ?? "default";
705
+ const ch = _channels.get(accountId);
706
+ if (!ch) return { ok: false, status: "disconnected", error: "Channel not started" };
707
+ const state = ch.state;
708
+ return {
709
+ ok: state === "ready",
710
+ status: state,
711
+ deviceId: ch.deviceId ?? void 0,
712
+ sessions: ch.sessionCount
713
+ };
714
+ },
715
+ /** Status for `openclaw health --json` per-channel summary */
716
+ status: (ctx) => {
717
+ const accountId = ctx?.accountId ?? "default";
718
+ const ch = _channels.get(accountId);
719
+ if (!ch) return { connected: false, status: "not_started" };
720
+ return {
721
+ connected: ch.state === "ready",
722
+ status: ch.state,
723
+ deviceId: ch.deviceId ?? void 0,
724
+ sessions: ch.sessionCount,
725
+ encrypted: true
726
+ };
727
+ },
702
728
  startAccount: async (ctx) => {
703
729
  const { account, cfg, log, abortSignal } = ctx;
704
730
  if (!account.configured) {
@@ -856,6 +882,59 @@ var openclaw_entry_default = {
856
882
  }
857
883
  });
858
884
  api.registerChannel({ plugin: agentVaultPlugin });
885
+ try {
886
+ api.registerTool?.({
887
+ name: "agentvault_status",
888
+ description: "Check the AgentVault encrypted channel status, connection state, and session count.",
889
+ parameters: {
890
+ type: "object",
891
+ properties: {
892
+ accountId: {
893
+ type: "string",
894
+ description: "Account ID to check (default: 'default')"
895
+ }
896
+ }
897
+ },
898
+ execute: async (_id, params) => {
899
+ const id = params.accountId ?? "default";
900
+ const ch = _channels.get(id);
901
+ if (!ch) {
902
+ return { content: [{ type: "text", text: JSON.stringify({ connected: false, error: "Channel not started" }) }] };
903
+ }
904
+ return {
905
+ content: [{
906
+ type: "text",
907
+ text: JSON.stringify({
908
+ connected: ch.state === "ready",
909
+ state: ch.state,
910
+ deviceId: ch.deviceId,
911
+ sessions: ch.sessionCount,
912
+ encrypted: true
913
+ })
914
+ }]
915
+ };
916
+ }
917
+ }, { optional: true });
918
+ } catch {
919
+ }
920
+ try {
921
+ api.registerCommand?.({
922
+ name: "agentvault",
923
+ description: "Show AgentVault encrypted channel status",
924
+ handler: () => {
925
+ const statuses = [];
926
+ if (_channels.size === 0) {
927
+ statuses.push("AgentVault: no active channels");
928
+ } else {
929
+ for (const [id, ch] of _channels) {
930
+ statuses.push(`AgentVault [${id}]: ${ch.state} | sessions: ${ch.sessionCount} | encrypted: yes`);
931
+ }
932
+ }
933
+ return { text: statuses.join("\n") };
934
+ }
935
+ });
936
+ } catch {
937
+ }
859
938
  }
860
939
  };
861
940
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/openclaw-entry.ts", "../src/account-config.ts", "../src/fetch-interceptor.ts"],
4
- "sourcesContent": ["/**\n * OpenClaw channel plugin entry point.\n *\n * Intentionally thin \u2014 no heavy imports (libsodium etc.) at module load time.\n * SecureChannel is dynamically imported inside gateway.startAccount (already async)\n * so libsodium's top-level await never runs during plugin registration.\n *\n * Loaded by OpenClaw via the `openclaw.extensions` field in package.json.\n */\n\nimport { resolve } from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport { listAccountIds, resolveAccount } from \"./account-config.js\";\nimport { installFetchInterceptor, runWithTraceContext } from \"./fetch-interceptor.js\";\n\n// --- Runtime and active channels (set during register) ---\nlet _ocRuntime: any = null;\nconst _channels = new Map<string, any>();\nconst _messageQueue: Array<() => Promise<void>> = [];\n\nfunction _setRuntime(rt: any) {\n _ocRuntime = rt;\n // Flush any messages that arrived before runtime was ready\n if (_messageQueue.length > 0) {\n const pending = _messageQueue.splice(0);\n for (const fn of pending) {\n fn().catch(() => {});\n }\n }\n}\n\n// --- @mention filtering for multi-agent rooms ---\n\n/** Extract @mention names from plaintext. Returns lowercased names. */\nfunction _parseMentions(text: string): string[] {\n const mentions: string[] = [];\n // Match @word at word boundary \u2014 supports multi-word via sequential matching\n const re = /@(\\w[\\w]*)/gi;\n let match: RegExpExecArray | null;\n while ((match = re.exec(text)) !== null) {\n mentions.push(match[1].toLowerCase());\n }\n return mentions;\n}\n\n/** Determine whether this agent should process a room message based on @mentions. */\nfunction _shouldProcessRoomMessage(\n plaintext: string,\n agentName: string,\n accountId: string,\n): boolean {\n const mentions = _parseMentions(plaintext);\n // No mentions \u2192 broadcast to all agents (current behavior)\n if (mentions.length === 0) return true;\n // @all / @everyone \u2192 all agents process\n if (mentions.includes(\"all\") || mentions.includes(\"everyone\")) return true;\n // Check if this agent is mentioned (by name or accountId)\n const nameLower = agentName.toLowerCase();\n const idLower = accountId.toLowerCase();\n // Match first word of agent name (e.g., \"Cortina\" from \"Cortina (Coder)\")\n const firstWord = nameLower.split(/[\\s(]/)[0];\n return mentions.some(\n (m) => m === nameLower || m === firstWord || m === idLower,\n );\n}\n\n/** Strip the matching @mention prefix from plaintext so the agent sees clean text. */\nfunction _stripMentions(\n text: string,\n agentName: string,\n accountId: string,\n): string {\n const nameLower = agentName.toLowerCase();\n const firstWord = nameLower.split(/[\\s(]/)[0];\n const idLower = accountId.toLowerCase();\n // Remove all @mentions that match this agent (case-insensitive)\n return text\n .replace(/@(\\w[\\w]*)/gi, (full, name) => {\n const lower = name.toLowerCase();\n if (lower === nameLower || lower === firstWord || lower === idLower) {\n return \"\";\n }\n // Also strip @all/@everyone since they're routing directives\n if (lower === \"all\" || lower === \"everyone\") return \"\";\n return full;\n })\n .replace(/^\\s+/, \"\") // trim leading whitespace left by stripped mention\n .trim();\n}\n\n// --- Inbound message dispatch ---\n\nasync function handleInbound(params: {\n plaintext: string;\n metadata: any;\n channel: any;\n account: any;\n cfg: any;\n}): Promise<void> {\n const { plaintext: rawPlaintext, metadata, channel, account, cfg } = params;\n const isRoomMessage = Boolean(metadata.roomId);\n\n // @mention filtering: only for room messages\n if (isRoomMessage) {\n if (!_shouldProcessRoomMessage(rawPlaintext, account.agentName ?? \"\", account.accountId ?? \"\")) {\n return; // This agent is not mentioned \u2014 skip silently\n }\n }\n\n // Strip @mentions from plaintext so the agent sees clean text\n const plaintext = isRoomMessage\n ? _stripMentions(rawPlaintext, account.agentName ?? \"\", account.accountId ?? \"\")\n : rawPlaintext;\n\n // Telemetry: hierarchical spans for the full message lifecycle\n const startTime = Date.now();\n const traceId = randomBytes(16).toString(\"hex\");\n const rootSpanId = randomBytes(8).toString(\"hex\");\n const inferenceSpanId = randomBytes(8).toString(\"hex\");\n // Instrumentation context for agent code to report LLM/tool/error spans\n /** Helper: send an activity span over WS for real-time owner display. */\n const _sendActivity = (spanData: Record<string, unknown>) => {\n try { channel.sendActivitySpan({ ...spanData, trace_id: traceId, parent_span_id: inferenceSpanId }); } catch {}\n };\n\n const _instrument = {\n reportLlm: (opts: any) => {\n try { channel.telemetry?.reportLlmCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"llm\", span_name: opts.model ?? \"LLM\",\n status: opts.status === \"error\" ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.llm.model\": opts.model ?? \"\" },\n tokens_input: opts.tokensInput, tokens_output: opts.tokensOutput,\n });\n },\n reportTool: (opts: any) => {\n try { channel.telemetry?.reportToolCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"tool\", span_name: opts.toolName ?? \"tool\",\n status: opts.success === false ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.tool.name\": opts.toolName ?? \"\" },\n tool_success: opts.success,\n });\n },\n reportError: (opts: any) => {\n try { channel.telemetry?.reportError({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"error\", span_name: opts.errorType ?? \"error\",\n status: \"error\",\n start_time: new Date().toISOString(), end_time: new Date().toISOString(), duration_ms: 0,\n attributes: { \"ai.agent.error.type\": opts.errorType ?? \"\" },\n error_type: opts.errorType, error_message: opts.errorMessage,\n });\n },\n reportHttp: (opts: any) => {\n try { channel.telemetry?.reportHttpCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"http\",\n span_name: (() => { try { return new URL(opts.url).hostname; } catch { return opts.url?.slice(0, 40) ?? \"http\"; } })(),\n status: (opts.statusCode ?? 200) >= 400 ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.http.method\": opts.method ?? \"\", \"ai.agent.http.url\": opts.url ?? \"\" },\n http_method: opts.method, http_status_code: opts.statusCode, http_url: opts.url,\n });\n },\n reportAction: (opts: any) => {\n try { channel.telemetry?.reportActionCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"action\",\n span_name: `${opts.actionType ?? \"action\"}: ${opts.target ?? \"\"}`,\n status: opts.success === false ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.action.type\": opts.actionType ?? \"\", \"ai.agent.action.target\": opts.target ?? \"\" },\n action_type: opts.actionType, action_target: opts.target,\n });\n },\n reportNav: (opts: any) => {\n try { channel.telemetry?.reportNavCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"nav\",\n span_name: opts.toUrl?.slice(0, 40) ?? \"navigate\",\n status: opts.status === \"error\" ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.nav.to_url\": opts.toUrl ?? \"\" },\n });\n },\n traceId,\n parentSpanId: inferenceSpanId,\n };\n let replyCount = 0;\n let totalReplyChars = 0;\n let firstReplyTime: number | null = null;\n const replySpans: Array<{ startTime: number; endTime: number; chars: number; index: number }> = [];\n\n // Emit \"receive\" child span immediately \u2014 marks inbound arrival\n _emitChildSpan(channel, {\n traceId,\n parentSpanId: rootSpanId,\n name: \"ai.agent.message.receive\",\n startTime,\n endTime: startTime + 1, // instant\n attributes: {\n \"ai.agent.message.input_chars\": plaintext.length,\n \"ai.agent.message.type\": metadata.roomId ? \"room\" : \"direct\",\n },\n status: \"ok\",\n });\n\n // Send typing indicator to owner (non-critical, best-effort)\n try { channel.sendTyping(); } catch { /* ignore */ }\n\n const core = _ocRuntime;\n\n const route = core.channel.routing.resolveAgentRoute({\n cfg,\n channel: \"agentvault\",\n accountId: account.accountId,\n peer: { kind: \"direct\", id: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\" },\n });\n\n const storePath = core.channel.session.resolveStorePath(cfg?.session?.store, {\n agentId: route.agentId,\n });\n\n const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);\n const previousTimestamp = core.channel.session.readSessionUpdatedAt({\n storePath,\n sessionKey: route.sessionKey,\n });\n\n const body = core.channel.reply.formatAgentEnvelope({\n channel: \"AgentVault\",\n from: isRoomMessage ? \"Room\" : \"Owner\",\n timestamp: new Date(metadata.timestamp).getTime(),\n previousTimestamp,\n envelope: envelopeOptions,\n body: plaintext,\n });\n\n // Build attachment fields for the context payload\n const attachmentFields: Record<string, any> = {};\n if (metadata.attachment) {\n attachmentFields.AttachmentPath = metadata.attachment.filePath;\n attachmentFields.AttachmentFilename = metadata.attachment.filename;\n attachmentFields.AttachmentMime = metadata.attachment.mime;\n\n // For images: include as MediaUrl so the LLM can see the visual content\n if (metadata.attachment.base64) {\n attachmentFields.MediaUrl = metadata.attachment.base64;\n attachmentFields.NumMedia = \"1\";\n }\n\n // For text files: content is already inlined in plaintext body\n }\n\n const ctxPayload = core.channel.reply.finalizeInboundContext({\n Body: body,\n RawBody: plaintext,\n CommandBody: plaintext,\n From: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\",\n To: `agentvault:agent:${account.accountId}`,\n SessionKey: route.sessionKey,\n AccountId: account.accountId,\n ChatType: isRoomMessage ? \"room\" : \"direct\",\n ConversationLabel: isRoomMessage ? \"AgentVault Room\" : \"AgentVault\",\n SenderName: isRoomMessage ? \"Room\" : \"Owner\",\n SenderId: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\",\n Provider: \"agentvault\",\n Surface: \"agentvault\",\n MessageSid: metadata.messageId,\n Timestamp: new Date(metadata.timestamp).getTime(),\n OriginatingChannel: \"agentvault\",\n OriginatingTo: `agentvault:agent:${account.accountId}`,\n CommandAuthorized: true,\n Instrument: _instrument, // OpenClaw ctx convention\n AgentVaultTelemetry: _instrument, // AgentVault-specific accessor\n ...attachmentFields,\n });\n\n await core.channel.session.recordInboundSession({\n storePath,\n sessionKey: ctxPayload.SessionKey ?? route.sessionKey,\n ctx: ctxPayload,\n onRecordError: (err: Error) => {\n core.error?.(`[AgentVault] session record failed: ${String(err)}`);\n },\n });\n\n try {\n await runWithTraceContext(\n { traceId, parentSpanId: inferenceSpanId },\n () => core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: ctxPayload,\n cfg,\n dispatcherOptions: {\n deliver: async (payload: { text?: string; kind?: string }) => {\n // Filter out thinking/reasoning blocks \u2014 only deliver actual responses\n if (payload.kind === \"thinking\" || payload.kind === \"reasoning\") return;\n const text = (payload.text ?? \"\").trim();\n if (!text) return;\n // Heuristic: skip blocks that look like leaked chain-of-thought\n if (/^(Reasoning|Thinking|Let me think|I need to|Let me check):/i.test(text)) return;\n\n const replyStart = Date.now();\n replyCount++;\n totalReplyChars += text.length;\n if (!firstReplyTime) firstReplyTime = replyStart;\n\n // Route reply: room messages go back to the room, 1:1 goes to owner\n if (isRoomMessage) {\n await channel.sendToRoom(metadata.roomId, text, {\n metadata: { content_length: text.length },\n });\n } else {\n await channel.send(text, {\n conversationId: metadata.conversationId,\n topicId: metadata.topicId,\n });\n }\n\n const replyEnd = Date.now();\n replySpans.push({ startTime: replyStart, endTime: replyEnd, chars: text.length, index: replyCount });\n },\n onError: (err: Error, info?: { kind?: string }) => {\n core.error?.(`[AgentVault] ${info?.kind ?? \"reply\"} error: ${String(err)}`);\n },\n },\n replyOptions: {},\n }),\n );\n\n const endTime = Date.now();\n\n // Emit child spans for the completed message lifecycle\n _emitHierarchicalSpans(channel, {\n traceId,\n rootSpanId,\n inferenceSpanId,\n startTime,\n endTime,\n firstReplyTime,\n replySpans,\n inputChars: plaintext.length,\n replyCount,\n totalReplyChars,\n isRoom: isRoomMessage,\n status: \"ok\",\n });\n } catch (err) {\n const endTime = Date.now();\n\n // Emit spans even on error \u2014 shows where failure occurred\n _emitHierarchicalSpans(channel, {\n traceId,\n rootSpanId,\n inferenceSpanId,\n startTime,\n endTime,\n firstReplyTime,\n replySpans,\n inputChars: plaintext.length,\n replyCount,\n totalReplyChars,\n isRoom: isRoomMessage,\n status: \"error\",\n statusMessage: String(err),\n });\n // Dedicated error span for the Errors tab\n _emitChildSpan(channel, {\n traceId,\n parentSpanId: rootSpanId,\n name: \"error\",\n startTime: endTime,\n endTime: endTime,\n attributes: {\n \"ai.agent.error.type\": (err as any)?.constructor?.name ?? \"Error\",\n \"ai.agent.error.message\": String(err),\n },\n status: \"error\",\n statusMessage: String(err),\n });\n throw err;\n }\n}\n\n/** Infer a span type from the span name for activity stream display. */\nfunction _inferSpanType(name: string): \"llm\" | \"tool\" | \"http\" | \"action\" | \"error\" | \"nav\" {\n if (name === \"error\" || name.includes(\"error\")) return \"error\";\n if (name.startsWith(\"llm.\") || name.includes(\"inference\")) return \"llm\";\n if (name.startsWith(\"tool.\") || name.includes(\"tool\")) return \"tool\";\n if (name.startsWith(\"http.\") || name.includes(\"http\")) return \"http\";\n if (name.startsWith(\"nav.\") || name.includes(\"nav\")) return \"nav\";\n if (name.startsWith(\"action.\") || name.includes(\"action\")) return \"action\";\n return \"action\"; // default fallback\n}\n\n/** Extract a human-readable span name from span attributes. */\nfunction _extractSpanName(name: string, attrs: Record<string, string | number | boolean>): string {\n if (attrs[\"ai.agent.llm.model\"]) return String(attrs[\"ai.agent.llm.model\"]);\n if (attrs[\"ai.agent.tool.name\"]) return String(attrs[\"ai.agent.tool.name\"]);\n if (attrs[\"ai.agent.http.url\"]) {\n try { return new URL(String(attrs[\"ai.agent.http.url\"])).hostname; } catch { /* use raw */ }\n return String(attrs[\"ai.agent.http.url\"]).slice(0, 40);\n }\n if (attrs[\"ai.agent.action.type\"]) return `${attrs[\"ai.agent.action.type\"]}: ${attrs[\"ai.agent.action.target\"] ?? \"\"}`;\n if (attrs[\"ai.agent.nav.to_url\"]) return String(attrs[\"ai.agent.nav.to_url\"]).slice(0, 40);\n if (attrs[\"ai.agent.error.type\"]) return String(attrs[\"ai.agent.error.type\"]);\n return name;\n}\n\n/** Emit a single child span via the channel's telemetry reporter + WS activity stream. */\nfunction _emitChildSpan(channel: any, opts: {\n traceId: string;\n parentSpanId: string;\n spanId?: string;\n name: string;\n startTime: number;\n endTime: number;\n attributes: Record<string, string | number | boolean>;\n status: \"ok\" | \"error\";\n statusMessage?: string;\n}): void {\n try {\n const reporter = channel.telemetry;\n if (!reporter) return;\n\n const spanId = opts.spanId ?? randomBytes(8).toString(\"hex\");\n\n reporter.reportCustomSpan({\n traceId: opts.traceId,\n spanId,\n parentSpanId: opts.parentSpanId,\n name: opts.name,\n kind: \"internal\" as const,\n startTime: opts.startTime,\n endTime: opts.endTime,\n attributes: opts.attributes,\n status: {\n code: opts.status === \"ok\" ? 1 : 2,\n message: opts.statusMessage,\n },\n });\n\n // Dual-path: also send via WS for real-time activity streaming\n try {\n const spanType = _inferSpanType(opts.name);\n const spanName = _extractSpanName(opts.name, opts.attributes);\n const durationMs = opts.endTime - opts.startTime;\n channel.sendActivitySpan({\n trace_id: opts.traceId,\n span_id: spanId,\n parent_span_id: opts.parentSpanId,\n span_type: spanType,\n span_name: spanName,\n status: opts.status,\n start_time: new Date(opts.startTime).toISOString(),\n end_time: new Date(opts.endTime).toISOString(),\n duration_ms: durationMs,\n attributes: opts.attributes,\n ...(spanType === \"llm\" ? {\n tokens_input: opts.attributes[\"ai.agent.llm.tokens_input\"],\n tokens_output: opts.attributes[\"ai.agent.llm.tokens_output\"],\n } : {}),\n ...(spanType === \"http\" ? {\n http_method: opts.attributes[\"ai.agent.http.method\"],\n http_status_code: opts.attributes[\"ai.agent.http.status_code\"],\n http_url: opts.attributes[\"ai.agent.http.url\"],\n } : {}),\n ...(spanType === \"tool\" ? {\n tool_success: opts.attributes[\"ai.agent.tool.success\"],\n } : {}),\n ...(spanType === \"error\" ? {\n error_type: opts.attributes[\"ai.agent.error.type\"],\n error_message: opts.attributes[\"ai.agent.error.message\"],\n } : {}),\n });\n } catch { /* WS activity is best-effort */ }\n } catch { /* telemetry is best-effort */ }\n}\n\n/** Emit the full hierarchical span tree for a message lifecycle. */\nfunction _emitHierarchicalSpans(channel: any, opts: {\n traceId: string;\n rootSpanId: string;\n inferenceSpanId?: string;\n startTime: number;\n endTime: number;\n firstReplyTime: number | null;\n replySpans: Array<{ startTime: number; endTime: number; chars: number; index: number }>;\n inputChars: number;\n replyCount: number;\n totalReplyChars: number;\n isRoom: boolean;\n status: \"ok\" | \"error\";\n statusMessage?: string;\n}): void {\n try {\n const reporter = channel.telemetry;\n if (!reporter) return;\n\n // 1. Inference span: from message arrival to first reply (or end if no replies)\n const inferenceEnd = opts.firstReplyTime ?? opts.endTime;\n _emitChildSpan(channel, {\n traceId: opts.traceId,\n parentSpanId: opts.rootSpanId,\n spanId: opts.inferenceSpanId,\n name: \"ai.agent.inference\",\n startTime: opts.startTime + 1, // just after receive\n endTime: inferenceEnd,\n attributes: {\n \"ai.agent.inference.latency_ms\": inferenceEnd - opts.startTime,\n \"ai.agent.message.input_chars\": opts.inputChars,\n },\n status: opts.status,\n statusMessage: opts.status === \"error\" ? opts.statusMessage : undefined,\n });\n\n // 2. Individual reply spans\n for (const reply of opts.replySpans) {\n _emitChildSpan(channel, {\n traceId: opts.traceId,\n parentSpanId: opts.rootSpanId,\n name: \"ai.agent.reply\",\n startTime: reply.startTime,\n endTime: reply.endTime,\n attributes: {\n \"ai.agent.reply.index\": reply.index,\n \"ai.agent.reply.chars\": reply.chars,\n },\n status: \"ok\",\n });\n }\n\n // 3. Root span (wraps everything) \u2014 emitted last\n reporter.reportCustomSpan({\n traceId: opts.traceId,\n spanId: opts.rootSpanId,\n name: \"ai.agent.message\",\n kind: \"server\" as const,\n startTime: opts.startTime,\n endTime: opts.endTime,\n attributes: {\n \"ai.agent.message.input_chars\": opts.inputChars,\n \"ai.agent.message.reply_count\": opts.replyCount,\n \"ai.agent.message.reply_chars\": opts.totalReplyChars,\n \"ai.agent.message.latency_ms\": opts.endTime - opts.startTime,\n \"ai.agent.message.type\": opts.isRoom ? \"room\" : \"direct\",\n },\n status: {\n code: opts.status === \"ok\" ? 1 : 2,\n message: opts.statusMessage,\n },\n });\n } catch { /* telemetry is best-effort */ }\n}\n\n// --- Channel plugin definition ---\n\nconst agentVaultPlugin = {\n id: \"agentvault\",\n meta: {\n id: \"agentvault\",\n label: \"AgentVault\",\n selectionLabel: \"AgentVault (E2E Encrypted)\",\n docsPath: \"https://agentvault.chat/docs\",\n blurb: \"Zero-knowledge, end-to-end encrypted messaging between owners and their AI agents.\",\n aliases: [\"av\", \"agent-vault\"],\n },\n capabilities: { chatTypes: [\"direct\"] },\n config: { listAccountIds, resolveAccount },\n\n gateway: {\n startAccount: async (ctx: any) => {\n const { account, cfg, log, abortSignal } = ctx;\n\n if (!account.configured) {\n throw new Error(\n \"AgentVault channel not configured. Run: npx @agentvault/agentvault setup --token=av_tok_...\\nThen restart OpenClaw.\",\n );\n }\n\n const dataDir = resolve(account.dataDir.replace(/^~/, process.env.HOME ?? \"~\"));\n log?.info(`[AgentVault] starting (dataDir=${dataDir})`);\n\n // Lazy import \u2014 defers libsodium initialization until channel actually starts\n const { SecureChannel } = await import(\"./index.js\");\n\n // startAccount must STAY PENDING while the channel is running.\n // Resolving signals \"channel stopped\" to the gateway health monitor,\n // which triggers auto-restart. We block here until the abortSignal\n // fires (gateway shutdown / config reload), then clean up.\n await new Promise<void>((resolve, reject) => {\n let channel: any;\n\n const onAbort = async () => {\n await channel?.stop();\n _channels.delete(account.accountId);\n resolve();\n };\n\n abortSignal?.addEventListener(\"abort\", () => void onAbort());\n\n // Lazy import \u2014 defers libsodium initialization until channel starts\n import(\"./index.js\").then(({ SecureChannel }) => {\n channel = new SecureChannel({\n inviteToken: \"\",\n dataDir,\n apiUrl: account.apiUrl,\n agentName: account.agentName,\n onMessage: async (plaintext: string, metadata: any) => {\n if (!_ocRuntime) {\n log?.info(\"[AgentVault] runtime not ready, queuing message\");\n _messageQueue.push(async () => {\n await handleInbound({ plaintext, metadata, channel, account, cfg });\n });\n return;\n }\n try {\n await handleInbound({ plaintext, metadata, channel, account, cfg });\n } catch (err) {\n log?.info(`[AgentVault] inbound error: ${String(err)}`);\n }\n },\n onStateChange: (state: string) => {\n log?.info(`[AgentVault] \u2192 ${state}`);\n // \"error\" is a permanent failure \u2014 reject so gateway can restart\n if (state === \"error\") reject(new Error(\"AgentVault channel permanent error\"));\n // All other states (connecting/ready/disconnected) are handled\n // internally by SecureChannel's reconnect logic \u2014 do NOT resolve.\n },\n });\n\n _channels.set(account.accountId, channel);\n\n // Prevent unhandled \"error\" events from crashing the process.\n // Without this handler, Node.js EventEmitter throws on emit(\"error\").\n channel.on(\"error\", (err: any) => {\n log?.info(`[AgentVault] channel error (non-fatal): ${String(err)}`);\n });\n\n // Start local HTTP server for proactive sends\n const httpPort = account.httpPort ?? 18790;\n channel.on(\"ready\", () => {\n channel.startHttpServer(httpPort);\n log?.info(`[AgentVault] HTTP send server listening on http://127.0.0.1:${httpPort}`);\n });\n\n channel.start().catch(reject);\n }).catch(reject);\n });\n\n return { stop: async () => {} }; // Channel already stopped via abortSignal by this point\n },\n },\n\n outbound: {\n deliveryMode: \"direct\" as const,\n\n // Register valid send targets so OpenClaw's `message` tool can route\n // proactive (agent-initiated) sends \u2014 not just replies to inbound messages.\n targets: [\n {\n id: \"owner\",\n label: \"AgentVault Owner\",\n accountId: \"default\",\n },\n {\n id: \"default\",\n label: \"AgentVault Owner (default)\",\n accountId: \"default\",\n },\n ],\n\n sendText: async ({ to, text, accountId }: { to: string; text: string; accountId?: string }) => {\n const resolvedId = accountId ?? \"default\";\n const ch = _channels.get(resolvedId);\n if (!ch) return { ok: false, error: \"AgentVault channel not connected\" };\n try {\n const wasReady = ch.state === \"ready\";\n await ch.send(text);\n return { ok: true, queued: !wasReady };\n } catch (err) {\n return { ok: false, error: String(err) };\n }\n },\n\n sendMedia: async ({ to, text, mediaUrl, accountId }: { to: string; text?: string; mediaUrl: string; accountId?: string }) => {\n const resolvedId = accountId ?? \"default\";\n const ch = _channels.get(resolvedId);\n if (!ch) return { ok: false, error: \"AgentVault channel not connected\" };\n try {\n // For now, send media URL as text \u2014 AgentVault handles attachments separately\n const message = text ? `${text}\\n${mediaUrl}` : mediaUrl;\n const wasReady = ch.state === \"ready\";\n await ch.send(message);\n return { ok: true, queued: !wasReady };\n } catch (err) {\n return { ok: false, error: String(err) };\n }\n },\n },\n};\n\n// --- Exported for testing ---\nexport { _parseMentions, _shouldProcessRoomMessage, _stripMentions };\n\n// --- Plugin export ---\n\nexport default {\n id: \"agentvault\",\n name: \"AgentVault\",\n description: \"End-to-end encrypted, zero-knowledge messaging between AI agent owners and their agents.\",\n register(api: any) {\n _setRuntime(api.runtime);\n\n // Install fetch interceptor to capture all outbound HTTP from the gateway process.\n installFetchInterceptor({\n onHttpCall: (report) => {\n // Find an active channel to emit through\n const ch = _channels.values().next().value;\n if (!ch) return;\n\n // Telemetry reporter is optional \u2014 may not be initialized\n if (ch.telemetry) {\n try {\n ch.telemetry.reportHttpCall({\n method: report.method,\n url: report.url,\n statusCode: report.statusCode,\n latencyMs: report.latencyMs,\n ...(report.traceId ? { traceId: report.traceId } : {}),\n ...(report.parentSpanId ? { parentSpanId: report.parentSpanId } : {}),\n });\n } catch { /* best-effort */ }\n }\n\n // Activity span always fires (uses WS, not telemetry reporter)\n try {\n const hostname = (() => { try { return new URL(report.url).hostname; } catch { return report.url.slice(0, 40); } })();\n ch.sendActivitySpan({\n trace_id: report.traceId ?? \"\",\n parent_span_id: report.parentSpanId ?? \"\",\n span_id: randomBytes(8).toString(\"hex\"),\n span_type: \"http\",\n span_name: hostname,\n status: report.statusCode >= 400 || report.statusCode === 0 ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - report.latencyMs).toISOString(),\n end_time: new Date().toISOString(),\n duration_ms: report.latencyMs,\n attributes: {\n \"ai.agent.http.method\": report.method,\n \"ai.agent.http.url\": report.url,\n },\n http_method: report.method,\n http_status_code: report.statusCode,\n http_url: report.url,\n });\n } catch { /* best-effort */ }\n },\n });\n\n api.registerChannel({ plugin: agentVaultPlugin });\n },\n};\n", "/**\n * Shared multi-account config resolution for AgentVault OpenClaw plugin.\n *\n * Supports two config shapes:\n * 1. Legacy single-agent: channels.agentvault.dataDir (returns [\"default\"])\n * 2. Multi-agent: channels.agentvault.accounts.{id}.dataDir (returns account keys)\n *\n * When `accounts` key is present, it takes precedence over top-level dataDir.\n */\n\nconst DEFAULT_API_URL = \"https://api.agentvault.chat\";\nconst DEFAULT_HTTP_PORT = 18790;\n\nexport interface ResolvedAccount {\n accountId: string;\n dataDir: string;\n apiUrl: string;\n agentName: string;\n httpPort: number;\n configured: boolean;\n}\n\nexport function listAccountIds(cfg: any): string[] {\n const av = cfg?.channels?.agentvault;\n if (!av) return [];\n if (av.accounts && typeof av.accounts === \"object\") {\n return Object.keys(av.accounts);\n }\n return av.dataDir ? [\"default\"] : [];\n}\n\nexport function resolveAccount(cfg: any, accountId?: string): ResolvedAccount {\n const av = cfg?.channels?.agentvault ?? {};\n const id = accountId ?? \"default\";\n\n if (av.accounts && typeof av.accounts === \"object\") {\n const acct = av.accounts[id];\n if (!acct) {\n return {\n accountId: id,\n dataDir: \"\",\n apiUrl: av.apiUrl ?? DEFAULT_API_URL,\n agentName: id,\n httpPort: DEFAULT_HTTP_PORT,\n configured: false,\n };\n }\n\n let httpPort = acct.httpPort;\n if (httpPort == null) {\n const keys = Object.keys(av.accounts);\n const index = keys.indexOf(id);\n httpPort = DEFAULT_HTTP_PORT + (index >= 0 ? index : 0);\n }\n\n return {\n accountId: id,\n dataDir: acct.dataDir ?? \"\",\n apiUrl: acct.apiUrl ?? av.apiUrl ?? DEFAULT_API_URL,\n agentName: acct.agentName ?? id,\n httpPort,\n configured: Boolean(acct.dataDir),\n };\n }\n\n return {\n accountId: id,\n dataDir: av.dataDir ?? \"~/.openclaw/agentvault\",\n apiUrl: av.apiUrl ?? DEFAULT_API_URL,\n agentName: av.agentName ?? \"OpenClaw Agent\",\n httpPort: av.httpPort ?? DEFAULT_HTTP_PORT,\n configured: Boolean(av.dataDir),\n };\n}\n", "/**\n * HTTP interceptor for capturing outbound HTTP calls during message handling.\n *\n * Uses Node.js diagnostics_channel to subscribe to undici request events,\n * capturing ALL outbound HTTP from the process (including LLM SDKs, Playwright\n * navigations, and any library that uses undici under the hood).\n *\n * Also monkey-patches globalThis.fetch as a fallback for non-undici HTTP.\n *\n * Uses AsyncLocalStorage to associate intercepted calls with the active\n * message's traceId/parentSpanId.\n *\n * Built-in skip patterns prevent capturing internal infrastructure requests\n * (localhost, AgentVault API, Clerk auth).\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport diagnosticsChannel from \"node:diagnostics_channel\";\n\n// \u2500\u2500 Public types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface HttpCallReport {\n method: string;\n url: string;\n statusCode: number;\n latencyMs: number;\n traceId?: string;\n parentSpanId?: string;\n}\n\nexport interface TraceContext {\n traceId: string;\n parentSpanId: string;\n}\n\nexport interface FetchInterceptorOptions {\n onHttpCall: (report: HttpCallReport) => void;\n skipPatterns?: RegExp[];\n}\n\n// \u2500\u2500 Internal state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst traceStore = new AsyncLocalStorage<TraceContext>();\n\nconst DEFAULT_SKIP_PATTERNS: RegExp[] = [\n /^https?:\\/\\/localhost(:\\d+)?/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?/,\n /\\.agentvault\\.chat/,\n /\\.agentvault\\.dev/,\n /\\.clerk\\./,\n];\n\nlet installed = false;\nlet originalFetch: typeof globalThis.fetch | undefined;\n\n// Track in-flight undici requests: request \u2192 { url, method, startTime }\nconst inflightRequests = new WeakMap<\n object,\n { url: string; method: string; startTime: number }\n>();\n\n// Diagnostics channel subscriptions\nlet unsubCreate: (() => void) | undefined;\nlet unsubHeaders: (() => void) | undefined;\nlet unsubError: (() => void) | undefined;\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction shouldSkip(url: string, extraPatterns: RegExp[]): boolean {\n const allPatterns = [...DEFAULT_SKIP_PATTERNS, ...extraPatterns];\n return allPatterns.some((p) => p.test(url));\n}\n\nfunction extractUrl(origin: string, path: string): string {\n // undici gives us origin (e.g., \"https://api.openai.com\") and path (e.g., \"/v1/chat/completions\")\n return `${origin}${path}`;\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Install HTTP interceptor using both undici diagnostics channels and\n * globalThis.fetch monkey-patching. Idempotent.\n */\nexport function installFetchInterceptor(opts: FetchInterceptorOptions): void {\n if (installed) return;\n installed = true;\n\n const skipPatterns = [\n ...DEFAULT_SKIP_PATTERNS,\n ...(opts.skipPatterns ?? []),\n ];\n\n // \u2500\u2500 1. Undici diagnostics channel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // undici publishes events for every HTTP request it makes.\n // This captures LLM SDK calls, playwright navigations, etc.\n\n try {\n const createChannel = diagnosticsChannel.channel(\"undici:request:create\");\n const headersChannel = diagnosticsChannel.channel(\"undici:request:headers\");\n const errorChannel = diagnosticsChannel.channel(\"undici:request:error\");\n\n const onRequestCreate = (message: unknown) => {\n try {\n const msg = message as {\n request: {\n method?: string;\n origin?: string;\n path?: string;\n };\n };\n const req = msg.request;\n if (!req) return;\n\n const origin = String(req.origin ?? \"\");\n const path = String(req.path ?? \"/\");\n const url = extractUrl(origin, path);\n\n if (shouldSkip(url, skipPatterns)) return;\n\n inflightRequests.set(req, {\n url,\n method: String(req.method ?? \"GET\").toUpperCase(),\n startTime: Date.now(),\n });\n } catch { /* best-effort */ }\n };\n\n const onRequestHeaders = (message: unknown) => {\n try {\n const msg = message as {\n request: object;\n response: { statusCode?: number };\n };\n const tracked = inflightRequests.get(msg.request);\n if (!tracked) return;\n inflightRequests.delete(msg.request);\n\n const latencyMs = Date.now() - tracked.startTime;\n const ctx = traceStore.getStore();\n\n opts.onHttpCall({\n method: tracked.method,\n url: tracked.url,\n statusCode: msg.response?.statusCode ?? 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n };\n\n const onRequestError = (message: unknown) => {\n try {\n const msg = message as { request: object; error?: Error };\n const tracked = inflightRequests.get(msg.request);\n if (!tracked) return;\n inflightRequests.delete(msg.request);\n\n const latencyMs = Date.now() - tracked.startTime;\n const ctx = traceStore.getStore();\n\n opts.onHttpCall({\n method: tracked.method,\n url: tracked.url,\n statusCode: 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n };\n\n createChannel.subscribe(onRequestCreate);\n headersChannel.subscribe(onRequestHeaders);\n errorChannel.subscribe(onRequestError);\n\n unsubCreate = () => createChannel.unsubscribe(onRequestCreate);\n unsubHeaders = () => headersChannel.unsubscribe(onRequestHeaders);\n unsubError = () => errorChannel.unsubscribe(onRequestError);\n } catch {\n // diagnostics_channel not available or undici not loaded \u2014 fall through to fetch-only\n }\n\n // \u2500\u2500 2. globalThis.fetch monkey-patch (fallback) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Catches any HTTP that doesn't go through undici (e.g., native fetch\n // in newer Node.js, or custom HTTP implementations).\n\n originalFetch = globalThis.fetch;\n const savedOriginal = originalFetch;\n\n globalThis.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url =\n input instanceof Request\n ? input.url\n : input instanceof URL\n ? input.href\n : String(input);\n\n if (shouldSkip(url, skipPatterns)) {\n return savedOriginal(input, init);\n }\n\n const method =\n input instanceof Request\n ? input.method\n : init?.method ?? \"GET\";\n\n const ctx = traceStore.getStore();\n const start = Date.now();\n\n try {\n const response = await savedOriginal(input, init);\n const latencyMs = Date.now() - start;\n\n try {\n opts.onHttpCall({\n method,\n url,\n statusCode: response.status,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n\n return response;\n } catch (err) {\n const latencyMs = Date.now() - start;\n\n try {\n opts.onHttpCall({\n method,\n url,\n statusCode: 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n\n throw err;\n }\n };\n}\n\n/**\n * Uninstall all interceptors. Safe to call even if not installed.\n */\nexport function uninstallFetchInterceptor(): void {\n if (!installed) return;\n\n // Restore fetch\n if (originalFetch) {\n globalThis.fetch = originalFetch;\n originalFetch = undefined;\n }\n\n // Unsubscribe from diagnostics channels\n unsubCreate?.();\n unsubHeaders?.();\n unsubError?.();\n unsubCreate = undefined;\n unsubHeaders = undefined;\n unsubError = undefined;\n\n installed = false;\n}\n\n/**\n * Run an async function with trace context attached via AsyncLocalStorage.\n * Any HTTP calls made within `fn` (via undici or fetch) will include\n * traceId/parentSpanId in their HttpCallReport.\n */\nexport function runWithTraceContext<T>(\n ctx: TraceContext,\n fn: () => T | Promise<T>,\n): Promise<T> {\n return traceStore.run(ctx, fn) as Promise<T>;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * OpenClaw channel plugin entry point.\n *\n * Intentionally thin \u2014 no heavy imports (libsodium etc.) at module load time.\n * SecureChannel is dynamically imported inside gateway.startAccount (already async)\n * so libsodium's top-level await never runs during plugin registration.\n *\n * Loaded by OpenClaw via the `openclaw.extensions` field in package.json.\n */\n\nimport { resolve } from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport { listAccountIds, resolveAccount } from \"./account-config.js\";\nimport { installFetchInterceptor, runWithTraceContext } from \"./fetch-interceptor.js\";\n\n// --- Runtime and active channels (set during register) ---\nlet _ocRuntime: any = null;\nconst _channels = new Map<string, any>();\nconst _messageQueue: Array<() => Promise<void>> = [];\n\nfunction _setRuntime(rt: any) {\n _ocRuntime = rt;\n // Flush any messages that arrived before runtime was ready\n if (_messageQueue.length > 0) {\n const pending = _messageQueue.splice(0);\n for (const fn of pending) {\n fn().catch(() => {});\n }\n }\n}\n\n// --- @mention filtering for multi-agent rooms ---\n\n/** Extract @mention names from plaintext. Returns lowercased names. */\nfunction _parseMentions(text: string): string[] {\n const mentions: string[] = [];\n // Match @word at word boundary \u2014 supports multi-word via sequential matching\n const re = /@(\\w[\\w]*)/gi;\n let match: RegExpExecArray | null;\n while ((match = re.exec(text)) !== null) {\n mentions.push(match[1].toLowerCase());\n }\n return mentions;\n}\n\n/** Determine whether this agent should process a room message based on @mentions. */\nfunction _shouldProcessRoomMessage(\n plaintext: string,\n agentName: string,\n accountId: string,\n): boolean {\n const mentions = _parseMentions(plaintext);\n // No mentions \u2192 broadcast to all agents (current behavior)\n if (mentions.length === 0) return true;\n // @all / @everyone \u2192 all agents process\n if (mentions.includes(\"all\") || mentions.includes(\"everyone\")) return true;\n // Check if this agent is mentioned (by name or accountId)\n const nameLower = agentName.toLowerCase();\n const idLower = accountId.toLowerCase();\n // Match first word of agent name (e.g., \"Cortina\" from \"Cortina (Coder)\")\n const firstWord = nameLower.split(/[\\s(]/)[0];\n return mentions.some(\n (m) => m === nameLower || m === firstWord || m === idLower,\n );\n}\n\n/** Strip the matching @mention prefix from plaintext so the agent sees clean text. */\nfunction _stripMentions(\n text: string,\n agentName: string,\n accountId: string,\n): string {\n const nameLower = agentName.toLowerCase();\n const firstWord = nameLower.split(/[\\s(]/)[0];\n const idLower = accountId.toLowerCase();\n // Remove all @mentions that match this agent (case-insensitive)\n return text\n .replace(/@(\\w[\\w]*)/gi, (full, name) => {\n const lower = name.toLowerCase();\n if (lower === nameLower || lower === firstWord || lower === idLower) {\n return \"\";\n }\n // Also strip @all/@everyone since they're routing directives\n if (lower === \"all\" || lower === \"everyone\") return \"\";\n return full;\n })\n .replace(/^\\s+/, \"\") // trim leading whitespace left by stripped mention\n .trim();\n}\n\n// --- Inbound message dispatch ---\n\nasync function handleInbound(params: {\n plaintext: string;\n metadata: any;\n channel: any;\n account: any;\n cfg: any;\n}): Promise<void> {\n const { plaintext: rawPlaintext, metadata, channel, account, cfg } = params;\n const isRoomMessage = Boolean(metadata.roomId);\n\n // @mention filtering: only for room messages\n if (isRoomMessage) {\n if (!_shouldProcessRoomMessage(rawPlaintext, account.agentName ?? \"\", account.accountId ?? \"\")) {\n return; // This agent is not mentioned \u2014 skip silently\n }\n }\n\n // Strip @mentions from plaintext so the agent sees clean text\n const plaintext = isRoomMessage\n ? _stripMentions(rawPlaintext, account.agentName ?? \"\", account.accountId ?? \"\")\n : rawPlaintext;\n\n // Telemetry: hierarchical spans for the full message lifecycle\n const startTime = Date.now();\n const traceId = randomBytes(16).toString(\"hex\");\n const rootSpanId = randomBytes(8).toString(\"hex\");\n const inferenceSpanId = randomBytes(8).toString(\"hex\");\n // Instrumentation context for agent code to report LLM/tool/error spans\n /** Helper: send an activity span over WS for real-time owner display. */\n const _sendActivity = (spanData: Record<string, unknown>) => {\n try { channel.sendActivitySpan({ ...spanData, trace_id: traceId, parent_span_id: inferenceSpanId }); } catch {}\n };\n\n const _instrument = {\n reportLlm: (opts: any) => {\n try { channel.telemetry?.reportLlmCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"llm\", span_name: opts.model ?? \"LLM\",\n status: opts.status === \"error\" ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.llm.model\": opts.model ?? \"\" },\n tokens_input: opts.tokensInput, tokens_output: opts.tokensOutput,\n });\n },\n reportTool: (opts: any) => {\n try { channel.telemetry?.reportToolCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"tool\", span_name: opts.toolName ?? \"tool\",\n status: opts.success === false ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.tool.name\": opts.toolName ?? \"\" },\n tool_success: opts.success,\n });\n },\n reportError: (opts: any) => {\n try { channel.telemetry?.reportError({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"error\", span_name: opts.errorType ?? \"error\",\n status: \"error\",\n start_time: new Date().toISOString(), end_time: new Date().toISOString(), duration_ms: 0,\n attributes: { \"ai.agent.error.type\": opts.errorType ?? \"\" },\n error_type: opts.errorType, error_message: opts.errorMessage,\n });\n },\n reportHttp: (opts: any) => {\n try { channel.telemetry?.reportHttpCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"http\",\n span_name: (() => { try { return new URL(opts.url).hostname; } catch { return opts.url?.slice(0, 40) ?? \"http\"; } })(),\n status: (opts.statusCode ?? 200) >= 400 ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.http.method\": opts.method ?? \"\", \"ai.agent.http.url\": opts.url ?? \"\" },\n http_method: opts.method, http_status_code: opts.statusCode, http_url: opts.url,\n });\n },\n reportAction: (opts: any) => {\n try { channel.telemetry?.reportActionCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"action\",\n span_name: `${opts.actionType ?? \"action\"}: ${opts.target ?? \"\"}`,\n status: opts.success === false ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.action.type\": opts.actionType ?? \"\", \"ai.agent.action.target\": opts.target ?? \"\" },\n action_type: opts.actionType, action_target: opts.target,\n });\n },\n reportNav: (opts: any) => {\n try { channel.telemetry?.reportNavCall({ ...opts, traceId, parentSpanId: inferenceSpanId }); } catch {}\n _sendActivity({\n span_id: randomBytes(8).toString(\"hex\"), span_type: \"nav\",\n span_name: opts.toUrl?.slice(0, 40) ?? \"navigate\",\n status: opts.status === \"error\" ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - (opts.latencyMs ?? 0)).toISOString(),\n end_time: new Date().toISOString(), duration_ms: opts.latencyMs ?? 0,\n attributes: { \"ai.agent.nav.to_url\": opts.toUrl ?? \"\" },\n });\n },\n traceId,\n parentSpanId: inferenceSpanId,\n };\n let replyCount = 0;\n let totalReplyChars = 0;\n let firstReplyTime: number | null = null;\n const replySpans: Array<{ startTime: number; endTime: number; chars: number; index: number }> = [];\n\n // Emit \"receive\" child span immediately \u2014 marks inbound arrival\n _emitChildSpan(channel, {\n traceId,\n parentSpanId: rootSpanId,\n name: \"ai.agent.message.receive\",\n startTime,\n endTime: startTime + 1, // instant\n attributes: {\n \"ai.agent.message.input_chars\": plaintext.length,\n \"ai.agent.message.type\": metadata.roomId ? \"room\" : \"direct\",\n },\n status: \"ok\",\n });\n\n // Send typing indicator to owner (non-critical, best-effort)\n try { channel.sendTyping(); } catch { /* ignore */ }\n\n const core = _ocRuntime;\n\n const route = core.channel.routing.resolveAgentRoute({\n cfg,\n channel: \"agentvault\",\n accountId: account.accountId,\n peer: { kind: \"direct\", id: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\" },\n });\n\n const storePath = core.channel.session.resolveStorePath(cfg?.session?.store, {\n agentId: route.agentId,\n });\n\n const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);\n const previousTimestamp = core.channel.session.readSessionUpdatedAt({\n storePath,\n sessionKey: route.sessionKey,\n });\n\n const body = core.channel.reply.formatAgentEnvelope({\n channel: \"AgentVault\",\n from: isRoomMessage ? \"Room\" : \"Owner\",\n timestamp: new Date(metadata.timestamp).getTime(),\n previousTimestamp,\n envelope: envelopeOptions,\n body: plaintext,\n });\n\n // Build attachment fields for the context payload\n const attachmentFields: Record<string, any> = {};\n if (metadata.attachment) {\n attachmentFields.AttachmentPath = metadata.attachment.filePath;\n attachmentFields.AttachmentFilename = metadata.attachment.filename;\n attachmentFields.AttachmentMime = metadata.attachment.mime;\n\n // For images: include as MediaUrl so the LLM can see the visual content\n if (metadata.attachment.base64) {\n attachmentFields.MediaUrl = metadata.attachment.base64;\n attachmentFields.NumMedia = \"1\";\n }\n\n // For text files: content is already inlined in plaintext body\n }\n\n const ctxPayload = core.channel.reply.finalizeInboundContext({\n Body: body,\n RawBody: plaintext,\n CommandBody: plaintext,\n From: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\",\n To: `agentvault:agent:${account.accountId}`,\n SessionKey: route.sessionKey,\n AccountId: account.accountId,\n ChatType: isRoomMessage ? \"room\" : \"direct\",\n ConversationLabel: isRoomMessage ? \"AgentVault Room\" : \"AgentVault\",\n SenderName: isRoomMessage ? \"Room\" : \"Owner\",\n SenderId: isRoomMessage ? `agentvault:room:${metadata.roomId}` : \"agentvault:owner\",\n Provider: \"agentvault\",\n Surface: \"agentvault\",\n MessageSid: metadata.messageId,\n Timestamp: new Date(metadata.timestamp).getTime(),\n OriginatingChannel: \"agentvault\",\n OriginatingTo: `agentvault:agent:${account.accountId}`,\n CommandAuthorized: true,\n Instrument: _instrument, // OpenClaw ctx convention\n AgentVaultTelemetry: _instrument, // AgentVault-specific accessor\n ...attachmentFields,\n });\n\n await core.channel.session.recordInboundSession({\n storePath,\n sessionKey: ctxPayload.SessionKey ?? route.sessionKey,\n ctx: ctxPayload,\n onRecordError: (err: Error) => {\n core.error?.(`[AgentVault] session record failed: ${String(err)}`);\n },\n });\n\n try {\n await runWithTraceContext(\n { traceId, parentSpanId: inferenceSpanId },\n () => core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: ctxPayload,\n cfg,\n dispatcherOptions: {\n deliver: async (payload: { text?: string; kind?: string }) => {\n // Filter out thinking/reasoning blocks \u2014 only deliver actual responses\n if (payload.kind === \"thinking\" || payload.kind === \"reasoning\") return;\n const text = (payload.text ?? \"\").trim();\n if (!text) return;\n // Heuristic: skip blocks that look like leaked chain-of-thought\n if (/^(Reasoning|Thinking|Let me think|I need to|Let me check):/i.test(text)) return;\n\n const replyStart = Date.now();\n replyCount++;\n totalReplyChars += text.length;\n if (!firstReplyTime) firstReplyTime = replyStart;\n\n // Route reply: room messages go back to the room, 1:1 goes to owner\n if (isRoomMessage) {\n await channel.sendToRoom(metadata.roomId, text, {\n metadata: { content_length: text.length },\n });\n } else {\n await channel.send(text, {\n conversationId: metadata.conversationId,\n topicId: metadata.topicId,\n });\n }\n\n const replyEnd = Date.now();\n replySpans.push({ startTime: replyStart, endTime: replyEnd, chars: text.length, index: replyCount });\n },\n onError: (err: Error, info?: { kind?: string }) => {\n core.error?.(`[AgentVault] ${info?.kind ?? \"reply\"} error: ${String(err)}`);\n },\n },\n replyOptions: {},\n }),\n );\n\n const endTime = Date.now();\n\n // Emit child spans for the completed message lifecycle\n _emitHierarchicalSpans(channel, {\n traceId,\n rootSpanId,\n inferenceSpanId,\n startTime,\n endTime,\n firstReplyTime,\n replySpans,\n inputChars: plaintext.length,\n replyCount,\n totalReplyChars,\n isRoom: isRoomMessage,\n status: \"ok\",\n });\n } catch (err) {\n const endTime = Date.now();\n\n // Emit spans even on error \u2014 shows where failure occurred\n _emitHierarchicalSpans(channel, {\n traceId,\n rootSpanId,\n inferenceSpanId,\n startTime,\n endTime,\n firstReplyTime,\n replySpans,\n inputChars: plaintext.length,\n replyCount,\n totalReplyChars,\n isRoom: isRoomMessage,\n status: \"error\",\n statusMessage: String(err),\n });\n // Dedicated error span for the Errors tab\n _emitChildSpan(channel, {\n traceId,\n parentSpanId: rootSpanId,\n name: \"error\",\n startTime: endTime,\n endTime: endTime,\n attributes: {\n \"ai.agent.error.type\": (err as any)?.constructor?.name ?? \"Error\",\n \"ai.agent.error.message\": String(err),\n },\n status: \"error\",\n statusMessage: String(err),\n });\n throw err;\n }\n}\n\n/** Infer a span type from the span name for activity stream display. */\nfunction _inferSpanType(name: string): \"llm\" | \"tool\" | \"http\" | \"action\" | \"error\" | \"nav\" {\n if (name === \"error\" || name.includes(\"error\")) return \"error\";\n if (name.startsWith(\"llm.\") || name.includes(\"inference\")) return \"llm\";\n if (name.startsWith(\"tool.\") || name.includes(\"tool\")) return \"tool\";\n if (name.startsWith(\"http.\") || name.includes(\"http\")) return \"http\";\n if (name.startsWith(\"nav.\") || name.includes(\"nav\")) return \"nav\";\n if (name.startsWith(\"action.\") || name.includes(\"action\")) return \"action\";\n return \"action\"; // default fallback\n}\n\n/** Extract a human-readable span name from span attributes. */\nfunction _extractSpanName(name: string, attrs: Record<string, string | number | boolean>): string {\n if (attrs[\"ai.agent.llm.model\"]) return String(attrs[\"ai.agent.llm.model\"]);\n if (attrs[\"ai.agent.tool.name\"]) return String(attrs[\"ai.agent.tool.name\"]);\n if (attrs[\"ai.agent.http.url\"]) {\n try { return new URL(String(attrs[\"ai.agent.http.url\"])).hostname; } catch { /* use raw */ }\n return String(attrs[\"ai.agent.http.url\"]).slice(0, 40);\n }\n if (attrs[\"ai.agent.action.type\"]) return `${attrs[\"ai.agent.action.type\"]}: ${attrs[\"ai.agent.action.target\"] ?? \"\"}`;\n if (attrs[\"ai.agent.nav.to_url\"]) return String(attrs[\"ai.agent.nav.to_url\"]).slice(0, 40);\n if (attrs[\"ai.agent.error.type\"]) return String(attrs[\"ai.agent.error.type\"]);\n return name;\n}\n\n/** Emit a single child span via the channel's telemetry reporter + WS activity stream. */\nfunction _emitChildSpan(channel: any, opts: {\n traceId: string;\n parentSpanId: string;\n spanId?: string;\n name: string;\n startTime: number;\n endTime: number;\n attributes: Record<string, string | number | boolean>;\n status: \"ok\" | \"error\";\n statusMessage?: string;\n}): void {\n try {\n const reporter = channel.telemetry;\n if (!reporter) return;\n\n const spanId = opts.spanId ?? randomBytes(8).toString(\"hex\");\n\n reporter.reportCustomSpan({\n traceId: opts.traceId,\n spanId,\n parentSpanId: opts.parentSpanId,\n name: opts.name,\n kind: \"internal\" as const,\n startTime: opts.startTime,\n endTime: opts.endTime,\n attributes: opts.attributes,\n status: {\n code: opts.status === \"ok\" ? 1 : 2,\n message: opts.statusMessage,\n },\n });\n\n // Dual-path: also send via WS for real-time activity streaming\n try {\n const spanType = _inferSpanType(opts.name);\n const spanName = _extractSpanName(opts.name, opts.attributes);\n const durationMs = opts.endTime - opts.startTime;\n channel.sendActivitySpan({\n trace_id: opts.traceId,\n span_id: spanId,\n parent_span_id: opts.parentSpanId,\n span_type: spanType,\n span_name: spanName,\n status: opts.status,\n start_time: new Date(opts.startTime).toISOString(),\n end_time: new Date(opts.endTime).toISOString(),\n duration_ms: durationMs,\n attributes: opts.attributes,\n ...(spanType === \"llm\" ? {\n tokens_input: opts.attributes[\"ai.agent.llm.tokens_input\"],\n tokens_output: opts.attributes[\"ai.agent.llm.tokens_output\"],\n } : {}),\n ...(spanType === \"http\" ? {\n http_method: opts.attributes[\"ai.agent.http.method\"],\n http_status_code: opts.attributes[\"ai.agent.http.status_code\"],\n http_url: opts.attributes[\"ai.agent.http.url\"],\n } : {}),\n ...(spanType === \"tool\" ? {\n tool_success: opts.attributes[\"ai.agent.tool.success\"],\n } : {}),\n ...(spanType === \"error\" ? {\n error_type: opts.attributes[\"ai.agent.error.type\"],\n error_message: opts.attributes[\"ai.agent.error.message\"],\n } : {}),\n });\n } catch { /* WS activity is best-effort */ }\n } catch { /* telemetry is best-effort */ }\n}\n\n/** Emit the full hierarchical span tree for a message lifecycle. */\nfunction _emitHierarchicalSpans(channel: any, opts: {\n traceId: string;\n rootSpanId: string;\n inferenceSpanId?: string;\n startTime: number;\n endTime: number;\n firstReplyTime: number | null;\n replySpans: Array<{ startTime: number; endTime: number; chars: number; index: number }>;\n inputChars: number;\n replyCount: number;\n totalReplyChars: number;\n isRoom: boolean;\n status: \"ok\" | \"error\";\n statusMessage?: string;\n}): void {\n try {\n const reporter = channel.telemetry;\n if (!reporter) return;\n\n // 1. Inference span: from message arrival to first reply (or end if no replies)\n const inferenceEnd = opts.firstReplyTime ?? opts.endTime;\n _emitChildSpan(channel, {\n traceId: opts.traceId,\n parentSpanId: opts.rootSpanId,\n spanId: opts.inferenceSpanId,\n name: \"ai.agent.inference\",\n startTime: opts.startTime + 1, // just after receive\n endTime: inferenceEnd,\n attributes: {\n \"ai.agent.inference.latency_ms\": inferenceEnd - opts.startTime,\n \"ai.agent.message.input_chars\": opts.inputChars,\n },\n status: opts.status,\n statusMessage: opts.status === \"error\" ? opts.statusMessage : undefined,\n });\n\n // 2. Individual reply spans\n for (const reply of opts.replySpans) {\n _emitChildSpan(channel, {\n traceId: opts.traceId,\n parentSpanId: opts.rootSpanId,\n name: \"ai.agent.reply\",\n startTime: reply.startTime,\n endTime: reply.endTime,\n attributes: {\n \"ai.agent.reply.index\": reply.index,\n \"ai.agent.reply.chars\": reply.chars,\n },\n status: \"ok\",\n });\n }\n\n // 3. Root span (wraps everything) \u2014 emitted last\n reporter.reportCustomSpan({\n traceId: opts.traceId,\n spanId: opts.rootSpanId,\n name: \"ai.agent.message\",\n kind: \"server\" as const,\n startTime: opts.startTime,\n endTime: opts.endTime,\n attributes: {\n \"ai.agent.message.input_chars\": opts.inputChars,\n \"ai.agent.message.reply_count\": opts.replyCount,\n \"ai.agent.message.reply_chars\": opts.totalReplyChars,\n \"ai.agent.message.latency_ms\": opts.endTime - opts.startTime,\n \"ai.agent.message.type\": opts.isRoom ? \"room\" : \"direct\",\n },\n status: {\n code: opts.status === \"ok\" ? 1 : 2,\n message: opts.statusMessage,\n },\n });\n } catch { /* telemetry is best-effort */ }\n}\n\n// --- Channel plugin definition ---\n\nconst agentVaultPlugin = {\n id: \"agentvault\",\n meta: {\n id: \"agentvault\",\n label: \"AgentVault\",\n selectionLabel: \"AgentVault (E2E Encrypted)\",\n docsPath: \"https://agentvault.chat/docs\",\n blurb: \"Zero-knowledge, end-to-end encrypted messaging between owners and their AI agents.\",\n aliases: [\"av\", \"agent-vault\"],\n },\n capabilities: { chatTypes: [\"direct\", \"room\"] },\n config: { listAccountIds, resolveAccount },\n\n gateway: {\n /** Health probe for `openclaw channels status --probe` */\n probe: async (ctx: any) => {\n const accountId = ctx?.accountId ?? \"default\";\n const ch = _channels.get(accountId);\n if (!ch) return { ok: false, status: \"disconnected\", error: \"Channel not started\" };\n const state = ch.state;\n return {\n ok: state === \"ready\",\n status: state,\n deviceId: ch.deviceId ?? undefined,\n sessions: ch.sessionCount,\n };\n },\n\n /** Status for `openclaw health --json` per-channel summary */\n status: (ctx: any) => {\n const accountId = ctx?.accountId ?? \"default\";\n const ch = _channels.get(accountId);\n if (!ch) return { connected: false, status: \"not_started\" };\n return {\n connected: ch.state === \"ready\",\n status: ch.state,\n deviceId: ch.deviceId ?? undefined,\n sessions: ch.sessionCount,\n encrypted: true,\n };\n },\n\n startAccount: async (ctx: any) => {\n const { account, cfg, log, abortSignal } = ctx;\n\n if (!account.configured) {\n throw new Error(\n \"AgentVault channel not configured. Run: npx @agentvault/agentvault setup --token=av_tok_...\\nThen restart OpenClaw.\",\n );\n }\n\n const dataDir = resolve(account.dataDir.replace(/^~/, process.env.HOME ?? \"~\"));\n log?.info(`[AgentVault] starting (dataDir=${dataDir})`);\n\n // Lazy import \u2014 defers libsodium initialization until channel actually starts\n const { SecureChannel } = await import(\"./index.js\");\n\n // startAccount must STAY PENDING while the channel is running.\n // Resolving signals \"channel stopped\" to the gateway health monitor,\n // which triggers auto-restart. We block here until the abortSignal\n // fires (gateway shutdown / config reload), then clean up.\n await new Promise<void>((resolve, reject) => {\n let channel: any;\n\n const onAbort = async () => {\n await channel?.stop();\n _channels.delete(account.accountId);\n resolve();\n };\n\n abortSignal?.addEventListener(\"abort\", () => void onAbort());\n\n // Lazy import \u2014 defers libsodium initialization until channel starts\n import(\"./index.js\").then(({ SecureChannel }) => {\n channel = new SecureChannel({\n inviteToken: \"\",\n dataDir,\n apiUrl: account.apiUrl,\n agentName: account.agentName,\n onMessage: async (plaintext: string, metadata: any) => {\n if (!_ocRuntime) {\n log?.info(\"[AgentVault] runtime not ready, queuing message\");\n _messageQueue.push(async () => {\n await handleInbound({ plaintext, metadata, channel, account, cfg });\n });\n return;\n }\n try {\n await handleInbound({ plaintext, metadata, channel, account, cfg });\n } catch (err) {\n log?.info(`[AgentVault] inbound error: ${String(err)}`);\n }\n },\n onStateChange: (state: string) => {\n log?.info(`[AgentVault] \u2192 ${state}`);\n // \"error\" is a permanent failure \u2014 reject so gateway can restart\n if (state === \"error\") reject(new Error(\"AgentVault channel permanent error\"));\n // All other states (connecting/ready/disconnected) are handled\n // internally by SecureChannel's reconnect logic \u2014 do NOT resolve.\n },\n });\n\n _channels.set(account.accountId, channel);\n\n // Prevent unhandled \"error\" events from crashing the process.\n // Without this handler, Node.js EventEmitter throws on emit(\"error\").\n channel.on(\"error\", (err: any) => {\n log?.info(`[AgentVault] channel error (non-fatal): ${String(err)}`);\n });\n\n // Start local HTTP server for proactive sends\n const httpPort = account.httpPort ?? 18790;\n channel.on(\"ready\", () => {\n channel.startHttpServer(httpPort);\n log?.info(`[AgentVault] HTTP send server listening on http://127.0.0.1:${httpPort}`);\n });\n\n channel.start().catch(reject);\n }).catch(reject);\n });\n\n return { stop: async () => {} }; // Channel already stopped via abortSignal by this point\n },\n },\n\n outbound: {\n deliveryMode: \"direct\" as const,\n\n // Register valid send targets so OpenClaw's `message` tool can route\n // proactive (agent-initiated) sends \u2014 not just replies to inbound messages.\n targets: [\n {\n id: \"owner\",\n label: \"AgentVault Owner\",\n accountId: \"default\",\n },\n {\n id: \"default\",\n label: \"AgentVault Owner (default)\",\n accountId: \"default\",\n },\n ],\n\n sendText: async ({ to, text, accountId }: { to: string; text: string; accountId?: string }) => {\n const resolvedId = accountId ?? \"default\";\n const ch = _channels.get(resolvedId);\n if (!ch) return { ok: false, error: \"AgentVault channel not connected\" };\n try {\n const wasReady = ch.state === \"ready\";\n await ch.send(text);\n return { ok: true, queued: !wasReady };\n } catch (err) {\n return { ok: false, error: String(err) };\n }\n },\n\n sendMedia: async ({ to, text, mediaUrl, accountId }: { to: string; text?: string; mediaUrl: string; accountId?: string }) => {\n const resolvedId = accountId ?? \"default\";\n const ch = _channels.get(resolvedId);\n if (!ch) return { ok: false, error: \"AgentVault channel not connected\" };\n try {\n // For now, send media URL as text \u2014 AgentVault handles attachments separately\n const message = text ? `${text}\\n${mediaUrl}` : mediaUrl;\n const wasReady = ch.state === \"ready\";\n await ch.send(message);\n return { ok: true, queued: !wasReady };\n } catch (err) {\n return { ok: false, error: String(err) };\n }\n },\n },\n};\n\n// --- Exported for testing ---\nexport { _parseMentions, _shouldProcessRoomMessage, _stripMentions };\n\n// --- Plugin export ---\n\nexport default {\n id: \"agentvault\",\n name: \"AgentVault\",\n description: \"End-to-end encrypted, zero-knowledge messaging between AI agent owners and their agents.\",\n register(api: any) {\n _setRuntime(api.runtime);\n\n // Install fetch interceptor to capture all outbound HTTP from the gateway process.\n installFetchInterceptor({\n onHttpCall: (report) => {\n // Find an active channel to emit through\n const ch = _channels.values().next().value;\n if (!ch) return;\n\n // Telemetry reporter is optional \u2014 may not be initialized\n if (ch.telemetry) {\n try {\n ch.telemetry.reportHttpCall({\n method: report.method,\n url: report.url,\n statusCode: report.statusCode,\n latencyMs: report.latencyMs,\n ...(report.traceId ? { traceId: report.traceId } : {}),\n ...(report.parentSpanId ? { parentSpanId: report.parentSpanId } : {}),\n });\n } catch { /* best-effort */ }\n }\n\n // Activity span always fires (uses WS, not telemetry reporter)\n try {\n const hostname = (() => { try { return new URL(report.url).hostname; } catch { return report.url.slice(0, 40); } })();\n ch.sendActivitySpan({\n trace_id: report.traceId ?? \"\",\n parent_span_id: report.parentSpanId ?? \"\",\n span_id: randomBytes(8).toString(\"hex\"),\n span_type: \"http\",\n span_name: hostname,\n status: report.statusCode >= 400 || report.statusCode === 0 ? \"error\" : \"ok\",\n start_time: new Date(Date.now() - report.latencyMs).toISOString(),\n end_time: new Date().toISOString(),\n duration_ms: report.latencyMs,\n attributes: {\n \"ai.agent.http.method\": report.method,\n \"ai.agent.http.url\": report.url,\n },\n http_method: report.method,\n http_status_code: report.statusCode,\n http_url: report.url,\n });\n } catch { /* best-effort */ }\n },\n });\n\n api.registerChannel({ plugin: agentVaultPlugin });\n\n // --- Agent tool: agentvault_status ---\n // Lets the agent check its own encrypted channel status\n try {\n api.registerTool?.({\n name: \"agentvault_status\",\n description: \"Check the AgentVault encrypted channel status, connection state, and session count.\",\n parameters: {\n type: \"object\",\n properties: {\n accountId: {\n type: \"string\",\n description: \"Account ID to check (default: 'default')\",\n },\n },\n },\n execute: async (_id: string, params: { accountId?: string }) => {\n const id = params.accountId ?? \"default\";\n const ch = _channels.get(id);\n if (!ch) {\n return { content: [{ type: \"text\", text: JSON.stringify({ connected: false, error: \"Channel not started\" }) }] };\n }\n return {\n content: [{\n type: \"text\",\n text: JSON.stringify({\n connected: ch.state === \"ready\",\n state: ch.state,\n deviceId: ch.deviceId,\n sessions: ch.sessionCount,\n encrypted: true,\n }),\n }],\n };\n },\n }, { optional: true });\n } catch { /* registerTool may not be available in older OpenClaw versions */ }\n\n // --- Auto-reply command: /agentvault ---\n // Quick status check without AI involvement\n try {\n api.registerCommand?.({\n name: \"agentvault\",\n description: \"Show AgentVault encrypted channel status\",\n handler: () => {\n const statuses: string[] = [];\n if (_channels.size === 0) {\n statuses.push(\"AgentVault: no active channels\");\n } else {\n for (const [id, ch] of _channels) {\n statuses.push(`AgentVault [${id}]: ${ch.state} | sessions: ${ch.sessionCount} | encrypted: yes`);\n }\n }\n return { text: statuses.join(\"\\n\") };\n },\n });\n } catch { /* registerCommand may not be available in older OpenClaw versions */ }\n },\n};\n", "/**\n * Shared multi-account config resolution for AgentVault OpenClaw plugin.\n *\n * Supports two config shapes:\n * 1. Legacy single-agent: channels.agentvault.dataDir (returns [\"default\"])\n * 2. Multi-agent: channels.agentvault.accounts.{id}.dataDir (returns account keys)\n *\n * When `accounts` key is present, it takes precedence over top-level dataDir.\n */\n\nconst DEFAULT_API_URL = \"https://api.agentvault.chat\";\nconst DEFAULT_HTTP_PORT = 18790;\n\nexport interface ResolvedAccount {\n accountId: string;\n dataDir: string;\n apiUrl: string;\n agentName: string;\n httpPort: number;\n configured: boolean;\n}\n\nexport function listAccountIds(cfg: any): string[] {\n const av = cfg?.channels?.agentvault;\n if (!av) return [];\n if (av.accounts && typeof av.accounts === \"object\") {\n return Object.keys(av.accounts);\n }\n return av.dataDir ? [\"default\"] : [];\n}\n\nexport function resolveAccount(cfg: any, accountId?: string): ResolvedAccount {\n const av = cfg?.channels?.agentvault ?? {};\n const id = accountId ?? \"default\";\n\n if (av.accounts && typeof av.accounts === \"object\") {\n const acct = av.accounts[id];\n if (!acct) {\n return {\n accountId: id,\n dataDir: \"\",\n apiUrl: av.apiUrl ?? DEFAULT_API_URL,\n agentName: id,\n httpPort: DEFAULT_HTTP_PORT,\n configured: false,\n };\n }\n\n let httpPort = acct.httpPort;\n if (httpPort == null) {\n const keys = Object.keys(av.accounts);\n const index = keys.indexOf(id);\n httpPort = DEFAULT_HTTP_PORT + (index >= 0 ? index : 0);\n }\n\n return {\n accountId: id,\n dataDir: acct.dataDir ?? \"\",\n apiUrl: acct.apiUrl ?? av.apiUrl ?? DEFAULT_API_URL,\n agentName: acct.agentName ?? id,\n httpPort,\n configured: Boolean(acct.dataDir),\n };\n }\n\n return {\n accountId: id,\n dataDir: av.dataDir ?? \"~/.openclaw/agentvault\",\n apiUrl: av.apiUrl ?? DEFAULT_API_URL,\n agentName: av.agentName ?? \"OpenClaw Agent\",\n httpPort: av.httpPort ?? DEFAULT_HTTP_PORT,\n configured: Boolean(av.dataDir),\n };\n}\n", "/**\n * HTTP interceptor for capturing outbound HTTP calls during message handling.\n *\n * Uses Node.js diagnostics_channel to subscribe to undici request events,\n * capturing ALL outbound HTTP from the process (including LLM SDKs, Playwright\n * navigations, and any library that uses undici under the hood).\n *\n * Also monkey-patches globalThis.fetch as a fallback for non-undici HTTP.\n *\n * Uses AsyncLocalStorage to associate intercepted calls with the active\n * message's traceId/parentSpanId.\n *\n * Built-in skip patterns prevent capturing internal infrastructure requests\n * (localhost, AgentVault API, Clerk auth).\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport diagnosticsChannel from \"node:diagnostics_channel\";\n\n// \u2500\u2500 Public types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface HttpCallReport {\n method: string;\n url: string;\n statusCode: number;\n latencyMs: number;\n traceId?: string;\n parentSpanId?: string;\n}\n\nexport interface TraceContext {\n traceId: string;\n parentSpanId: string;\n}\n\nexport interface FetchInterceptorOptions {\n onHttpCall: (report: HttpCallReport) => void;\n skipPatterns?: RegExp[];\n}\n\n// \u2500\u2500 Internal state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst traceStore = new AsyncLocalStorage<TraceContext>();\n\nconst DEFAULT_SKIP_PATTERNS: RegExp[] = [\n /^https?:\\/\\/localhost(:\\d+)?/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?/,\n /\\.agentvault\\.chat/,\n /\\.agentvault\\.dev/,\n /\\.clerk\\./,\n];\n\nlet installed = false;\nlet originalFetch: typeof globalThis.fetch | undefined;\n\n// Track in-flight undici requests: request \u2192 { url, method, startTime }\nconst inflightRequests = new WeakMap<\n object,\n { url: string; method: string; startTime: number }\n>();\n\n// Diagnostics channel subscriptions\nlet unsubCreate: (() => void) | undefined;\nlet unsubHeaders: (() => void) | undefined;\nlet unsubError: (() => void) | undefined;\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction shouldSkip(url: string, extraPatterns: RegExp[]): boolean {\n const allPatterns = [...DEFAULT_SKIP_PATTERNS, ...extraPatterns];\n return allPatterns.some((p) => p.test(url));\n}\n\nfunction extractUrl(origin: string, path: string): string {\n // undici gives us origin (e.g., \"https://api.openai.com\") and path (e.g., \"/v1/chat/completions\")\n return `${origin}${path}`;\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Install HTTP interceptor using both undici diagnostics channels and\n * globalThis.fetch monkey-patching. Idempotent.\n */\nexport function installFetchInterceptor(opts: FetchInterceptorOptions): void {\n if (installed) return;\n installed = true;\n\n const skipPatterns = [\n ...DEFAULT_SKIP_PATTERNS,\n ...(opts.skipPatterns ?? []),\n ];\n\n // \u2500\u2500 1. Undici diagnostics channel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // undici publishes events for every HTTP request it makes.\n // This captures LLM SDK calls, playwright navigations, etc.\n\n try {\n const createChannel = diagnosticsChannel.channel(\"undici:request:create\");\n const headersChannel = diagnosticsChannel.channel(\"undici:request:headers\");\n const errorChannel = diagnosticsChannel.channel(\"undici:request:error\");\n\n const onRequestCreate = (message: unknown) => {\n try {\n const msg = message as {\n request: {\n method?: string;\n origin?: string;\n path?: string;\n };\n };\n const req = msg.request;\n if (!req) return;\n\n const origin = String(req.origin ?? \"\");\n const path = String(req.path ?? \"/\");\n const url = extractUrl(origin, path);\n\n if (shouldSkip(url, skipPatterns)) return;\n\n inflightRequests.set(req, {\n url,\n method: String(req.method ?? \"GET\").toUpperCase(),\n startTime: Date.now(),\n });\n } catch { /* best-effort */ }\n };\n\n const onRequestHeaders = (message: unknown) => {\n try {\n const msg = message as {\n request: object;\n response: { statusCode?: number };\n };\n const tracked = inflightRequests.get(msg.request);\n if (!tracked) return;\n inflightRequests.delete(msg.request);\n\n const latencyMs = Date.now() - tracked.startTime;\n const ctx = traceStore.getStore();\n\n opts.onHttpCall({\n method: tracked.method,\n url: tracked.url,\n statusCode: msg.response?.statusCode ?? 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n };\n\n const onRequestError = (message: unknown) => {\n try {\n const msg = message as { request: object; error?: Error };\n const tracked = inflightRequests.get(msg.request);\n if (!tracked) return;\n inflightRequests.delete(msg.request);\n\n const latencyMs = Date.now() - tracked.startTime;\n const ctx = traceStore.getStore();\n\n opts.onHttpCall({\n method: tracked.method,\n url: tracked.url,\n statusCode: 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n };\n\n createChannel.subscribe(onRequestCreate);\n headersChannel.subscribe(onRequestHeaders);\n errorChannel.subscribe(onRequestError);\n\n unsubCreate = () => createChannel.unsubscribe(onRequestCreate);\n unsubHeaders = () => headersChannel.unsubscribe(onRequestHeaders);\n unsubError = () => errorChannel.unsubscribe(onRequestError);\n } catch {\n // diagnostics_channel not available or undici not loaded \u2014 fall through to fetch-only\n }\n\n // \u2500\u2500 2. globalThis.fetch monkey-patch (fallback) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Catches any HTTP that doesn't go through undici (e.g., native fetch\n // in newer Node.js, or custom HTTP implementations).\n\n originalFetch = globalThis.fetch;\n const savedOriginal = originalFetch;\n\n globalThis.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url =\n input instanceof Request\n ? input.url\n : input instanceof URL\n ? input.href\n : String(input);\n\n if (shouldSkip(url, skipPatterns)) {\n return savedOriginal(input, init);\n }\n\n const method =\n input instanceof Request\n ? input.method\n : init?.method ?? \"GET\";\n\n const ctx = traceStore.getStore();\n const start = Date.now();\n\n try {\n const response = await savedOriginal(input, init);\n const latencyMs = Date.now() - start;\n\n try {\n opts.onHttpCall({\n method,\n url,\n statusCode: response.status,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n\n return response;\n } catch (err) {\n const latencyMs = Date.now() - start;\n\n try {\n opts.onHttpCall({\n method,\n url,\n statusCode: 0,\n latencyMs,\n traceId: ctx?.traceId,\n parentSpanId: ctx?.parentSpanId,\n });\n } catch { /* best-effort */ }\n\n throw err;\n }\n };\n}\n\n/**\n * Uninstall all interceptors. Safe to call even if not installed.\n */\nexport function uninstallFetchInterceptor(): void {\n if (!installed) return;\n\n // Restore fetch\n if (originalFetch) {\n globalThis.fetch = originalFetch;\n originalFetch = undefined;\n }\n\n // Unsubscribe from diagnostics channels\n unsubCreate?.();\n unsubHeaders?.();\n unsubError?.();\n unsubCreate = undefined;\n unsubHeaders = undefined;\n unsubError = undefined;\n\n installed = false;\n}\n\n/**\n * Run an async function with trace context attached via AsyncLocalStorage.\n * Any HTTP calls made within `fn` (via undici or fetch) will include\n * traceId/parentSpanId in their HttpCallReport.\n */\nexport function runWithTraceContext<T>(\n ctx: TraceContext,\n fn: () => T | Promise<T>,\n): Promise<T> {\n return traceStore.run(ctx, fn) as Promise<T>;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["resolve", "SecureChannel"]
7
7
  }
@@ -32,6 +32,34 @@ export declare const agentVaultPlugin: {
32
32
  resolveAccount: typeof resolveAccount;
33
33
  };
34
34
  gateway: {
35
+ /** Health probe for `openclaw channels status --probe` */
36
+ probe: (ctx: any) => Promise<{
37
+ ok: boolean;
38
+ status: string;
39
+ error: string;
40
+ deviceId?: undefined;
41
+ sessions?: undefined;
42
+ } | {
43
+ ok: boolean;
44
+ status: import("./types.js").ChannelState;
45
+ deviceId: string | undefined;
46
+ sessions: number;
47
+ error?: undefined;
48
+ }>;
49
+ /** Status for `openclaw health --json` per-channel summary */
50
+ status: (ctx: any) => {
51
+ connected: boolean;
52
+ status: string;
53
+ deviceId?: undefined;
54
+ sessions?: undefined;
55
+ encrypted?: undefined;
56
+ } | {
57
+ connected: boolean;
58
+ status: import("./types.js").ChannelState;
59
+ deviceId: string | undefined;
60
+ sessions: number;
61
+ encrypted: boolean;
62
+ };
35
63
  startAccount: (ctx: any) => Promise<{
36
64
  stop: () => Promise<void>;
37
65
  }>;
@@ -51,6 +79,15 @@ export declare const agentVaultPlugin: {
51
79
  ok: boolean;
52
80
  error?: string;
53
81
  }>;
82
+ sendMedia: ({ text, mediaUrl, accountId, }: {
83
+ to: string;
84
+ text?: string;
85
+ mediaUrl: string;
86
+ accountId?: string;
87
+ }) => Promise<{
88
+ ok: boolean;
89
+ error?: string;
90
+ }>;
54
91
  };
55
92
  };
56
93
  //# sourceMappingURL=openclaw-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openclaw-plugin.d.ts","sourceRoot":"","sources":["../src/openclaw-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAwB,MAAM,qBAAqB,CAAC;AAQ3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,SAAS,SAAY,GAAG,aAAa,GAAG,SAAS,CAEjF;AAMD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;4BAkBC,GAAG;;;;;;;;;;;mDA8F1B;YACD,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;CAc/C,CAAC"}
1
+ {"version":3,"file":"openclaw-plugin.d.ts","sourceRoot":"","sources":["../src/openclaw-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAwB,MAAM,qBAAqB,CAAC;AAQ3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,SAAS,SAAY,GAAG,aAAa,GAAG,SAAS,CAEjF;AAMD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;QAkBzB,0DAA0D;qBACvC,GAAG;;;;;;;;;;;;;QAatB,8DAA8D;sBAChD,GAAG;;;;;;;;;;;;;4BAaS,GAAG;;;;;;;;;;;mDA8F1B;YACD,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;oDAkBzC;YACD,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,EAAE,MAAM,CAAC;YACjB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,KAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;CAe/C,CAAC"}
@@ -2,7 +2,8 @@
2
2
  "id": "agentvault",
3
3
  "name": "AgentVault",
4
4
  "description": "End-to-end encrypted, zero-knowledge messaging between AI agent owners and their agents.",
5
- "version": "0.13.8",
5
+ "version": "0.13.9",
6
+ "kind": "channel",
6
7
  "channels": ["agentvault"],
7
8
  "outbound": {
8
9
  "deliveryMode": "direct",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvault/agentvault",
3
- "version": "0.13.8",
3
+ "version": "0.13.10",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,6 +11,14 @@
11
11
  }
12
12
  },
13
13
  "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/motiveflowllc/agentvault-openclaw-plugin.git"
17
+ },
18
+ "homepage": "https://agentvault.chat",
19
+ "bugs": {
20
+ "url": "https://github.com/motiveflowllc/agentvault-openclaw-plugin/issues"
21
+ },
14
22
  "scripts": {
15
23
  "build": "tsc --emitDeclarationOnly && node build.mjs",
16
24
  "test": "vitest run",