@agentvault/secure-channel 0.5.0 → 0.6.0

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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { SecureChannel } from "./channel.js";
2
2
  export type { SecureChannelConfig, ChannelState, MessageMetadata, PersistedState, LegacyPersistedState, DeviceSession, HistoryEntry, } from "./types.js";
3
- export declare const VERSION = "0.3.0";
3
+ export { agentVaultPlugin, setOcRuntime, getActiveChannel } from "./openclaw-plugin.js";
4
+ export declare const VERSION = "0.5.1";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExF,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -87,7 +87,7 @@ var randomValuesStandard;
87
87
  var crypto;
88
88
  var randomValueNodeJS;
89
89
  var _Module = Module;
90
- Module.ready = new Promise(function(resolve, reject) {
90
+ Module.ready = new Promise(function(resolve2, reject) {
91
91
  var Module2 = _Module;
92
92
  Module2.onAbort = reject;
93
93
  Module2.print = function(what) {
@@ -99,13 +99,13 @@ Module.ready = new Promise(function(resolve, reject) {
99
99
  Module2.onRuntimeInitialized = function() {
100
100
  try {
101
101
  Module2._crypto_secretbox_keybytes();
102
- resolve();
102
+ resolve2();
103
103
  } catch (err2) {
104
104
  reject(err2);
105
105
  }
106
106
  };
107
107
  Module2.useBackupModule = function() {
108
- return new Promise(function(resolve2, reject2) {
108
+ return new Promise(function(resolve3, reject2) {
109
109
  var Module3 = {};
110
110
  Module3.onAbort = reject2;
111
111
  Module3.getRandomValue = _Module.getRandomValue;
@@ -118,7 +118,7 @@ Module.ready = new Promise(function(resolve, reject) {
118
118
  Object.keys(Module3).forEach(function(k2) {
119
119
  _Module[k2] = Module3[k2];
120
120
  });
121
- resolve2();
121
+ resolve3();
122
122
  };
123
123
  var Module3 = typeof Module3 != "undefined" ? Module3 : {};
124
124
  var ENVIRONMENT_IS_WEB2 = !!globalThis.window;
@@ -178,13 +178,13 @@ Module.ready = new Promise(function(resolve, reject) {
178
178
  }
179
179
  readAsync2 = async (url) => {
180
180
  if (isFileURI2(url)) {
181
- return new Promise((resolve3, reject3) => {
181
+ return new Promise((resolve4, reject3) => {
182
182
  var xhr = new XMLHttpRequest();
183
183
  xhr.open("GET", url, true);
184
184
  xhr.responseType = "arraybuffer";
185
185
  xhr.onload = () => {
186
186
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
187
- resolve3(xhr.response);
187
+ resolve4(xhr.response);
188
188
  return;
189
189
  }
190
190
  reject3(xhr.status);
@@ -40097,9 +40097,9 @@ Module.ready = new Promise(function(resolve, reject) {
40097
40097
  }
40098
40098
  var info = getWasmImports2();
40099
40099
  if (Module3["instantiateWasm"]) {
40100
- return new Promise((resolve3, reject3) => {
40100
+ return new Promise((resolve4, reject3) => {
40101
40101
  Module3["instantiateWasm"](info, (inst, mod) => {
40102
- resolve3(receiveInstance(inst, mod));
40102
+ resolve4(receiveInstance(inst, mod));
40103
40103
  });
40104
40104
  });
40105
40105
  }
@@ -41002,13 +41002,13 @@ Module.ready = new Promise(function(resolve, reject) {
41002
41002
  }
41003
41003
  readAsync = async (url) => {
41004
41004
  if (isFileURI(url)) {
41005
- return new Promise((resolve2, reject2) => {
41005
+ return new Promise((resolve3, reject2) => {
41006
41006
  var xhr = new XMLHttpRequest();
41007
41007
  xhr.open("GET", url, true);
41008
41008
  xhr.responseType = "arraybuffer";
41009
41009
  xhr.onload = () => {
41010
41010
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
41011
- resolve2(xhr.response);
41011
+ resolve3(xhr.response);
41012
41012
  return;
41013
41013
  }
41014
41014
  reject2(xhr.status);
@@ -41122,9 +41122,9 @@ Module.ready = new Promise(function(resolve, reject) {
41122
41122
  }
41123
41123
  var info = getWasmImports();
41124
41124
  if (Module2["instantiateWasm"]) {
41125
- return new Promise((resolve2, reject2) => {
41125
+ return new Promise((resolve3, reject2) => {
41126
41126
  Module2["instantiateWasm"](info, (inst, mod) => {
41127
- resolve2(receiveInstance(inst, mod));
41127
+ resolve3(receiveInstance(inst, mod));
41128
41128
  });
41129
41129
  });
41130
41130
  }
@@ -45011,6 +45011,9 @@ async function enrollDevice(apiUrl, inviteToken, identityPkHex, ephemeralPkHex,
45011
45011
  }
45012
45012
  async function pollDeviceStatus(apiUrl, deviceId) {
45013
45013
  const res = await fetch(`${apiUrl}/api/v1/devices/${deviceId}/status`);
45014
+ if (res.status === 429) {
45015
+ return { device_id: deviceId, status: "PENDING", fingerprint: "", rateLimited: true };
45016
+ }
45014
45017
  if (!res.ok) {
45015
45018
  const detail = await res.text();
45016
45019
  throw new Error(`Status poll failed (${res.status}): ${detail}`);
@@ -45031,7 +45034,7 @@ async function activateDevice(apiUrl, deviceId) {
45031
45034
  }
45032
45035
 
45033
45036
  // src/channel.ts
45034
- var POLL_INTERVAL_MS = 3e3;
45037
+ var POLL_INTERVAL_MS = 6e3;
45035
45038
  var RECONNECT_BASE_MS = 1e3;
45036
45039
  var RECONNECT_MAX_MS = 3e4;
45037
45040
  function migratePersistedState(raw) {
@@ -45316,6 +45319,10 @@ var SecureChannel = class extends EventEmitter {
45316
45319
  this.config.apiUrl,
45317
45320
  this._deviceId
45318
45321
  );
45322
+ if (status.rateLimited) {
45323
+ this._pollTimer = setTimeout(doPoll, POLL_INTERVAL_MS * 2);
45324
+ return;
45325
+ }
45319
45326
  if (status.status === "APPROVED") {
45320
45327
  await this._activate();
45321
45328
  return;
@@ -45765,10 +45772,191 @@ var SecureChannel = class extends EventEmitter {
45765
45772
  }
45766
45773
  };
45767
45774
 
45775
+ // src/openclaw-plugin.ts
45776
+ import { resolve } from "node:path";
45777
+ var _ocRuntime = null;
45778
+ var _channels = /* @__PURE__ */ new Map();
45779
+ function setOcRuntime(runtime) {
45780
+ _ocRuntime = runtime;
45781
+ }
45782
+ function getActiveChannel(accountId = "default") {
45783
+ return _channels.get(accountId);
45784
+ }
45785
+ var agentVaultPlugin = {
45786
+ id: "agentvault",
45787
+ meta: {
45788
+ id: "agentvault",
45789
+ label: "AgentVault",
45790
+ selectionLabel: "AgentVault (E2E Encrypted)",
45791
+ docsPath: "https://agentvault.chat/docs",
45792
+ blurb: "Zero-knowledge, end-to-end encrypted messaging between owners and their AI agents.",
45793
+ aliases: ["av", "agent-vault"]
45794
+ },
45795
+ capabilities: {
45796
+ chatTypes: ["direct"]
45797
+ },
45798
+ config: {
45799
+ listAccountIds: (cfg) => {
45800
+ const av = cfg?.channels?.agentvault;
45801
+ return av?.dataDir ? ["default"] : [];
45802
+ },
45803
+ resolveAccount: (cfg, accountId) => {
45804
+ const av = cfg?.channels?.agentvault ?? {};
45805
+ return {
45806
+ accountId: accountId ?? "default",
45807
+ dataDir: av.dataDir ?? "~/.openclaw/agentvault",
45808
+ apiUrl: av.apiUrl ?? "https://api.agentvault.chat",
45809
+ agentName: av.agentName ?? "OpenClaw Agent",
45810
+ configured: Boolean(av.dataDir)
45811
+ };
45812
+ }
45813
+ },
45814
+ gateway: {
45815
+ startAccount: async (ctx) => {
45816
+ const { account, cfg, log, abortSignal } = ctx;
45817
+ if (!account.configured) {
45818
+ throw new Error(
45819
+ "AgentVault channel is not configured.\nRun the one-time setup: npx @agentvault/secure-channel setup --token=av_tok_...\nThen restart OpenClaw: openclaw gateway restart"
45820
+ );
45821
+ }
45822
+ const dataDir = resolve(account.dataDir.replace(/^~/, process.env.HOME ?? "~"));
45823
+ log?.(`[AgentVault] starting channel (dataDir=${dataDir})`);
45824
+ const channel = new SecureChannel({
45825
+ // No invite token needed — resuming from persisted enrolled state
45826
+ inviteToken: "",
45827
+ dataDir,
45828
+ apiUrl: account.apiUrl,
45829
+ agentName: account.agentName,
45830
+ onMessage: async (plaintext, metadata) => {
45831
+ if (!_ocRuntime) {
45832
+ log?.("[AgentVault] runtime not ready \u2014 dropping inbound message");
45833
+ return;
45834
+ }
45835
+ try {
45836
+ await _handleInbound({ plaintext, metadata, channel, account, cfg });
45837
+ } catch (err) {
45838
+ log?.(`[AgentVault] inbound dispatch error: ${String(err)}`);
45839
+ }
45840
+ },
45841
+ onStateChange: (state) => {
45842
+ log?.(`[AgentVault] state \u2192 ${state}`);
45843
+ }
45844
+ });
45845
+ _channels.set(account.accountId, channel);
45846
+ abortSignal?.addEventListener("abort", () => {
45847
+ _channels.delete(account.accountId);
45848
+ });
45849
+ await channel.start();
45850
+ return {
45851
+ stop: async () => {
45852
+ await channel.stop();
45853
+ _channels.delete(account.accountId);
45854
+ }
45855
+ };
45856
+ }
45857
+ },
45858
+ outbound: {
45859
+ deliveryMode: "direct",
45860
+ sendText: async ({
45861
+ text,
45862
+ accountId
45863
+ }) => {
45864
+ const channel = _channels.get(accountId ?? "default");
45865
+ if (!channel) {
45866
+ return { ok: false, error: "AgentVault channel is not connected" };
45867
+ }
45868
+ try {
45869
+ await channel.send(text);
45870
+ return { ok: true };
45871
+ } catch (err) {
45872
+ return { ok: false, error: String(err) };
45873
+ }
45874
+ }
45875
+ }
45876
+ };
45877
+ async function _handleInbound(params) {
45878
+ const { plaintext, metadata, channel, account, cfg } = params;
45879
+ const core = _ocRuntime;
45880
+ const sessionKey = `agentvault:${account.accountId}:${(metadata.conversationId ?? "default").slice(0, 8)}`;
45881
+ const senderId = `agentvault:owner`;
45882
+ const route = core.channel.routing.resolveAgentRoute({
45883
+ cfg,
45884
+ channel: "agentvault",
45885
+ accountId: account.accountId,
45886
+ peer: { kind: "direct", id: senderId }
45887
+ });
45888
+ const storePath = core.channel.session.resolveStorePath(cfg?.session?.store, {
45889
+ agentId: route.agentId
45890
+ });
45891
+ const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
45892
+ const previousTimestamp = core.channel.session.readSessionUpdatedAt({
45893
+ storePath,
45894
+ sessionKey: route.sessionKey
45895
+ });
45896
+ const body = core.channel.reply.formatAgentEnvelope({
45897
+ channel: "AgentVault",
45898
+ from: "Owner",
45899
+ timestamp: new Date(metadata.timestamp).getTime(),
45900
+ previousTimestamp,
45901
+ envelope: envelopeOptions,
45902
+ body: plaintext
45903
+ });
45904
+ const ctxPayload = core.channel.reply.finalizeInboundContext({
45905
+ Body: body,
45906
+ RawBody: plaintext,
45907
+ CommandBody: plaintext,
45908
+ From: senderId,
45909
+ To: `agentvault:agent:${account.accountId}`,
45910
+ SessionKey: route.sessionKey,
45911
+ AccountId: account.accountId,
45912
+ ChatType: "direct",
45913
+ ConversationLabel: "AgentVault",
45914
+ SenderName: "Owner",
45915
+ SenderId: senderId,
45916
+ Provider: "agentvault",
45917
+ Surface: "agentvault",
45918
+ MessageSid: metadata.messageId,
45919
+ Timestamp: new Date(metadata.timestamp).getTime(),
45920
+ OriginatingChannel: "agentvault",
45921
+ OriginatingTo: `agentvault:agent:${account.accountId}`,
45922
+ // Owner is cryptographically verified via X3DH + Double Ratchet enrollment
45923
+ CommandAuthorized: true
45924
+ });
45925
+ await core.channel.session.recordInboundSession({
45926
+ storePath,
45927
+ sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
45928
+ ctx: ctxPayload,
45929
+ onRecordError: (err) => {
45930
+ core.error?.(`[AgentVault] session record failed: ${String(err)}`);
45931
+ }
45932
+ });
45933
+ await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
45934
+ ctx: ctxPayload,
45935
+ cfg,
45936
+ dispatcherOptions: {
45937
+ deliver: async (payload) => {
45938
+ const text = (payload.text ?? "").trim();
45939
+ if (text) {
45940
+ await channel.send(text);
45941
+ }
45942
+ },
45943
+ onError: (err, info) => {
45944
+ core.error?.(
45945
+ `[AgentVault] ${info?.kind ?? "reply"} error: ${String(err)}`
45946
+ );
45947
+ }
45948
+ },
45949
+ replyOptions: {}
45950
+ });
45951
+ }
45952
+
45768
45953
  // src/index.ts
45769
- var VERSION = "0.3.0";
45954
+ var VERSION = "0.5.1";
45770
45955
  export {
45771
45956
  SecureChannel,
45772
- VERSION
45957
+ VERSION,
45958
+ agentVaultPlugin,
45959
+ getActiveChannel,
45960
+ setOcRuntime
45773
45961
  };
45774
45962
  //# sourceMappingURL=index.js.map