echoclaw-relay-agent 0.22.5 → 0.22.7

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.
@@ -469,11 +469,20 @@ export class RelayAgent extends EventEmitter {
469
469
  this.transport.on('connect_timeout', (timeoutMs) => {
470
470
  this.emit('error', Object.assign(new Error(`Connection timed out after ${timeoutMs / 1000}s`), { code: 'CONNECT_TIMEOUT' }));
471
471
  });
472
- // Handle server fatal CLOSE messages (SESSION_NOT_FOUND, SESSION_PROTOCOL_MISMATCH, etc.)
472
+ // Handle server messages (DESKTOP_RECONNECTED, fatal errors, etc.)
473
473
  const SESSION_FATAL = new Set(['SESSION_NOT_FOUND', 'INVALID_SESSION', 'SESSION_PROTOCOL_MISMATCH']);
474
474
  this.transport.on('message', (msg) => {
475
475
  if ((msg.type === 'CLOSE' || msg.type === 'STATUS') && msg.sender_role === 'server') {
476
476
  const payload = typeof msg.payload === 'string' ? msg.payload : '';
477
+ // Desktop restarted — reset FrameCrypto receive sequence counter.
478
+ // Desktop creates a new FrameCrypto on resumeSession() (sendSeq starts at 0),
479
+ // but Agent's FrameCrypto still has recvHighestSeq from the old session.
480
+ // Without this reset, all messages from Desktop are rejected as "Sequence regression".
481
+ if (payload === 'DESKTOP_RECONNECTED') {
482
+ this.frameCrypto?.reset();
483
+ this.emit('peer_reconnected');
484
+ return;
485
+ }
477
486
  if (payload === 'UNPAIRED' || SESSION_FATAL.has(payload)) {
478
487
  this.sessionStore.clear().catch(() => { });
479
488
  this._paired = false;
@@ -399,6 +399,14 @@ export class RelayClient extends EventEmitter {
399
399
  this.transport.on('message', (msg) => {
400
400
  if ((msg.type === 'CLOSE' || msg.type === 'STATUS') && msg.sender_role === 'server') {
401
401
  const payload = typeof msg.payload === 'string' ? msg.payload : '';
402
+ // Agent restarted — reset FrameCrypto receive sequence counter.
403
+ // Same issue as DESKTOP_RECONNECTED: Agent creates new FrameCrypto on restart
404
+ // (sendSeq starts at 0), but Desktop's recvHighestSeq is still from old session.
405
+ if (payload === 'AGENT_RESTARTED') {
406
+ this.frameCrypto?.reset();
407
+ this.emit('peer_reconnected');
408
+ return;
409
+ }
402
410
  if (PEER_STATUS.has(payload)) {
403
411
  this.emit('peer_status', {
404
412
  status: payload === 'AGENT_ONLINE' ? 'online' : 'warning',
@@ -31,6 +31,11 @@ const DEFAULT_SESSION_KEY = 'main';
31
31
  const STATUS_THROTTLE_MS = 3000;
32
32
  // ── InstallHandler ───────────────────────────────────────────────
33
33
  export class InstallHandler {
34
+ // ── ICP (disabled until packages are on npm) ──
35
+ // private readonly _icpOrchestrator: IcpOrchestrator;
36
+ // private static readonly ICP_ACTIONS = new Set([
37
+ // 'install_with_config', 'complete_template', 'generate_fresh', 'adapt',
38
+ // ]);
34
39
  constructor(wsClient, chatHandler, config) {
35
40
  Object.defineProperty(this, "_wsClient", {
36
41
  enumerable: true,
@@ -95,6 +100,11 @@ export class InstallHandler {
95
100
  this._timeoutMs = config?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
96
101
  this._sessionKey = config?.sessionKey ?? DEFAULT_SESSION_KEY;
97
102
  this._rpcTimeoutMs = config?.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS;
103
+ // ICP orchestrator init disabled until packages are on npm
104
+ // this._icpOrchestrator = new IcpOrchestrator({
105
+ // outputTimeoutMs: this._timeoutMs,
106
+ // reviewTimeoutMs: this._timeoutMs,
107
+ // });
98
108
  // Listen for chat events — only process runs we own
99
109
  this._wsClient.on('chat', (payload) => {
100
110
  const runId = payload?.runId;
@@ -149,6 +159,8 @@ export class InstallHandler {
149
159
  requestId,
150
160
  status: 'accepted',
151
161
  });
162
+ // ── ICP workspace routing (disabled until packages are on npm) ──
163
+ // if (InstallHandler.ICP_ACTIONS.has(action) && this._workspaceSynced) { ... }
152
164
  // Create active install tracker
153
165
  const install = {
154
166
  requestId,
@@ -246,6 +258,8 @@ export class InstallHandler {
246
258
  this._activeInstalls.clear();
247
259
  this._runToRequest.clear();
248
260
  }
261
+ // ── ICP Workspace Flow (disabled until @echoclaw/claw-engine & icp-orchestrator are on npm) ──
262
+ // See git history for full ICP integration code.
249
263
  // ── Private: Event Handling ────────────────────────────────────
250
264
  /**
251
265
  * Handle a streaming chat event for an install run.
@@ -33,6 +33,8 @@ export interface InstallRequest {
33
33
  };
34
34
  /** Confirmed preview plan (for action='install' following a preview). */
35
35
  confirmedPlan?: InstallPreviewData;
36
+ /** User's original request text (for action='generate_fresh'). */
37
+ userRequest?: string;
36
38
  /** Target app ID (for action='adapt'). */
37
39
  appId?: string;
38
40
  /** App manifest (for action='adapt'). */
@@ -120,7 +122,7 @@ export interface InstallAck {
120
122
  reason?: string;
121
123
  }
122
124
  /** Install processing phases. */
123
- export type InstallPhase = 'sending' | 'ai_processing' | 'parsing' | 'validating' | 'previewing' | 'awaiting_confirm' | 'executing';
125
+ export type InstallPhase = 'sending' | 'ai_processing' | 'parsing' | 'validating' | 'previewing' | 'awaiting_confirm' | 'executing' | 'icp_writing_task' | 'icp_waiting_output' | 'icp_validating' | 'icp_reviewing' | 'icp_fallback' | 'icp_delivering';
124
126
  /**
125
127
  * Progress update during install processing.
126
128
  */
@@ -192,6 +194,10 @@ export declare const INSTALL_ERROR_CODES: {
192
194
  readonly AI_ERROR: "INSTALL_AI_ERROR";
193
195
  /** V2: AI response didn't contain preview data. */
194
196
  readonly NO_PREVIEW_DATA: "INSTALL_NO_PREVIEW_DATA";
197
+ /** V3/ICP: Workspace output timed out, falling back to chat-based. */
198
+ readonly ICP_TIMEOUT: "INSTALL_ICP_TIMEOUT";
199
+ /** V3/ICP: ICP orchestrator failed. */
200
+ readonly ICP_FAILED: "INSTALL_ICP_FAILED";
195
201
  };
196
202
  /** All install-related messages from Desktop to Agent. */
197
203
  export type InstallIncoming = InstallRequest | InstallAbort;
@@ -33,4 +33,8 @@ export const INSTALL_ERROR_CODES = {
33
33
  AI_ERROR: 'INSTALL_AI_ERROR',
34
34
  /** V2: AI response didn't contain preview data. */
35
35
  NO_PREVIEW_DATA: 'INSTALL_NO_PREVIEW_DATA',
36
+ /** V3/ICP: Workspace output timed out, falling back to chat-based. */
37
+ ICP_TIMEOUT: 'INSTALL_ICP_TIMEOUT',
38
+ /** V3/ICP: ICP orchestrator failed. */
39
+ ICP_FAILED: 'INSTALL_ICP_FAILED',
36
40
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "echoclaw-relay-agent",
3
- "version": "0.22.5",
3
+ "version": "0.22.7",
4
4
  "description": "EchoClaw Relay Connection — E2E encrypted relay transport, pairing, and session management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",