@zhigang1992/happy-cli 0.12.1 → 0.12.3
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/dist/{index-DsHtmQqP.mjs → index-DNeoLdzx.mjs} +8 -7
- package/dist/{index-BOBrKhX5.cjs → index-y8CVImEp.cjs} +9 -8
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -2
- package/dist/lib.mjs +1 -2
- package/dist/{list-hET5tyMc.mjs → list-D_NjiLPx.mjs} +1 -1
- package/dist/{list-BW6QBLa1.cjs → list-DiamEbqL.cjs} +1 -1
- package/dist/{prompt-Dz7G8yGx.mjs → prompt-CJh1Mo2A.mjs} +1 -2
- package/dist/{prompt-DXkgjktW.cjs → prompt-Cu47wZlI.cjs} +1 -2
- package/dist/{runCodex-CLGYMNs2.mjs → runCodex-B5ZlUUec.mjs} +3 -3
- package/dist/{runCodex-CylcX5Ug.cjs → runCodex-DErgypij.cjs} +3 -3
- package/dist/{types-BsjUgWOx.cjs → types-CllU28mx.cjs} +31 -13
- package/dist/{types-CGco5Y-r.mjs → types-D4_aCy-H.mjs} +33 -15
- package/package.json +2 -4
- package/scripts/download-tool.cjs +187 -0
- package/scripts/ripgrep_launcher.cjs +53 -2
- package/scripts/tools-config.cjs +119 -0
- package/tools/archives/difftastic-LICENSE +0 -21
- package/tools/archives/difftastic-arm64-darwin.tar.gz +0 -0
- package/tools/archives/difftastic-arm64-linux.tar.gz +0 -0
- package/tools/archives/difftastic-x64-darwin.tar.gz +0 -0
- package/tools/archives/difftastic-x64-linux.tar.gz +0 -0
- package/tools/archives/difftastic-x64-win32.tar.gz +0 -0
- package/tools/archives/ripgrep-LICENSE +0 -3
- package/tools/archives/ripgrep-arm64-darwin.tar.gz +0 -0
- package/tools/archives/ripgrep-arm64-linux.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-darwin.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-linux.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-win32.tar.gz +0 -0
- package/tools/licenses/difftastic-LICENSE +0 -21
- package/tools/licenses/ripgrep-LICENSE +0 -3
- package/tools/unpacked/difft +0 -0
- package/tools/unpacked/rg +0 -0
- package/tools/unpacked/ripgrep.node +0 -0
|
@@ -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-D4_aCy-H.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';
|
|
@@ -16,10 +16,10 @@ import 'node:events';
|
|
|
16
16
|
import 'socket.io-client';
|
|
17
17
|
import tweetnacl from 'tweetnacl';
|
|
18
18
|
import 'expo-server-sdk';
|
|
19
|
+
import { basename, join as join$1 } from 'path';
|
|
19
20
|
import { createHash, randomBytes as randomBytes$1 } from 'crypto';
|
|
20
21
|
import { spawn as spawn$1, execSync as execSync$1, exec } from 'child_process';
|
|
21
22
|
import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync, chmodSync, unlinkSync } from 'fs';
|
|
22
|
-
import { join as join$1 } from 'path';
|
|
23
23
|
import psList from 'ps-list';
|
|
24
24
|
import spawn$2 from 'cross-spawn';
|
|
25
25
|
import os from 'os';
|
|
@@ -2823,9 +2823,10 @@ async function claudeRemoteLauncher(session) {
|
|
|
2823
2823
|
onReady: () => {
|
|
2824
2824
|
if (!pending && session.queue.size() === 0) {
|
|
2825
2825
|
session.client.sendSessionEvent({ type: "ready" });
|
|
2826
|
+
const folderName = basename(session.path);
|
|
2826
2827
|
session.api.push().sendToAllDevices(
|
|
2827
|
-
|
|
2828
|
-
|
|
2828
|
+
`Ready`,
|
|
2829
|
+
folderName,
|
|
2829
2830
|
{ sessionId: session.client.sessionId }
|
|
2830
2831
|
);
|
|
2831
2832
|
}
|
|
@@ -6192,7 +6193,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6192
6193
|
return;
|
|
6193
6194
|
} else if (subcommand === "codex") {
|
|
6194
6195
|
try {
|
|
6195
|
-
const { runCodex } = await import('./runCodex-
|
|
6196
|
+
const { runCodex } = await import('./runCodex-B5ZlUUec.mjs');
|
|
6196
6197
|
let startedBy = void 0;
|
|
6197
6198
|
for (let i = 1; i < args.length; i++) {
|
|
6198
6199
|
if (args[i] === "--started-by") {
|
|
@@ -6237,7 +6238,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6237
6238
|
} else if (subcommand === "list") {
|
|
6238
6239
|
try {
|
|
6239
6240
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6240
|
-
const { listSessions } = await import('./list-
|
|
6241
|
+
const { listSessions } = await import('./list-D_NjiLPx.mjs');
|
|
6241
6242
|
let sessionId;
|
|
6242
6243
|
let titleFilter;
|
|
6243
6244
|
let recentMsgs;
|
|
@@ -6339,7 +6340,7 @@ Examples:
|
|
|
6339
6340
|
process.exit(1);
|
|
6340
6341
|
}
|
|
6341
6342
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6342
|
-
const { promptSession } = await import('./prompt-
|
|
6343
|
+
const { promptSession } = await import('./prompt-CJh1Mo2A.mjs');
|
|
6343
6344
|
await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
|
|
6344
6345
|
} catch (error) {
|
|
6345
6346
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -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-CllU28mx.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');
|
|
@@ -18,10 +18,10 @@ require('node:events');
|
|
|
18
18
|
require('socket.io-client');
|
|
19
19
|
var tweetnacl = require('tweetnacl');
|
|
20
20
|
require('expo-server-sdk');
|
|
21
|
+
var path = require('path');
|
|
21
22
|
var crypto = require('crypto');
|
|
22
23
|
var child_process = require('child_process');
|
|
23
24
|
var fs$2 = require('fs');
|
|
24
|
-
var path = require('path');
|
|
25
25
|
var psList = require('ps-list');
|
|
26
26
|
var spawn = require('cross-spawn');
|
|
27
27
|
var os$1 = require('os');
|
|
@@ -984,7 +984,7 @@ class AbortError extends Error {
|
|
|
984
984
|
}
|
|
985
985
|
}
|
|
986
986
|
|
|
987
|
-
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-
|
|
987
|
+
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-y8CVImEp.cjs', document.baseURI).href)));
|
|
988
988
|
const __dirname$1 = node_path.join(__filename$1, "..");
|
|
989
989
|
function getDefaultClaudeCodePath() {
|
|
990
990
|
return node_path.join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
@@ -2846,9 +2846,10 @@ async function claudeRemoteLauncher(session) {
|
|
|
2846
2846
|
onReady: () => {
|
|
2847
2847
|
if (!pending && session.queue.size() === 0) {
|
|
2848
2848
|
session.client.sendSessionEvent({ type: "ready" });
|
|
2849
|
+
const folderName = path.basename(session.path);
|
|
2849
2850
|
session.api.push().sendToAllDevices(
|
|
2850
|
-
|
|
2851
|
-
|
|
2851
|
+
`Ready`,
|
|
2852
|
+
folderName,
|
|
2852
2853
|
{ sessionId: session.client.sessionId }
|
|
2853
2854
|
);
|
|
2854
2855
|
}
|
|
@@ -6215,7 +6216,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6215
6216
|
return;
|
|
6216
6217
|
} else if (subcommand === "codex") {
|
|
6217
6218
|
try {
|
|
6218
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
6219
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DErgypij.cjs'); });
|
|
6219
6220
|
let startedBy = void 0;
|
|
6220
6221
|
for (let i = 1; i < args.length; i++) {
|
|
6221
6222
|
if (args[i] === "--started-by") {
|
|
@@ -6260,7 +6261,7 @@ async function handleConnectVendor(vendor, displayName) {
|
|
|
6260
6261
|
} else if (subcommand === "list") {
|
|
6261
6262
|
try {
|
|
6262
6263
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6263
|
-
const { listSessions } = await Promise.resolve().then(function () { return require('./list-
|
|
6264
|
+
const { listSessions } = await Promise.resolve().then(function () { return require('./list-DiamEbqL.cjs'); });
|
|
6264
6265
|
let sessionId;
|
|
6265
6266
|
let titleFilter;
|
|
6266
6267
|
let recentMsgs;
|
|
@@ -6362,7 +6363,7 @@ Examples:
|
|
|
6362
6363
|
process.exit(1);
|
|
6363
6364
|
}
|
|
6364
6365
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
6365
|
-
const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-
|
|
6366
|
+
const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-Cu47wZlI.cjs'); });
|
|
6366
6367
|
await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
|
|
6367
6368
|
} catch (error) {
|
|
6368
6369
|
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-y8CVImEp.cjs');
|
|
5
|
+
require('./types-CllU28mx.cjs');
|
|
6
6
|
require('zod');
|
|
7
7
|
require('node:child_process');
|
|
8
8
|
require('node:os');
|
|
@@ -20,10 +20,10 @@ require('node:events');
|
|
|
20
20
|
require('socket.io-client');
|
|
21
21
|
require('tweetnacl');
|
|
22
22
|
require('expo-server-sdk');
|
|
23
|
+
require('path');
|
|
23
24
|
require('crypto');
|
|
24
25
|
require('child_process');
|
|
25
26
|
require('fs');
|
|
26
|
-
require('path');
|
|
27
27
|
require('ps-list');
|
|
28
28
|
require('cross-spawn');
|
|
29
29
|
require('os');
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'chalk';
|
|
2
|
-
import './index-
|
|
3
|
-
import './types-
|
|
2
|
+
import './index-DNeoLdzx.mjs';
|
|
3
|
+
import './types-D4_aCy-H.mjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import 'node:child_process';
|
|
6
6
|
import 'node:os';
|
|
@@ -18,10 +18,10 @@ import 'node:events';
|
|
|
18
18
|
import 'socket.io-client';
|
|
19
19
|
import 'tweetnacl';
|
|
20
20
|
import 'expo-server-sdk';
|
|
21
|
+
import 'path';
|
|
21
22
|
import 'crypto';
|
|
22
23
|
import 'child_process';
|
|
23
24
|
import 'fs';
|
|
24
|
-
import 'path';
|
|
25
25
|
import 'ps-list';
|
|
26
26
|
import 'cross-spawn';
|
|
27
27
|
import 'os';
|
package/dist/lib.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var types = require('./types-
|
|
3
|
+
var types = require('./types-CllU28mx.cjs');
|
|
4
4
|
require('axios');
|
|
5
5
|
require('chalk');
|
|
6
6
|
require('fs');
|
|
@@ -19,7 +19,6 @@ require('fs/promises');
|
|
|
19
19
|
require('crypto');
|
|
20
20
|
require('path');
|
|
21
21
|
require('url');
|
|
22
|
-
require('os');
|
|
23
22
|
require('expo-server-sdk');
|
|
24
23
|
|
|
25
24
|
|
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-D4_aCy-H.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -17,5 +17,4 @@ import 'fs/promises';
|
|
|
17
17
|
import 'crypto';
|
|
18
18
|
import 'path';
|
|
19
19
|
import 'url';
|
|
20
|
-
import 'os';
|
|
21
20
|
import 'expo-server-sdk';
|
|
@@ -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-D4_aCy-H.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-D4_aCy-H.mjs';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { io } from 'socket.io-client';
|
|
4
4
|
import 'chalk';
|
|
@@ -17,7 +17,6 @@ import 'fs/promises';
|
|
|
17
17
|
import 'crypto';
|
|
18
18
|
import 'path';
|
|
19
19
|
import 'url';
|
|
20
|
-
import 'os';
|
|
21
20
|
import 'expo-server-sdk';
|
|
22
21
|
|
|
23
22
|
const DEFAULT_TIMEOUT_MINUTES = 20;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var types = require('./types-
|
|
3
|
+
var types = require('./types-CllU28mx.cjs');
|
|
4
4
|
var axios = require('axios');
|
|
5
5
|
var socket_ioClient = require('socket.io-client');
|
|
6
6
|
require('chalk');
|
|
@@ -19,7 +19,6 @@ require('fs/promises');
|
|
|
19
19
|
require('crypto');
|
|
20
20
|
require('path');
|
|
21
21
|
require('url');
|
|
22
|
-
require('os');
|
|
23
22
|
require('expo-server-sdk');
|
|
24
23
|
|
|
25
24
|
const DEFAULT_TIMEOUT_MINUTES = 20;
|
|
@@ -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
|
-
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-D4_aCy-H.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-DNeoLdzx.mjs';
|
|
11
11
|
import os from 'node:os';
|
|
12
12
|
import { resolve, join } from 'node:path';
|
|
13
13
|
import fs from 'node:fs';
|
|
@@ -23,13 +23,13 @@ import 'fs/promises';
|
|
|
23
23
|
import 'crypto';
|
|
24
24
|
import 'path';
|
|
25
25
|
import 'url';
|
|
26
|
-
import 'os';
|
|
27
26
|
import 'expo-server-sdk';
|
|
28
27
|
import 'node:child_process';
|
|
29
28
|
import 'node:readline';
|
|
30
29
|
import 'node:url';
|
|
31
30
|
import 'ps-list';
|
|
32
31
|
import 'cross-spawn';
|
|
32
|
+
import 'os';
|
|
33
33
|
import 'tmp';
|
|
34
34
|
import 'qrcode-terminal';
|
|
35
35
|
import 'open';
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
5
|
+
var types = require('./types-CllU28mx.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-y8CVImEp.cjs');
|
|
13
13
|
var os = require('node:os');
|
|
14
14
|
var node_path = require('node:path');
|
|
15
15
|
var fs = require('node:fs');
|
|
@@ -25,13 +25,13 @@ require('fs/promises');
|
|
|
25
25
|
require('crypto');
|
|
26
26
|
require('path');
|
|
27
27
|
require('url');
|
|
28
|
-
require('os');
|
|
29
28
|
require('expo-server-sdk');
|
|
30
29
|
require('node:child_process');
|
|
31
30
|
require('node:readline');
|
|
32
31
|
require('node:url');
|
|
33
32
|
require('ps-list');
|
|
34
33
|
require('cross-spawn');
|
|
34
|
+
require('os');
|
|
35
35
|
require('tmp');
|
|
36
36
|
require('qrcode-terminal');
|
|
37
37
|
require('open');
|
|
@@ -18,7 +18,6 @@ var fs$2 = require('fs/promises');
|
|
|
18
18
|
var crypto = require('crypto');
|
|
19
19
|
var path = require('path');
|
|
20
20
|
var url = require('url');
|
|
21
|
-
var os$1 = require('os');
|
|
22
21
|
var expoServerSdk = require('expo-server-sdk');
|
|
23
22
|
|
|
24
23
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -42,7 +41,7 @@ function _interopNamespaceDefault(e) {
|
|
|
42
41
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
43
42
|
|
|
44
43
|
var name = "@zhigang1992/happy-cli";
|
|
45
|
-
var version = "0.12.
|
|
44
|
+
var version = "0.12.2";
|
|
46
45
|
var description = "Mobile and Web client for Claude Code and Codex";
|
|
47
46
|
var author = "Kirill Dubovitskiy";
|
|
48
47
|
var license = "MIT";
|
|
@@ -93,7 +92,6 @@ var files = [
|
|
|
93
92
|
"dist",
|
|
94
93
|
"bin",
|
|
95
94
|
"scripts",
|
|
96
|
-
"tools",
|
|
97
95
|
"package.json"
|
|
98
96
|
];
|
|
99
97
|
var scripts = {
|
|
@@ -106,8 +104,7 @@ var scripts = {
|
|
|
106
104
|
"dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
107
105
|
"dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
|
|
108
106
|
prepublishOnly: "yarn build && yarn test",
|
|
109
|
-
release: "release-it"
|
|
110
|
-
postinstall: "node scripts/unpack-tools.cjs"
|
|
107
|
+
release: "release-it"
|
|
111
108
|
};
|
|
112
109
|
var dependencies = {
|
|
113
110
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
@@ -1076,7 +1073,7 @@ class RpcHandlerManager {
|
|
|
1076
1073
|
}
|
|
1077
1074
|
}
|
|
1078
1075
|
|
|
1079
|
-
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-
|
|
1076
|
+
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-CllU28mx.cjs', document.baseURI).href))));
|
|
1080
1077
|
function projectPath() {
|
|
1081
1078
|
const path$1 = path.resolve(__dirname$1, "..");
|
|
1082
1079
|
return path$1;
|
|
@@ -1110,14 +1107,35 @@ function run$1(args, options) {
|
|
|
1110
1107
|
});
|
|
1111
1108
|
}
|
|
1112
1109
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1110
|
+
const toolsConfig = require(path.join(projectPath(), "scripts", "tools-config.cjs"));
|
|
1111
|
+
require(path.join(projectPath(), "scripts", "download-tool.cjs"));
|
|
1112
|
+
let cachedBinaryPath = null;
|
|
1113
|
+
function getBinaryPathSync() {
|
|
1114
|
+
if (cachedBinaryPath && fs$1.existsSync(cachedBinaryPath)) {
|
|
1115
|
+
return cachedBinaryPath;
|
|
1116
|
+
}
|
|
1117
|
+
const expectedPath = toolsConfig.getToolPath("difftastic");
|
|
1118
|
+
if (fs$1.existsSync(expectedPath)) {
|
|
1119
|
+
cachedBinaryPath = expectedPath;
|
|
1120
|
+
return expectedPath;
|
|
1121
|
+
}
|
|
1122
|
+
const result = child_process.spawnSync(process.execPath, [
|
|
1123
|
+
path.join(projectPath(), "scripts", "download-tool.cjs"),
|
|
1124
|
+
"difftastic"
|
|
1125
|
+
], {
|
|
1126
|
+
encoding: "utf-8",
|
|
1127
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
1128
|
+
// Show download progress on stderr
|
|
1129
|
+
});
|
|
1130
|
+
if (result.status !== 0) {
|
|
1131
|
+
throw new Error(`Failed to download difftastic: ${result.stderr || "unknown error"}`);
|
|
1132
|
+
}
|
|
1133
|
+
cachedBinaryPath = result.stdout.trim();
|
|
1134
|
+
return cachedBinaryPath;
|
|
1117
1135
|
}
|
|
1118
1136
|
function run(args, options) {
|
|
1119
|
-
const binaryPath =
|
|
1120
|
-
return new Promise((
|
|
1137
|
+
const binaryPath = getBinaryPathSync();
|
|
1138
|
+
return new Promise((resolve, reject) => {
|
|
1121
1139
|
const child = child_process.spawn(binaryPath, args, {
|
|
1122
1140
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1123
1141
|
cwd: options?.cwd,
|
|
@@ -1136,7 +1154,7 @@ function run(args, options) {
|
|
|
1136
1154
|
stderr += data.toString();
|
|
1137
1155
|
});
|
|
1138
1156
|
child.on("close", (code) => {
|
|
1139
|
-
|
|
1157
|
+
resolve({
|
|
1140
1158
|
exitCode: code || 0,
|
|
1141
1159
|
stdout,
|
|
1142
1160
|
stderr
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import axios from 'axios';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { appendFileSync } from 'fs';
|
|
3
|
+
import { appendFileSync, existsSync as existsSync$1 } from 'fs';
|
|
4
4
|
import { existsSync, mkdirSync, constants, readFileSync, unlinkSync, writeFileSync, readdirSync, statSync } from 'node:fs';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { join, basename } from 'node:path';
|
|
@@ -11,17 +11,16 @@ import { createHash, createDecipheriv, createCipheriv, randomBytes, randomUUID }
|
|
|
11
11
|
import tweetnacl from 'tweetnacl';
|
|
12
12
|
import { EventEmitter } from 'node:events';
|
|
13
13
|
import { io } from 'socket.io-client';
|
|
14
|
-
import { spawn, exec } from 'child_process';
|
|
14
|
+
import { spawn, spawnSync, exec } from 'child_process';
|
|
15
15
|
import { promisify } from 'util';
|
|
16
16
|
import { readFile as readFile$1, stat as stat$1, writeFile as writeFile$1, readdir } from 'fs/promises';
|
|
17
17
|
import { createHash as createHash$1 } from 'crypto';
|
|
18
18
|
import { dirname, resolve, join as join$1 } from 'path';
|
|
19
19
|
import { fileURLToPath } from 'url';
|
|
20
|
-
import { platform } from 'os';
|
|
21
20
|
import { Expo } from 'expo-server-sdk';
|
|
22
21
|
|
|
23
22
|
var name = "@zhigang1992/happy-cli";
|
|
24
|
-
var version = "0.12.
|
|
23
|
+
var version = "0.12.2";
|
|
25
24
|
var description = "Mobile and Web client for Claude Code and Codex";
|
|
26
25
|
var author = "Kirill Dubovitskiy";
|
|
27
26
|
var license = "MIT";
|
|
@@ -72,7 +71,6 @@ var files = [
|
|
|
72
71
|
"dist",
|
|
73
72
|
"bin",
|
|
74
73
|
"scripts",
|
|
75
|
-
"tools",
|
|
76
74
|
"package.json"
|
|
77
75
|
];
|
|
78
76
|
var scripts = {
|
|
@@ -85,8 +83,7 @@ var scripts = {
|
|
|
85
83
|
"dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
86
84
|
"dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
|
|
87
85
|
prepublishOnly: "yarn build && yarn test",
|
|
88
|
-
release: "release-it"
|
|
89
|
-
postinstall: "node scripts/unpack-tools.cjs"
|
|
86
|
+
release: "release-it"
|
|
90
87
|
};
|
|
91
88
|
var dependencies = {
|
|
92
89
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
@@ -1089,14 +1086,35 @@ function run$1(args, options) {
|
|
|
1089
1086
|
});
|
|
1090
1087
|
}
|
|
1091
1088
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1089
|
+
const toolsConfig = require(join$1(projectPath(), "scripts", "tools-config.cjs"));
|
|
1090
|
+
require(join$1(projectPath(), "scripts", "download-tool.cjs"));
|
|
1091
|
+
let cachedBinaryPath = null;
|
|
1092
|
+
function getBinaryPathSync() {
|
|
1093
|
+
if (cachedBinaryPath && existsSync$1(cachedBinaryPath)) {
|
|
1094
|
+
return cachedBinaryPath;
|
|
1095
|
+
}
|
|
1096
|
+
const expectedPath = toolsConfig.getToolPath("difftastic");
|
|
1097
|
+
if (existsSync$1(expectedPath)) {
|
|
1098
|
+
cachedBinaryPath = expectedPath;
|
|
1099
|
+
return expectedPath;
|
|
1100
|
+
}
|
|
1101
|
+
const result = spawnSync(process.execPath, [
|
|
1102
|
+
join$1(projectPath(), "scripts", "download-tool.cjs"),
|
|
1103
|
+
"difftastic"
|
|
1104
|
+
], {
|
|
1105
|
+
encoding: "utf-8",
|
|
1106
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
1107
|
+
// Show download progress on stderr
|
|
1108
|
+
});
|
|
1109
|
+
if (result.status !== 0) {
|
|
1110
|
+
throw new Error(`Failed to download difftastic: ${result.stderr || "unknown error"}`);
|
|
1111
|
+
}
|
|
1112
|
+
cachedBinaryPath = result.stdout.trim();
|
|
1113
|
+
return cachedBinaryPath;
|
|
1096
1114
|
}
|
|
1097
1115
|
function run(args, options) {
|
|
1098
|
-
const binaryPath =
|
|
1099
|
-
return new Promise((
|
|
1116
|
+
const binaryPath = getBinaryPathSync();
|
|
1117
|
+
return new Promise((resolve, reject) => {
|
|
1100
1118
|
const child = spawn(binaryPath, args, {
|
|
1101
1119
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1102
1120
|
cwd: options?.cwd,
|
|
@@ -1115,7 +1133,7 @@ function run(args, options) {
|
|
|
1115
1133
|
stderr += data.toString();
|
|
1116
1134
|
});
|
|
1117
1135
|
child.on("close", (code) => {
|
|
1118
|
-
|
|
1136
|
+
resolve({
|
|
1119
1137
|
exitCode: code || 0,
|
|
1120
1138
|
stdout,
|
|
1121
1139
|
stderr
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhigang1992/happy-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Mobile and Web client for Claude Code and Codex",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
"dist",
|
|
52
52
|
"bin",
|
|
53
53
|
"scripts",
|
|
54
|
-
"tools",
|
|
55
54
|
"package.json"
|
|
56
55
|
],
|
|
57
56
|
"scripts": {
|
|
@@ -64,8 +63,7 @@
|
|
|
64
63
|
"dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
65
64
|
"dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
|
|
66
65
|
"prepublishOnly": "yarn build && yarn test",
|
|
67
|
-
"release": "release-it"
|
|
68
|
-
"postinstall": "node scripts/unpack-tools.cjs"
|
|
66
|
+
"release": "release-it"
|
|
69
67
|
},
|
|
70
68
|
"dependencies": {
|
|
71
69
|
"@anthropic-ai/claude-code": "2.0.55",
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Downloads and extracts a tool binary on first use
|
|
5
|
+
* Usage: node download-tool.cjs <toolName>
|
|
6
|
+
*
|
|
7
|
+
* This script is designed to be called before using a tool.
|
|
8
|
+
* It's idempotent - if the tool is already downloaded, it does nothing.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
const https = require('https');
|
|
15
|
+
const { createGunzip } = require('zlib');
|
|
16
|
+
const { pipeline } = require('stream/promises');
|
|
17
|
+
const { getDownloadUrl, getBinaryName, getToolPath, TOOLS } = require('./tools-config.cjs');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Follow redirects and download a file
|
|
21
|
+
*/
|
|
22
|
+
function downloadFile(url, destPath, maxRedirects = 5) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
if (maxRedirects <= 0) {
|
|
25
|
+
reject(new Error('Too many redirects'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const protocol = url.startsWith('https') ? https : require('http');
|
|
30
|
+
|
|
31
|
+
protocol.get(url, (response) => {
|
|
32
|
+
// Handle redirects
|
|
33
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
34
|
+
downloadFile(response.headers.location, destPath, maxRedirects - 1)
|
|
35
|
+
.then(resolve)
|
|
36
|
+
.catch(reject);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (response.statusCode !== 200) {
|
|
41
|
+
reject(new Error(`Download failed with status ${response.statusCode}`));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
46
|
+
response.pipe(fileStream);
|
|
47
|
+
|
|
48
|
+
fileStream.on('finish', () => {
|
|
49
|
+
fileStream.close();
|
|
50
|
+
resolve();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
fileStream.on('error', (err) => {
|
|
54
|
+
fs.unlink(destPath, () => {}); // Clean up partial file
|
|
55
|
+
reject(err);
|
|
56
|
+
});
|
|
57
|
+
}).on('error', reject);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Extract a tar.gz file
|
|
63
|
+
*/
|
|
64
|
+
async function extractTarGz(archivePath, destDir, toolName) {
|
|
65
|
+
const tar = require('tar');
|
|
66
|
+
const tool = TOOLS[toolName];
|
|
67
|
+
|
|
68
|
+
await tar.extract({
|
|
69
|
+
file: archivePath,
|
|
70
|
+
cwd: destDir,
|
|
71
|
+
filter: (entryPath) => {
|
|
72
|
+
// Only extract the binary we need
|
|
73
|
+
const binaryName = getBinaryName(toolName, os.platform());
|
|
74
|
+
return entryPath.endsWith(binaryName);
|
|
75
|
+
},
|
|
76
|
+
strip: tool.archiveStructure === 'nested' ? 1 : 0
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Extract a zip file (for Windows)
|
|
82
|
+
*/
|
|
83
|
+
async function extractZip(archivePath, destDir, toolName) {
|
|
84
|
+
const AdmZip = require('adm-zip');
|
|
85
|
+
const tool = TOOLS[toolName];
|
|
86
|
+
const binaryName = getBinaryName(toolName, os.platform());
|
|
87
|
+
|
|
88
|
+
const zip = new AdmZip(archivePath);
|
|
89
|
+
const entries = zip.getEntries();
|
|
90
|
+
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
if (entry.entryName.endsWith(binaryName)) {
|
|
93
|
+
const content = entry.getData();
|
|
94
|
+
const destPath = path.join(destDir, binaryName);
|
|
95
|
+
fs.writeFileSync(destPath, content);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Ensure a tool is downloaded and available
|
|
103
|
+
*/
|
|
104
|
+
async function ensureTool(toolName) {
|
|
105
|
+
const tool = TOOLS[toolName];
|
|
106
|
+
if (!tool) {
|
|
107
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const platform = os.platform();
|
|
111
|
+
const arch = os.arch();
|
|
112
|
+
const toolPath = getToolPath(toolName);
|
|
113
|
+
|
|
114
|
+
// Check if already downloaded
|
|
115
|
+
if (fs.existsSync(toolPath)) {
|
|
116
|
+
return toolPath;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const toolDir = path.dirname(toolPath);
|
|
120
|
+
fs.mkdirSync(toolDir, { recursive: true });
|
|
121
|
+
|
|
122
|
+
// Get download URL
|
|
123
|
+
const url = getDownloadUrl(toolName, platform, arch);
|
|
124
|
+
const isZip = url.endsWith('.zip');
|
|
125
|
+
const archivePath = path.join(toolDir, `archive${isZip ? '.zip' : '.tar.gz'}`);
|
|
126
|
+
|
|
127
|
+
console.error(`[happy-cli] Downloading ${toolName} v${tool.version}...`);
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// Download the archive
|
|
131
|
+
await downloadFile(url, archivePath);
|
|
132
|
+
|
|
133
|
+
// Extract
|
|
134
|
+
if (isZip) {
|
|
135
|
+
await extractZip(archivePath, toolDir, toolName);
|
|
136
|
+
} else {
|
|
137
|
+
await extractTarGz(archivePath, toolDir, toolName);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Set executable permission on Unix
|
|
141
|
+
if (platform !== 'win32') {
|
|
142
|
+
fs.chmodSync(toolPath, 0o755);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Clean up archive
|
|
146
|
+
fs.unlinkSync(archivePath);
|
|
147
|
+
|
|
148
|
+
console.error(`[happy-cli] ${toolName} v${tool.version} installed to ${toolPath}`);
|
|
149
|
+
return toolPath;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
// Clean up on failure
|
|
152
|
+
try {
|
|
153
|
+
fs.unlinkSync(archivePath);
|
|
154
|
+
} catch {}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Run a tool, downloading it first if necessary
|
|
161
|
+
* Returns the path to the binary
|
|
162
|
+
*/
|
|
163
|
+
async function getOrDownloadTool(toolName) {
|
|
164
|
+
return ensureTool(toolName);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// If run directly, download the specified tool
|
|
168
|
+
if (require.main === module) {
|
|
169
|
+
const toolName = process.argv[2];
|
|
170
|
+
if (!toolName) {
|
|
171
|
+
console.error('Usage: node download-tool.cjs <toolName>');
|
|
172
|
+
console.error('Available tools:', Object.keys(TOOLS).join(', '));
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
ensureTool(toolName)
|
|
177
|
+
.then((toolPath) => {
|
|
178
|
+
// Output the path so callers can use it
|
|
179
|
+
console.log(toolPath);
|
|
180
|
+
})
|
|
181
|
+
.catch((error) => {
|
|
182
|
+
console.error(`Failed to download ${toolName}:`, error.message);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = { ensureTool, getOrDownloadTool };
|
|
@@ -3,12 +3,63 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Ripgrep runner - executed as a subprocess to run the native module
|
|
5
5
|
* This file is intentionally written in CommonJS to avoid ESM complexities
|
|
6
|
+
*
|
|
7
|
+
* Uses the ripgrep.node native module bundled with @anthropic-ai/claude-code
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const fs = require('fs');
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Get the platform-specific directory name for claude-code vendor
|
|
16
|
+
*/
|
|
17
|
+
function getPlatformDir() {
|
|
18
|
+
const platform = os.platform();
|
|
19
|
+
const arch = os.arch();
|
|
20
|
+
|
|
21
|
+
if (platform === 'darwin') {
|
|
22
|
+
return arch === 'arm64' ? 'arm64-darwin' : 'x64-darwin';
|
|
23
|
+
} else if (platform === 'linux') {
|
|
24
|
+
return arch === 'arm64' ? 'arm64-linux' : 'x64-linux';
|
|
25
|
+
} else if (platform === 'win32') {
|
|
26
|
+
return 'x64-win32';
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Find the ripgrep.node native module
|
|
33
|
+
* First checks claude-code vendor directory, falls back to local tools
|
|
34
|
+
*/
|
|
35
|
+
function findRipgrepModule() {
|
|
36
|
+
const platformDir = getPlatformDir();
|
|
37
|
+
|
|
38
|
+
// Try claude-code vendor first (preferred - it's always up to date)
|
|
39
|
+
const claudeCodePaths = [
|
|
40
|
+
// When installed as a dependency
|
|
41
|
+
path.join(__dirname, '..', 'node_modules', '@anthropic-ai', 'claude-code', 'vendor', 'ripgrep', platformDir, 'ripgrep.node'),
|
|
42
|
+
// When running from workspace root
|
|
43
|
+
path.join(__dirname, '..', '..', 'node_modules', '@anthropic-ai', 'claude-code', 'vendor', 'ripgrep', platformDir, 'ripgrep.node'),
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
for (const modulePath of claudeCodePaths) {
|
|
47
|
+
if (fs.existsSync(modulePath)) {
|
|
48
|
+
return modulePath;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Fallback to local tools/unpacked (for development)
|
|
53
|
+
const localPath = path.join(__dirname, '..', 'tools', 'unpacked', 'ripgrep.node');
|
|
54
|
+
if (fs.existsSync(localPath)) {
|
|
55
|
+
return localPath;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new Error('Could not find ripgrep.node native module. Make sure @anthropic-ai/claude-code is installed.');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Load the native module
|
|
62
|
+
const modulePath = findRipgrepModule();
|
|
12
63
|
const ripgrepNative = require(modulePath);
|
|
13
64
|
|
|
14
65
|
// Get arguments from command line (skip node and script name)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for external tool binaries
|
|
3
|
+
* These are downloaded on first use, not bundled with the package
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const TOOLS = {
|
|
7
|
+
difftastic: {
|
|
8
|
+
version: '0.64.0',
|
|
9
|
+
repo: 'Wilfred/difftastic',
|
|
10
|
+
// Map platform/arch to GitHub release asset names
|
|
11
|
+
assets: {
|
|
12
|
+
'darwin-arm64': 'difft-aarch64-apple-darwin.tar.gz',
|
|
13
|
+
'darwin-x64': 'difft-x86_64-apple-darwin.tar.gz',
|
|
14
|
+
'linux-arm64': 'difft-aarch64-unknown-linux-gnu.tar.gz',
|
|
15
|
+
'linux-x64': 'difft-x86_64-unknown-linux-gnu.tar.gz',
|
|
16
|
+
'win32-x64': 'difft-x86_64-pc-windows-msvc.zip',
|
|
17
|
+
},
|
|
18
|
+
// Binary name inside the archive (or after extraction)
|
|
19
|
+
binaryName: {
|
|
20
|
+
'win32': 'difft.exe',
|
|
21
|
+
'default': 'difft'
|
|
22
|
+
},
|
|
23
|
+
// Some archives have the binary in a subdirectory
|
|
24
|
+
archiveStructure: 'flat' // binary is at root of archive
|
|
25
|
+
},
|
|
26
|
+
ripgrep: {
|
|
27
|
+
version: '14.1.1',
|
|
28
|
+
repo: 'BurntSushi/ripgrep',
|
|
29
|
+
assets: {
|
|
30
|
+
'darwin-arm64': 'ripgrep-14.1.1-aarch64-apple-darwin.tar.gz',
|
|
31
|
+
'darwin-x64': 'ripgrep-14.1.1-x86_64-apple-darwin.tar.gz',
|
|
32
|
+
'linux-arm64': 'ripgrep-14.1.1-aarch64-unknown-linux-gnu.tar.gz',
|
|
33
|
+
'linux-x64': 'ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz',
|
|
34
|
+
'win32-x64': 'ripgrep-14.1.1-x86_64-pc-windows-msvc.zip',
|
|
35
|
+
},
|
|
36
|
+
binaryName: {
|
|
37
|
+
'win32': 'rg.exe',
|
|
38
|
+
'default': 'rg'
|
|
39
|
+
},
|
|
40
|
+
// ripgrep archives have files in a subdirectory named after the archive
|
|
41
|
+
archiveStructure: 'nested' // binary is in a subdirectory
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get download URL for a tool
|
|
47
|
+
*/
|
|
48
|
+
function getDownloadUrl(toolName, platform, arch) {
|
|
49
|
+
const tool = TOOLS[toolName];
|
|
50
|
+
if (!tool) {
|
|
51
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const key = `${platform}-${arch}`;
|
|
55
|
+
const asset = tool.assets[key];
|
|
56
|
+
if (!asset) {
|
|
57
|
+
throw new Error(`Unsupported platform for ${toolName}: ${key}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return `https://github.com/${tool.repo}/releases/download/${tool.version}/${asset}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get binary name for a tool on the current platform
|
|
65
|
+
*/
|
|
66
|
+
function getBinaryName(toolName, platform) {
|
|
67
|
+
const tool = TOOLS[toolName];
|
|
68
|
+
if (!tool) {
|
|
69
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return tool.binaryName[platform] || tool.binaryName['default'];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get cache directory for tools
|
|
77
|
+
* Uses ~/.cache/happy-cli/tools on Unix, %LOCALAPPDATA%/happy-cli/tools on Windows
|
|
78
|
+
*/
|
|
79
|
+
function getCacheDir() {
|
|
80
|
+
const os = require('os');
|
|
81
|
+
const path = require('path');
|
|
82
|
+
|
|
83
|
+
const platform = os.platform();
|
|
84
|
+
const homeDir = os.homedir();
|
|
85
|
+
|
|
86
|
+
if (platform === 'win32') {
|
|
87
|
+
const localAppData = process.env.LOCALAPPDATA || path.join(homeDir, 'AppData', 'Local');
|
|
88
|
+
return path.join(localAppData, 'happy-cli', 'tools');
|
|
89
|
+
} else {
|
|
90
|
+
const cacheHome = process.env.XDG_CACHE_HOME || path.join(homeDir, '.cache');
|
|
91
|
+
return path.join(cacheHome, 'happy-cli', 'tools');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the expected path for a tool binary
|
|
97
|
+
*/
|
|
98
|
+
function getToolPath(toolName) {
|
|
99
|
+
const os = require('os');
|
|
100
|
+
const path = require('path');
|
|
101
|
+
|
|
102
|
+
const tool = TOOLS[toolName];
|
|
103
|
+
if (!tool) {
|
|
104
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const cacheDir = getCacheDir();
|
|
108
|
+
const binaryName = getBinaryName(toolName, os.platform());
|
|
109
|
+
|
|
110
|
+
return path.join(cacheDir, toolName, tool.version, binaryName);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
TOOLS,
|
|
115
|
+
getDownloadUrl,
|
|
116
|
+
getBinaryName,
|
|
117
|
+
getCacheDir,
|
|
118
|
+
getToolPath
|
|
119
|
+
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2021-2025 Wilfred Hughes
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2021-2025 Wilfred Hughes
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/tools/unpacked/difft
DELETED
|
Binary file
|
package/tools/unpacked/rg
DELETED
|
Binary file
|
|
Binary file
|