@agentvault/secure-channel 0.6.19 → 0.6.21

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/channel.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from "node:events";
2
- import type { SecureChannelConfig, ChannelState, SendOptions } from "./types.js";
2
+ import type { SecureChannelConfig, ChannelState, SendOptions, DecisionRequest, DecisionResponse, HeartbeatStatus, StatusAlert } from "./types.js";
3
3
  export declare class SecureChannel extends EventEmitter {
4
4
  private config;
5
5
  private _state;
@@ -20,6 +20,9 @@ export declare class SecureChannel extends EventEmitter {
20
20
  private _persisted;
21
21
  private _httpServer;
22
22
  private _pollFallbackTimer;
23
+ private _heartbeatTimer;
24
+ private _heartbeatCallback;
25
+ private _heartbeatIntervalSeconds;
23
26
  private _syncMessageIds;
24
27
  private static readonly PING_INTERVAL_MS;
25
28
  private static readonly SILENCE_TIMEOUT_MS;
@@ -50,6 +53,24 @@ export declare class SecureChannel extends EventEmitter {
50
53
  * Ephemeral (unencrypted metadata), no ratchet advancement.
51
54
  */
52
55
  sendTyping(): void;
56
+ /**
57
+ * Send a decision request to the owner.
58
+ * Builds a structured envelope with decision metadata and sends it
59
+ * as a high-priority message. Returns the generated decision_id.
60
+ */
61
+ sendDecisionRequest(request: DecisionRequest): Promise<string>;
62
+ /**
63
+ * Wait for a decision response matching the given decisionId.
64
+ * Listens on the "message" event for messages where
65
+ * metadata.messageType === "decision_response" and the parsed plaintext
66
+ * contains a matching decision.decision_id.
67
+ * Optional timeout rejects with an Error.
68
+ */
69
+ waitForDecision(decisionId: string, timeoutMs?: number): Promise<DecisionResponse>;
70
+ startHeartbeat(intervalSeconds: number, statusCallback: () => HeartbeatStatus): void;
71
+ stopHeartbeat(): Promise<void>;
72
+ sendStatusAlert(alert: StatusAlert): Promise<void>;
73
+ private _sendHeartbeat;
53
74
  stop(): Promise<void>;
54
75
  startHttpServer(port: number): void;
55
76
  private _stopHttpServer;
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -45189,6 +45189,9 @@ var init_channel = __esm({
45189
45189
  _persisted = null;
45190
45190
  _httpServer = null;
45191
45191
  _pollFallbackTimer = null;
45192
+ _heartbeatTimer = null;
45193
+ _heartbeatCallback = null;
45194
+ _heartbeatIntervalSeconds = 0;
45192
45195
  _syncMessageIds = null;
45193
45196
  // Liveness detection: server sends app-level {"event":"ping"} every 30s.
45194
45197
  // We check every 30s; if no data received in 90s (3 missed pings), connection is dead.
@@ -45345,8 +45348,139 @@ var init_channel = __esm({
45345
45348
  );
45346
45349
  }
45347
45350
  }
45351
+ /**
45352
+ * Send a decision request to the owner.
45353
+ * Builds a structured envelope with decision metadata and sends it
45354
+ * as a high-priority message. Returns the generated decision_id.
45355
+ */
45356
+ async sendDecisionRequest(request) {
45357
+ const decision_id = `dec_${randomUUID().replace(/-/g, "").slice(0, 16)}`;
45358
+ const payload = JSON.stringify({
45359
+ type: "message",
45360
+ text: `\u{1F4CB} ${request.title}`,
45361
+ decision: {
45362
+ decision_id,
45363
+ ...request
45364
+ }
45365
+ });
45366
+ await this.send(payload, {
45367
+ messageType: "decision_request",
45368
+ priority: "high",
45369
+ metadata: {
45370
+ decision_id,
45371
+ title: request.title,
45372
+ description: request.description,
45373
+ options: request.options,
45374
+ context_refs: request.context_refs,
45375
+ deadline: request.deadline,
45376
+ auto_action: request.auto_action
45377
+ }
45378
+ });
45379
+ return decision_id;
45380
+ }
45381
+ /**
45382
+ * Wait for a decision response matching the given decisionId.
45383
+ * Listens on the "message" event for messages where
45384
+ * metadata.messageType === "decision_response" and the parsed plaintext
45385
+ * contains a matching decision.decision_id.
45386
+ * Optional timeout rejects with an Error.
45387
+ */
45388
+ waitForDecision(decisionId, timeoutMs) {
45389
+ return new Promise((resolve3, reject) => {
45390
+ let timer = null;
45391
+ const handler = (plaintext, metadata) => {
45392
+ if (metadata.messageType !== "decision_response") return;
45393
+ try {
45394
+ const parsed = JSON.parse(plaintext);
45395
+ if (parsed.decision?.decision_id === decisionId) {
45396
+ if (timer) clearTimeout(timer);
45397
+ this.removeListener("message", handler);
45398
+ resolve3({
45399
+ decision_id: parsed.decision.decision_id,
45400
+ selected_option_id: parsed.decision.selected_option_id,
45401
+ resolved_at: parsed.decision.resolved_at
45402
+ });
45403
+ }
45404
+ } catch {
45405
+ }
45406
+ };
45407
+ this.on("message", handler);
45408
+ if (timeoutMs !== void 0) {
45409
+ timer = setTimeout(() => {
45410
+ this.removeListener("message", handler);
45411
+ reject(new Error(`Decision ${decisionId} timed out after ${timeoutMs}ms`));
45412
+ }, timeoutMs);
45413
+ }
45414
+ });
45415
+ }
45416
+ startHeartbeat(intervalSeconds, statusCallback) {
45417
+ this.stopHeartbeat();
45418
+ this._heartbeatCallback = statusCallback;
45419
+ this._heartbeatIntervalSeconds = intervalSeconds;
45420
+ this._sendHeartbeat();
45421
+ this._heartbeatTimer = setInterval(() => {
45422
+ this._sendHeartbeat();
45423
+ }, intervalSeconds * 1e3);
45424
+ }
45425
+ async stopHeartbeat() {
45426
+ if (this._heartbeatTimer) {
45427
+ clearInterval(this._heartbeatTimer);
45428
+ this._heartbeatTimer = null;
45429
+ }
45430
+ if (this._heartbeatCallback && this._state === "ready") {
45431
+ try {
45432
+ await this.send(
45433
+ JSON.stringify({
45434
+ agent_status: "shutting_down",
45435
+ current_task: "",
45436
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
45437
+ }),
45438
+ {
45439
+ messageType: "heartbeat",
45440
+ metadata: { next_heartbeat_seconds: this._heartbeatIntervalSeconds }
45441
+ }
45442
+ );
45443
+ } catch {
45444
+ }
45445
+ }
45446
+ this._heartbeatCallback = null;
45447
+ }
45448
+ async sendStatusAlert(alert) {
45449
+ const priority = alert.severity === "error" || alert.severity === "critical" ? "high" : "normal";
45450
+ await this.send(
45451
+ JSON.stringify({
45452
+ title: alert.title,
45453
+ message: alert.message,
45454
+ severity: alert.severity,
45455
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
45456
+ }),
45457
+ {
45458
+ messageType: "status_alert",
45459
+ priority,
45460
+ metadata: { severity: alert.severity }
45461
+ }
45462
+ );
45463
+ }
45464
+ _sendHeartbeat() {
45465
+ if (this._state !== "ready" || !this._heartbeatCallback) return;
45466
+ const status = this._heartbeatCallback();
45467
+ this.send(
45468
+ JSON.stringify({
45469
+ agent_status: status.agent_status,
45470
+ current_task: status.current_task,
45471
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
45472
+ }),
45473
+ {
45474
+ messageType: "heartbeat",
45475
+ metadata: { next_heartbeat_seconds: this._heartbeatIntervalSeconds }
45476
+ }
45477
+ ).catch((err) => {
45478
+ this.emit("error", new Error(`Heartbeat send failed: ${err}`));
45479
+ });
45480
+ }
45348
45481
  async stop() {
45349
45482
  this._stopped = true;
45483
+ await this.stopHeartbeat();
45350
45484
  this._flushAcks();
45351
45485
  this._stopPing();
45352
45486
  this._stopPollFallback();