very-happy-cli 0.2.153 → 0.2.155

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 (55) hide show
  1. package/dist/{AcpBackend-YDGv4E-g.mjs → AcpBackend-DVB0nzgR.mjs} +2 -2
  2. package/dist/{AcpBackend-DSt8nTYm.cjs → AcpBackend-DmFcRh54.cjs} +3 -3
  3. package/dist/{AcpSessionManager-uov6I9C8.cjs → AcpSessionManager-CWaSYTnT.cjs} +1 -1
  4. package/dist/{AcpSessionManager-Cxf5HQX1.mjs → AcpSessionManager-dGDgNb-p.mjs} +1 -1
  5. package/dist/agentGuidance-BWxFC6UL.mjs +1613 -0
  6. package/dist/agentGuidance-un7YPryB.cjs +1665 -0
  7. package/dist/{agentHome-D68Xh2ae.mjs → agentHome-ByLb2HFg.mjs} +5 -5
  8. package/dist/{agentHome-BJ7bde35.cjs → agentHome-aucT8BHw.cjs} +5 -5
  9. package/dist/{auto-CcXxfqkC.mjs → auto-BQnD6gVx.mjs} +21 -21
  10. package/dist/{auto-C-90ojIH.cjs → auto-P9RoJaY0.cjs} +24 -24
  11. package/dist/codex/happyMcpStdioBridge.cjs +6 -3
  12. package/dist/codex/happyMcpStdioBridge.mjs +6 -3
  13. package/dist/{config-CHJ189UJ.mjs → config-BPZ2Y6o8.mjs} +8 -8
  14. package/dist/{config-D23kF0_u.cjs → config-BoePh9PX.cjs} +8 -8
  15. package/dist/{index-D49WvbDT.cjs → index--KCpVs1c.cjs} +7 -7
  16. package/dist/{index-BacwoXzs.mjs → index-B4oXnbYw.mjs} +522 -729
  17. package/dist/{index-BgYZGODP.mjs → index-BjzdXb9x.mjs} +21 -13
  18. package/dist/{index-DEOVn46R.cjs → index-DRrLaljt.cjs} +21 -13
  19. package/dist/{index-BXA9fxbK.mjs → index-DVVRqaVG.mjs} +7 -7
  20. package/dist/{index-DHrwHxHf.cjs → index-D_fYUxVg.cjs} +579 -798
  21. package/dist/index.cjs +6 -6
  22. package/dist/index.mjs +6 -6
  23. package/dist/{install-BiOXBnnS.cjs → install-CGigiocs.cjs} +1 -1
  24. package/dist/{install-Ca7_Z3bV.mjs → install-DP5aPNEX.mjs} +1 -1
  25. package/dist/{installTerminalHooks-BF0kL0ae.cjs → installTerminalHooks-XrcPvfBs.cjs} +5 -5
  26. package/dist/{installTerminalHooks-Bpl32K75.mjs → installTerminalHooks-tIg7mANc.mjs} +5 -5
  27. package/dist/lib.cjs +2 -2
  28. package/dist/lib.mjs +2 -2
  29. package/dist/{limits-BtAuKRl2.mjs → limits-C_DW0M0q.mjs} +309 -13
  30. package/dist/{limits-DY_sFA3J.cjs → limits-DkfHJ3nS.cjs} +329 -12
  31. package/dist/{mcp-JpqI2POW.cjs → mcp-BqlXl10F.cjs} +23 -23
  32. package/dist/{mcp-DQkmk4VV.mjs → mcp-o7QglAQM.mjs} +17 -17
  33. package/dist/{piRuntime-DRbbeQ72.cjs → piRuntime-BxP4B_zY.cjs} +2 -2
  34. package/dist/{piRuntime-DBpe12NN.mjs → piRuntime-MjiJI-nV.mjs} +2 -2
  35. package/dist/{piTerminal-qdJ9KZVL.cjs → piTerminal-DYzRcwgb.cjs} +6 -6
  36. package/dist/{piTerminal-BoHvPEZ_.mjs → piTerminal-Dpq6yqKU.mjs} +6 -6
  37. package/dist/{runGemini-CtOEFvhf.cjs → runGemini-8Pxh94Fm.cjs} +7 -7
  38. package/dist/{runGemini-YqH7a-7O.mjs → runGemini-CDlcQ-OA.mjs} +6 -6
  39. package/dist/{runOpenClaw-DoqZXBvL.cjs → runOpenClaw-B5FSZIbK.cjs} +6 -6
  40. package/dist/{runOpenClaw-DSSyFQBb.mjs → runOpenClaw-YkhsgPs0.mjs} +5 -5
  41. package/dist/{send-9075kHZP.cjs → send-CwrYXTPr.cjs} +58 -54
  42. package/dist/{send-Cs-RwqNf.mjs → send-DJStmLBv.mjs} +56 -53
  43. package/dist/{sessions-iBnYzVUK.mjs → sessions-JaVXlSqj.mjs} +88 -45
  44. package/dist/{sessions-qULzUzlI.cjs → sessions-MX21NJXd.cjs} +99 -56
  45. package/dist/{spawn-C6fRkedx.mjs → spawn-BaPnjClT.mjs} +22 -22
  46. package/dist/{spawn-od9V23cc.cjs → spawn-cIoglKVf.cjs} +30 -30
  47. package/dist/{teams-CkrWQ4uM.mjs → teams-DXV5Pwwt.mjs} +8 -8
  48. package/dist/{teams-CrCzU-AV.cjs → teams-Dqk7F3D-.cjs} +8 -8
  49. package/dist/{todo-aCZmSt27.mjs → todo-2Z1REhfx.mjs} +8 -6
  50. package/dist/{todo-BCT_ZPuV.cjs → todo-Buuqn9gm.cjs} +8 -6
  51. package/dist/{types-BvqOVUOW.mjs → types-CkbfdRzq.mjs} +7 -267
  52. package/dist/{types-CUCU7Vw8.cjs → types-a2xsH2UI.cjs} +19 -295
  53. package/package.json +7 -7
  54. package/dist/agentGuidance-BM4kMNyr.cjs +0 -553
  55. package/dist/agentGuidance-C8unGWp7.mjs +0 -529
@@ -3,21 +3,21 @@ import { randomUUID } from 'node:crypto';
3
3
  import { createServer } from 'node:http';
4
4
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
5
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
- import { p as preparePiTeamsRuntime } from './piRuntime-DBpe12NN.mjs';
7
- import { registerMcpTools, registerTerminalTitleSuggest } from './mcp-DQkmk4VV.mjs';
8
- import './agentGuidance-C8unGWp7.mjs';
6
+ import { p as preparePiTeamsRuntime } from './piRuntime-MjiJI-nV.mjs';
7
+ import { registerMcpTools, registerTerminalTitleSuggest } from './mcp-o7QglAQM.mjs';
8
+ import './agentGuidance-BWxFC6UL.mjs';
9
9
  import 'node:fs/promises';
10
10
  import 'node:os';
11
11
  import 'zod';
12
- import './limits-BtAuKRl2.mjs';
12
+ import './limits-C_DW0M0q.mjs';
13
13
  import 'axios';
14
14
  import 'tweetnacl';
15
15
  import 'socket.io-client';
16
- import './types-BvqOVUOW.mjs';
16
+ import './types-CkbfdRzq.mjs';
17
17
  import 'node:fs';
18
18
  import 'node:path';
19
19
  import { r as resolveMcpTerminalId } from './terminalToolContext-CFeGeaNm.mjs';
20
- import './index-BacwoXzs.mjs';
20
+ import './index-B4oXnbYw.mjs';
21
21
  import 'chalk';
22
22
  import 'cross-spawn';
23
23
  import 'node:readline';
@@ -4,12 +4,12 @@ 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 index$1 = require('./types-CUCU7Vw8.cjs');
8
- var persistence = require('./limits-DY_sFA3J.cjs');
9
- var index = require('./index-DHrwHxHf.cjs');
7
+ var index$1 = require('./types-a2xsH2UI.cjs');
8
+ var persistence = require('./limits-DkfHJ3nS.cjs');
9
+ var index = require('./index-D_fYUxVg.cjs');
10
10
  var terminalTitleSuggest = require('./terminalTitleSuggest-Dji8I0Jy.cjs');
11
- var AcpBackend = require('./AcpBackend-DSt8nTYm.cjs');
12
- var config = require('./config-D23kF0_u.cjs');
11
+ var AcpBackend = require('./AcpBackend-DmFcRh54.cjs');
12
+ var config = require('./config-BoePh9PX.cjs');
13
13
  require('axios');
14
14
  require('node:events');
15
15
  require('socket.io-client');
@@ -34,7 +34,7 @@ require('@anthropic-ai/sandbox-runtime');
34
34
  require('expo-server-sdk');
35
35
  require('chalk');
36
36
  require('node:util');
37
- require('./agentGuidance-BM4kMNyr.cjs');
37
+ require('./agentGuidance-un7YPryB.cjs');
38
38
  require('@anthropic-ai/claude-agent-sdk');
39
39
  require('ps-list');
40
40
  require('tmp');
@@ -943,7 +943,7 @@ async function runGemini(opts) {
943
943
  if (response) {
944
944
  try {
945
945
  persistence.logger.debug(`[START] Reporting session ${response.id} to daemon`);
946
- const result = await index$1.notifyDaemonSessionStarted(response.id, metadata, {
946
+ const result = await persistence.notifyDaemonSessionStarted(response.id, metadata, {
947
947
  encryptionKey: persistence.encodeBase64(response.encryptionKey),
948
948
  encryptionVariant: response.encryptionVariant,
949
949
  seq: response.seq,
@@ -2,12 +2,12 @@ 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 { o as connectionState, A as ApiClient, t as errorLogMetadata, q as notifyDaemonSessionStarted, u as contentLogMetadata } from './types-BvqOVUOW.mjs';
6
- import { l as logger, r as readSettings, j as encodeBase64 } from './limits-BtAuKRl2.mjs';
7
- import { Y as GEMINI_API_KEY_ENV, Z as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, U as BasePermissionHandler, _ as BaseReasoningProcessor, B as initialMachineMetadata, C as createSessionMetadata, E as setupOfflineReconnection, H as MessageQueue2, I as hashObject, $ as MessageBuffer, a0 as CHANGE_TITLE_INSTRUCTION, N as registerKillSessionHandler, J as startHappyServer } from './index-BacwoXzs.mjs';
5
+ import { h as connectionState, A as ApiClient, i as errorLogMetadata, j as contentLogMetadata } from './types-CkbfdRzq.mjs';
6
+ import { l as logger, r as readSettings, v as notifyDaemonSessionStarted, w as encodeBase64 } from './limits-C_DW0M0q.mjs';
7
+ import { I as GEMINI_API_KEY_ENV, J as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, K as BaseReasoningProcessor, h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, M as MessageQueue2, m as hashObject, L as MessageBuffer, N as CHANGE_TITLE_INSTRUCTION, v as registerKillSessionHandler, n as startHappyServer } from './index-B4oXnbYw.mjs';
8
8
  import { p as projectPath } from './terminalTitleSuggest-DKgX3osW.mjs';
9
- import { A as AcpBackend } from './AcpBackend-YDGv4E-g.mjs';
10
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-CHJ189UJ.mjs';
9
+ import { A as AcpBackend } from './AcpBackend-DVB0nzgR.mjs';
10
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-BPZ2Y6o8.mjs';
11
11
  import 'axios';
12
12
  import 'node:events';
13
13
  import 'socket.io-client';
@@ -32,7 +32,7 @@ import '@anthropic-ai/sandbox-runtime';
32
32
  import 'expo-server-sdk';
33
33
  import 'chalk';
34
34
  import 'node:util';
35
- import './agentGuidance-C8unGWp7.mjs';
35
+ import './agentGuidance-BWxFC6UL.mjs';
36
36
  import '@anthropic-ai/claude-agent-sdk';
37
37
  import 'ps-list';
38
38
  import 'tmp';
@@ -5,10 +5,10 @@ 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 index = require('./types-CUCU7Vw8.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-uov6I9C8.cjs');
10
- var persistence = require('./limits-DY_sFA3J.cjs');
11
- var index$1 = require('./index-DHrwHxHf.cjs');
8
+ var index = require('./types-a2xsH2UI.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-CWaSYTnT.cjs');
10
+ var persistence = require('./limits-DkfHJ3nS.cjs');
11
+ var index$1 = require('./index-D_fYUxVg.cjs');
12
12
  var WebSocket = require('ws');
13
13
  var ed = require('@noble/ed25519');
14
14
  var sha2_js = require('@noble/hashes/sha2.js');
@@ -35,7 +35,7 @@ require('@anthropic-ai/sandbox-runtime');
35
35
  require('expo-server-sdk');
36
36
  require('chalk');
37
37
  require('node:util');
38
- require('./agentGuidance-BM4kMNyr.cjs');
38
+ require('./agentGuidance-un7YPryB.cjs');
39
39
  require('ink');
40
40
  require('react');
41
41
  require('@anthropic-ai/claude-agent-sdk');
@@ -865,7 +865,7 @@ async function runOpenClaw(opts) {
865
865
  session = initialSession;
866
866
  if (response) {
867
867
  try {
868
- await index.notifyDaemonSessionStarted(response.id, metadata, {
868
+ await persistence.notifyDaemonSessionStarted(response.id, metadata, {
869
869
  encryptionKey: persistence.encodeBase64(response.encryptionKey),
870
870
  encryptionVariant: response.encryptionVariant,
871
871
  seq: response.seq,
@@ -3,10 +3,10 @@ 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 { t as errorLogMetadata, u as contentLogMetadata, o as connectionState, A as ApiClient, q as notifyDaemonSessionStarted } from './types-BvqOVUOW.mjs';
7
- import { A as AcpSessionManager } from './AcpSessionManager-Cxf5HQX1.mjs';
8
- import { m as ensurePrivateDirectorySync, n as hardenPrivateFileSync, w as writePrivateFileSync, r as readSettings, j as encodeBase64, l as logger, c as configuration } from './limits-BtAuKRl2.mjs';
9
- import { B as initialMachineMetadata, C as createSessionMetadata, E as setupOfflineReconnection, H as MessageQueue2, N as registerKillSessionHandler } from './index-BacwoXzs.mjs';
6
+ import { i as errorLogMetadata, j as contentLogMetadata, h as connectionState, A as ApiClient } from './types-CkbfdRzq.mjs';
7
+ import { A as AcpSessionManager } from './AcpSessionManager-dGDgNb-p.mjs';
8
+ import { z as ensurePrivateDirectorySync, D as hardenPrivateFileSync, E as writePrivateFileSync, r as readSettings, v as notifyDaemonSessionStarted, w as encodeBase64, l as logger, c as configuration } from './limits-C_DW0M0q.mjs';
9
+ import { h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, M as MessageQueue2, v as registerKillSessionHandler } from './index-B4oXnbYw.mjs';
10
10
  import WebSocket from 'ws';
11
11
  import * as ed from '@noble/ed25519';
12
12
  import { sha512 } from '@noble/hashes/sha2.js';
@@ -33,7 +33,7 @@ import '@anthropic-ai/sandbox-runtime';
33
33
  import 'expo-server-sdk';
34
34
  import 'chalk';
35
35
  import 'node:util';
36
- import './agentGuidance-C8unGWp7.mjs';
36
+ import './agentGuidance-BWxFC6UL.mjs';
37
37
  import 'ink';
38
38
  import 'react';
39
39
  import '@anthropic-ai/claude-agent-sdk';
@@ -3,54 +3,21 @@
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('./limits-DY_sFA3J.cjs');
7
- var index = require('./index-DHrwHxHf.cjs');
8
- require('node:fs/promises');
9
- require('node:os');
6
+ var persistence = require('./limits-DkfHJ3nS.cjs');
7
+ var agentGuidance = require('./agentGuidance-un7YPryB.cjs');
10
8
  require('zod');
9
+ require('@paralleldrive/cuid2');
10
+ require('node:fs/promises');
11
11
  require('node:crypto');
12
12
  require('tweetnacl');
13
13
  require('node:util');
14
- require('@paralleldrive/cuid2');
15
- require('./types-CUCU7Vw8.cjs');
14
+ require('node:os');
16
15
  require('axios');
17
- require('node:events');
18
16
  require('socket.io-client');
19
- require('child_process');
20
- require('util');
21
- require('fs/promises');
22
- require('crypto');
23
- require('path');
24
- require('cross-spawn');
25
- require('./terminalTitleSuggest-Dji8I0Jy.cjs');
26
- require('url');
27
- require('os');
28
- require('node:child_process');
29
- require('node-pty');
30
- require('fs');
31
- require('node:readline');
32
- require('@anthropic-ai/sandbox-runtime');
33
- require('expo-server-sdk');
34
- require('./agentGuidance-BM4kMNyr.cjs');
35
- require('ink');
36
- require('react');
37
- require('@anthropic-ai/claude-agent-sdk');
38
- require('ps-list');
39
- require('tmp');
40
- require('open');
41
- require('fastify');
42
- require('fastify-type-provider-zod');
43
- require('node:module');
44
- require('@modelcontextprotocol/sdk/server/mcp.js');
45
- require('node:http');
46
- require('@modelcontextprotocol/sdk/server/streamableHttp.js');
47
- require('http');
48
- require('inquirer');
49
- require('node:url');
50
- require('node:readline/promises');
51
17
 
18
+ const EXIT_SESSION_NOT_LIVE = 3;
52
19
  function parseSendArgs(args) {
53
- const options = { json: false, help: false };
20
+ const options = { resume: false, json: false, help: false };
54
21
  for (let i = 0; i < args.length; i++) {
55
22
  const arg = args[i];
56
23
  if (arg === "--session" || arg === "-s") {
@@ -69,6 +36,8 @@ function parseSendArgs(args) {
69
36
  const value = args[++i];
70
37
  if (value === void 0 || value.trim().length === 0) throw new Error("--model requires a value");
71
38
  options.model = value;
39
+ } else if (arg === "--resume") {
40
+ options.resume = true;
72
41
  } else if (arg === "--json") {
73
42
  options.json = true;
74
43
  } else if (arg === "--help" || arg === "-h") {
@@ -88,7 +57,7 @@ ${chalk.bold("very-happy send")} - Send a message into an existing session (for
88
57
 
89
58
  ${chalk.bold("Usage:")}
90
59
  very-happy send --session <id> (--prompt <text> | --prompt-file <file>)
91
- [--model <id>] [--json]
60
+ [--model <id>] [--resume] [--json]
92
61
 
93
62
  ${chalk.bold("Options:")}
94
63
  --session, -s <id> Target session id (required)
@@ -97,7 +66,10 @@ ${chalk.bold("Options:")}
97
66
  --model, -m <id> Switch the session to this model with this message
98
67
  ('default' = the machine default). Without it the
99
68
  session keeps whatever model it is on.
100
- --json Machine-readable output: {"sessionId", "url", "delivered"}
69
+ --resume If the session is archived or offline, bring it back
70
+ on THIS machine first (same as the web's Restore),
71
+ wait until it is live, then send.
72
+ --json Machine-readable output (see below)
101
73
  -h, --help Show this help
102
74
 
103
75
  ${chalk.bold("Behavior:")}
@@ -105,9 +77,23 @@ ${chalk.bold("Behavior:")}
105
77
  encryption key must be in ${persistence.configuration.sessionsFile}); sessions from
106
78
  other machines or from daemons too old to persist keys cannot be reached.
107
79
 
80
+ Before sending, the session is classified from the local daemon and the
81
+ server: live (a wrapper is attached, here or on another machine), archived,
82
+ offline (wrapper exited / presence timed out) or not_found. The server
83
+ stores messages for any session, so only "live" means someone will read it;
84
+ anything else is refused with exit 3 unless --resume is given.
85
+
86
+ ${chalk.bold("JSON output:")}
87
+ delivered {"sessionId","url","delivered":true,"status":"live","resumed":false|true}
88
+ refused {"sessionId","url","delivered":false,"status":"archived"|"offline"|"not_found",
89
+ "error":"...","resume":{"ok":false,"error":"..."}} (resume only with --resume)
90
+ dropped {"delivered":false,"stored":true,...} the POST succeeded but the wrapper
91
+ went away meanwhile: the message is stored server-side, unread
92
+
108
93
  ${chalk.bold("Exit codes:")}
109
- 0 message delivered
110
- 1 bad arguments, unknown session, or delivery failed
94
+ 0 message delivered to a live wrapper
95
+ 1 bad arguments, unknown session, or transport failure
96
+ 3 session not live (archived / offline / not found) or resume failed
111
97
  `);
112
98
  }
113
99
  function fail(options, sessionId, message) {
@@ -115,7 +101,7 @@ function fail(options, sessionId, message) {
115
101
  const payload = { delivered: false, error: message };
116
102
  if (sessionId) {
117
103
  payload.sessionId = sessionId;
118
- payload.url = index.sessionWebUrl(sessionId);
104
+ payload.url = agentGuidance.sessionWebUrl(sessionId);
119
105
  }
120
106
  console.log(JSON.stringify(payload));
121
107
  } else {
@@ -166,27 +152,45 @@ async function handleSendCommand(args) {
166
152
  `Session ${sessionId} has no encryption key in ${persistence.configuration.sessionsFile}. It was not spawned by this machine's daemon, or the daemon is too old to persist session keys.`
167
153
  );
168
154
  }
155
+ let result;
169
156
  try {
170
- await index.sendUserMessage(
171
- sessionId,
172
- persisted,
173
- prompt,
174
- "cli-send",
175
- options.model !== void 0 ? { model: options.model === "default" ? null : options.model } : {}
176
- );
157
+ result = await agentGuidance.deliverToSession(sessionId, persisted, prompt, "cli-send", {
158
+ resume: options.resume,
159
+ ...options.model !== void 0 ? { model: options.model === "default" ? null : options.model } : {}
160
+ });
177
161
  } catch (error) {
178
162
  fail(options, sessionId, `Failed to send message: ${error instanceof Error ? error.message : String(error)}`);
179
163
  }
180
- const url = index.sessionWebUrl(sessionId);
164
+ const url = agentGuidance.sessionWebUrl(sessionId);
165
+ if (!result.delivered) {
166
+ if (options.json) {
167
+ console.log(JSON.stringify({
168
+ sessionId,
169
+ url,
170
+ delivered: false,
171
+ status: result.status,
172
+ resumed: result.resumed,
173
+ stored: result.stored,
174
+ error: result.error,
175
+ ...result.resume ? { resume: result.resume } : {}
176
+ }));
177
+ } else {
178
+ console.error(chalk.red("Not delivered:"), result.error ?? `session is ${result.status}`);
179
+ if (result.stored) console.error(chalk.yellow("The message is stored server-side; nothing is reading it."));
180
+ }
181
+ process.exit(EXIT_SESSION_NOT_LIVE);
182
+ }
181
183
  if (options.json) {
182
- console.log(JSON.stringify({ sessionId, url, delivered: true }));
184
+ console.log(JSON.stringify({ sessionId, url, delivered: true, status: "live", resumed: result.resumed }));
183
185
  } else {
184
186
  console.log(`${chalk.bold("Session:")} ${sessionId}`);
185
187
  console.log(`${chalk.bold("URL:")} ${url}`);
188
+ if (result.resumed) console.log(chalk.green("Session resumed on this machine."));
186
189
  console.log(chalk.green("Message sent."));
187
190
  }
188
191
  process.exit(0);
189
192
  }
190
193
 
194
+ exports.EXIT_SESSION_NOT_LIVE = EXIT_SESSION_NOT_LIVE;
191
195
  exports.handleSendCommand = handleSendCommand;
192
196
  exports.parseSendArgs = parseSendArgs;
@@ -1,54 +1,21 @@
1
1
  import chalk from 'chalk';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { d as readPersistedSessions, c as configuration } from './limits-BtAuKRl2.mjs';
5
- import { d as sendUserMessage, e as sessionWebUrl } from './index-BacwoXzs.mjs';
6
- import 'node:fs/promises';
7
- import 'node:os';
4
+ import { d as readPersistedSessions, c as configuration } from './limits-C_DW0M0q.mjs';
5
+ import { n as deliverToSession, o as sessionWebUrl } from './agentGuidance-BWxFC6UL.mjs';
8
6
  import 'zod';
7
+ import '@paralleldrive/cuid2';
8
+ import 'node:fs/promises';
9
9
  import 'node:crypto';
10
10
  import 'tweetnacl';
11
11
  import 'node:util';
12
- import '@paralleldrive/cuid2';
13
- import './types-BvqOVUOW.mjs';
12
+ import 'node:os';
14
13
  import 'axios';
15
- import 'node:events';
16
14
  import 'socket.io-client';
17
- import 'child_process';
18
- import 'util';
19
- import 'fs/promises';
20
- import 'crypto';
21
- import 'path';
22
- import 'cross-spawn';
23
- import './terminalTitleSuggest-DKgX3osW.mjs';
24
- import 'url';
25
- import 'os';
26
- import 'node:child_process';
27
- import 'node-pty';
28
- import 'fs';
29
- import 'node:readline';
30
- import '@anthropic-ai/sandbox-runtime';
31
- import 'expo-server-sdk';
32
- import './agentGuidance-C8unGWp7.mjs';
33
- import 'ink';
34
- import 'react';
35
- import '@anthropic-ai/claude-agent-sdk';
36
- import 'ps-list';
37
- import 'tmp';
38
- import 'open';
39
- import 'fastify';
40
- import 'fastify-type-provider-zod';
41
- import 'node:module';
42
- import '@modelcontextprotocol/sdk/server/mcp.js';
43
- import 'node:http';
44
- import '@modelcontextprotocol/sdk/server/streamableHttp.js';
45
- import 'http';
46
- import 'inquirer';
47
- import 'node:url';
48
- import 'node:readline/promises';
49
15
 
16
+ const EXIT_SESSION_NOT_LIVE = 3;
50
17
  function parseSendArgs(args) {
51
- const options = { json: false, help: false };
18
+ const options = { resume: false, json: false, help: false };
52
19
  for (let i = 0; i < args.length; i++) {
53
20
  const arg = args[i];
54
21
  if (arg === "--session" || arg === "-s") {
@@ -67,6 +34,8 @@ function parseSendArgs(args) {
67
34
  const value = args[++i];
68
35
  if (value === void 0 || value.trim().length === 0) throw new Error("--model requires a value");
69
36
  options.model = value;
37
+ } else if (arg === "--resume") {
38
+ options.resume = true;
70
39
  } else if (arg === "--json") {
71
40
  options.json = true;
72
41
  } else if (arg === "--help" || arg === "-h") {
@@ -86,7 +55,7 @@ ${chalk.bold("very-happy send")} - Send a message into an existing session (for
86
55
 
87
56
  ${chalk.bold("Usage:")}
88
57
  very-happy send --session <id> (--prompt <text> | --prompt-file <file>)
89
- [--model <id>] [--json]
58
+ [--model <id>] [--resume] [--json]
90
59
 
91
60
  ${chalk.bold("Options:")}
92
61
  --session, -s <id> Target session id (required)
@@ -95,7 +64,10 @@ ${chalk.bold("Options:")}
95
64
  --model, -m <id> Switch the session to this model with this message
96
65
  ('default' = the machine default). Without it the
97
66
  session keeps whatever model it is on.
98
- --json Machine-readable output: {"sessionId", "url", "delivered"}
67
+ --resume If the session is archived or offline, bring it back
68
+ on THIS machine first (same as the web's Restore),
69
+ wait until it is live, then send.
70
+ --json Machine-readable output (see below)
99
71
  -h, --help Show this help
100
72
 
101
73
  ${chalk.bold("Behavior:")}
@@ -103,9 +75,23 @@ ${chalk.bold("Behavior:")}
103
75
  encryption key must be in ${configuration.sessionsFile}); sessions from
104
76
  other machines or from daemons too old to persist keys cannot be reached.
105
77
 
78
+ Before sending, the session is classified from the local daemon and the
79
+ server: live (a wrapper is attached, here or on another machine), archived,
80
+ offline (wrapper exited / presence timed out) or not_found. The server
81
+ stores messages for any session, so only "live" means someone will read it;
82
+ anything else is refused with exit 3 unless --resume is given.
83
+
84
+ ${chalk.bold("JSON output:")}
85
+ delivered {"sessionId","url","delivered":true,"status":"live","resumed":false|true}
86
+ refused {"sessionId","url","delivered":false,"status":"archived"|"offline"|"not_found",
87
+ "error":"...","resume":{"ok":false,"error":"..."}} (resume only with --resume)
88
+ dropped {"delivered":false,"stored":true,...} the POST succeeded but the wrapper
89
+ went away meanwhile: the message is stored server-side, unread
90
+
106
91
  ${chalk.bold("Exit codes:")}
107
- 0 message delivered
108
- 1 bad arguments, unknown session, or delivery failed
92
+ 0 message delivered to a live wrapper
93
+ 1 bad arguments, unknown session, or transport failure
94
+ 3 session not live (archived / offline / not found) or resume failed
109
95
  `);
110
96
  }
111
97
  function fail(options, sessionId, message) {
@@ -164,26 +150,43 @@ async function handleSendCommand(args) {
164
150
  `Session ${sessionId} has no encryption key in ${configuration.sessionsFile}. It was not spawned by this machine's daemon, or the daemon is too old to persist session keys.`
165
151
  );
166
152
  }
153
+ let result;
167
154
  try {
168
- await sendUserMessage(
169
- sessionId,
170
- persisted,
171
- prompt,
172
- "cli-send",
173
- options.model !== void 0 ? { model: options.model === "default" ? null : options.model } : {}
174
- );
155
+ result = await deliverToSession(sessionId, persisted, prompt, "cli-send", {
156
+ resume: options.resume,
157
+ ...options.model !== void 0 ? { model: options.model === "default" ? null : options.model } : {}
158
+ });
175
159
  } catch (error) {
176
160
  fail(options, sessionId, `Failed to send message: ${error instanceof Error ? error.message : String(error)}`);
177
161
  }
178
162
  const url = sessionWebUrl(sessionId);
163
+ if (!result.delivered) {
164
+ if (options.json) {
165
+ console.log(JSON.stringify({
166
+ sessionId,
167
+ url,
168
+ delivered: false,
169
+ status: result.status,
170
+ resumed: result.resumed,
171
+ stored: result.stored,
172
+ error: result.error,
173
+ ...result.resume ? { resume: result.resume } : {}
174
+ }));
175
+ } else {
176
+ console.error(chalk.red("Not delivered:"), result.error ?? `session is ${result.status}`);
177
+ if (result.stored) console.error(chalk.yellow("The message is stored server-side; nothing is reading it."));
178
+ }
179
+ process.exit(EXIT_SESSION_NOT_LIVE);
180
+ }
179
181
  if (options.json) {
180
- console.log(JSON.stringify({ sessionId, url, delivered: true }));
182
+ console.log(JSON.stringify({ sessionId, url, delivered: true, status: "live", resumed: result.resumed }));
181
183
  } else {
182
184
  console.log(`${chalk.bold("Session:")} ${sessionId}`);
183
185
  console.log(`${chalk.bold("URL:")} ${url}`);
186
+ if (result.resumed) console.log(chalk.green("Session resumed on this machine."));
184
187
  console.log(chalk.green("Message sent."));
185
188
  }
186
189
  process.exit(0);
187
190
  }
188
191
 
189
- export { handleSendCommand, parseSendArgs };
192
+ export { EXIT_SESSION_NOT_LIVE, handleSendCommand, parseSendArgs };