@zhigang1992/happy-cli 0.12.5 → 0.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/dist/codex/happyMcpStdioBridge.cjs +2 -5
- package/dist/codex/happyMcpStdioBridge.mjs +2 -5
- package/dist/{index-B8KwpPnt.cjs → index-DvMFDzz3.cjs} +14 -11
- package/dist/{index-BfGA--2C.mjs → index-iFxcl7Hn.mjs} +21 -18
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +5 -0
- package/dist/lib.d.mts +5 -0
- package/dist/lib.mjs +1 -1
- package/dist/{list-B0EZS1nk.mjs → list-DqbAuRvF.mjs} +1 -1
- package/dist/{list-BmyKI4UO.cjs → list-sCcVgML_.cjs} +1 -1
- package/dist/{prompt-SOUeW7vB.cjs → prompt-DQyb25aY.cjs} +1 -1
- package/dist/{prompt-COmkBtjd.mjs → prompt-DwjhpAf5.mjs} +1 -1
- package/dist/{runCodex-CLxMptoC.cjs → runCodex-B33w9tjC.cjs} +35 -6
- package/dist/{runCodex-Cxhf8ktE.mjs → runCodex-BeLLGX3X.mjs} +35 -6
- package/dist/{types-BmcSXhbq.mjs → types-BQ_WM2tI.mjs} +23 -15
- package/dist/{types-0ILrOpLt.cjs → types-DU-KcuRq.cjs} +18 -10
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# Happy CLI (Fork)
|
|
2
|
+
|
|
3
|
+
> **This is a personal fork of [happy-cli](https://github.com/slopus/happy-cli) from the amazing [Happy](https://happy.engineering) project.**
|
|
4
|
+
>
|
|
5
|
+
> All credit goes to the original authors. I've made some tweaks for my own self-hosted setup, but my changes are too scattered and experimental to submit upstream. If you're looking for the official version, please visit [github.com/slopus/happy-cli](https://github.com/slopus/happy-cli).
|
|
6
|
+
|
|
7
|
+
## Fork Changes
|
|
8
|
+
|
|
9
|
+
- Renamed package to `@zhigang1992/happy-cli` for personal npm publishing
|
|
10
|
+
- Changed default server URLs to `happy-server.reily.app` and `happy.reily.app`
|
|
11
|
+
- Switched from yarn to bun
|
|
12
|
+
- Lazy download of tools to reduce package size (~110MB to ~186KB)
|
|
13
|
+
- Added image attachment support in messages
|
|
14
|
+
- Improved push notifications with folder name
|
|
15
|
+
- Various bug fixes and improvements
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
1
19
|
# Happy
|
|
2
20
|
|
|
3
21
|
Code on the go controlling claude code from your mobile device.
|
|
@@ -41,8 +59,8 @@ This will:
|
|
|
41
59
|
|
|
42
60
|
## Environment Variables
|
|
43
61
|
|
|
44
|
-
- `HAPPY_SERVER_URL` - Custom server URL (default: https://
|
|
45
|
-
- `HAPPY_WEBAPP_URL` - Custom web app URL (default: https://
|
|
62
|
+
- `HAPPY_SERVER_URL` - Custom server URL (default: https://happy-server.reily.app)
|
|
63
|
+
- `HAPPY_WEBAPP_URL` - Custom web app URL (default: https://happy.reily.app)
|
|
46
64
|
- `HAPPY_HOME_DIR` - Custom home directory for Happy data (default: ~/.happy)
|
|
47
65
|
- `HAPPY_DISABLE_CAFFEINATE` - Disable macOS sleep prevention (set to `true`, `1`, or `yes`)
|
|
48
66
|
- `HAPPY_EXPERIMENTAL` - Enable experimental features (set to `true`, `1`, or `yes`)
|
|
@@ -29,10 +29,7 @@ async function main() {
|
|
|
29
29
|
let httpClient = null;
|
|
30
30
|
async function ensureHttpClient() {
|
|
31
31
|
if (httpClient) return httpClient;
|
|
32
|
-
const client = new index_js.Client(
|
|
33
|
-
{ name: "happy-stdio-bridge", version: "1.0.0" },
|
|
34
|
-
{ capabilities: { tools: {} } }
|
|
35
|
-
);
|
|
32
|
+
const client = new index_js.Client({ name: "happy-stdio-bridge", version: "1.0.0" });
|
|
36
33
|
const transport = new streamableHttp_js.StreamableHTTPClientTransport(new URL(baseUrl));
|
|
37
34
|
await client.connect(transport);
|
|
38
35
|
httpClient = client;
|
|
@@ -41,7 +38,7 @@ async function main() {
|
|
|
41
38
|
const server = new mcp_js.McpServer({
|
|
42
39
|
name: "Happy MCP Bridge",
|
|
43
40
|
version: "1.0.0",
|
|
44
|
-
|
|
41
|
+
title: "STDIO bridge forwarding to Happy HTTP MCP"
|
|
45
42
|
});
|
|
46
43
|
server.registerTool(
|
|
47
44
|
"change_title",
|
|
@@ -27,10 +27,7 @@ async function main() {
|
|
|
27
27
|
let httpClient = null;
|
|
28
28
|
async function ensureHttpClient() {
|
|
29
29
|
if (httpClient) return httpClient;
|
|
30
|
-
const client = new Client(
|
|
31
|
-
{ name: "happy-stdio-bridge", version: "1.0.0" },
|
|
32
|
-
{ capabilities: { tools: {} } }
|
|
33
|
-
);
|
|
30
|
+
const client = new Client({ name: "happy-stdio-bridge", version: "1.0.0" });
|
|
34
31
|
const transport = new StreamableHTTPClientTransport(new URL(baseUrl));
|
|
35
32
|
await client.connect(transport);
|
|
36
33
|
httpClient = client;
|
|
@@ -39,7 +36,7 @@ async function main() {
|
|
|
39
36
|
const server = new McpServer({
|
|
40
37
|
name: "Happy MCP Bridge",
|
|
41
38
|
version: "1.0.0",
|
|
42
|
-
|
|
39
|
+
title: "STDIO bridge forwarding to Happy HTTP MCP"
|
|
43
40
|
});
|
|
44
41
|
server.registerTool(
|
|
45
42
|
"change_title",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var types = require('./types-
|
|
6
|
+
var types = require('./types-DU-KcuRq.cjs');
|
|
7
7
|
var node_child_process = require('node:child_process');
|
|
8
8
|
var node_path = require('node:path');
|
|
9
9
|
var node_readline = require('node:readline');
|
|
@@ -22,10 +22,10 @@ require('node:events');
|
|
|
22
22
|
require('socket.io-client');
|
|
23
23
|
var tweetnacl = require('tweetnacl');
|
|
24
24
|
require('expo-server-sdk');
|
|
25
|
+
var os$1 = require('os');
|
|
25
26
|
var crypto = require('crypto');
|
|
26
27
|
var psList = require('ps-list');
|
|
27
28
|
var spawn = require('cross-spawn');
|
|
28
|
-
var os$1 = require('os');
|
|
29
29
|
var tmp = require('tmp');
|
|
30
30
|
var qrcode = require('qrcode-terminal');
|
|
31
31
|
var open = require('open');
|
|
@@ -56,6 +56,7 @@ function _interopNamespaceDefault(e) {
|
|
|
56
56
|
return Object.freeze(n);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os$1);
|
|
59
60
|
var tmp__namespace = /*#__PURE__*/_interopNamespaceDefault(tmp);
|
|
60
61
|
var hex__namespace = /*#__PURE__*/_interopNamespaceDefault(hex);
|
|
61
62
|
|
|
@@ -1082,7 +1083,7 @@ class AbortError extends Error {
|
|
|
1082
1083
|
}
|
|
1083
1084
|
}
|
|
1084
1085
|
|
|
1085
|
-
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-
|
|
1086
|
+
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-DvMFDzz3.cjs', document.baseURI).href)));
|
|
1086
1087
|
const __dirname$1 = node_path.join(__filename$1, "..");
|
|
1087
1088
|
function getDefaultClaudeCodePath() {
|
|
1088
1089
|
return node_path.join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
@@ -2984,10 +2985,12 @@ async function claudeRemoteLauncher(session) {
|
|
|
2984
2985
|
onReady: () => {
|
|
2985
2986
|
if (!pending && session.queue.size() === 0) {
|
|
2986
2987
|
session.client.sendSessionEvent({ type: "ready" });
|
|
2987
|
-
const
|
|
2988
|
+
const hostname = os__namespace.hostname();
|
|
2989
|
+
const notificationTitle = `(${hostname}) ${session.path}`;
|
|
2990
|
+
const sessionName = session.client.getSummary() || path.basename(session.path);
|
|
2988
2991
|
session.api.push().sendToAllDevices(
|
|
2989
|
-
|
|
2990
|
-
|
|
2992
|
+
notificationTitle,
|
|
2993
|
+
sessionName,
|
|
2991
2994
|
{ sessionId: session.client.sessionId }
|
|
2992
2995
|
);
|
|
2993
2996
|
}
|
|
@@ -4902,7 +4905,7 @@ async function startHappyServer(client) {
|
|
|
4902
4905
|
const mcp = new mcp_js.McpServer({
|
|
4903
4906
|
name: "Happy MCP",
|
|
4904
4907
|
version: "1.0.0",
|
|
4905
|
-
|
|
4908
|
+
title: "Happy CLI MCP Server"
|
|
4906
4909
|
});
|
|
4907
4910
|
mcp.registerTool("change_title", {
|
|
4908
4911
|
description: "Change the title of the current chat session",
|
|
@@ -6315,7 +6318,7 @@ ${chalk.bold("Examples:")}
|
|
|
6315
6318
|
${chalk.bold("Notes:")}
|
|
6316
6319
|
\u2022 You must be authenticated with Happy first (run 'happy auth login')
|
|
6317
6320
|
\u2022 API keys are encrypted and stored securely in Happy cloud
|
|
6318
|
-
\u2022 You can manage your stored keys at
|
|
6321
|
+
\u2022 You can manage your stored keys at happy.reily.app
|
|
6319
6322
|
`);
|
|
6320
6323
|
}
|
|
6321
6324
|
async function handleConnectVendor(vendor, displayName) {
|
|
@@ -6393,7 +6396,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6393
6396
|
return;
|
|
6394
6397
|
} else if (subcommand === "codex") {
|
|
6395
6398
|
try {
|
|
6396
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
6399
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-B33w9tjC.cjs'); });
|
|
6397
6400
|
let startedBy = void 0;
|
|
6398
6401
|
for (let i = 1; i < args.length; i++) {
|
|
6399
6402
|
if (args[i] === "--started-by") {
|
|
@@ -6438,7 +6441,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6438
6441
|
} else if (subcommand === "list") {
|
|
6439
6442
|
try {
|
|
6440
6443
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6441
|
-
const { listSessions } = await Promise.resolve().then(function () { return require('./list-
|
|
6444
|
+
const { listSessions } = await Promise.resolve().then(function () { return require('./list-sCcVgML_.cjs'); });
|
|
6442
6445
|
let sessionId;
|
|
6443
6446
|
let titleFilter;
|
|
6444
6447
|
let recentMsgs;
|
|
@@ -6540,7 +6543,7 @@ Examples:
|
|
|
6540
6543
|
process.exit(1);
|
|
6541
6544
|
}
|
|
6542
6545
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6543
|
-
const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-
|
|
6546
|
+
const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-DQyb25aY.cjs'); });
|
|
6544
6547
|
await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
|
|
6545
6548
|
} catch (error) {
|
|
6546
6549
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import os$1, { homedir } from 'node:os';
|
|
3
3
|
import { randomUUID, randomBytes, createHmac } from 'node:crypto';
|
|
4
|
-
import { l as logger, p as projectPath, j as backoff, k as delay, R as RawJSONLinesSchema, m as AsyncLock, c as configuration, n as readDaemonState, o as clearDaemonState, i as packageJson, r as readSettings, q as readCredentials, g as encodeBase64, u as updateSettings, s as encodeBase64Url, d as decodeBase64, w as writeCredentialsLegacy, t as writeCredentialsDataKey, v as acquireDaemonLock, x as writeDaemonState, A as ApiClient, y as releaseDaemonLock, z as authChallenge, B as clearCredentials, C as clearMachineId, D as getLatestDaemonLog } from './types-
|
|
4
|
+
import { l as logger, p as projectPath, j as backoff, k as delay, R as RawJSONLinesSchema, m as AsyncLock, c as configuration, n as readDaemonState, o as clearDaemonState, i as packageJson, r as readSettings, q as readCredentials, g as encodeBase64, u as updateSettings, s as encodeBase64Url, d as decodeBase64, w as writeCredentialsLegacy, t as writeCredentialsDataKey, v as acquireDaemonLock, x as writeDaemonState, A as ApiClient, y as releaseDaemonLock, z as authChallenge, B as clearCredentials, C as clearMachineId, D as getLatestDaemonLog } from './types-BQ_WM2tI.mjs';
|
|
5
5
|
import { spawn, execSync, execFileSync } from 'node:child_process';
|
|
6
6
|
import { resolve, join } from 'node:path';
|
|
7
7
|
import { createInterface } from 'node:readline';
|
|
@@ -20,10 +20,11 @@ import 'node:events';
|
|
|
20
20
|
import 'socket.io-client';
|
|
21
21
|
import tweetnacl from 'tweetnacl';
|
|
22
22
|
import 'expo-server-sdk';
|
|
23
|
+
import * as os from 'os';
|
|
24
|
+
import os__default from 'os';
|
|
23
25
|
import { createHash, randomBytes as randomBytes$1 } from 'crypto';
|
|
24
26
|
import psList from 'ps-list';
|
|
25
27
|
import spawn$2 from 'cross-spawn';
|
|
26
|
-
import os from 'os';
|
|
27
28
|
import * as tmp from 'tmp';
|
|
28
29
|
import qrcode from 'qrcode-terminal';
|
|
29
30
|
import open from 'open';
|
|
@@ -1059,10 +1060,10 @@ class AbortError extends Error {
|
|
|
1059
1060
|
}
|
|
1060
1061
|
}
|
|
1061
1062
|
|
|
1062
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1063
|
-
const __dirname = join(__filename, "..");
|
|
1063
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
1064
|
+
const __dirname$1 = join(__filename$1, "..");
|
|
1064
1065
|
function getDefaultClaudeCodePath() {
|
|
1065
|
-
return join(__dirname, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
1066
|
+
return join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
1066
1067
|
}
|
|
1067
1068
|
function logDebug(message) {
|
|
1068
1069
|
if (process.env.DEBUG) {
|
|
@@ -2961,10 +2962,12 @@ async function claudeRemoteLauncher(session) {
|
|
|
2961
2962
|
onReady: () => {
|
|
2962
2963
|
if (!pending && session.queue.size() === 0) {
|
|
2963
2964
|
session.client.sendSessionEvent({ type: "ready" });
|
|
2964
|
-
const
|
|
2965
|
+
const hostname = os.hostname();
|
|
2966
|
+
const notificationTitle = `(${hostname}) ${session.path}`;
|
|
2967
|
+
const sessionName = session.client.getSummary() || basename(session.path);
|
|
2965
2968
|
session.api.push().sendToAllDevices(
|
|
2966
|
-
|
|
2967
|
-
|
|
2969
|
+
notificationTitle,
|
|
2970
|
+
sessionName,
|
|
2968
2971
|
{ sessionId: session.client.sessionId }
|
|
2969
2972
|
);
|
|
2970
2973
|
}
|
|
@@ -4468,10 +4471,10 @@ function startDaemonControlServer({
|
|
|
4468
4471
|
}
|
|
4469
4472
|
|
|
4470
4473
|
const initialMachineMetadata = {
|
|
4471
|
-
host:
|
|
4472
|
-
platform:
|
|
4474
|
+
host: os__default.hostname(),
|
|
4475
|
+
platform: os__default.platform(),
|
|
4473
4476
|
happyCliVersion: packageJson.version,
|
|
4474
|
-
homeDir:
|
|
4477
|
+
homeDir: os__default.homedir(),
|
|
4475
4478
|
happyHomeDir: configuration.happyHomeDir,
|
|
4476
4479
|
happyLibDir: projectPath()
|
|
4477
4480
|
};
|
|
@@ -4879,7 +4882,7 @@ async function startHappyServer(client) {
|
|
|
4879
4882
|
const mcp = new McpServer({
|
|
4880
4883
|
name: "Happy MCP",
|
|
4881
4884
|
version: "1.0.0",
|
|
4882
|
-
|
|
4885
|
+
title: "Happy CLI MCP Server"
|
|
4883
4886
|
});
|
|
4884
4887
|
mcp.registerTool("change_title", {
|
|
4885
4888
|
description: "Change the title of the current chat session",
|
|
@@ -5306,10 +5309,10 @@ async function install$1() {
|
|
|
5306
5309
|
<true/>
|
|
5307
5310
|
|
|
5308
5311
|
<key>StandardErrorPath</key>
|
|
5309
|
-
<string>${
|
|
5312
|
+
<string>${os__default.homedir()}/.happy/daemon.err</string>
|
|
5310
5313
|
|
|
5311
5314
|
<key>StandardOutPath</key>
|
|
5312
|
-
<string>${
|
|
5315
|
+
<string>${os__default.homedir()}/.happy/daemon.log</string>
|
|
5313
5316
|
|
|
5314
5317
|
<key>WorkingDirectory</key>
|
|
5315
5318
|
<string>/tmp</string>
|
|
@@ -6292,7 +6295,7 @@ ${chalk.bold("Examples:")}
|
|
|
6292
6295
|
${chalk.bold("Notes:")}
|
|
6293
6296
|
\u2022 You must be authenticated with Happy first (run 'happy auth login')
|
|
6294
6297
|
\u2022 API keys are encrypted and stored securely in Happy cloud
|
|
6295
|
-
\u2022 You can manage your stored keys at
|
|
6298
|
+
\u2022 You can manage your stored keys at happy.reily.app
|
|
6296
6299
|
`);
|
|
6297
6300
|
}
|
|
6298
6301
|
async function handleConnectVendor(vendor, displayName) {
|
|
@@ -6370,7 +6373,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6370
6373
|
return;
|
|
6371
6374
|
} else if (subcommand === "codex") {
|
|
6372
6375
|
try {
|
|
6373
|
-
const { runCodex } = await import('./runCodex-
|
|
6376
|
+
const { runCodex } = await import('./runCodex-BeLLGX3X.mjs');
|
|
6374
6377
|
let startedBy = void 0;
|
|
6375
6378
|
for (let i = 1; i < args.length; i++) {
|
|
6376
6379
|
if (args[i] === "--started-by") {
|
|
@@ -6415,7 +6418,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6415
6418
|
} else if (subcommand === "list") {
|
|
6416
6419
|
try {
|
|
6417
6420
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6418
|
-
const { listSessions } = await import('./list-
|
|
6421
|
+
const { listSessions } = await import('./list-DqbAuRvF.mjs');
|
|
6419
6422
|
let sessionId;
|
|
6420
6423
|
let titleFilter;
|
|
6421
6424
|
let recentMsgs;
|
|
@@ -6517,7 +6520,7 @@ Examples:
|
|
|
6517
6520
|
process.exit(1);
|
|
6518
6521
|
}
|
|
6519
6522
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6520
|
-
const { promptSession } = await import('./prompt-
|
|
6523
|
+
const { promptSession } = await import('./prompt-DwjhpAf5.mjs');
|
|
6521
6524
|
await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
|
|
6522
6525
|
} catch (error) {
|
|
6523
6526
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
require('chalk');
|
|
4
|
-
require('./index-
|
|
5
|
-
require('./types-
|
|
4
|
+
require('./index-DvMFDzz3.cjs');
|
|
5
|
+
require('./types-DU-KcuRq.cjs');
|
|
6
6
|
require('zod');
|
|
7
7
|
require('node:child_process');
|
|
8
8
|
require('node:os');
|
|
@@ -24,10 +24,10 @@ require('node:events');
|
|
|
24
24
|
require('socket.io-client');
|
|
25
25
|
require('tweetnacl');
|
|
26
26
|
require('expo-server-sdk');
|
|
27
|
+
require('os');
|
|
27
28
|
require('crypto');
|
|
28
29
|
require('ps-list');
|
|
29
30
|
require('cross-spawn');
|
|
30
|
-
require('os');
|
|
31
31
|
require('tmp');
|
|
32
32
|
require('qrcode-terminal');
|
|
33
33
|
require('open');
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'chalk';
|
|
2
|
-
import './index-
|
|
3
|
-
import './types-
|
|
2
|
+
import './index-iFxcl7Hn.mjs';
|
|
3
|
+
import './types-BQ_WM2tI.mjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import 'node:child_process';
|
|
6
6
|
import 'node:os';
|
|
@@ -22,10 +22,10 @@ import 'node:events';
|
|
|
22
22
|
import 'socket.io-client';
|
|
23
23
|
import 'tweetnacl';
|
|
24
24
|
import 'expo-server-sdk';
|
|
25
|
+
import 'os';
|
|
25
26
|
import 'crypto';
|
|
26
27
|
import 'ps-list';
|
|
27
28
|
import 'cross-spawn';
|
|
28
|
-
import 'os';
|
|
29
29
|
import 'tmp';
|
|
30
30
|
import 'qrcode-terminal';
|
|
31
31
|
import 'open';
|
package/dist/lib.cjs
CHANGED
package/dist/lib.d.cts
CHANGED
|
@@ -430,6 +430,11 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
430
430
|
* Send usage data to the server
|
|
431
431
|
*/
|
|
432
432
|
sendUsageData(usage: Usage): void;
|
|
433
|
+
/**
|
|
434
|
+
* Get the current session summary/title
|
|
435
|
+
* @returns The summary text or undefined if not set
|
|
436
|
+
*/
|
|
437
|
+
getSummary(): string | undefined;
|
|
433
438
|
/**
|
|
434
439
|
* Update session metadata
|
|
435
440
|
* @param handler - Handler function that returns the updated metadata
|
package/dist/lib.d.mts
CHANGED
|
@@ -430,6 +430,11 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
430
430
|
* Send usage data to the server
|
|
431
431
|
*/
|
|
432
432
|
sendUsageData(usage: Usage): void;
|
|
433
|
+
/**
|
|
434
|
+
* Get the current session summary/title
|
|
435
|
+
* @returns The summary text or undefined if not set
|
|
436
|
+
*/
|
|
437
|
+
getSummary(): string | undefined;
|
|
433
438
|
/**
|
|
434
439
|
* Update session metadata
|
|
435
440
|
* @param handler - Handler function that returns the updated metadata
|
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-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-BQ_WM2tI.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-
|
|
1
|
+
import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-BQ_WM2tI.mjs';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { existsSync, readdirSync, statSync, readFileSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-
|
|
1
|
+
import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-BQ_WM2tI.mjs';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { io } from 'socket.io-client';
|
|
4
4
|
import 'chalk';
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
5
|
+
var types = require('./types-DU-KcuRq.cjs');
|
|
6
6
|
var index_js = require('@modelcontextprotocol/sdk/client/index.js');
|
|
7
7
|
var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
8
8
|
var z = require('zod');
|
|
9
9
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
10
10
|
var child_process = require('child_process');
|
|
11
11
|
var node_crypto = require('node:crypto');
|
|
12
|
-
var index = require('./index-
|
|
12
|
+
var index = require('./index-DvMFDzz3.cjs');
|
|
13
13
|
var os = require('node:os');
|
|
14
14
|
var node_path = require('node:path');
|
|
15
15
|
var fs = require('node:fs');
|
|
16
|
+
var toml = require('@iarna/toml');
|
|
16
17
|
require('axios');
|
|
17
18
|
require('chalk');
|
|
18
19
|
require('fs');
|
|
@@ -29,9 +30,9 @@ require('expo-server-sdk');
|
|
|
29
30
|
require('node:child_process');
|
|
30
31
|
require('node:readline');
|
|
31
32
|
require('node:url');
|
|
33
|
+
require('os');
|
|
32
34
|
require('ps-list');
|
|
33
35
|
require('cross-spawn');
|
|
34
|
-
require('os');
|
|
35
36
|
require('tmp');
|
|
36
37
|
require('qrcode-terminal');
|
|
37
38
|
require('open');
|
|
@@ -76,7 +77,7 @@ class CodexMcpClient {
|
|
|
76
77
|
constructor() {
|
|
77
78
|
this.client = new index_js.Client(
|
|
78
79
|
{ name: "happy-codex-client", version: "1.0.0" },
|
|
79
|
-
{ capabilities: {
|
|
80
|
+
{ capabilities: { elicitation: {} } }
|
|
80
81
|
);
|
|
81
82
|
this.client.setNotificationHandler(z.z.object({
|
|
82
83
|
method: z.z.literal("codex/event"),
|
|
@@ -875,8 +876,10 @@ async function runCodex(opts) {
|
|
|
875
876
|
const sendReady = () => {
|
|
876
877
|
session.sendSessionEvent({ type: "ready" });
|
|
877
878
|
try {
|
|
879
|
+
const hostname = os.hostname();
|
|
880
|
+
const notificationTitle = `(${hostname}) ${process.cwd()}`;
|
|
878
881
|
api.push().sendToAllDevices(
|
|
879
|
-
|
|
882
|
+
notificationTitle,
|
|
880
883
|
"Codex is waiting for your command",
|
|
881
884
|
{ sessionId: session.sessionId }
|
|
882
885
|
);
|
|
@@ -1141,13 +1144,39 @@ async function runCodex(opts) {
|
|
|
1141
1144
|
}
|
|
1142
1145
|
}
|
|
1143
1146
|
});
|
|
1147
|
+
let existingMcpServers = {};
|
|
1148
|
+
try {
|
|
1149
|
+
const codexConfigPath = node_path.join(os.homedir(), ".codex", "config.toml");
|
|
1150
|
+
if (fs.existsSync(codexConfigPath)) {
|
|
1151
|
+
const configContents = fs.readFileSync(codexConfigPath, "utf8");
|
|
1152
|
+
const parsedConfig = toml.parse(configContents);
|
|
1153
|
+
const parsedServers = parsedConfig?.mcp_servers;
|
|
1154
|
+
if (parsedServers && typeof parsedServers === "object") {
|
|
1155
|
+
for (const [name, rawConfig] of Object.entries(parsedServers)) {
|
|
1156
|
+
if (!rawConfig || typeof rawConfig !== "object") {
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
const command = rawConfig.command;
|
|
1160
|
+
if (typeof command !== "string") {
|
|
1161
|
+
types.logger.debug(`[codex] Skipping MCP server "${name}" because command is missing`);
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
existingMcpServers[name] = rawConfig;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1170
|
+
types.logger.debug(`[codex] Error reading Codex config: ${message}`);
|
|
1171
|
+
}
|
|
1144
1172
|
const happyServer = await index.startHappyServer(session);
|
|
1145
1173
|
const bridgeCommand = node_path.join(types.projectPath(), "bin", "happy-mcp.mjs");
|
|
1146
1174
|
const mcpServers = {
|
|
1147
1175
|
happy: {
|
|
1148
1176
|
command: bridgeCommand,
|
|
1149
1177
|
args: ["--url", happyServer.url]
|
|
1150
|
-
}
|
|
1178
|
+
},
|
|
1179
|
+
...existingMcpServers
|
|
1151
1180
|
};
|
|
1152
1181
|
let first = true;
|
|
1153
1182
|
try {
|
|
@@ -1,16 +1,17 @@
|
|
|
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, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-
|
|
3
|
+
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-BQ_WM2tI.mjs';
|
|
4
4
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { execSync } from 'child_process';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
|
-
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-
|
|
10
|
+
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-iFxcl7Hn.mjs';
|
|
11
11
|
import os from 'node:os';
|
|
12
12
|
import { resolve, join } from 'node:path';
|
|
13
13
|
import fs from 'node:fs';
|
|
14
|
+
import { parse } from '@iarna/toml';
|
|
14
15
|
import 'axios';
|
|
15
16
|
import 'chalk';
|
|
16
17
|
import 'fs';
|
|
@@ -27,9 +28,9 @@ import 'expo-server-sdk';
|
|
|
27
28
|
import 'node:child_process';
|
|
28
29
|
import 'node:readline';
|
|
29
30
|
import 'node:url';
|
|
31
|
+
import 'os';
|
|
30
32
|
import 'ps-list';
|
|
31
33
|
import 'cross-spawn';
|
|
32
|
-
import 'os';
|
|
33
34
|
import 'tmp';
|
|
34
35
|
import 'qrcode-terminal';
|
|
35
36
|
import 'open';
|
|
@@ -74,7 +75,7 @@ class CodexMcpClient {
|
|
|
74
75
|
constructor() {
|
|
75
76
|
this.client = new Client(
|
|
76
77
|
{ name: "happy-codex-client", version: "1.0.0" },
|
|
77
|
-
{ capabilities: {
|
|
78
|
+
{ capabilities: { elicitation: {} } }
|
|
78
79
|
);
|
|
79
80
|
this.client.setNotificationHandler(z.object({
|
|
80
81
|
method: z.literal("codex/event"),
|
|
@@ -873,8 +874,10 @@ async function runCodex(opts) {
|
|
|
873
874
|
const sendReady = () => {
|
|
874
875
|
session.sendSessionEvent({ type: "ready" });
|
|
875
876
|
try {
|
|
877
|
+
const hostname = os.hostname();
|
|
878
|
+
const notificationTitle = `(${hostname}) ${process.cwd()}`;
|
|
876
879
|
api.push().sendToAllDevices(
|
|
877
|
-
|
|
880
|
+
notificationTitle,
|
|
878
881
|
"Codex is waiting for your command",
|
|
879
882
|
{ sessionId: session.sessionId }
|
|
880
883
|
);
|
|
@@ -1139,13 +1142,39 @@ async function runCodex(opts) {
|
|
|
1139
1142
|
}
|
|
1140
1143
|
}
|
|
1141
1144
|
});
|
|
1145
|
+
let existingMcpServers = {};
|
|
1146
|
+
try {
|
|
1147
|
+
const codexConfigPath = join(os.homedir(), ".codex", "config.toml");
|
|
1148
|
+
if (fs.existsSync(codexConfigPath)) {
|
|
1149
|
+
const configContents = fs.readFileSync(codexConfigPath, "utf8");
|
|
1150
|
+
const parsedConfig = parse(configContents);
|
|
1151
|
+
const parsedServers = parsedConfig?.mcp_servers;
|
|
1152
|
+
if (parsedServers && typeof parsedServers === "object") {
|
|
1153
|
+
for (const [name, rawConfig] of Object.entries(parsedServers)) {
|
|
1154
|
+
if (!rawConfig || typeof rawConfig !== "object") {
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
const command = rawConfig.command;
|
|
1158
|
+
if (typeof command !== "string") {
|
|
1159
|
+
logger.debug(`[codex] Skipping MCP server "${name}" because command is missing`);
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
existingMcpServers[name] = rawConfig;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
} catch (error) {
|
|
1167
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1168
|
+
logger.debug(`[codex] Error reading Codex config: ${message}`);
|
|
1169
|
+
}
|
|
1142
1170
|
const happyServer = await startHappyServer(session);
|
|
1143
1171
|
const bridgeCommand = join(projectPath(), "bin", "happy-mcp.mjs");
|
|
1144
1172
|
const mcpServers = {
|
|
1145
1173
|
happy: {
|
|
1146
1174
|
command: bridgeCommand,
|
|
1147
1175
|
args: ["--url", happyServer.url]
|
|
1148
|
-
}
|
|
1176
|
+
},
|
|
1177
|
+
...existingMcpServers
|
|
1149
1178
|
};
|
|
1150
1179
|
let first = true;
|
|
1151
1180
|
try {
|
|
@@ -20,7 +20,7 @@ import { fileURLToPath } from 'url';
|
|
|
20
20
|
import { Expo } from 'expo-server-sdk';
|
|
21
21
|
|
|
22
22
|
var name = "@zhigang1992/happy-cli";
|
|
23
|
-
var version = "0.12.
|
|
23
|
+
var version = "0.12.9";
|
|
24
24
|
var description = "Mobile and Web client for Claude Code and Codex";
|
|
25
25
|
var author = "Kirill Dubovitskiy";
|
|
26
26
|
var license = "MIT";
|
|
@@ -33,9 +33,9 @@ var bin = {
|
|
|
33
33
|
"happy-mcp": "./bin/happy-mcp.mjs"
|
|
34
34
|
};
|
|
35
35
|
var main = "./dist/index.cjs";
|
|
36
|
-
var module = "./dist/index.mjs";
|
|
36
|
+
var module$1 = "./dist/index.mjs";
|
|
37
37
|
var types = "./dist/index.d.cts";
|
|
38
|
-
var exports = {
|
|
38
|
+
var exports$1 = {
|
|
39
39
|
".": {
|
|
40
40
|
require: {
|
|
41
41
|
types: "./dist/index.d.cts",
|
|
@@ -77,18 +77,19 @@ var scripts = {
|
|
|
77
77
|
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
|
|
78
78
|
typecheck: "tsc --noEmit",
|
|
79
79
|
build: "shx rm -rf dist && npx tsc --noEmit && pkgroll",
|
|
80
|
-
test: "
|
|
81
|
-
start: "
|
|
80
|
+
test: "bun run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
|
81
|
+
start: "bun run build && ./bin/happy.mjs",
|
|
82
82
|
dev: "tsx src/index.ts",
|
|
83
|
-
"dev:local-server": "
|
|
84
|
-
"dev:integration-test-env": "
|
|
85
|
-
prepublishOnly: "
|
|
83
|
+
"dev:local-server": "bun run build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
84
|
+
"dev:integration-test-env": "bun run build && tsx --env-file .env.integration-test src/index.ts",
|
|
85
|
+
prepublishOnly: "bun run build && bun test",
|
|
86
86
|
release: "release-it"
|
|
87
87
|
};
|
|
88
88
|
var dependencies = {
|
|
89
89
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
90
90
|
"@anthropic-ai/sdk": "0.65.0",
|
|
91
91
|
"@elevenlabs/elevenlabs-js": "^2.25.1",
|
|
92
|
+
"@iarna/toml": "^3.0.0",
|
|
92
93
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
93
94
|
"@stablelib/base64": "^2.0.1",
|
|
94
95
|
"@stablelib/hex": "^2.0.1",
|
|
@@ -140,7 +141,7 @@ var resolutions = {
|
|
|
140
141
|
var publishConfig = {
|
|
141
142
|
registry: "https://registry.npmjs.org"
|
|
142
143
|
};
|
|
143
|
-
var packageManager = "
|
|
144
|
+
var packageManager = "bun@1.3.3";
|
|
144
145
|
var packageJson = {
|
|
145
146
|
name: name,
|
|
146
147
|
version: version,
|
|
@@ -153,9 +154,9 @@ var packageJson = {
|
|
|
153
154
|
repository: repository,
|
|
154
155
|
bin: bin,
|
|
155
156
|
main: main,
|
|
156
|
-
module: module,
|
|
157
|
+
module: module$1,
|
|
157
158
|
types: types,
|
|
158
|
-
exports: exports,
|
|
159
|
+
exports: exports$1,
|
|
159
160
|
files: files,
|
|
160
161
|
scripts: scripts,
|
|
161
162
|
dependencies: dependencies,
|
|
@@ -180,8 +181,8 @@ class Configuration {
|
|
|
180
181
|
isExperimentalEnabled;
|
|
181
182
|
disableCaffeinate;
|
|
182
183
|
constructor() {
|
|
183
|
-
this.serverUrl = process.env.HAPPY_SERVER_URL || "https://
|
|
184
|
-
this.webappUrl = process.env.HAPPY_WEBAPP_URL || "https://
|
|
184
|
+
this.serverUrl = process.env.HAPPY_SERVER_URL || "https://happy-server.reily.app";
|
|
185
|
+
this.webappUrl = process.env.HAPPY_WEBAPP_URL || "https://happy.reily.app";
|
|
185
186
|
const args = process.argv.slice(2);
|
|
186
187
|
this.isDaemonProcess = args.length >= 2 && args[0] === "daemon" && args[1] === "start-sync";
|
|
187
188
|
if (process.env.HAPPY_HOME_DIR) {
|
|
@@ -1128,9 +1129,9 @@ class RpcHandlerManager {
|
|
|
1128
1129
|
}
|
|
1129
1130
|
}
|
|
1130
1131
|
|
|
1131
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1132
|
+
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
1132
1133
|
function projectPath() {
|
|
1133
|
-
const path = resolve(__dirname, "..");
|
|
1134
|
+
const path = resolve(__dirname$1, "..");
|
|
1134
1135
|
return path;
|
|
1135
1136
|
}
|
|
1136
1137
|
|
|
@@ -1696,6 +1697,13 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1696
1697
|
logger.debugLargeJson("[SOCKET] Sending usage data:", usageReport);
|
|
1697
1698
|
this.socket.emit("usage-report", usageReport);
|
|
1698
1699
|
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Get the current session summary/title
|
|
1702
|
+
* @returns The summary text or undefined if not set
|
|
1703
|
+
*/
|
|
1704
|
+
getSummary() {
|
|
1705
|
+
return this.metadata?.summary?.text;
|
|
1706
|
+
}
|
|
1699
1707
|
/**
|
|
1700
1708
|
* Update session metadata
|
|
1701
1709
|
* @param handler - Handler function that returns the updated metadata
|
|
@@ -41,7 +41,7 @@ function _interopNamespaceDefault(e) {
|
|
|
41
41
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
42
42
|
|
|
43
43
|
var name = "@zhigang1992/happy-cli";
|
|
44
|
-
var version = "0.12.
|
|
44
|
+
var version = "0.12.9";
|
|
45
45
|
var description = "Mobile and Web client for Claude Code and Codex";
|
|
46
46
|
var author = "Kirill Dubovitskiy";
|
|
47
47
|
var license = "MIT";
|
|
@@ -98,18 +98,19 @@ var scripts = {
|
|
|
98
98
|
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
|
|
99
99
|
typecheck: "tsc --noEmit",
|
|
100
100
|
build: "shx rm -rf dist && npx tsc --noEmit && pkgroll",
|
|
101
|
-
test: "
|
|
102
|
-
start: "
|
|
101
|
+
test: "bun run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
|
102
|
+
start: "bun run build && ./bin/happy.mjs",
|
|
103
103
|
dev: "tsx src/index.ts",
|
|
104
|
-
"dev:local-server": "
|
|
105
|
-
"dev:integration-test-env": "
|
|
106
|
-
prepublishOnly: "
|
|
104
|
+
"dev:local-server": "bun run build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
105
|
+
"dev:integration-test-env": "bun run build && tsx --env-file .env.integration-test src/index.ts",
|
|
106
|
+
prepublishOnly: "bun run build && bun test",
|
|
107
107
|
release: "release-it"
|
|
108
108
|
};
|
|
109
109
|
var dependencies = {
|
|
110
110
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
111
111
|
"@anthropic-ai/sdk": "0.65.0",
|
|
112
112
|
"@elevenlabs/elevenlabs-js": "^2.25.1",
|
|
113
|
+
"@iarna/toml": "^3.0.0",
|
|
113
114
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
114
115
|
"@stablelib/base64": "^2.0.1",
|
|
115
116
|
"@stablelib/hex": "^2.0.1",
|
|
@@ -161,7 +162,7 @@ var resolutions = {
|
|
|
161
162
|
var publishConfig = {
|
|
162
163
|
registry: "https://registry.npmjs.org"
|
|
163
164
|
};
|
|
164
|
-
var packageManager = "
|
|
165
|
+
var packageManager = "bun@1.3.3";
|
|
165
166
|
var packageJson = {
|
|
166
167
|
name: name,
|
|
167
168
|
version: version,
|
|
@@ -201,8 +202,8 @@ class Configuration {
|
|
|
201
202
|
isExperimentalEnabled;
|
|
202
203
|
disableCaffeinate;
|
|
203
204
|
constructor() {
|
|
204
|
-
this.serverUrl = process.env.HAPPY_SERVER_URL || "https://
|
|
205
|
-
this.webappUrl = process.env.HAPPY_WEBAPP_URL || "https://
|
|
205
|
+
this.serverUrl = process.env.HAPPY_SERVER_URL || "https://happy-server.reily.app";
|
|
206
|
+
this.webappUrl = process.env.HAPPY_WEBAPP_URL || "https://happy.reily.app";
|
|
206
207
|
const args = process.argv.slice(2);
|
|
207
208
|
this.isDaemonProcess = args.length >= 2 && args[0] === "daemon" && args[1] === "start-sync";
|
|
208
209
|
if (process.env.HAPPY_HOME_DIR) {
|
|
@@ -1149,7 +1150,7 @@ class RpcHandlerManager {
|
|
|
1149
1150
|
}
|
|
1150
1151
|
}
|
|
1151
1152
|
|
|
1152
|
-
const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1153
|
+
const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-DU-KcuRq.cjs', document.baseURI).href))));
|
|
1153
1154
|
function projectPath() {
|
|
1154
1155
|
const path$1 = path.resolve(__dirname$1, "..");
|
|
1155
1156
|
return path$1;
|
|
@@ -1717,6 +1718,13 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1717
1718
|
logger.debugLargeJson("[SOCKET] Sending usage data:", usageReport);
|
|
1718
1719
|
this.socket.emit("usage-report", usageReport);
|
|
1719
1720
|
}
|
|
1721
|
+
/**
|
|
1722
|
+
* Get the current session summary/title
|
|
1723
|
+
* @returns The summary text or undefined if not set
|
|
1724
|
+
*/
|
|
1725
|
+
getSummary() {
|
|
1726
|
+
return this.metadata?.summary?.text;
|
|
1727
|
+
}
|
|
1720
1728
|
/**
|
|
1721
1729
|
* Update session metadata
|
|
1722
1730
|
* @param handler - Handler function that returns the updated metadata
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhigang1992/happy-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.9",
|
|
4
4
|
"description": "Mobile and Web client for Claude Code and Codex",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,18 +57,19 @@
|
|
|
57
57
|
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
|
|
58
58
|
"typecheck": "tsc --noEmit",
|
|
59
59
|
"build": "shx rm -rf dist && npx tsc --noEmit && pkgroll",
|
|
60
|
-
"test": "
|
|
61
|
-
"start": "
|
|
60
|
+
"test": "bun run build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
|
61
|
+
"start": "bun run build && ./bin/happy.mjs",
|
|
62
62
|
"dev": "tsx src/index.ts",
|
|
63
|
-
"dev:local-server": "
|
|
64
|
-
"dev:integration-test-env": "
|
|
65
|
-
"prepublishOnly": "
|
|
63
|
+
"dev:local-server": "bun run build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
64
|
+
"dev:integration-test-env": "bun run build && tsx --env-file .env.integration-test src/index.ts",
|
|
65
|
+
"prepublishOnly": "bun run build && bun test",
|
|
66
66
|
"release": "release-it"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
70
70
|
"@anthropic-ai/sdk": "0.65.0",
|
|
71
71
|
"@elevenlabs/elevenlabs-js": "^2.25.1",
|
|
72
|
+
"@iarna/toml": "^3.0.0",
|
|
72
73
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
73
74
|
"@stablelib/base64": "^2.0.1",
|
|
74
75
|
"@stablelib/hex": "^2.0.1",
|
|
@@ -120,5 +121,5 @@
|
|
|
120
121
|
"publishConfig": {
|
|
121
122
|
"registry": "https://registry.npmjs.org"
|
|
122
123
|
},
|
|
123
|
-
"packageManager": "
|
|
124
|
+
"packageManager": "bun@1.3.3"
|
|
124
125
|
}
|