@zonease/happy 0.6.37 → 0.6.38

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.
@@ -4,7 +4,7 @@ var fs = require('fs');
4
4
  var path = require('path');
5
5
  var os = require('os');
6
6
  var child_process = require('child_process');
7
- var persistence = require('./types-BrTorNAy.cjs');
7
+ var persistence = require('./types-DvTsFaqR.cjs');
8
8
  var constants = require('./constants-B4x1K7by.cjs');
9
9
  require('axios');
10
10
  require('chalk');
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { homedir } from 'os';
4
4
  import { execSync } from 'child_process';
5
- import { l as logger } from './types-DYCJXXdA.mjs';
5
+ import { l as logger } from './types-BWpRU1VN.mjs';
6
6
  import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './constants-BO9OAFOT.mjs';
7
7
  import 'axios';
8
8
  import 'chalk';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk = require('chalk');
4
- var persistence = require('./types-BrTorNAy.cjs');
4
+ var persistence = require('./types-DvTsFaqR.cjs');
5
5
  var os = require('node:os');
6
6
  var node_crypto = require('node:crypto');
7
7
  var fs = require('node:fs');
@@ -1151,7 +1151,7 @@ function getRuntime() {
1151
1151
  }
1152
1152
  const isBun = () => getRuntime() === "bun";
1153
1153
 
1154
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BlkHOkB3.cjs', document.baseURI).href)));
1154
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BbCDDvoB.cjs', document.baseURI).href)));
1155
1155
  const __dirname$1 = path.join(__filename$1, "..");
1156
1156
  function getGlobalClaudeVersion() {
1157
1157
  try {
@@ -6814,6 +6814,7 @@ async function listDevices(credentials) {
6814
6814
  return {
6815
6815
  id: row.id,
6816
6816
  name: row.displayName || metadata?.displayName || metadata?.host || row.id.slice(0, 12),
6817
+ description: row.description ?? null,
6817
6818
  platform: metadata?.platform ?? null,
6818
6819
  active: row.active,
6819
6820
  lastActiveAt: row.activeAt ?? row.lastActiveAt ?? 0
@@ -6889,7 +6890,7 @@ function createMcpServer(client, options) {
6889
6890
  const lines = devices.map((device) => {
6890
6891
  const marks = [device.active ? "online" : "offline"];
6891
6892
  if (target.includes(device.id)) marks.push("session default");
6892
- return `${device.id} ${device.name}${device.platform ? ` (${device.platform})` : ""} [${marks.join(", ")}]`;
6893
+ return `${device.id} ${device.name}${device.platform ? ` (${device.platform})` : ""} [${marks.join(", ")}]${device.description ? ` \u2014 ${device.description}` : ""}`;
6893
6894
  });
6894
6895
  return { content: [{ type: "text", text: lines.length ? lines.join("\n") : "No devices enrolled yet." }] };
6895
6896
  } catch (error) {
@@ -8143,6 +8144,62 @@ function matchDevice(devices, query) {
8143
8144
  const lowered = query.trim().toLowerCase();
8144
8145
  return devices.find((device) => device.id === query) ?? devices.find((device) => device.name.toLowerCase() === lowered) ?? devices.find((device) => device.name.toLowerCase().startsWith(lowered)) ?? devices.find((device) => device.name.toLowerCase().includes(lowered)) ?? null;
8145
8146
  }
8147
+ const DEFAULT_COMMAND_TIMEOUT_MS = 3e5;
8148
+ function parseSshArgs(args) {
8149
+ const separator = args.indexOf("--");
8150
+ const head = separator >= 0 ? args.slice(0, separator) : args;
8151
+ const command = separator >= 0 ? args.slice(separator + 1).join(" ") : null;
8152
+ let target = null;
8153
+ let timeoutMs = DEFAULT_COMMAND_TIMEOUT_MS;
8154
+ for (let i = 0; i < head.length; i++) {
8155
+ if (head[i] === "--timeout" || head[i] === "-t") {
8156
+ const seconds = Number(head[++i]);
8157
+ if (Number.isFinite(seconds) && seconds > 0) timeoutMs = seconds * 1e3;
8158
+ continue;
8159
+ }
8160
+ if (!target && !head[i].startsWith("-")) target = head[i];
8161
+ }
8162
+ return { target, command: command && command.trim() ? command : null, timeoutMs };
8163
+ }
8164
+ async function runOnDevice(credentials, query, command, options = {}) {
8165
+ const { devices } = await listDevicesWithNames(credentials);
8166
+ const device = matchDevice(devices, query);
8167
+ if (!device) {
8168
+ console.error(`No enrolled device matches "${query}". Run "happy ssh" with no arguments to list devices.`);
8169
+ return 1;
8170
+ }
8171
+ if (!device.active) {
8172
+ console.error(`Device "${device.name}" is offline.`);
8173
+ return 1;
8174
+ }
8175
+ const { key, variant } = await ensureDeviceKey(credentials, device.id, () => {
8176
+ console.error("Waiting for approval in the Happy app (Devices \u2192 pending request)...");
8177
+ });
8178
+ const socket = socket_ioClient.io(persistence.configuration.serverUrl, {
8179
+ auth: { token: credentials.token, clientType: "user-scoped" },
8180
+ path: "/v1/updates",
8181
+ transports: ["websocket"]
8182
+ });
8183
+ await new Promise((resolve, reject) => {
8184
+ socket.once("connect", () => resolve());
8185
+ socket.once("connect_error", reject);
8186
+ });
8187
+ try {
8188
+ const result = await deviceExec(socket, credentials, device.id, command, {
8189
+ deviceKeyBase64: persistence.encodeBase64(key),
8190
+ deviceKeyVariant: variant,
8191
+ timeout: options.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS
8192
+ });
8193
+ if (result.stdout) process.stdout.write(result.stdout);
8194
+ if (result.stderr) process.stderr.write(result.stderr);
8195
+ if (result.error && !result.error.startsWith("Command failed:")) {
8196
+ console.error(result.error);
8197
+ }
8198
+ return result.exitCode ?? (result.success ? 0 : 1);
8199
+ } finally {
8200
+ socket.close();
8201
+ }
8202
+ }
8146
8203
  async function sshDevice(credentials, query) {
8147
8204
  const { devices } = await listDevicesWithNames(credentials);
8148
8205
  const device = matchDevice(devices, query);
@@ -10048,7 +10105,7 @@ async function handleTaskCommand(args) {
10048
10105
  await printOrWriteOutput(brief, stringFlag(parsed, "--out"));
10049
10106
  }
10050
10107
 
10051
- const CLI_PACKAGE_ROOT = path.resolve(path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BlkHOkB3.cjs', document.baseURI).href)))), "..", "..");
10108
+ const CLI_PACKAGE_ROOT = path.resolve(path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BbCDDvoB.cjs', document.baseURI).href)))), "..", "..");
10052
10109
  function printReleaseHelp() {
10053
10110
  console.log(`
10054
10111
  ${chalk.bold("happy release")} - Verify before publishing
@@ -10549,7 +10606,7 @@ async function spawnAndWaitForDaemon() {
10549
10606
  if (!args.includes("--version")) ;
10550
10607
  if (subcommand === "orchestrator-oneshot") {
10551
10608
  try {
10552
- const { runOrchestratorOneShot } = await Promise.resolve().then(function () { return require('./runOneShot-CXhbFJ2j.cjs'); });
10609
+ const { runOrchestratorOneShot } = await Promise.resolve().then(function () { return require('./runOneShot-BQNkNW61.cjs'); });
10553
10610
  const exitCode = await runOrchestratorOneShot(args.slice(1));
10554
10611
  process.exit(exitCode);
10555
10612
  } catch (error) {
@@ -10595,7 +10652,7 @@ async function spawnAndWaitForDaemon() {
10595
10652
  return;
10596
10653
  } else if (subcommand === "codex") {
10597
10654
  try {
10598
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BTt3fxG4.cjs'); });
10655
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-skq0j05d.cjs'); });
10599
10656
  let startedBy = void 0;
10600
10657
  for (let i = 1; i < args.length; i++) {
10601
10658
  if (args[i] === "--started-by") {
@@ -10699,9 +10756,9 @@ async function spawnAndWaitForDaemon() {
10699
10756
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
10700
10757
  const projectId = args[3];
10701
10758
  try {
10702
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-D_g6ohaV.cjs'); });
10703
- const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./types-BrTorNAy.cjs'); }).then(function (n) { return n.persistence; });
10704
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BrTorNAy.cjs'); }).then(function (n) { return n.api; });
10759
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-0Xnc8ARM.cjs'); });
10760
+ const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./types-DvTsFaqR.cjs'); }).then(function (n) { return n.persistence; });
10761
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DvTsFaqR.cjs'); }).then(function (n) { return n.api; });
10705
10762
  let userEmail = void 0;
10706
10763
  try {
10707
10764
  const credentials = await readCredentials2();
@@ -10732,7 +10789,7 @@ async function spawnAndWaitForDaemon() {
10732
10789
  }
10733
10790
  if (geminiSubcommand === "project" && args[2] === "get") {
10734
10791
  try {
10735
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-D_g6ohaV.cjs'); });
10792
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-0Xnc8ARM.cjs'); });
10736
10793
  const config = readGeminiLocalConfig();
10737
10794
  if (config.googleCloudProject) {
10738
10795
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -10772,7 +10829,7 @@ async function spawnAndWaitForDaemon() {
10772
10829
  process.exit(0);
10773
10830
  }
10774
10831
  try {
10775
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-C-0nSFBv.cjs'); });
10832
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CVp-CEIh.cjs'); });
10776
10833
  let startedBy = void 0;
10777
10834
  for (let i = 1; i < args.length; i++) {
10778
10835
  if (args[i] === "--started-by") {
@@ -10909,7 +10966,7 @@ async function spawnAndWaitForDaemon() {
10909
10966
  process.exit(1);
10910
10967
  }
10911
10968
  try {
10912
- const { runMcpServe } = await Promise.resolve().then(function () { return require('./serve-DZAq-_1F.cjs'); });
10969
+ const { runMcpServe } = await Promise.resolve().then(function () { return require('./serve-BECdtivY.cjs'); });
10913
10970
  await runMcpServe();
10914
10971
  } catch (error) {
10915
10972
  process.stderr.write(`[happy-mcp] fatal: ${error instanceof Error ? error.message : "unknown error"}
@@ -10923,8 +10980,15 @@ async function spawnAndWaitForDaemon() {
10923
10980
  console.error(chalk.red("Error:"), 'Not authenticated. Run "happy auth" first.');
10924
10981
  process.exit(1);
10925
10982
  }
10926
- const target = args[1];
10983
+ const { target, command, timeoutMs } = parseSshArgs(args.slice(1));
10927
10984
  try {
10985
+ if (command) {
10986
+ if (!target) {
10987
+ console.error(chalk.red("Error:"), "Which device? Usage: happy ssh <device> -- <command>");
10988
+ process.exit(1);
10989
+ }
10990
+ process.exit(await runOnDevice(credentials, target, command, { timeoutMs }));
10991
+ }
10928
10992
  if (!target) {
10929
10993
  process.exit(await sshPickAndConnect(credentials));
10930
10994
  }
@@ -1,5 +1,5 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, j as projectPath, y as delay, I as InvalidateSync, R as RawJSONLinesSchema, o as isDebug, D as AsyncLock, c as configuration, E as readDaemonState, F as clearDaemonState, k as packageJson, x as readSettings, r as readCredentials, e as encodeBase64, H as updateSettings, J as encodeBase64Url, f as decodeBase64, K as writeCredentialsLegacy, L as writeCredentialsDataKey, N as acquireDaemonLock, O as writeDaemonState, A as ApiClient, P as releaseDaemonLock, Q as validateProfileForAgent, S as getProfileEnvironmentVariables, g as decrypt, d as encrypt, w as connectionState, h as resolveToolsDir, s as startOfflineReconnection, T as findClaudeProjectId, U as libsodiumPublicKeyFromSecretKey, V as clearCredentials, W as clearMachineId, X as decryptLegacy, Y as decryptWithDataKey, Z as readCachedSessionKey, _ as getLatestDaemonLog } from './types-DYCJXXdA.mjs';
2
+ import { l as logger, j as projectPath, y as delay, I as InvalidateSync, R as RawJSONLinesSchema, o as isDebug, D as AsyncLock, c as configuration, E as readDaemonState, F as clearDaemonState, k as packageJson, x as readSettings, r as readCredentials, e as encodeBase64, H as updateSettings, J as encodeBase64Url, f as decodeBase64, K as writeCredentialsLegacy, L as writeCredentialsDataKey, N as acquireDaemonLock, O as writeDaemonState, A as ApiClient, P as releaseDaemonLock, Q as validateProfileForAgent, S as getProfileEnvironmentVariables, d as encrypt, g as decrypt, w as connectionState, h as resolveToolsDir, s as startOfflineReconnection, T as findClaudeProjectId, U as libsodiumPublicKeyFromSecretKey, V as clearCredentials, W as clearMachineId, X as decryptLegacy, Y as decryptWithDataKey, Z as readCachedSessionKey, _ as getLatestDaemonLog } from './types-BWpRU1VN.mjs';
3
3
  import os$1, { homedir, hostname } from 'node:os';
4
4
  import { randomUUID, randomBytes, createHmac } from 'node:crypto';
5
5
  import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, createReadStream, writeFileSync as writeFileSync$1, unlinkSync, rmSync, realpathSync, constants } from 'node:fs';
@@ -6792,6 +6792,7 @@ async function listDevices(credentials) {
6792
6792
  return {
6793
6793
  id: row.id,
6794
6794
  name: row.displayName || metadata?.displayName || metadata?.host || row.id.slice(0, 12),
6795
+ description: row.description ?? null,
6795
6796
  platform: metadata?.platform ?? null,
6796
6797
  active: row.active,
6797
6798
  lastActiveAt: row.activeAt ?? row.lastActiveAt ?? 0
@@ -6867,7 +6868,7 @@ function createMcpServer(client, options) {
6867
6868
  const lines = devices.map((device) => {
6868
6869
  const marks = [device.active ? "online" : "offline"];
6869
6870
  if (target.includes(device.id)) marks.push("session default");
6870
- return `${device.id} ${device.name}${device.platform ? ` (${device.platform})` : ""} [${marks.join(", ")}]`;
6871
+ return `${device.id} ${device.name}${device.platform ? ` (${device.platform})` : ""} [${marks.join(", ")}]${device.description ? ` \u2014 ${device.description}` : ""}`;
6871
6872
  });
6872
6873
  return { content: [{ type: "text", text: lines.length ? lines.join("\n") : "No devices enrolled yet." }] };
6873
6874
  } catch (error) {
@@ -8121,6 +8122,62 @@ function matchDevice(devices, query) {
8121
8122
  const lowered = query.trim().toLowerCase();
8122
8123
  return devices.find((device) => device.id === query) ?? devices.find((device) => device.name.toLowerCase() === lowered) ?? devices.find((device) => device.name.toLowerCase().startsWith(lowered)) ?? devices.find((device) => device.name.toLowerCase().includes(lowered)) ?? null;
8123
8124
  }
8125
+ const DEFAULT_COMMAND_TIMEOUT_MS = 3e5;
8126
+ function parseSshArgs(args) {
8127
+ const separator = args.indexOf("--");
8128
+ const head = separator >= 0 ? args.slice(0, separator) : args;
8129
+ const command = separator >= 0 ? args.slice(separator + 1).join(" ") : null;
8130
+ let target = null;
8131
+ let timeoutMs = DEFAULT_COMMAND_TIMEOUT_MS;
8132
+ for (let i = 0; i < head.length; i++) {
8133
+ if (head[i] === "--timeout" || head[i] === "-t") {
8134
+ const seconds = Number(head[++i]);
8135
+ if (Number.isFinite(seconds) && seconds > 0) timeoutMs = seconds * 1e3;
8136
+ continue;
8137
+ }
8138
+ if (!target && !head[i].startsWith("-")) target = head[i];
8139
+ }
8140
+ return { target, command: command && command.trim() ? command : null, timeoutMs };
8141
+ }
8142
+ async function runOnDevice(credentials, query, command, options = {}) {
8143
+ const { devices } = await listDevicesWithNames(credentials);
8144
+ const device = matchDevice(devices, query);
8145
+ if (!device) {
8146
+ console.error(`No enrolled device matches "${query}". Run "happy ssh" with no arguments to list devices.`);
8147
+ return 1;
8148
+ }
8149
+ if (!device.active) {
8150
+ console.error(`Device "${device.name}" is offline.`);
8151
+ return 1;
8152
+ }
8153
+ const { key, variant } = await ensureDeviceKey(credentials, device.id, () => {
8154
+ console.error("Waiting for approval in the Happy app (Devices \u2192 pending request)...");
8155
+ });
8156
+ const socket = io(configuration.serverUrl, {
8157
+ auth: { token: credentials.token, clientType: "user-scoped" },
8158
+ path: "/v1/updates",
8159
+ transports: ["websocket"]
8160
+ });
8161
+ await new Promise((resolve, reject) => {
8162
+ socket.once("connect", () => resolve());
8163
+ socket.once("connect_error", reject);
8164
+ });
8165
+ try {
8166
+ const result = await deviceExec(socket, credentials, device.id, command, {
8167
+ deviceKeyBase64: encodeBase64(key),
8168
+ deviceKeyVariant: variant,
8169
+ timeout: options.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS
8170
+ });
8171
+ if (result.stdout) process.stdout.write(result.stdout);
8172
+ if (result.stderr) process.stderr.write(result.stderr);
8173
+ if (result.error && !result.error.startsWith("Command failed:")) {
8174
+ console.error(result.error);
8175
+ }
8176
+ return result.exitCode ?? (result.success ? 0 : 1);
8177
+ } finally {
8178
+ socket.close();
8179
+ }
8180
+ }
8124
8181
  async function sshDevice(credentials, query) {
8125
8182
  const { devices } = await listDevicesWithNames(credentials);
8126
8183
  const device = matchDevice(devices, query);
@@ -10527,7 +10584,7 @@ async function spawnAndWaitForDaemon() {
10527
10584
  if (!args.includes("--version")) ;
10528
10585
  if (subcommand === "orchestrator-oneshot") {
10529
10586
  try {
10530
- const { runOrchestratorOneShot } = await import('./runOneShot-USX8QPfE.mjs');
10587
+ const { runOrchestratorOneShot } = await import('./runOneShot-ltCpHbBB.mjs');
10531
10588
  const exitCode = await runOrchestratorOneShot(args.slice(1));
10532
10589
  process.exit(exitCode);
10533
10590
  } catch (error) {
@@ -10573,7 +10630,7 @@ async function spawnAndWaitForDaemon() {
10573
10630
  return;
10574
10631
  } else if (subcommand === "codex") {
10575
10632
  try {
10576
- const { runCodex } = await import('./runCodex-BXCB5trB.mjs');
10633
+ const { runCodex } = await import('./runCodex-DiKzBf9q.mjs');
10577
10634
  let startedBy = void 0;
10578
10635
  for (let i = 1; i < args.length; i++) {
10579
10636
  if (args[i] === "--started-by") {
@@ -10677,9 +10734,9 @@ async function spawnAndWaitForDaemon() {
10677
10734
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
10678
10735
  const projectId = args[3];
10679
10736
  try {
10680
- const { saveGoogleCloudProjectToConfig } = await import('./config-DPn-cbpz.mjs');
10681
- const { readCredentials: readCredentials2 } = await import('./types-DYCJXXdA.mjs').then(function (n) { return n.$; });
10682
- const { ApiClient: ApiClient2 } = await import('./types-DYCJXXdA.mjs').then(function (n) { return n.a0; });
10737
+ const { saveGoogleCloudProjectToConfig } = await import('./config-_GW4YBCP.mjs');
10738
+ const { readCredentials: readCredentials2 } = await import('./types-BWpRU1VN.mjs').then(function (n) { return n.$; });
10739
+ const { ApiClient: ApiClient2 } = await import('./types-BWpRU1VN.mjs').then(function (n) { return n.a0; });
10683
10740
  let userEmail = void 0;
10684
10741
  try {
10685
10742
  const credentials = await readCredentials2();
@@ -10710,7 +10767,7 @@ async function spawnAndWaitForDaemon() {
10710
10767
  }
10711
10768
  if (geminiSubcommand === "project" && args[2] === "get") {
10712
10769
  try {
10713
- const { readGeminiLocalConfig } = await import('./config-DPn-cbpz.mjs');
10770
+ const { readGeminiLocalConfig } = await import('./config-_GW4YBCP.mjs');
10714
10771
  const config = readGeminiLocalConfig();
10715
10772
  if (config.googleCloudProject) {
10716
10773
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -10750,7 +10807,7 @@ async function spawnAndWaitForDaemon() {
10750
10807
  process.exit(0);
10751
10808
  }
10752
10809
  try {
10753
- const { runGemini } = await import('./runGemini-37HHbp9n.mjs');
10810
+ const { runGemini } = await import('./runGemini-BeqrVq8R.mjs');
10754
10811
  let startedBy = void 0;
10755
10812
  for (let i = 1; i < args.length; i++) {
10756
10813
  if (args[i] === "--started-by") {
@@ -10887,7 +10944,7 @@ async function spawnAndWaitForDaemon() {
10887
10944
  process.exit(1);
10888
10945
  }
10889
10946
  try {
10890
- const { runMcpServe } = await import('./serve-BRedJPzL.mjs');
10947
+ const { runMcpServe } = await import('./serve-BNdoEDVx.mjs');
10891
10948
  await runMcpServe();
10892
10949
  } catch (error) {
10893
10950
  process.stderr.write(`[happy-mcp] fatal: ${error instanceof Error ? error.message : "unknown error"}
@@ -10901,8 +10958,15 @@ async function spawnAndWaitForDaemon() {
10901
10958
  console.error(chalk.red("Error:"), 'Not authenticated. Run "happy auth" first.');
10902
10959
  process.exit(1);
10903
10960
  }
10904
- const target = args[1];
10961
+ const { target, command, timeoutMs } = parseSshArgs(args.slice(1));
10905
10962
  try {
10963
+ if (command) {
10964
+ if (!target) {
10965
+ console.error(chalk.red("Error:"), "Which device? Usage: happy ssh <device> -- <command>");
10966
+ process.exit(1);
10967
+ }
10968
+ process.exit(await runOnDevice(credentials, target, command, { timeoutMs }));
10969
+ }
10906
10970
  if (!target) {
10907
10971
  process.exit(await sshPickAndConnect(credentials));
10908
10972
  }
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./types-BrTorNAy.cjs');
5
- require('./index-BlkHOkB3.cjs');
4
+ require('./types-DvTsFaqR.cjs');
5
+ require('./index-BbCDDvoB.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('axios');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './types-DYCJXXdA.mjs';
3
- import './index-DJ2VpGiR.mjs';
2
+ import './types-BWpRU1VN.mjs';
3
+ import './index-vvZXdswy.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'axios';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./types-BrTorNAy.cjs');
3
+ var persistence = require('./types-DvTsFaqR.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');
package/dist/lib.d.cts CHANGED
@@ -321,53 +321,53 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
321
321
  createdAt: z.ZodNumber;
322
322
  updatedAt: z.ZodNumber;
323
323
  }, "strip", z.ZodTypeAny, {
324
+ id: string;
325
+ seq: number;
324
326
  content: {
325
327
  c: string;
326
328
  t: "encrypted";
327
329
  };
328
- id: string;
329
- seq: number;
330
330
  createdAt: number;
331
331
  updatedAt: number;
332
332
  localId?: string | null | undefined;
333
333
  }, {
334
+ id: string;
335
+ seq: number;
334
336
  content: {
335
337
  c: string;
336
338
  t: "encrypted";
337
339
  };
338
- id: string;
339
- seq: number;
340
340
  createdAt: number;
341
341
  updatedAt: number;
342
342
  localId?: string | null | undefined;
343
343
  }>;
344
344
  }, "strip", z.ZodTypeAny, {
345
+ t: "new-message";
345
346
  message: {
347
+ id: string;
348
+ seq: number;
346
349
  content: {
347
350
  c: string;
348
351
  t: "encrypted";
349
352
  };
350
- id: string;
351
- seq: number;
352
353
  createdAt: number;
353
354
  updatedAt: number;
354
355
  localId?: string | null | undefined;
355
356
  };
356
- t: "new-message";
357
357
  sid: string;
358
358
  }, {
359
+ t: "new-message";
359
360
  message: {
361
+ id: string;
362
+ seq: number;
360
363
  content: {
361
364
  c: string;
362
365
  t: "encrypted";
363
366
  };
364
- id: string;
365
- seq: number;
366
367
  createdAt: number;
367
368
  updatedAt: number;
368
369
  localId?: string | null | undefined;
369
370
  };
370
- t: "new-message";
371
371
  sid: string;
372
372
  }>, z.ZodObject<{
373
373
  t: z.ZodLiteral<"update-session">;
@@ -472,18 +472,18 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
472
472
  seq: number;
473
473
  createdAt: number;
474
474
  body: {
475
+ t: "new-message";
475
476
  message: {
477
+ id: string;
478
+ seq: number;
476
479
  content: {
477
480
  c: string;
478
481
  t: "encrypted";
479
482
  };
480
- id: string;
481
- seq: number;
482
483
  createdAt: number;
483
484
  updatedAt: number;
484
485
  localId?: string | null | undefined;
485
486
  };
486
- t: "new-message";
487
487
  sid: string;
488
488
  } | {
489
489
  t: "update-session";
@@ -515,18 +515,18 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
515
515
  seq: number;
516
516
  createdAt: number;
517
517
  body: {
518
+ t: "new-message";
518
519
  message: {
520
+ id: string;
521
+ seq: number;
519
522
  content: {
520
523
  c: string;
521
524
  t: "encrypted";
522
525
  };
523
- id: string;
524
- seq: number;
525
526
  createdAt: number;
526
527
  updatedAt: number;
527
528
  localId?: string | null | undefined;
528
529
  };
529
- t: "new-message";
530
530
  sid: string;
531
531
  } | {
532
532
  t: "update-session";
package/dist/lib.d.mts CHANGED
@@ -321,53 +321,53 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
321
321
  createdAt: z.ZodNumber;
322
322
  updatedAt: z.ZodNumber;
323
323
  }, "strip", z.ZodTypeAny, {
324
+ id: string;
325
+ seq: number;
324
326
  content: {
325
327
  c: string;
326
328
  t: "encrypted";
327
329
  };
328
- id: string;
329
- seq: number;
330
330
  createdAt: number;
331
331
  updatedAt: number;
332
332
  localId?: string | null | undefined;
333
333
  }, {
334
+ id: string;
335
+ seq: number;
334
336
  content: {
335
337
  c: string;
336
338
  t: "encrypted";
337
339
  };
338
- id: string;
339
- seq: number;
340
340
  createdAt: number;
341
341
  updatedAt: number;
342
342
  localId?: string | null | undefined;
343
343
  }>;
344
344
  }, "strip", z.ZodTypeAny, {
345
+ t: "new-message";
345
346
  message: {
347
+ id: string;
348
+ seq: number;
346
349
  content: {
347
350
  c: string;
348
351
  t: "encrypted";
349
352
  };
350
- id: string;
351
- seq: number;
352
353
  createdAt: number;
353
354
  updatedAt: number;
354
355
  localId?: string | null | undefined;
355
356
  };
356
- t: "new-message";
357
357
  sid: string;
358
358
  }, {
359
+ t: "new-message";
359
360
  message: {
361
+ id: string;
362
+ seq: number;
360
363
  content: {
361
364
  c: string;
362
365
  t: "encrypted";
363
366
  };
364
- id: string;
365
- seq: number;
366
367
  createdAt: number;
367
368
  updatedAt: number;
368
369
  localId?: string | null | undefined;
369
370
  };
370
- t: "new-message";
371
371
  sid: string;
372
372
  }>, z.ZodObject<{
373
373
  t: z.ZodLiteral<"update-session">;
@@ -472,18 +472,18 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
472
472
  seq: number;
473
473
  createdAt: number;
474
474
  body: {
475
+ t: "new-message";
475
476
  message: {
477
+ id: string;
478
+ seq: number;
476
479
  content: {
477
480
  c: string;
478
481
  t: "encrypted";
479
482
  };
480
- id: string;
481
- seq: number;
482
483
  createdAt: number;
483
484
  updatedAt: number;
484
485
  localId?: string | null | undefined;
485
486
  };
486
- t: "new-message";
487
487
  sid: string;
488
488
  } | {
489
489
  t: "update-session";
@@ -515,18 +515,18 @@ declare const CoreUpdateContainerSchema: z.ZodObject<{
515
515
  seq: number;
516
516
  createdAt: number;
517
517
  body: {
518
+ t: "new-message";
518
519
  message: {
520
+ id: string;
521
+ seq: number;
519
522
  content: {
520
523
  c: string;
521
524
  t: "encrypted";
522
525
  };
523
- id: string;
524
- seq: number;
525
526
  createdAt: number;
526
527
  updatedAt: number;
527
528
  localId?: string | null | undefined;
528
529
  };
529
- t: "new-message";
530
530
  sid: string;
531
531
  } | {
532
532
  t: "update-session";
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-DYCJXXdA.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-BWpRU1VN.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'fs';
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./types-BrTorNAy.cjs');
3
+ var persistence = require('./types-DvTsFaqR.cjs');
4
4
  var node_crypto = require('node:crypto');
5
5
  var fs = require('node:fs');
6
6
  var os = require('node:os');
7
7
  var path = require('node:path');
8
- var index = require('./index-BlkHOkB3.cjs');
8
+ var index = require('./index-BbCDDvoB.cjs');
9
9
 
10
10
  class BasePermissionHandler {
11
11
  pendingRequests = /* @__PURE__ */ new Map();
@@ -1,9 +1,9 @@
1
- import { l as logger, h as resolveToolsDir, j as projectPath, c as configuration, k as packageJson, s as startOfflineReconnection, m as saveToolOutputRecord } from './types-DYCJXXdA.mjs';
1
+ import { l as logger, h as resolveToolsDir, j as projectPath, c as configuration, k as packageJson, s as startOfflineReconnection, m as saveToolOutputRecord } from './types-BWpRU1VN.mjs';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { readFileSync, existsSync, readdirSync } from 'node:fs';
4
4
  import os, { homedir } from 'node:os';
5
5
  import { join, basename, dirname } from 'node:path';
6
- import { e as detectGitWorktree } from './index-DJ2VpGiR.mjs';
6
+ import { e as detectGitWorktree } from './index-vvZXdswy.mjs';
7
7
 
8
8
  class BasePermissionHandler {
9
9
  pendingRequests = /* @__PURE__ */ new Map();
@@ -1,11 +1,11 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
- import { l as logger, n as saveDiffRecords, o as isDebug, q as extractUserText, t as isSystemMessage, u as generateStableUuid, v as findCodexSessionFile, w as connectionState, A as ApiClient, x as readSettings } from './types-DYCJXXdA.mjs';
3
+ import { l as logger, n as saveDiffRecords, o as isDebug, q as extractUserText, t as isSystemMessage, u as generateStableUuid, v as findCodexSessionFile, w as connectionState, A as ApiClient, x as readSettings } from './types-BWpRU1VN.mjs';
4
4
  import { spawn, execSync } from 'node:child_process';
5
5
  import { createInterface } from 'node:readline';
6
- import { B as BasePermissionHandler, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection, h as handleConfigMetadataEvent, b as summarizeBashToolOutput } from './loadableToolOutput-lQH8Kb_w.mjs';
6
+ import { B as BasePermissionHandler, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection, h as handleConfigMetadataEvent, b as summarizeBashToolOutput } from './loadableToolOutput-va3RLplh.mjs';
7
7
  import { randomUUID } from 'node:crypto';
8
- import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, g as createMcpContext, j as registerKillSessionHandler, k as MessageBuffer, p as parseClear, l as downloadImage, m as stopCaffeinate } from './index-DJ2VpGiR.mjs';
8
+ import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, g as createMcpContext, j as registerKillSessionHandler, k as MessageBuffer, p as parseClear, l as downloadImage, m as stopCaffeinate } from './index-vvZXdswy.mjs';
9
9
  import { g as getFirstTurnInstruction } from './constants-BO9OAFOT.mjs';
10
10
  import { inspect } from 'node:util';
11
11
  import { readFile } from 'node:fs/promises';
@@ -2,12 +2,12 @@
2
2
 
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
- var persistence = require('./types-BrTorNAy.cjs');
5
+ var persistence = require('./types-DvTsFaqR.cjs');
6
6
  var node_child_process = require('node:child_process');
7
7
  var node_readline = require('node:readline');
8
- var loadableToolOutput = require('./loadableToolOutput-CasonFIt.cjs');
8
+ var loadableToolOutput = require('./loadableToolOutput-5vdQB98M.cjs');
9
9
  var node_crypto = require('node:crypto');
10
- var index = require('./index-BlkHOkB3.cjs');
10
+ var index = require('./index-BbCDDvoB.cjs');
11
11
  var constants = require('./constants-B4x1K7by.cjs');
12
12
  var node_util = require('node:util');
13
13
  var promises = require('node:fs/promises');
@@ -1,13 +1,13 @@
1
1
  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
- import { l as logger, G as GEMINI_MODEL_MODES, k as packageJson, y as delay, o as isDebug, n as saveDiffRecords, z as readGeminiSessionLog, w as connectionState, A as ApiClient, x as readSettings, B as GeminiSessionWriter, C as buildResumeContextFromSessionLog } from './types-DYCJXXdA.mjs';
5
- import { d as handleAgentMessageChunk, e as handleToolCallUpdate, f as handleAgentThoughtChunk, g as handleToolCall, i as handleLegacyMessageChunk, j as handlePlanUpdate, k as handleThinkingUpdate, B as BasePermissionHandler, a as BaseReasoningProcessor, b as summarizeBashToolOutput, c as createSessionMetadata, s as setupOfflineReconnection, h as handleConfigMetadataEvent } from './loadableToolOutput-lQH8Kb_w.mjs';
6
- import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, k as MessageBuffer, j as registerKillSessionHandler, g as createMcpContext, p as parseClear, o as formatMessageForGemini, m as stopCaffeinate } from './index-DJ2VpGiR.mjs';
4
+ import { l as logger, G as GEMINI_MODEL_MODES, k as packageJson, y as delay, o as isDebug, n as saveDiffRecords, z as readGeminiSessionLog, w as connectionState, A as ApiClient, x as readSettings, B as GeminiSessionWriter, C as buildResumeContextFromSessionLog } from './types-BWpRU1VN.mjs';
5
+ import { d as handleAgentMessageChunk, e as handleToolCallUpdate, f as handleAgentThoughtChunk, g as handleToolCall, i as handleLegacyMessageChunk, j as handlePlanUpdate, k as handleThinkingUpdate, B as BasePermissionHandler, a as BaseReasoningProcessor, b as summarizeBashToolOutput, c as createSessionMetadata, s as setupOfflineReconnection, h as handleConfigMetadataEvent } from './loadableToolOutput-va3RLplh.mjs';
6
+ import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, k as MessageBuffer, j as registerKillSessionHandler, g as createMcpContext, p as parseClear, o as formatMessageForGemini, m as stopCaffeinate } from './index-vvZXdswy.mjs';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
9
9
  import { a as GEMINI_API_KEY_ENV, b as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, g as getFirstTurnInstruction } from './constants-BO9OAFOT.mjs';
10
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DPn-cbpz.mjs';
10
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-_GW4YBCP.mjs';
11
11
  import 'axios';
12
12
  import 'chalk';
13
13
  import 'fs';
@@ -3,13 +3,13 @@
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
5
  var node_crypto = require('node:crypto');
6
- var persistence = require('./types-BrTorNAy.cjs');
7
- var loadableToolOutput = require('./loadableToolOutput-CasonFIt.cjs');
8
- var index = require('./index-BlkHOkB3.cjs');
6
+ var persistence = require('./types-DvTsFaqR.cjs');
7
+ var loadableToolOutput = require('./loadableToolOutput-5vdQB98M.cjs');
8
+ var index = require('./index-BbCDDvoB.cjs');
9
9
  var node_child_process = require('node:child_process');
10
10
  var sdk = require('@agentclientprotocol/sdk');
11
11
  var constants = require('./constants-B4x1K7by.cjs');
12
- var config = require('./config-D_g6ohaV.cjs');
12
+ var config = require('./config-0Xnc8ARM.cjs');
13
13
  require('axios');
14
14
  require('chalk');
15
15
  require('fs');
@@ -2,8 +2,8 @@
2
2
 
3
3
  var node_child_process = require('node:child_process');
4
4
  var fs = require('node:fs');
5
- var index = require('./index-BlkHOkB3.cjs');
6
- var persistence = require('./types-BrTorNAy.cjs');
5
+ var index = require('./index-BbCDDvoB.cjs');
6
+ var persistence = require('./types-DvTsFaqR.cjs');
7
7
  var mcpToolSchemas = require('./mcpToolSchemas-f-kttjFw.cjs');
8
8
  require('chalk');
9
9
  require('node:os');
@@ -1,7 +1,7 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { existsSync } from 'node:fs';
3
- import { c as claudeCliPath } from './index-DJ2VpGiR.mjs';
4
- import { l as logger, i as isModelModeForAgent, M as MODEL_MODE_DEFAULT, p as parseCodexModelMode, b as parseClaudeModelMode } from './types-DYCJXXdA.mjs';
3
+ import { c as claudeCliPath } from './index-vvZXdswy.mjs';
4
+ import { l as logger, i as isModelModeForAgent, M as MODEL_MODE_DEFAULT, p as parseCodexModelMode, b as parseClaudeModelMode } from './types-BWpRU1VN.mjs';
5
5
  import { i as isOrchestratorProvider, O as ORCHESTRATOR_ENV_KEYS, d as decodePromptFromBase64 } from './mcpToolSchemas-CdPXJQmb.mjs';
6
6
  import 'chalk';
7
7
  import 'node:os';
@@ -2,8 +2,8 @@
2
2
 
3
3
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
4
4
  var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
5
- var persistence = require('./types-BrTorNAy.cjs');
6
- var index = require('./index-BlkHOkB3.cjs');
5
+ var persistence = require('./types-DvTsFaqR.cjs');
6
+ var index = require('./index-BbCDDvoB.cjs');
7
7
  var axios = require('axios');
8
8
  var z = require('zod');
9
9
  var node_crypto = require('node:crypto');
@@ -1,7 +1,7 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { c as configuration, e as encodeBase64, d as encrypt, f as decodeBase64, g as decrypt, r as readCredentials } from './types-DYCJXXdA.mjs';
4
- import { f as fetchSessionById, d as decryptMessage, s as sessionListInputSchema, a as sessionSummaryInputSchema, r as runSessionList, b as runSessionSummary } from './index-DJ2VpGiR.mjs';
3
+ import { c as configuration, e as encodeBase64, d as encrypt, f as decodeBase64, g as decrypt, r as readCredentials } from './types-BWpRU1VN.mjs';
4
+ import { f as fetchSessionById, d as decryptMessage, s as sessionListInputSchema, a as sessionSummaryInputSchema, r as runSessionList, b as runSessionSummary } from './index-vvZXdswy.mjs';
5
5
  import axios from 'axios';
6
6
  import { z } from 'zod';
7
7
  import { randomUUID } from 'node:crypto';
@@ -32,7 +32,7 @@ function isDebug() {
32
32
  }
33
33
 
34
34
  var name = "@zonease/happy";
35
- var version = "0.6.37";
35
+ var version = "0.6.38";
36
36
  var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
37
37
  var author = "ZonEaseTech";
38
38
  var license = "MIT";
@@ -53,7 +53,7 @@ function isDebug() {
53
53
  }
54
54
 
55
55
  var name = "@zonease/happy";
56
- var version = "0.6.37";
56
+ var version = "0.6.38";
57
57
  var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
58
58
  var author = "ZonEaseTech";
59
59
  var license = "MIT";
@@ -2500,7 +2500,7 @@ No git repository was found from session cwd or workspace repo metadata. Session
2500
2500
  };
2501
2501
  }
2502
2502
 
2503
- const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-BrTorNAy.cjs', document.baseURI).href))));
2503
+ const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-DvTsFaqR.cjs', document.baseURI).href))));
2504
2504
  function projectPath() {
2505
2505
  const path = path$1.resolve(__dirname$1, "..");
2506
2506
  return path;
@@ -2551,7 +2551,7 @@ function resolveToolsDir() {
2551
2551
  }
2552
2552
  function findToolsDir() {
2553
2553
  try {
2554
- const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-BrTorNAy.cjs', document.baseURI).href))).resolve(`${toolsPackageName()}/package.json`);
2554
+ const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-DvTsFaqR.cjs', document.baseURI).href))).resolve(`${toolsPackageName()}/package.json`);
2555
2555
  return path.dirname(manifest);
2556
2556
  } catch {
2557
2557
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zonease/happy",
3
- "version": "0.6.37",
3
+ "version": "0.6.38",
4
4
  "description": "Mobile and Web client for Claude Code, Codex, and Gemini",
5
5
  "author": "ZonEaseTech",
6
6
  "license": "MIT",