very-happy-cli 0.2.90 → 0.2.92

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.
Files changed (31) hide show
  1. package/dist/{AcpBackend-CnYZFdd0.cjs → AcpBackend-BP7id8L6.cjs} +1 -1
  2. package/dist/{AcpBackend-BV4wSnJ3.mjs → AcpBackend-DDEsgc1c.mjs} +1 -1
  3. package/dist/{AcpSessionManager-Cyne6Rmg.mjs → AcpSessionManager-C29t6wb_.mjs} +1 -1
  4. package/dist/{AcpSessionManager-BPBdrrME.cjs → AcpSessionManager-Cys1Hsb8.cjs} +1 -1
  5. package/dist/{config-CgXitj0f.cjs → config-B77vhdwT.cjs} +2 -2
  6. package/dist/{config-BEdyyciP.mjs → config-CJQw0z1o.mjs} +2 -2
  7. package/dist/{index-an09rejO.mjs → index-8LDXVYWi.mjs} +409 -51
  8. package/dist/{index-4YmVbx7j.cjs → index-B63Vjt4W.cjs} +425 -67
  9. package/dist/{index-Dfu5uvjk.mjs → index-BP9pfzdZ.mjs} +5 -5
  10. package/dist/{index-B1wTVXjt.cjs → index-L3o5Gz-2.cjs} +4 -4
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-DDpVxk8-.cjs → installTerminalHooks-BBc2nij4.cjs} +2 -2
  14. package/dist/{installTerminalHooks-C-OgZr5k.mjs → installTerminalHooks-DDRrUG_n.mjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +103 -3
  17. package/dist/lib.d.mts +103 -3
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-Du-N0qlK.mjs → mcp-CYJAl5pk.mjs} +2 -2
  20. package/dist/{mcp-B6Nq-RUL.cjs → mcp-DbYXyw1U.cjs} +2 -2
  21. package/dist/{runGemini-ChG7cGMC.cjs → runGemini-BDSWSID6.cjs} +4 -4
  22. package/dist/{runGemini-DBr_TiTL.mjs → runGemini-DHYs_Beq.mjs} +4 -4
  23. package/dist/{runOpenClaw-D2jtVgpC.cjs → runOpenClaw-DC9gb1bd.cjs} +3 -3
  24. package/dist/{runOpenClaw-Cbde8t92.mjs → runOpenClaw-DTaXxvNd.mjs} +3 -3
  25. package/dist/{send-Bjen1TUE.cjs → send-BEdGwmA-.cjs} +2 -2
  26. package/dist/{send-BHliX59m.mjs → send-BQSaVz9r.mjs} +2 -2
  27. package/dist/{spawn-CH1Rq-LW.cjs → spawn-CK1ma_qc.cjs} +2 -2
  28. package/dist/{spawn-JxaPHAoP.mjs → spawn-DS-Uz_Hw.mjs} +2 -2
  29. package/dist/{types-DS3i_5LV.mjs → types-B_8X_rZk.mjs} +572 -93
  30. package/dist/{types-BNGeiP1C.cjs → types-CjlB_fKT.cjs} +573 -93
  31. package/package.json +7 -7
@@ -1,10 +1,10 @@
1
- import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-BV4wSnJ3.mjs';
2
- export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-BV4wSnJ3.mjs';
3
- import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-DS3i_5LV.mjs';
4
- import { A as AcpSessionManager } from './AcpSessionManager-Cyne6Rmg.mjs';
1
+ import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-DDEsgc1c.mjs';
2
+ export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-DDEsgc1c.mjs';
3
+ import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-B_8X_rZk.mjs';
4
+ import { A as AcpSessionManager } from './AcpSessionManager-C29t6wb_.mjs';
5
5
  import { randomUUID } from 'node:crypto';
6
6
  import { join } from 'node:path';
7
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-an09rejO.mjs';
7
+ import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-8LDXVYWi.mjs';
8
8
  import 'node:child_process';
9
9
  import '@agentclientprotocol/sdk';
10
10
  import 'axios';
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-CnYZFdd0.cjs');
4
- var persistence = require('./types-BNGeiP1C.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-BPBdrrME.cjs');
3
+ var AcpBackend = require('./AcpBackend-BP7id8L6.cjs');
4
+ var persistence = require('./types-CjlB_fKT.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-Cys1Hsb8.cjs');
6
6
  var node_crypto = require('node:crypto');
7
7
  var path = require('node:path');
8
- var index = require('./index-4YmVbx7j.cjs');
8
+ var index = require('./index-B63Vjt4W.cjs');
9
9
  require('node:child_process');
10
10
  require('@agentclientprotocol/sdk');
11
11
  require('axios');
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-4YmVbx7j.cjs');
5
- require('./types-BNGeiP1C.cjs');
4
+ require('./index-B63Vjt4W.cjs');
5
+ require('./types-CjlB_fKT.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:os');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-an09rejO.mjs';
3
- import './types-DS3i_5LV.mjs';
2
+ import './index-8LDXVYWi.mjs';
3
+ import './types-B_8X_rZk.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
@@ -5,8 +5,8 @@ var path = require('node:path');
5
5
  var os = require('node:os');
6
6
  var node_child_process = require('node:child_process');
7
7
  var chalk = require('chalk');
8
- var persistence = require('./types-BNGeiP1C.cjs');
9
- var index = require('./index-4YmVbx7j.cjs');
8
+ var persistence = require('./types-CjlB_fKT.cjs');
9
+ var index = require('./index-B63Vjt4W.cjs');
10
10
  require('axios');
11
11
  require('node:util');
12
12
  require('node:fs/promises');
@@ -3,8 +3,8 @@ import { join, resolve } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import chalk from 'chalk';
6
- import { p as projectPath } from './types-DS3i_5LV.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-an09rejO.mjs';
6
+ import { p as projectPath } from './types-B_8X_rZk.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-8LDXVYWi.mjs';
8
8
  import 'axios';
9
9
  import 'node:util';
10
10
  import 'node:fs/promises';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./types-BNGeiP1C.cjs');
3
+ var persistence = require('./types-CjlB_fKT.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.d.cts CHANGED
@@ -45,6 +45,17 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
45
45
  }, z.core.$strip>, z.ZodObject<{
46
46
  t: z.ZodLiteral<"tool-call-end">;
47
47
  call: z.ZodString;
48
+ result: z.ZodOptional<z.ZodObject<{
49
+ text: z.ZodString;
50
+ truncated: z.ZodOptional<z.ZodBoolean>;
51
+ isError: z.ZodOptional<z.ZodBoolean>;
52
+ stats: z.ZodOptional<z.ZodObject<{
53
+ toolUses: z.ZodOptional<z.ZodNumber>;
54
+ totalTokens: z.ZodOptional<z.ZodNumber>;
55
+ durationMs: z.ZodOptional<z.ZodNumber>;
56
+ toolStats: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
57
+ }, z.core.$strip>>;
58
+ }, z.core.$strip>>;
48
59
  }, z.core.$strip>, z.ZodObject<{
49
60
  t: z.ZodLiteral<"file">;
50
61
  ref: z.ZodString;
@@ -61,6 +72,8 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
61
72
  }, z.core.$strip>, z.ZodObject<{
62
73
  t: z.ZodLiteral<"start">;
63
74
  title: z.ZodOptional<z.ZodString>;
75
+ description: z.ZodOptional<z.ZodString>;
76
+ subagentType: z.ZodOptional<z.ZodString>;
64
77
  }, z.core.$strip>, z.ZodObject<{
65
78
  t: z.ZodLiteral<"turn-end">;
66
79
  status: z.ZodEnum<{
@@ -80,6 +93,27 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
80
93
  }, z.core.$strip>>;
81
94
  }, z.core.$strip>, z.ZodObject<{
82
95
  t: z.ZodLiteral<"stop">;
96
+ status: z.ZodOptional<z.ZodEnum<{
97
+ completed: "completed";
98
+ failed: "failed";
99
+ stopped: "stopped";
100
+ }>>;
101
+ result: z.ZodOptional<z.ZodObject<{
102
+ text: z.ZodString;
103
+ truncated: z.ZodOptional<z.ZodBoolean>;
104
+ }, z.core.$strip>>;
105
+ usage: z.ZodOptional<z.ZodObject<{
106
+ toolUses: z.ZodOptional<z.ZodNumber>;
107
+ totalTokens: z.ZodOptional<z.ZodNumber>;
108
+ durationMs: z.ZodOptional<z.ZodNumber>;
109
+ }, z.core.$strip>>;
110
+ }, z.core.$strip>, z.ZodObject<{
111
+ t: z.ZodLiteral<"progress">;
112
+ toolUses: z.ZodNumber;
113
+ lastTool: z.ZodOptional<z.ZodString>;
114
+ totalTokens: z.ZodOptional<z.ZodNumber>;
115
+ durationMs: z.ZodOptional<z.ZodNumber>;
116
+ summary: z.ZodOptional<z.ZodString>;
83
117
  }, z.core.$strip>], "t">;
84
118
  }, z.core.$strip>;
85
119
  type SessionEnvelope = z.infer<typeof sessionEnvelopeSchema>;
@@ -287,6 +321,7 @@ declare const DaemonStateSchema: z$1.ZodObject<{
287
321
  }>>;
288
322
  mirrorSessionId: z$1.ZodOptional<z$1.ZodString>;
289
323
  restoredAt: z$1.ZodOptional<z$1.ZodNumber>;
324
+ manual: z$1.ZodOptional<z$1.ZodBoolean>;
290
325
  }, z$1.core.$strip>>;
291
326
  }, z$1.core.$strip>>;
292
327
  closedTerminals: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
@@ -299,8 +334,14 @@ declare const DaemonStateSchema: z$1.ZodObject<{
299
334
  closed: "closed";
300
335
  "daemon-gap": "daemon-gap";
301
336
  }>>;
337
+ tags: z$1.ZodOptional<z$1.ZodArray<z$1.ZodString>>;
338
+ manual: z$1.ZodOptional<z$1.ZodBoolean>;
302
339
  closedAt: z$1.ZodNumber;
303
340
  }, z$1.core.$strip>>>;
341
+ terminalRestore: z$1.ZodOptional<z$1.ZodObject<{
342
+ rpcAvailable: z$1.ZodBoolean;
343
+ detectedAt: z$1.ZodNumber;
344
+ }, z$1.core.$strip>>;
304
345
  cliUpdate: z$1.ZodOptional<z$1.ZodObject<{
305
346
  currentVersion: z$1.ZodString;
306
347
  recommendedVersion: z$1.ZodNullable<z$1.ZodString>;
@@ -691,7 +732,14 @@ declare class ApiSessionClient extends EventEmitter {
691
732
  private readonly directInboundLocalIds;
692
733
  private readonly routedInboundLocalIds;
693
734
  private handoverInFlight;
694
- constructor(token: string, session: Session);
735
+ /** B-265 reconnect: the message cursor was seeded from the server, so
736
+ * nothing before it is history to replay — but socket fast-path routing
737
+ * must wait for the first fetch, otherwise a message that lands between
738
+ * the seed and the first fetch is routed twice (socket + fetch). */
739
+ private awaitingInitialFetch;
740
+ constructor(token: string, session: Session, opts?: {
741
+ initialSeq?: number;
742
+ });
695
743
  private createControlSocket;
696
744
  private startReleaseHandover;
697
745
  private releaseHandover;
@@ -1016,6 +1064,9 @@ interface TerminalListItem {
1016
1064
  * the claude conversation carried over. The web badges it until the user
1017
1065
  * opens it once; the mark is daemon-local and never persisted. */
1018
1066
  restoredAt?: number;
1067
+ /** B-265: `@vh_title_manual` is set — carried into close records so a
1068
+ * restore can put the flag back (old webs ignore it). */
1069
+ manual?: boolean;
1019
1070
  }
1020
1071
 
1021
1072
  /**
@@ -1029,6 +1080,11 @@ type MachineRpcHandlers = {
1029
1080
  model?: string;
1030
1081
  permissionMode?: string;
1031
1082
  }) => Promise<SpawnSessionResult>;
1083
+ /** B-264: stop a live-but-broken wrapper and relaunch it on the current CLI. */
1084
+ restartSession?: (sessionId: string, options?: {
1085
+ model?: string;
1086
+ permissionMode?: string;
1087
+ }) => Promise<SpawnSessionResult>;
1032
1088
  stopSession: (sessionId: string) => boolean;
1033
1089
  listTrackedSessionIds?: () => string[];
1034
1090
  requestShutdown: () => void;
@@ -1048,6 +1104,7 @@ declare class ApiMachineClient {
1048
1104
  private cliUpdatePushChain;
1049
1105
  private rpcHandlerManager;
1050
1106
  private resumeSessionHandler;
1107
+ private restartSessionHandler;
1051
1108
  private stopSessionHandler;
1052
1109
  private listTrackedSessionIds;
1053
1110
  private reconnectInterval;
@@ -1073,7 +1130,8 @@ declare class ApiMachineClient {
1073
1130
  /** Cache the latest relay policy locally and publish it now or on the next
1074
1131
  * socket connect. This makes startup/offline races harmless. */
1075
1132
  setCliUpdateState(state: CliUpdateState | null): void;
1076
- setRPCHandlers({ spawnSession, resumeSession, stopSession, listTrackedSessionIds, requestShutdown }: MachineRpcHandlers): void;
1133
+ setRPCHandlers({ spawnSession, resumeSession, restartSession, stopSession, listTrackedSessionIds, requestShutdown }: MachineRpcHandlers): void;
1134
+ private syncRestartSessionRpcRegistration;
1077
1135
  private syncResumeSessionRpcRegistration;
1078
1136
  /** Every pushed list also flows to the mirror manager (claude-exit
1079
1137
  * detection via pane observation). Set by the daemon at startup. */
@@ -1222,6 +1280,26 @@ declare class NotificationProducer {
1222
1280
  private clip;
1223
1281
  }
1224
1282
 
1283
+ /**
1284
+ * Reconnect-in-place helpers (B-265). A resumed process reattaches to an
1285
+ * EXISTING happy session (HAPPY_RECONNECT_*). Two truths must not be mixed up:
1286
+ *
1287
+ * - the server owns the conversation-level metadata (summary, tags,
1288
+ * claudeSessionId, board, …) and the message `seq`;
1289
+ * - the new process owns its own identity (pid, version, capabilities, …).
1290
+ *
1291
+ * Everything here is pure so the merge rules are unit-tested; the network
1292
+ * side is `api.getSession` and the wiring lives in runClaude / runCodex.
1293
+ */
1294
+
1295
+ interface ServerSessionSnapshot {
1296
+ seq: number;
1297
+ metadata: Metadata;
1298
+ metadataVersion: number;
1299
+ agentState: AgentState$1 | null;
1300
+ agentStateVersion: number;
1301
+ }
1302
+
1225
1303
  declare class ApiClient {
1226
1304
  static create(credential: Credentials): Promise<ApiClient>;
1227
1305
  private readonly credential;
@@ -1244,7 +1322,9 @@ declare class ApiClient {
1244
1322
  metadata: MachineMetadata;
1245
1323
  daemonState?: DaemonState;
1246
1324
  }): Promise<Machine>;
1247
- sessionSyncClient(session: Session): ApiSessionClient;
1325
+ sessionSyncClient(session: Session, opts?: {
1326
+ initialSeq?: number;
1327
+ }): ApiSessionClient;
1248
1328
  machineSyncClient(machine: Machine): ApiMachineClient;
1249
1329
  push(): PushNotificationClient;
1250
1330
  /**
@@ -1287,6 +1367,26 @@ declare class ApiClient {
1287
1367
  * response confirms the deactivate landed.
1288
1368
  */
1289
1369
  deactivateSession(sessionId: string): Promise<boolean>;
1370
+ /**
1371
+ * B-265: one session by id — the message cursor (`seq`), metadata and
1372
+ * agent state with their versions, decrypted with the session key the
1373
+ * reconnecting process already holds. `unsupported` = the server has no
1374
+ * such route (or the row is gone): callers fall back to the legacy
1375
+ * skip-all-history reconnect. Transient failures are retried a few times
1376
+ * first, because falling back silently discards the very message a restore
1377
+ * is meant to deliver.
1378
+ */
1379
+ getSession(sessionId: string, encryptionKey: Uint8Array, encryptionVariant: 'legacy' | 'dataKey', opts?: {
1380
+ attempts?: number;
1381
+ delaysMs?: number[];
1382
+ timeoutMs?: number;
1383
+ }): Promise<{
1384
+ ok: true;
1385
+ session: ServerSessionSnapshot;
1386
+ } | {
1387
+ ok: false;
1388
+ reason: 'unsupported' | 'unavailable';
1389
+ }>;
1290
1390
  /** Clear the server-owned archive tombstone before an intentional resume.
1291
1391
  * Older servers return 404 because the endpoint does not exist; that is a
1292
1392
  * compatible no-op because those servers also have no durable tombstone. */
package/dist/lib.d.mts CHANGED
@@ -45,6 +45,17 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
45
45
  }, z.core.$strip>, z.ZodObject<{
46
46
  t: z.ZodLiteral<"tool-call-end">;
47
47
  call: z.ZodString;
48
+ result: z.ZodOptional<z.ZodObject<{
49
+ text: z.ZodString;
50
+ truncated: z.ZodOptional<z.ZodBoolean>;
51
+ isError: z.ZodOptional<z.ZodBoolean>;
52
+ stats: z.ZodOptional<z.ZodObject<{
53
+ toolUses: z.ZodOptional<z.ZodNumber>;
54
+ totalTokens: z.ZodOptional<z.ZodNumber>;
55
+ durationMs: z.ZodOptional<z.ZodNumber>;
56
+ toolStats: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
57
+ }, z.core.$strip>>;
58
+ }, z.core.$strip>>;
48
59
  }, z.core.$strip>, z.ZodObject<{
49
60
  t: z.ZodLiteral<"file">;
50
61
  ref: z.ZodString;
@@ -61,6 +72,8 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
61
72
  }, z.core.$strip>, z.ZodObject<{
62
73
  t: z.ZodLiteral<"start">;
63
74
  title: z.ZodOptional<z.ZodString>;
75
+ description: z.ZodOptional<z.ZodString>;
76
+ subagentType: z.ZodOptional<z.ZodString>;
64
77
  }, z.core.$strip>, z.ZodObject<{
65
78
  t: z.ZodLiteral<"turn-end">;
66
79
  status: z.ZodEnum<{
@@ -80,6 +93,27 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
80
93
  }, z.core.$strip>>;
81
94
  }, z.core.$strip>, z.ZodObject<{
82
95
  t: z.ZodLiteral<"stop">;
96
+ status: z.ZodOptional<z.ZodEnum<{
97
+ completed: "completed";
98
+ failed: "failed";
99
+ stopped: "stopped";
100
+ }>>;
101
+ result: z.ZodOptional<z.ZodObject<{
102
+ text: z.ZodString;
103
+ truncated: z.ZodOptional<z.ZodBoolean>;
104
+ }, z.core.$strip>>;
105
+ usage: z.ZodOptional<z.ZodObject<{
106
+ toolUses: z.ZodOptional<z.ZodNumber>;
107
+ totalTokens: z.ZodOptional<z.ZodNumber>;
108
+ durationMs: z.ZodOptional<z.ZodNumber>;
109
+ }, z.core.$strip>>;
110
+ }, z.core.$strip>, z.ZodObject<{
111
+ t: z.ZodLiteral<"progress">;
112
+ toolUses: z.ZodNumber;
113
+ lastTool: z.ZodOptional<z.ZodString>;
114
+ totalTokens: z.ZodOptional<z.ZodNumber>;
115
+ durationMs: z.ZodOptional<z.ZodNumber>;
116
+ summary: z.ZodOptional<z.ZodString>;
83
117
  }, z.core.$strip>], "t">;
84
118
  }, z.core.$strip>;
85
119
  type SessionEnvelope = z.infer<typeof sessionEnvelopeSchema>;
@@ -287,6 +321,7 @@ declare const DaemonStateSchema: z$1.ZodObject<{
287
321
  }>>;
288
322
  mirrorSessionId: z$1.ZodOptional<z$1.ZodString>;
289
323
  restoredAt: z$1.ZodOptional<z$1.ZodNumber>;
324
+ manual: z$1.ZodOptional<z$1.ZodBoolean>;
290
325
  }, z$1.core.$strip>>;
291
326
  }, z$1.core.$strip>>;
292
327
  closedTerminals: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
@@ -299,8 +334,14 @@ declare const DaemonStateSchema: z$1.ZodObject<{
299
334
  closed: "closed";
300
335
  "daemon-gap": "daemon-gap";
301
336
  }>>;
337
+ tags: z$1.ZodOptional<z$1.ZodArray<z$1.ZodString>>;
338
+ manual: z$1.ZodOptional<z$1.ZodBoolean>;
302
339
  closedAt: z$1.ZodNumber;
303
340
  }, z$1.core.$strip>>>;
341
+ terminalRestore: z$1.ZodOptional<z$1.ZodObject<{
342
+ rpcAvailable: z$1.ZodBoolean;
343
+ detectedAt: z$1.ZodNumber;
344
+ }, z$1.core.$strip>>;
304
345
  cliUpdate: z$1.ZodOptional<z$1.ZodObject<{
305
346
  currentVersion: z$1.ZodString;
306
347
  recommendedVersion: z$1.ZodNullable<z$1.ZodString>;
@@ -691,7 +732,14 @@ declare class ApiSessionClient extends EventEmitter {
691
732
  private readonly directInboundLocalIds;
692
733
  private readonly routedInboundLocalIds;
693
734
  private handoverInFlight;
694
- constructor(token: string, session: Session);
735
+ /** B-265 reconnect: the message cursor was seeded from the server, so
736
+ * nothing before it is history to replay — but socket fast-path routing
737
+ * must wait for the first fetch, otherwise a message that lands between
738
+ * the seed and the first fetch is routed twice (socket + fetch). */
739
+ private awaitingInitialFetch;
740
+ constructor(token: string, session: Session, opts?: {
741
+ initialSeq?: number;
742
+ });
695
743
  private createControlSocket;
696
744
  private startReleaseHandover;
697
745
  private releaseHandover;
@@ -1016,6 +1064,9 @@ interface TerminalListItem {
1016
1064
  * the claude conversation carried over. The web badges it until the user
1017
1065
  * opens it once; the mark is daemon-local and never persisted. */
1018
1066
  restoredAt?: number;
1067
+ /** B-265: `@vh_title_manual` is set — carried into close records so a
1068
+ * restore can put the flag back (old webs ignore it). */
1069
+ manual?: boolean;
1019
1070
  }
1020
1071
 
1021
1072
  /**
@@ -1029,6 +1080,11 @@ type MachineRpcHandlers = {
1029
1080
  model?: string;
1030
1081
  permissionMode?: string;
1031
1082
  }) => Promise<SpawnSessionResult>;
1083
+ /** B-264: stop a live-but-broken wrapper and relaunch it on the current CLI. */
1084
+ restartSession?: (sessionId: string, options?: {
1085
+ model?: string;
1086
+ permissionMode?: string;
1087
+ }) => Promise<SpawnSessionResult>;
1032
1088
  stopSession: (sessionId: string) => boolean;
1033
1089
  listTrackedSessionIds?: () => string[];
1034
1090
  requestShutdown: () => void;
@@ -1048,6 +1104,7 @@ declare class ApiMachineClient {
1048
1104
  private cliUpdatePushChain;
1049
1105
  private rpcHandlerManager;
1050
1106
  private resumeSessionHandler;
1107
+ private restartSessionHandler;
1051
1108
  private stopSessionHandler;
1052
1109
  private listTrackedSessionIds;
1053
1110
  private reconnectInterval;
@@ -1073,7 +1130,8 @@ declare class ApiMachineClient {
1073
1130
  /** Cache the latest relay policy locally and publish it now or on the next
1074
1131
  * socket connect. This makes startup/offline races harmless. */
1075
1132
  setCliUpdateState(state: CliUpdateState | null): void;
1076
- setRPCHandlers({ spawnSession, resumeSession, stopSession, listTrackedSessionIds, requestShutdown }: MachineRpcHandlers): void;
1133
+ setRPCHandlers({ spawnSession, resumeSession, restartSession, stopSession, listTrackedSessionIds, requestShutdown }: MachineRpcHandlers): void;
1134
+ private syncRestartSessionRpcRegistration;
1077
1135
  private syncResumeSessionRpcRegistration;
1078
1136
  /** Every pushed list also flows to the mirror manager (claude-exit
1079
1137
  * detection via pane observation). Set by the daemon at startup. */
@@ -1222,6 +1280,26 @@ declare class NotificationProducer {
1222
1280
  private clip;
1223
1281
  }
1224
1282
 
1283
+ /**
1284
+ * Reconnect-in-place helpers (B-265). A resumed process reattaches to an
1285
+ * EXISTING happy session (HAPPY_RECONNECT_*). Two truths must not be mixed up:
1286
+ *
1287
+ * - the server owns the conversation-level metadata (summary, tags,
1288
+ * claudeSessionId, board, …) and the message `seq`;
1289
+ * - the new process owns its own identity (pid, version, capabilities, …).
1290
+ *
1291
+ * Everything here is pure so the merge rules are unit-tested; the network
1292
+ * side is `api.getSession` and the wiring lives in runClaude / runCodex.
1293
+ */
1294
+
1295
+ interface ServerSessionSnapshot {
1296
+ seq: number;
1297
+ metadata: Metadata;
1298
+ metadataVersion: number;
1299
+ agentState: AgentState$1 | null;
1300
+ agentStateVersion: number;
1301
+ }
1302
+
1225
1303
  declare class ApiClient {
1226
1304
  static create(credential: Credentials): Promise<ApiClient>;
1227
1305
  private readonly credential;
@@ -1244,7 +1322,9 @@ declare class ApiClient {
1244
1322
  metadata: MachineMetadata;
1245
1323
  daemonState?: DaemonState;
1246
1324
  }): Promise<Machine>;
1247
- sessionSyncClient(session: Session): ApiSessionClient;
1325
+ sessionSyncClient(session: Session, opts?: {
1326
+ initialSeq?: number;
1327
+ }): ApiSessionClient;
1248
1328
  machineSyncClient(machine: Machine): ApiMachineClient;
1249
1329
  push(): PushNotificationClient;
1250
1330
  /**
@@ -1287,6 +1367,26 @@ declare class ApiClient {
1287
1367
  * response confirms the deactivate landed.
1288
1368
  */
1289
1369
  deactivateSession(sessionId: string): Promise<boolean>;
1370
+ /**
1371
+ * B-265: one session by id — the message cursor (`seq`), metadata and
1372
+ * agent state with their versions, decrypted with the session key the
1373
+ * reconnecting process already holds. `unsupported` = the server has no
1374
+ * such route (or the row is gone): callers fall back to the legacy
1375
+ * skip-all-history reconnect. Transient failures are retried a few times
1376
+ * first, because falling back silently discards the very message a restore
1377
+ * is meant to deliver.
1378
+ */
1379
+ getSession(sessionId: string, encryptionKey: Uint8Array, encryptionVariant: 'legacy' | 'dataKey', opts?: {
1380
+ attempts?: number;
1381
+ delaysMs?: number[];
1382
+ timeoutMs?: number;
1383
+ }): Promise<{
1384
+ ok: true;
1385
+ session: ServerSessionSnapshot;
1386
+ } | {
1387
+ ok: false;
1388
+ reason: 'unsupported' | 'unavailable';
1389
+ }>;
1290
1390
  /** Clear the server-owned archive tombstone before an intentional resume.
1291
1391
  * Older servers return 404 because the endpoint does not exist; that is a
1292
1392
  * compatible no-op because those servers also have no durable tombstone. */
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-DS3i_5LV.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-B_8X_rZk.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'node:util';
@@ -1,9 +1,9 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { z } from 'zod';
4
- import { p as pushClipboardViaDaemon } from './index-an09rejO.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-8LDXVYWi.mjs';
5
5
  import { C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, c as CLIPBOARD_MAX_BYTES } from './limits-CwFb5S2b.mjs';
6
- import { l as logger } from './types-DS3i_5LV.mjs';
6
+ import { l as logger } from './types-B_8X_rZk.mjs';
7
7
  import 'chalk';
8
8
  import 'node:os';
9
9
  import 'node:crypto';
@@ -3,9 +3,9 @@
3
3
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
4
4
  var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
5
5
  var z = require('zod');
6
- var index = require('./index-4YmVbx7j.cjs');
6
+ var index = require('./index-B63Vjt4W.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-BNGeiP1C.cjs');
8
+ var persistence = require('./types-CjlB_fKT.cjs');
9
9
  require('chalk');
10
10
  require('node:os');
11
11
  require('node:crypto');
@@ -4,10 +4,10 @@ var ink = require('ink');
4
4
  var React = require('react');
5
5
  var node_crypto = require('node:crypto');
6
6
  var path = require('node:path');
7
- var persistence = require('./types-BNGeiP1C.cjs');
8
- var index = require('./index-4YmVbx7j.cjs');
9
- var AcpBackend = require('./AcpBackend-CnYZFdd0.cjs');
10
- var config = require('./config-CgXitj0f.cjs');
7
+ var persistence = require('./types-CjlB_fKT.cjs');
8
+ var index = require('./index-B63Vjt4W.cjs');
9
+ var AcpBackend = require('./AcpBackend-BP7id8L6.cjs');
10
+ var config = require('./config-B77vhdwT.cjs');
11
11
  require('axios');
12
12
  require('chalk');
13
13
  require('node:util');
@@ -2,10 +2,10 @@ import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { randomUUID } from 'node:crypto';
4
4
  import { join } from 'node:path';
5
- import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-DS3i_5LV.mjs';
6
- import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-an09rejO.mjs';
7
- import { A as AcpBackend } from './AcpBackend-BV4wSnJ3.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-BEdyyciP.mjs';
5
+ import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-B_8X_rZk.mjs';
6
+ import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-8LDXVYWi.mjs';
7
+ import { A as AcpBackend } from './AcpBackend-DDEsgc1c.mjs';
8
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-CJQw0z1o.mjs';
9
9
  import 'axios';
10
10
  import 'chalk';
11
11
  import 'node:util';
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
5
5
  var os = require('node:os');
6
6
  var node_fs = require('node:fs');
7
7
  var path = require('node:path');
8
- var persistence = require('./types-BNGeiP1C.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-BPBdrrME.cjs');
10
- var index = require('./index-4YmVbx7j.cjs');
8
+ var persistence = require('./types-CjlB_fKT.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-Cys1Hsb8.cjs');
10
+ var index = require('./index-B63Vjt4W.cjs');
11
11
  var WebSocket = require('ws');
12
12
  var ed = require('@noble/ed25519');
13
13
  var sha2_js = require('@noble/hashes/sha2.js');
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
3
3
  import os from 'node:os';
4
4
  import { existsSync, readFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
- import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-DS3i_5LV.mjs';
7
- import { A as AcpSessionManager } from './AcpSessionManager-Cyne6Rmg.mjs';
8
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-an09rejO.mjs';
6
+ import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-B_8X_rZk.mjs';
7
+ import { A as AcpSessionManager } from './AcpSessionManager-C29t6wb_.mjs';
8
+ import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-8LDXVYWi.mjs';
9
9
  import WebSocket from 'ws';
10
10
  import * as ed from '@noble/ed25519';
11
11
  import { sha512 } from '@noble/hashes/sha2.js';
@@ -3,8 +3,8 @@
3
3
  var chalk = require('chalk');
4
4
  var node_fs = require('node:fs');
5
5
  var path = require('node:path');
6
- var persistence = require('./types-BNGeiP1C.cjs');
7
- var index = require('./index-4YmVbx7j.cjs');
6
+ var persistence = require('./types-CjlB_fKT.cjs');
7
+ var index = require('./index-B63Vjt4W.cjs');
8
8
  require('axios');
9
9
  require('node:util');
10
10
  require('node:os');
@@ -1,8 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { r as readPersistedSessions, c as configuration } from './types-DS3i_5LV.mjs';
5
- import { b as sendUserMessage, a as sessionWebUrl } from './index-an09rejO.mjs';
4
+ import { r as readPersistedSessions, c as configuration } from './types-B_8X_rZk.mjs';
5
+ import { b as sendUserMessage, a as sessionWebUrl } from './index-8LDXVYWi.mjs';
6
6
  import 'axios';
7
7
  import 'node:util';
8
8
  import 'node:os';
@@ -3,8 +3,8 @@
3
3
  var chalk = require('chalk');
4
4
  var node_fs = require('node:fs');
5
5
  var path = require('node:path');
6
- var index = require('./index-4YmVbx7j.cjs');
7
- var persistence = require('./types-BNGeiP1C.cjs');
6
+ var index = require('./index-B63Vjt4W.cjs');
7
+ var persistence = require('./types-CjlB_fKT.cjs');
8
8
  require('node:os');
9
9
  require('node:crypto');
10
10
  require('cross-spawn');
@@ -1,8 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import { readFileSync, statSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-an09rejO.mjs';
5
- import { l as logger } from './types-DS3i_5LV.mjs';
4
+ import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-8LDXVYWi.mjs';
5
+ import { l as logger } from './types-B_8X_rZk.mjs';
6
6
  import 'node:os';
7
7
  import 'node:crypto';
8
8
  import 'cross-spawn';