@agentvault/agentvault 0.13.12 → 0.14.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/cli.js CHANGED
@@ -87,7 +87,7 @@ var init_libsodium_sumo = __esm({
87
87
  }
88
88
  }
89
89
  _Module = Module;
90
- Module.ready = new Promise(function(resolve3, reject) {
90
+ Module.ready = new Promise(function(resolve4, reject) {
91
91
  var Module2 = _Module;
92
92
  Module2.onAbort = reject;
93
93
  Module2.print = function(what) {
@@ -99,13 +99,13 @@ var init_libsodium_sumo = __esm({
99
99
  Module2.onRuntimeInitialized = function() {
100
100
  try {
101
101
  Module2._crypto_secretbox_keybytes();
102
- resolve3();
102
+ resolve4();
103
103
  } catch (err2) {
104
104
  reject(err2);
105
105
  }
106
106
  };
107
107
  Module2.useBackupModule = function() {
108
- return new Promise(function(resolve4, reject2) {
108
+ return new Promise(function(resolve5, reject2) {
109
109
  var Module3 = {};
110
110
  Module3.onAbort = reject2;
111
111
  Module3.getRandomValue = _Module.getRandomValue;
@@ -118,7 +118,7 @@ var init_libsodium_sumo = __esm({
118
118
  Object.keys(Module3).forEach(function(k2) {
119
119
  _Module[k2] = Module3[k2];
120
120
  });
121
- resolve4();
121
+ resolve5();
122
122
  };
123
123
  var Module3 = typeof Module3 != "undefined" ? Module3 : {};
124
124
  var ENVIRONMENT_IS_WEB2 = !!globalThis.window;
@@ -178,13 +178,13 @@ var init_libsodium_sumo = __esm({
178
178
  }
179
179
  readAsync2 = async (url) => {
180
180
  if (isFileURI2(url)) {
181
- return new Promise((resolve5, reject3) => {
181
+ return new Promise((resolve6, 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
- resolve5(xhr.response);
187
+ resolve6(xhr.response);
188
188
  return;
189
189
  }
190
190
  reject3(xhr.status);
@@ -40097,9 +40097,9 @@ var init_libsodium_sumo = __esm({
40097
40097
  }
40098
40098
  var info = getWasmImports2();
40099
40099
  if (Module3["instantiateWasm"]) {
40100
- return new Promise((resolve5, reject3) => {
40100
+ return new Promise((resolve6, reject3) => {
40101
40101
  Module3["instantiateWasm"](info, (inst, mod) => {
40102
- resolve5(receiveInstance(inst, mod));
40102
+ resolve6(receiveInstance(inst, mod));
40103
40103
  });
40104
40104
  });
40105
40105
  }
@@ -41002,13 +41002,13 @@ var init_libsodium_sumo = __esm({
41002
41002
  }
41003
41003
  readAsync = async (url) => {
41004
41004
  if (isFileURI(url)) {
41005
- return new Promise((resolve4, reject2) => {
41005
+ return new Promise((resolve5, 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
- resolve4(xhr.response);
41011
+ resolve5(xhr.response);
41012
41012
  return;
41013
41013
  }
41014
41014
  reject2(xhr.status);
@@ -41122,9 +41122,9 @@ var init_libsodium_sumo = __esm({
41122
41122
  }
41123
41123
  var info = getWasmImports();
41124
41124
  if (Module2["instantiateWasm"]) {
41125
- return new Promise((resolve4, reject2) => {
41125
+ return new Promise((resolve5, reject2) => {
41126
41126
  Module2["instantiateWasm"](info, (inst, mod) => {
41127
- resolve4(receiveInstance(inst, mod));
41127
+ resolve5(receiveInstance(inst, mod));
41128
41128
  });
41129
41129
  });
41130
41130
  }
@@ -45267,17 +45267,30 @@ function generateTraceId() {
45267
45267
  function generateSpanId() {
45268
45268
  return randomHex(8);
45269
45269
  }
45270
+ function applySkillName(attributes, skillName) {
45271
+ if (skillName) {
45272
+ attributes["ai.agent.skill.name"] = skillName;
45273
+ }
45274
+ }
45270
45275
  function buildLlmSpan(opts) {
45271
45276
  const now = Date.now();
45272
45277
  const attributes = {
45278
+ // Legacy (keep for backward compat)
45273
45279
  "ai.agent.llm.model": opts.model,
45274
45280
  "ai.agent.llm.latency_ms": opts.latencyMs,
45275
45281
  "ai.agent.llm.tokens_input": opts.tokensInput,
45276
- "ai.agent.llm.tokens_output": opts.tokensOutput
45282
+ "ai.agent.llm.tokens_output": opts.tokensOutput,
45283
+ // OTel gen_ai standard
45284
+ "gen_ai.request.model": opts.model,
45285
+ "gen_ai.usage.input_tokens": opts.tokensInput,
45286
+ "gen_ai.usage.output_tokens": opts.tokensOutput,
45287
+ "gen_ai.operation.name": "chat"
45277
45288
  };
45278
45289
  if (opts.provider !== void 0) {
45279
45290
  attributes["ai.agent.llm.provider"] = opts.provider;
45291
+ attributes["gen_ai.system"] = opts.provider;
45280
45292
  }
45293
+ applySkillName(attributes, opts.skillName);
45281
45294
  const isError = opts.status === "error";
45282
45295
  const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
45283
45296
  return {
@@ -45297,8 +45310,11 @@ function buildToolSpan(opts) {
45297
45310
  const attributes = {
45298
45311
  "ai.agent.tool.name": opts.toolName,
45299
45312
  "ai.agent.tool.latency_ms": opts.latencyMs,
45300
- "ai.agent.tool.success": opts.success
45313
+ "ai.agent.tool.success": opts.success,
45314
+ // OTel gen_ai standard
45315
+ "gen_ai.tool.name": opts.toolName
45301
45316
  };
45317
+ applySkillName(attributes, opts.skillName);
45302
45318
  const status = opts.success ? { code: 0 } : { code: 2, ...opts.errorMessage ? { message: opts.errorMessage } : {} };
45303
45319
  return {
45304
45320
  traceId: opts.traceId ?? generateTraceId(),
@@ -45314,6 +45330,13 @@ function buildToolSpan(opts) {
45314
45330
  }
45315
45331
  function buildErrorSpan(opts) {
45316
45332
  const now = Date.now();
45333
+ const attributes = {
45334
+ "ai.agent.error.type": opts.errorType,
45335
+ "ai.agent.error.message": opts.errorMessage,
45336
+ // OTel standard
45337
+ "error.type": opts.errorType
45338
+ };
45339
+ applySkillName(attributes, opts.skillName);
45317
45340
  return {
45318
45341
  traceId: opts.traceId ?? generateTraceId(),
45319
45342
  spanId: opts.spanId ?? generateSpanId(),
@@ -45322,10 +45345,7 @@ function buildErrorSpan(opts) {
45322
45345
  kind: opts.spanKind ?? "internal",
45323
45346
  startTime: now,
45324
45347
  endTime: now,
45325
- attributes: {
45326
- "ai.agent.error.type": opts.errorType,
45327
- "ai.agent.error.message": opts.errorMessage
45328
- },
45348
+ attributes,
45329
45349
  status: { code: 2, message: opts.errorMessage }
45330
45350
  };
45331
45351
  }
@@ -45335,8 +45355,13 @@ function buildHttpSpan(opts) {
45335
45355
  "ai.agent.http.method": opts.method,
45336
45356
  "ai.agent.http.url": opts.url,
45337
45357
  "ai.agent.http.status_code": opts.statusCode,
45338
- "ai.agent.http.latency_ms": opts.latencyMs
45358
+ "ai.agent.http.latency_ms": opts.latencyMs,
45359
+ // OTel HTTP standard
45360
+ "http.request.method": opts.method,
45361
+ "url.full": opts.url,
45362
+ "http.response.status_code": opts.statusCode
45339
45363
  };
45364
+ applySkillName(attributes, opts.skillName);
45340
45365
  const isError = opts.status === "error" || opts.statusCode >= 400;
45341
45366
  const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
45342
45367
  return {
@@ -45359,6 +45384,7 @@ function buildActionSpan(opts) {
45359
45384
  "ai.agent.action.latency_ms": opts.latencyMs,
45360
45385
  "ai.agent.action.success": opts.success
45361
45386
  };
45387
+ applySkillName(attributes, opts.skillName);
45362
45388
  const status = opts.success ? { code: 0 } : { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} };
45363
45389
  return {
45364
45390
  traceId: opts.traceId ?? generateTraceId(),
@@ -45378,6 +45404,7 @@ function buildNavSpan(opts) {
45378
45404
  "ai.agent.nav.to_url": opts.toUrl,
45379
45405
  "ai.agent.nav.latency_ms": opts.latencyMs
45380
45406
  };
45407
+ applySkillName(attributes, opts.skillName);
45381
45408
  const isError = opts.status === "error";
45382
45409
  const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
45383
45410
  return {
@@ -45392,6 +45419,60 @@ function buildNavSpan(opts) {
45392
45419
  status
45393
45420
  };
45394
45421
  }
45422
+ function buildTaskSpan(opts) {
45423
+ const now = Date.now();
45424
+ const attributes = {
45425
+ "ai.agent.task.id": opts.taskId,
45426
+ "ai.agent.task.name": opts.taskName,
45427
+ "ai.agent.task.status": opts.status,
45428
+ "gen_ai.operation.name": "task"
45429
+ };
45430
+ if (opts.taskType !== void 0)
45431
+ attributes["ai.agent.task.type"] = opts.taskType;
45432
+ if (opts.stepsCount !== void 0)
45433
+ attributes["ai.agent.task.steps_count"] = opts.stepsCount;
45434
+ if (opts.tokensUsed !== void 0)
45435
+ attributes["ai.agent.task.tokens_used"] = opts.tokensUsed;
45436
+ applySkillName(attributes, opts.skillName);
45437
+ const isError = opts.status === "failed";
45438
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
45439
+ return {
45440
+ traceId: opts.traceId ?? generateTraceId(),
45441
+ spanId: opts.spanId ?? generateSpanId(),
45442
+ parentSpanId: opts.parentSpanId,
45443
+ name: "task.execute",
45444
+ kind: "internal",
45445
+ startTime: now - opts.latencyMs,
45446
+ endTime: now,
45447
+ attributes,
45448
+ status
45449
+ };
45450
+ }
45451
+ function buildEvalSpan(opts) {
45452
+ const now = Date.now();
45453
+ const attributes = {
45454
+ "gen_ai.evaluation.name": opts.evaluationName,
45455
+ "gen_ai.evaluation.score.value": opts.scoreValue
45456
+ };
45457
+ if (opts.scoreLabel)
45458
+ attributes["gen_ai.evaluation.score.label"] = opts.scoreLabel;
45459
+ if (opts.explanation)
45460
+ attributes["gen_ai.evaluation.explanation"] = opts.explanation;
45461
+ if (opts.targetSpanId)
45462
+ attributes["gen_ai.evaluation.target_span_id"] = opts.targetSpanId;
45463
+ applySkillName(attributes, opts.skillName);
45464
+ return {
45465
+ traceId: opts.traceId ?? generateTraceId(),
45466
+ spanId: opts.spanId ?? generateSpanId(),
45467
+ parentSpanId: opts.parentSpanId,
45468
+ name: "gen_ai.evaluation",
45469
+ kind: "internal",
45470
+ startTime: now,
45471
+ endTime: now,
45472
+ attributes,
45473
+ status: { code: 0 }
45474
+ };
45475
+ }
45395
45476
  var init_telemetry = __esm({
45396
45477
  "../crypto/dist/telemetry.js"() {
45397
45478
  "use strict";
@@ -45444,6 +45525,8 @@ var init_telemetry_reporter = __esm({
45444
45525
  _hubId;
45445
45526
  _authHeader;
45446
45527
  _fetch;
45528
+ _agentName;
45529
+ _agentVersion;
45447
45530
  _buffer = [];
45448
45531
  _timer = null;
45449
45532
  constructor(config) {
@@ -45451,6 +45534,8 @@ var init_telemetry_reporter = __esm({
45451
45534
  this._hubId = config.hubId;
45452
45535
  this._authHeader = config.authHeader;
45453
45536
  this._fetch = config.fetchImpl ?? globalThis.fetch;
45537
+ this._agentName = config.agentName ?? "unknown";
45538
+ this._agentVersion = config.agentVersion ?? "0.0.0";
45454
45539
  }
45455
45540
  /** Number of spans waiting to be flushed. */
45456
45541
  get pendingCount() {
@@ -45481,6 +45566,14 @@ var init_telemetry_reporter = __esm({
45481
45566
  reportNavCall(opts) {
45482
45567
  this._buffer.push(buildNavSpan(opts));
45483
45568
  }
45569
+ /** Record an evaluation event. */
45570
+ reportEvaluation(opts) {
45571
+ this._buffer.push(buildEvalSpan(opts));
45572
+ }
45573
+ /** Record a task lifecycle event. */
45574
+ reportTaskCall(opts) {
45575
+ this._buffer.push(buildTaskSpan(opts));
45576
+ }
45484
45577
  /** Record an arbitrary pre-built span. */
45485
45578
  reportCustomSpan(span) {
45486
45579
  this._buffer.push(span);
@@ -45508,6 +45601,12 @@ var init_telemetry_reporter = __esm({
45508
45601
  },
45509
45602
  body: JSON.stringify({
45510
45603
  hub_id: this._hubId,
45604
+ resource: {
45605
+ "gen_ai.agent.name": this._agentName,
45606
+ "gen_ai.agent.id": this._hubId,
45607
+ "gen_ai.agent.version": this._agentVersion,
45608
+ "service.name": "agentvault-agent"
45609
+ },
45511
45610
  spans: spans.map(spanToOtlp)
45512
45611
  })
45513
45612
  });
@@ -45702,6 +45801,156 @@ var init_transport2 = __esm({
45702
45801
  }
45703
45802
  });
45704
45803
 
45804
+ // src/openclaw-compat.ts
45805
+ var openclaw_compat_exports = {};
45806
+ __export(openclaw_compat_exports, {
45807
+ onAgentEvent: () => onAgentEvent,
45808
+ onSessionTranscriptUpdate: () => onSessionTranscriptUpdate,
45809
+ requestHeartbeatNow: () => requestHeartbeatNow
45810
+ });
45811
+ async function requestHeartbeatNow(opts) {
45812
+ if (_heartbeatFn === null) {
45813
+ try {
45814
+ const mod = await import("openclaw/dist/plugin-sdk/infra/heartbeat-wake.js");
45815
+ _heartbeatFn = mod.requestHeartbeatNow ?? mod.default?.requestHeartbeatNow ?? false;
45816
+ } catch {
45817
+ _heartbeatFn = false;
45818
+ }
45819
+ }
45820
+ if (typeof _heartbeatFn === "function") {
45821
+ try {
45822
+ await _heartbeatFn(opts);
45823
+ return true;
45824
+ } catch {
45825
+ return false;
45826
+ }
45827
+ }
45828
+ return false;
45829
+ }
45830
+ async function onAgentEvent(callback) {
45831
+ if (_agentEventFn === null) {
45832
+ try {
45833
+ const mod = await import("openclaw/dist/plugin-sdk/infra/agent-events.js");
45834
+ _agentEventFn = mod.onAgentEvent ?? mod.default?.onAgentEvent ?? false;
45835
+ } catch {
45836
+ _agentEventFn = false;
45837
+ }
45838
+ }
45839
+ if (typeof _agentEventFn === "function") {
45840
+ try {
45841
+ return _agentEventFn(callback);
45842
+ } catch {
45843
+ return () => {
45844
+ };
45845
+ }
45846
+ }
45847
+ return () => {
45848
+ };
45849
+ }
45850
+ async function onSessionTranscriptUpdate(callback) {
45851
+ if (_transcriptFn === null) {
45852
+ try {
45853
+ const mod = await import("openclaw/dist/plugin-sdk/sessions/transcript-events.js");
45854
+ _transcriptFn = mod.onSessionTranscriptUpdate ?? mod.default?.onSessionTranscriptUpdate ?? false;
45855
+ } catch {
45856
+ _transcriptFn = false;
45857
+ }
45858
+ }
45859
+ if (typeof _transcriptFn === "function") {
45860
+ try {
45861
+ return _transcriptFn(callback);
45862
+ } catch {
45863
+ return () => {
45864
+ };
45865
+ }
45866
+ }
45867
+ return () => {
45868
+ };
45869
+ }
45870
+ var _heartbeatFn, _agentEventFn, _transcriptFn;
45871
+ var init_openclaw_compat = __esm({
45872
+ "src/openclaw-compat.ts"() {
45873
+ "use strict";
45874
+ _heartbeatFn = null;
45875
+ _agentEventFn = null;
45876
+ _transcriptFn = null;
45877
+ }
45878
+ });
45879
+
45880
+ // src/http-handlers.ts
45881
+ var http_handlers_exports = {};
45882
+ __export(http_handlers_exports, {
45883
+ handleActionRequest: () => handleActionRequest,
45884
+ handleSendRequest: () => handleSendRequest,
45885
+ handleStatusRequest: () => handleStatusRequest
45886
+ });
45887
+ async function handleSendRequest(parsed, channel2) {
45888
+ const text = parsed.text;
45889
+ if (!text || typeof text !== "string") {
45890
+ return { status: 400, body: { ok: false, error: "Missing 'text' field" } };
45891
+ }
45892
+ try {
45893
+ if (parsed.room_id && typeof parsed.room_id === "string") {
45894
+ await channel2.sendToRoom(parsed.room_id, text, {
45895
+ messageType: parsed.message_type,
45896
+ priority: parsed.priority,
45897
+ metadata: parsed.metadata
45898
+ });
45899
+ } else if (parsed.file_path && typeof parsed.file_path === "string") {
45900
+ await channel2.sendWithAttachment(text, parsed.file_path, {
45901
+ topicId: parsed.topicId
45902
+ });
45903
+ } else {
45904
+ await channel2.send(text, {
45905
+ topicId: parsed.topicId,
45906
+ messageType: parsed.message_type,
45907
+ metadata: parsed.metadata
45908
+ });
45909
+ }
45910
+ return { status: 200, body: { ok: true } };
45911
+ } catch (err) {
45912
+ return { status: 500, body: { ok: false, error: String(err) } };
45913
+ }
45914
+ }
45915
+ async function handleActionRequest(parsed, channel2) {
45916
+ if (!parsed.action || typeof parsed.action !== "string") {
45917
+ return { status: 400, body: { ok: false, error: "Missing 'action' field" } };
45918
+ }
45919
+ try {
45920
+ const confirmation = {
45921
+ action: parsed.action,
45922
+ status: parsed.status ?? "completed",
45923
+ decisionId: parsed.decision_id,
45924
+ detail: parsed.detail,
45925
+ estimated_cost: parsed.estimated_cost
45926
+ };
45927
+ if (parsed.room_id && typeof parsed.room_id === "string") {
45928
+ await channel2.sendActionConfirmationToRoom(parsed.room_id, confirmation);
45929
+ } else {
45930
+ await channel2.sendActionConfirmation(confirmation);
45931
+ }
45932
+ return { status: 200, body: { ok: true } };
45933
+ } catch (err) {
45934
+ return { status: 500, body: { ok: false, error: String(err) } };
45935
+ }
45936
+ }
45937
+ function handleStatusRequest(channel2) {
45938
+ return {
45939
+ status: 200,
45940
+ body: {
45941
+ ok: true,
45942
+ state: channel2.state,
45943
+ deviceId: channel2.deviceId ?? void 0,
45944
+ sessions: channel2.sessionCount
45945
+ }
45946
+ };
45947
+ }
45948
+ var init_http_handlers = __esm({
45949
+ "src/http-handlers.ts"() {
45950
+ "use strict";
45951
+ }
45952
+ });
45953
+
45705
45954
  // src/channel.ts
45706
45955
  import { EventEmitter } from "node:events";
45707
45956
  import { createServer } from "node:http";
@@ -45924,6 +46173,8 @@ var init_channel = __esm({
45924
46173
  if (this._sessions.size === 0) {
45925
46174
  throw new Error("No active sessions");
45926
46175
  }
46176
+ Promise.resolve().then(() => (init_openclaw_compat(), openclaw_compat_exports)).then(({ requestHeartbeatNow: requestHeartbeatNow2 }) => requestHeartbeatNow2({ reason: "channel-send" })).catch(() => {
46177
+ });
45927
46178
  const targetConvId = options?.conversationId;
45928
46179
  const topicId = options?.topicId ?? this._lastIncomingTopicId ?? this._persisted?.defaultTopicId;
45929
46180
  const messageType = options?.messageType ?? "text";
@@ -46075,7 +46326,7 @@ var init_channel = __esm({
46075
46326
  * Optional timeout rejects with an Error.
46076
46327
  */
46077
46328
  waitForDecision(decisionId, timeoutMs) {
46078
- return new Promise((resolve3, reject) => {
46329
+ return new Promise((resolve4, reject) => {
46079
46330
  let timer = null;
46080
46331
  const handler = (plaintext, metadata) => {
46081
46332
  if (metadata.messageType !== "decision_response") return;
@@ -46084,7 +46335,7 @@ var init_channel = __esm({
46084
46335
  if (parsed.decision?.decision_id === decisionId) {
46085
46336
  if (timer) clearTimeout(timer);
46086
46337
  this.removeListener("message", handler);
46087
- resolve3({
46338
+ resolve4({
46088
46339
  decision_id: parsed.decision.decision_id,
46089
46340
  selected_option_id: parsed.decision.selected_option_id,
46090
46341
  resolved_at: parsed.decision.resolved_at,
@@ -46189,6 +46440,8 @@ var init_channel = __esm({
46189
46440
  if (!this._persisted?.rooms?.[roomId]) {
46190
46441
  throw new Error(`Room ${roomId} not found`);
46191
46442
  }
46443
+ Promise.resolve().then(() => (init_openclaw_compat(), openclaw_compat_exports)).then(({ requestHeartbeatNow: requestHeartbeatNow2 }) => requestHeartbeatNow2({ reason: "channel-sendToRoom" })).catch(() => {
46444
+ });
46192
46445
  const room = this._persisted.rooms[roomId];
46193
46446
  const messageType = opts?.messageType ?? "text";
46194
46447
  const recipients = [];
@@ -46456,6 +46709,11 @@ var init_channel = __esm({
46456
46709
  // --- Local HTTP server for proactive sends ---
46457
46710
  startHttpServer(port) {
46458
46711
  if (this._httpServer) return;
46712
+ let _handlers = null;
46713
+ const getHandlers = async () => {
46714
+ if (!_handlers) _handlers = await Promise.resolve().then(() => (init_http_handlers(), http_handlers_exports));
46715
+ return _handlers;
46716
+ };
46459
46717
  this._httpServer = createServer(async (req, res) => {
46460
46718
  const remote = req.socket.remoteAddress;
46461
46719
  if (remote !== "127.0.0.1" && remote !== "::1" && remote !== "::ffff:127.0.0.1") {
@@ -46463,6 +46721,7 @@ var init_channel = __esm({
46463
46721
  res.end(JSON.stringify({ ok: false, error: "Forbidden" }));
46464
46722
  return;
46465
46723
  }
46724
+ const handlers = await getHandlers();
46466
46725
  if (req.method === "POST" && req.url === "/send") {
46467
46726
  let body = "";
46468
46727
  req.on("data", (chunk) => {
@@ -46471,29 +46730,9 @@ var init_channel = __esm({
46471
46730
  req.on("end", async () => {
46472
46731
  try {
46473
46732
  const parsed = JSON.parse(body);
46474
- const text = parsed.text;
46475
- if (!text || typeof text !== "string") {
46476
- res.writeHead(400, { "Content-Type": "application/json" });
46477
- res.end(JSON.stringify({ ok: false, error: "Missing 'text' field" }));
46478
- return;
46479
- }
46480
- if (parsed.room_id && typeof parsed.room_id === "string") {
46481
- await this.sendToRoom(parsed.room_id, text, {
46482
- messageType: parsed.message_type,
46483
- priority: parsed.priority,
46484
- metadata: parsed.metadata
46485
- });
46486
- } else if (parsed.file_path && typeof parsed.file_path === "string") {
46487
- await this.sendWithAttachment(text, parsed.file_path, { topicId: parsed.topicId });
46488
- } else {
46489
- await this.send(text, {
46490
- topicId: parsed.topicId,
46491
- messageType: parsed.message_type,
46492
- metadata: parsed.metadata
46493
- });
46494
- }
46495
- res.writeHead(200, { "Content-Type": "application/json" });
46496
- res.end(JSON.stringify({ ok: true }));
46733
+ const result = await handlers.handleSendRequest(parsed, this);
46734
+ res.writeHead(result.status, { "Content-Type": "application/json" });
46735
+ res.end(JSON.stringify(result.body));
46497
46736
  } catch (err) {
46498
46737
  res.writeHead(500, { "Content-Type": "application/json" });
46499
46738
  res.end(JSON.stringify({ ok: false, error: String(err) }));
@@ -46507,38 +46746,18 @@ var init_channel = __esm({
46507
46746
  req.on("end", async () => {
46508
46747
  try {
46509
46748
  const parsed = JSON.parse(body);
46510
- if (!parsed.action || typeof parsed.action !== "string") {
46511
- res.writeHead(400, { "Content-Type": "application/json" });
46512
- res.end(JSON.stringify({ ok: false, error: "Missing 'action' field" }));
46513
- return;
46514
- }
46515
- const confirmation = {
46516
- action: parsed.action,
46517
- status: parsed.status ?? "completed",
46518
- decisionId: parsed.decision_id,
46519
- detail: parsed.detail,
46520
- estimated_cost: parsed.estimated_cost
46521
- };
46522
- if (parsed.room_id && typeof parsed.room_id === "string") {
46523
- await this.sendActionConfirmationToRoom(parsed.room_id, confirmation);
46524
- } else {
46525
- await this.sendActionConfirmation(confirmation);
46526
- }
46527
- res.writeHead(200, { "Content-Type": "application/json" });
46528
- res.end(JSON.stringify({ ok: true }));
46749
+ const result = await handlers.handleActionRequest(parsed, this);
46750
+ res.writeHead(result.status, { "Content-Type": "application/json" });
46751
+ res.end(JSON.stringify(result.body));
46529
46752
  } catch (err) {
46530
46753
  res.writeHead(500, { "Content-Type": "application/json" });
46531
46754
  res.end(JSON.stringify({ ok: false, error: String(err) }));
46532
46755
  }
46533
46756
  });
46534
46757
  } else if (req.method === "GET" && req.url === "/status") {
46535
- res.writeHead(200, { "Content-Type": "application/json" });
46536
- res.end(JSON.stringify({
46537
- ok: true,
46538
- state: this._state,
46539
- deviceId: this._deviceId,
46540
- sessions: this._sessions.size
46541
- }));
46758
+ const result = handlers.handleStatusRequest(this);
46759
+ res.writeHead(result.status, { "Content-Type": "application/json" });
46760
+ res.end(JSON.stringify(result.body));
46542
46761
  } else {
46543
46762
  res.writeHead(404, { "Content-Type": "application/json" });
46544
46763
  res.end(JSON.stringify({ ok: false, error: "Not found. Use POST /send, POST /action, or GET /status" }));
@@ -47015,7 +47234,9 @@ var init_channel = __esm({
47015
47234
  this._telemetryReporter = new TelemetryReporter({
47016
47235
  apiBase: this.config.apiUrl,
47017
47236
  hubId: this._persisted.hubId,
47018
- authHeader: `Bearer ${this._persisted.deviceJwt}`
47237
+ authHeader: `Bearer ${this._persisted.deviceJwt}`,
47238
+ agentName: this.config.agentName ?? this._persisted.hubAddress,
47239
+ agentVersion: this.config.agentVersion ?? "0.0.0"
47019
47240
  });
47020
47241
  this._telemetryReporter.startAutoFlush(3e4);
47021
47242
  }
@@ -47134,7 +47355,9 @@ var init_channel = __esm({
47134
47355
  this._telemetryReporter = new TelemetryReporter({
47135
47356
  apiBase: this.config.apiUrl,
47136
47357
  hubId: this._persisted.hubId,
47137
- authHeader: `Bearer ${this._persisted.deviceJwt}`
47358
+ authHeader: `Bearer ${this._persisted.deviceJwt}`,
47359
+ agentName: this.config.agentName ?? this._persisted.hubAddress,
47360
+ agentVersion: this.config.agentVersion ?? "0.0.0"
47138
47361
  });
47139
47362
  this._telemetryReporter.startAutoFlush(3e4);
47140
47363
  }
@@ -48455,6 +48678,7 @@ var init_openclaw_plugin = __esm({
48455
48678
  "use strict";
48456
48679
  await init_channel();
48457
48680
  init_account_config();
48681
+ init_openclaw_compat();
48458
48682
  }
48459
48683
  });
48460
48684
 
@@ -48467,6 +48691,9 @@ __export(gateway_send_exports, {
48467
48691
  function resolveBaseUrl(options) {
48468
48692
  const host = options?.host ?? "127.0.0.1";
48469
48693
  const port = options?.port ?? (process.env.GATEWAY_SEND_PORT ? Number(process.env.GATEWAY_SEND_PORT) : 18790);
48694
+ if (!options?.port && !options?.host && process.env.OPENCLAW_GATEWAY_URL) {
48695
+ return process.env.OPENCLAW_GATEWAY_URL;
48696
+ }
48470
48697
  return `http://${host}:${port}`;
48471
48698
  }
48472
48699
  function friendlyError(err) {
@@ -48479,9 +48706,12 @@ async function sendToOwner(text, options) {
48479
48706
  if (typeof text !== "string" || text.trim().length === 0) {
48480
48707
  return { ok: false, error: "Message text must be a non-empty string" };
48481
48708
  }
48709
+ requestHeartbeatNow({ reason: "proactive-send" }).catch(() => {
48710
+ });
48482
48711
  try {
48483
48712
  const base = resolveBaseUrl(options);
48484
- const res = await fetch(`${base}/send`, {
48713
+ const sendPath = process.env.OPENCLAW_GATEWAY_URL ? "/agentvault/send" : "/send";
48714
+ const res = await fetch(`${base}${sendPath}`, {
48485
48715
  method: "POST",
48486
48716
  headers: { "Content-Type": "application/json" },
48487
48717
  body: JSON.stringify({ text }),
@@ -48499,7 +48729,8 @@ async function sendToOwner(text, options) {
48499
48729
  async function checkGateway(options) {
48500
48730
  try {
48501
48731
  const base = resolveBaseUrl(options);
48502
- const res = await fetch(`${base}/status`, { signal: options?.signal });
48732
+ const statusPath = process.env.OPENCLAW_GATEWAY_URL ? "/agentvault/status" : "/status";
48733
+ const res = await fetch(`${base}${statusPath}`, { signal: options?.signal });
48503
48734
  if (!res.ok) {
48504
48735
  return { ok: false, error: `HTTP ${res.status}` };
48505
48736
  }
@@ -48517,6 +48748,28 @@ async function checkGateway(options) {
48517
48748
  var init_gateway_send = __esm({
48518
48749
  "src/gateway-send.ts"() {
48519
48750
  "use strict";
48751
+ init_openclaw_compat();
48752
+ }
48753
+ });
48754
+
48755
+ // src/fetch-interceptor.ts
48756
+ import { AsyncLocalStorage } from "node:async_hooks";
48757
+ var traceStore;
48758
+ var init_fetch_interceptor = __esm({
48759
+ "src/fetch-interceptor.ts"() {
48760
+ "use strict";
48761
+ traceStore = new AsyncLocalStorage();
48762
+ }
48763
+ });
48764
+
48765
+ // src/openclaw-entry.ts
48766
+ var init_openclaw_entry = __esm({
48767
+ "src/openclaw-entry.ts"() {
48768
+ "use strict";
48769
+ init_account_config();
48770
+ init_fetch_interceptor();
48771
+ init_http_handlers();
48772
+ init_openclaw_compat();
48520
48773
  }
48521
48774
  });
48522
48775
 
@@ -48529,7 +48782,10 @@ var init_index = __esm({
48529
48782
  init_account_config();
48530
48783
  await init_openclaw_plugin();
48531
48784
  init_gateway_send();
48532
- VERSION = "0.13.9";
48785
+ init_openclaw_compat();
48786
+ init_openclaw_entry();
48787
+ init_http_handlers();
48788
+ VERSION = "0.14.0";
48533
48789
  }
48534
48790
  });
48535
48791
 
@@ -48866,7 +49122,7 @@ async function promptAndRestart(env) {
48866
49122
  }
48867
49123
  }
48868
49124
  function ask(question) {
48869
- return new Promise((resolve3) => {
49125
+ return new Promise((resolve4) => {
48870
49126
  const rl2 = readline.createInterface({
48871
49127
  input: process.stdin,
48872
49128
  output: process.stdout,
@@ -48874,7 +49130,7 @@ function ask(question) {
48874
49130
  });
48875
49131
  rl2.question(question, (answer) => {
48876
49132
  rl2.close();
48877
- resolve3(answer);
49133
+ resolve4(answer);
48878
49134
  });
48879
49135
  });
48880
49136
  }
@@ -48887,10 +49143,104 @@ var init_setup = __esm({
48887
49143
  }
48888
49144
  });
48889
49145
 
49146
+ // src/skills-publish.ts
49147
+ var skills_publish_exports = {};
49148
+ __export(skills_publish_exports, {
49149
+ publishSkills: () => publishSkills
49150
+ });
49151
+ import { readFileSync } from "node:fs";
49152
+ import { resolve as resolve2 } from "node:path";
49153
+ async function publishSkills(opts) {
49154
+ if (!opts.manifest) {
49155
+ console.error("Error: --manifest is required");
49156
+ process.exit(1);
49157
+ }
49158
+ if (!opts.apiKey) {
49159
+ console.error("Error: --api-key or AGENTVAULT_API_KEY is required");
49160
+ process.exit(1);
49161
+ }
49162
+ const manifestPath = resolve2(opts.manifest);
49163
+ let raw;
49164
+ try {
49165
+ raw = readFileSync(manifestPath, "utf-8");
49166
+ } catch {
49167
+ console.error(`Error: Cannot read manifest file: ${manifestPath}`);
49168
+ process.exit(1);
49169
+ }
49170
+ let manifest;
49171
+ try {
49172
+ manifest = JSON.parse(raw);
49173
+ } catch {
49174
+ console.error("Error: Invalid JSON in manifest file");
49175
+ process.exit(1);
49176
+ }
49177
+ if (!Array.isArray(manifest.skills) || manifest.skills.length === 0) {
49178
+ console.error("Error: Manifest must contain a non-empty 'skills' array");
49179
+ process.exit(1);
49180
+ }
49181
+ for (const skill of manifest.skills) {
49182
+ if (!skill.name || typeof skill.name !== "string") {
49183
+ console.error("Error: Each skill must have a 'name' string");
49184
+ process.exit(1);
49185
+ }
49186
+ if (skill.sla?.max_error_rate !== void 0 && (skill.sla.max_error_rate < 0 || skill.sla.max_error_rate > 1)) {
49187
+ console.error(
49188
+ `Error: Skill "${skill.name}" max_error_rate must be 0.0-1.0`
49189
+ );
49190
+ process.exit(1);
49191
+ }
49192
+ if (skill.sla?.min_uptime_pct !== void 0 && (skill.sla.min_uptime_pct < 0 || skill.sla.min_uptime_pct > 100)) {
49193
+ console.error(
49194
+ `Error: Skill "${skill.name}" min_uptime_pct must be 0-100`
49195
+ );
49196
+ process.exit(1);
49197
+ }
49198
+ }
49199
+ const capabilities = manifest.skills.map((s2) => ({
49200
+ capability_name: s2.name,
49201
+ capability_version: s2.version ?? null,
49202
+ description: s2.description ?? null,
49203
+ sla_definition: s2.sla ? {
49204
+ p95_latency_ms: s2.sla.p95_latency_ms ?? null,
49205
+ max_error_rate: s2.sla.max_error_rate ?? null,
49206
+ min_uptime_pct: s2.sla.min_uptime_pct ?? null,
49207
+ max_avg_tokens: s2.sla.max_avg_tokens ?? null
49208
+ } : null
49209
+ }));
49210
+ const url = `${opts.apiUrl}/api/v1/hub/skills/publish`;
49211
+ const res = await fetch(url, {
49212
+ method: "POST",
49213
+ headers: {
49214
+ "Content-Type": "application/json",
49215
+ Authorization: `Bearer ${opts.apiKey}`
49216
+ },
49217
+ body: JSON.stringify(capabilities)
49218
+ });
49219
+ if (!res.ok) {
49220
+ const text = await res.text();
49221
+ console.error(`Error: API returned ${res.status}: ${text}`);
49222
+ process.exit(1);
49223
+ }
49224
+ const result = await res.json();
49225
+ console.log(`Published ${result.length} skill(s) successfully.`);
49226
+ for (const cap of result) {
49227
+ const status = cap.verification_status ?? "declared";
49228
+ const sla = cap.sla_definition ? " (SLA defined)" : "";
49229
+ console.log(
49230
+ ` - ${cap.capability_name}${cap.capability_version ? `@${cap.capability_version}` : ""}: ${status}${sla}`
49231
+ );
49232
+ }
49233
+ }
49234
+ var init_skills_publish = __esm({
49235
+ "src/skills-publish.ts"() {
49236
+ "use strict";
49237
+ }
49238
+ });
49239
+
48890
49240
  // src/cli.ts
48891
49241
  await init_channel();
48892
49242
  await init_setup();
48893
- import { resolve as resolve2 } from "node:path";
49243
+ import { resolve as resolve3 } from "node:path";
48894
49244
  import { createInterface as createInterface2 } from "node:readline";
48895
49245
  var _notifier = null;
48896
49246
  async function tryNotify(title, message) {
@@ -49005,6 +49355,20 @@ if (subcommand === "status") {
49005
49355
  }
49006
49356
  process.exit(0);
49007
49357
  }
49358
+ if (subcommand === "skills") {
49359
+ const subAction = args[1];
49360
+ if (subAction === "publish") {
49361
+ const { publishSkills: publishSkills2 } = await Promise.resolve().then(() => (init_skills_publish(), skills_publish_exports));
49362
+ await publishSkills2({
49363
+ manifest: flags["manifest"],
49364
+ apiKey: flags["api-key"] || process.env.AGENTVAULT_API_KEY,
49365
+ apiUrl
49366
+ });
49367
+ process.exit(0);
49368
+ }
49369
+ console.error(`Usage: agentvault skills publish --manifest=./skill-manifest.json`);
49370
+ process.exit(1);
49371
+ }
49008
49372
  if (!token) {
49009
49373
  console.error(`
49010
49374
  AgentVault Secure Channel CLI
@@ -49014,6 +49378,7 @@ Usage:
49014
49378
  npx @agentvault/agentvault pm2-setup # Configure pm2 (existing install)
49015
49379
  npx @agentvault/agentvault send "message" # Send a message to the owner
49016
49380
  npx @agentvault/agentvault status # Check gateway status
49381
+ npx @agentvault/agentvault skills publish --manifest=FILE # Publish skills from manifest
49017
49382
  npx @agentvault/agentvault --token=TOKEN # Standalone interactive CLI
49018
49383
 
49019
49384
  Options:
@@ -49021,6 +49386,7 @@ Options:
49021
49386
  --name=NAME Agent display name (default: "CLI Agent")
49022
49387
  --data-dir=PATH Directory for persistent state (default: ./agentvault-data)
49023
49388
  --api-url=URL API endpoint (default: https://api.agentvault.chat)
49389
+ --api-key=KEY API key for skills publish (or AGENTVAULT_API_KEY env var)
49024
49390
  --account-id=ID Multi-agent account identifier (e.g., "work", "research")
49025
49391
  --webhook-url=URL URL for HTTP webhook notifications on new messages
49026
49392
  --no-notifications Disable OS desktop notifications
@@ -49031,6 +49397,7 @@ Environment variables:
49031
49397
  AGENTVAULT_AGENT_NAME Same as --name
49032
49398
  AGENTVAULT_DATA_DIR Same as --data-dir
49033
49399
  AGENTVAULT_API_URL Same as --api-url
49400
+ AGENTVAULT_API_KEY Same as --api-key (for skills publish)
49034
49401
  AGENTVAULT_ACCOUNT_ID Same as --account-id
49035
49402
  AGENTVAULT_WEBHOOK_URL Same as --webhook-url
49036
49403
  AGENTVAULT_NO_NOTIFICATIONS Set to "1" to disable desktop notifications
@@ -49046,6 +49413,9 @@ Examples:
49046
49413
  # Check gateway status:
49047
49414
  npx @agentvault/agentvault status
49048
49415
 
49416
+ # Publish skills from a manifest (CI/CD):
49417
+ npx @agentvault/agentvault skills publish --manifest=./skill-manifest.json --api-key=av_agent_sk_...
49418
+
49049
49419
  # Standalone interactive CLI:
49050
49420
  npx @agentvault/agentvault --token=av_tok_abc123 --name="My Agent"
49051
49421
  `);
@@ -49063,7 +49433,7 @@ var stateMessages = {
49063
49433
  };
49064
49434
  var channel = new SecureChannel({
49065
49435
  inviteToken: token,
49066
- dataDir: resolve2(dataDir),
49436
+ dataDir: resolve3(dataDir),
49067
49437
  apiUrl,
49068
49438
  agentName: name,
49069
49439
  webhookUrl,