happy-coder 0.10.0-0 → 0.10.0-1
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.cjs +32 -277
- package/dist/index.mjs +29 -274
- package/dist/lib.cjs +7 -1
- package/dist/lib.d.cts +78 -21
- package/dist/lib.d.mts +78 -21
- package/dist/lib.mjs +7 -1
- package/dist/{types-CGbH1LGX.mjs → types-BUXwivpV.mjs} +407 -146
- package/dist/{types-fU2E-jQl.cjs → types-D9P2bndj.cjs} +408 -145
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import os$1, { homedir } from 'node:os';
|
|
3
3
|
import { randomUUID, randomBytes } from 'node:crypto';
|
|
4
|
-
import { l as logger, b as backoff, d as delay, R as RawJSONLinesSchema, e as AsyncLock, r as readDaemonState, f as clearDaemonState,
|
|
4
|
+
import { l as logger, p as projectPath, b as backoff, d as delay, R as RawJSONLinesSchema, e as AsyncLock, r as readDaemonState, f as clearDaemonState, g as packageJson, c as configuration, h as readSettings, i as readCredentials, j as encodeBase64, u as updateSettings, k as encodeBase64Url, m as decodeBase64, w as writeCredentials, n as acquireDaemonLock, o as writeDaemonState, A as ApiClient, q as releaseDaemonLock, s as clearCredentials, t as clearMachineId, v as getLatestDaemonLog } from './types-BUXwivpV.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';
|
|
8
8
|
import { existsSync, readFileSync, mkdirSync, watch, readdirSync, statSync, rmSync } from 'node:fs';
|
|
9
|
-
import { dirname, resolve as resolve$1, join as join$1 } from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
9
|
import { readFile } from 'node:fs/promises';
|
|
12
|
-
import fs, { watch as watch$1, access
|
|
10
|
+
import fs, { watch as watch$1, access } from 'fs/promises';
|
|
13
11
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
14
12
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
15
|
-
import { fileURLToPath
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
16
14
|
import axios from 'axios';
|
|
17
15
|
import 'node:events';
|
|
18
16
|
import 'socket.io-client';
|
|
19
17
|
import tweetnacl from 'tweetnacl';
|
|
20
18
|
import 'expo-server-sdk';
|
|
21
|
-
import { spawn as spawn$1, exec, execSync as execSync$1 } from 'child_process';
|
|
22
|
-
import { promisify } from 'util';
|
|
23
19
|
import { createHash, randomBytes as randomBytes$1 } from 'crypto';
|
|
20
|
+
import { spawn as spawn$1, execSync as execSync$1, exec } from 'child_process';
|
|
24
21
|
import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync, chmodSync, unlinkSync } from 'fs';
|
|
22
|
+
import { join as join$1 } from 'path';
|
|
25
23
|
import psList from 'ps-list';
|
|
26
24
|
import spawn$2 from 'cross-spawn';
|
|
27
25
|
import os from 'os';
|
|
@@ -34,6 +32,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
34
32
|
import { createServer } from 'node:http';
|
|
35
33
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
36
34
|
import { createServer as createServer$1 } from 'http';
|
|
35
|
+
import { promisify } from 'util';
|
|
36
|
+
import 'url';
|
|
37
37
|
|
|
38
38
|
class Session {
|
|
39
39
|
path;
|
|
@@ -145,12 +145,6 @@ function claudeCheckSession(sessionId, path) {
|
|
|
145
145
|
return hasGoodMessage;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
149
|
-
function projectPath() {
|
|
150
|
-
const path = resolve$1(__dirname$1, "..");
|
|
151
|
-
return path;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
148
|
function trimIdent(text) {
|
|
155
149
|
const lines = text.split("\n");
|
|
156
150
|
while (lines.length > 0 && lines[0].trim() === "") {
|
|
@@ -611,8 +605,8 @@ async function claudeLocalLauncher(session) {
|
|
|
611
605
|
}
|
|
612
606
|
await abort();
|
|
613
607
|
}
|
|
614
|
-
session.client.
|
|
615
|
-
session.client.
|
|
608
|
+
session.client.rpcHandlerManager.registerHandler("abort", doAbort);
|
|
609
|
+
session.client.rpcHandlerManager.registerHandler("switch", doSwitch);
|
|
616
610
|
session.queue.setOnMessage((message, mode) => {
|
|
617
611
|
doSwitch();
|
|
618
612
|
});
|
|
@@ -658,9 +652,9 @@ async function claudeLocalLauncher(session) {
|
|
|
658
652
|
}
|
|
659
653
|
} finally {
|
|
660
654
|
exutFuture.resolve(void 0);
|
|
661
|
-
session.client.
|
|
655
|
+
session.client.rpcHandlerManager.registerHandler("abort", async () => {
|
|
662
656
|
});
|
|
663
|
-
session.client.
|
|
657
|
+
session.client.rpcHandlerManager.registerHandler("switch", async () => {
|
|
664
658
|
});
|
|
665
659
|
session.queue.setOnMessage(null);
|
|
666
660
|
await scanner.cleanup();
|
|
@@ -927,7 +921,7 @@ class AbortError extends Error {
|
|
|
927
921
|
}
|
|
928
922
|
}
|
|
929
923
|
|
|
930
|
-
const __filename = fileURLToPath
|
|
924
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
931
925
|
const __dirname = join(__filename, "..");
|
|
932
926
|
function getDefaultClaudeCodePath() {
|
|
933
927
|
return join(__dirname, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
|
|
@@ -1922,7 +1916,7 @@ class PermissionHandler {
|
|
|
1922
1916
|
* Sets up the client handler for permission responses
|
|
1923
1917
|
*/
|
|
1924
1918
|
setupClientHandler() {
|
|
1925
|
-
this.session.client.
|
|
1919
|
+
this.session.client.rpcHandlerManager.registerHandler("permission", async (message) => {
|
|
1926
1920
|
logger.debug(`Permission response: ${JSON.stringify(message)}`);
|
|
1927
1921
|
const id = message.id;
|
|
1928
1922
|
const pending = this.pendingRequests.get(id);
|
|
@@ -2492,8 +2486,8 @@ async function claudeRemoteLauncher(session) {
|
|
|
2492
2486
|
}
|
|
2493
2487
|
await abort();
|
|
2494
2488
|
}
|
|
2495
|
-
session.client.
|
|
2496
|
-
session.client.
|
|
2489
|
+
session.client.rpcHandlerManager.registerHandler("abort", doAbort);
|
|
2490
|
+
session.client.rpcHandlerManager.registerHandler("switch", doSwitch);
|
|
2497
2491
|
const permissionHandler = new PermissionHandler(session);
|
|
2498
2492
|
const messageQueue = new OutgoingMessageQueue(
|
|
2499
2493
|
(logMessage) => session.client.sendClaudeSessionMessage(logMessage)
|
|
@@ -2809,255 +2803,6 @@ async function loop(opts) {
|
|
|
2809
2803
|
}
|
|
2810
2804
|
}
|
|
2811
2805
|
|
|
2812
|
-
function run(args, options) {
|
|
2813
|
-
const RUNNER_PATH = resolve$1(join$1(projectPath(), "scripts", "ripgrep_launcher.cjs"));
|
|
2814
|
-
return new Promise((resolve2, reject) => {
|
|
2815
|
-
const child = spawn$1("node", [RUNNER_PATH, JSON.stringify(args)], {
|
|
2816
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
2817
|
-
cwd: options?.cwd
|
|
2818
|
-
});
|
|
2819
|
-
let stdout = "";
|
|
2820
|
-
let stderr = "";
|
|
2821
|
-
child.stdout.on("data", (data) => {
|
|
2822
|
-
stdout += data.toString();
|
|
2823
|
-
});
|
|
2824
|
-
child.stderr.on("data", (data) => {
|
|
2825
|
-
stderr += data.toString();
|
|
2826
|
-
});
|
|
2827
|
-
child.on("close", (code) => {
|
|
2828
|
-
resolve2({
|
|
2829
|
-
exitCode: code || 0,
|
|
2830
|
-
stdout,
|
|
2831
|
-
stderr
|
|
2832
|
-
});
|
|
2833
|
-
});
|
|
2834
|
-
child.on("error", (err) => {
|
|
2835
|
-
reject(err);
|
|
2836
|
-
});
|
|
2837
|
-
});
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
const execAsync$1 = promisify(exec);
|
|
2841
|
-
function registerHandlers(session) {
|
|
2842
|
-
session.setHandler("bash", async (data) => {
|
|
2843
|
-
logger.debug("Shell command request:", data.command);
|
|
2844
|
-
try {
|
|
2845
|
-
const options = {
|
|
2846
|
-
cwd: data.cwd,
|
|
2847
|
-
timeout: data.timeout || 3e4
|
|
2848
|
-
// Default 30 seconds timeout
|
|
2849
|
-
};
|
|
2850
|
-
const { stdout, stderr } = await execAsync$1(data.command, options);
|
|
2851
|
-
return {
|
|
2852
|
-
success: true,
|
|
2853
|
-
stdout: stdout ? stdout.toString() : "",
|
|
2854
|
-
stderr: stderr ? stderr.toString() : "",
|
|
2855
|
-
exitCode: 0
|
|
2856
|
-
};
|
|
2857
|
-
} catch (error) {
|
|
2858
|
-
const execError = error;
|
|
2859
|
-
if (execError.code === "ETIMEDOUT" || execError.killed) {
|
|
2860
|
-
return {
|
|
2861
|
-
success: false,
|
|
2862
|
-
stdout: execError.stdout || "",
|
|
2863
|
-
stderr: execError.stderr || "",
|
|
2864
|
-
exitCode: typeof execError.code === "number" ? execError.code : -1,
|
|
2865
|
-
error: "Command timed out"
|
|
2866
|
-
};
|
|
2867
|
-
}
|
|
2868
|
-
return {
|
|
2869
|
-
success: false,
|
|
2870
|
-
stdout: execError.stdout ? execError.stdout.toString() : "",
|
|
2871
|
-
stderr: execError.stderr ? execError.stderr.toString() : execError.message || "Command failed",
|
|
2872
|
-
exitCode: typeof execError.code === "number" ? execError.code : 1,
|
|
2873
|
-
error: execError.message || "Command failed"
|
|
2874
|
-
};
|
|
2875
|
-
}
|
|
2876
|
-
});
|
|
2877
|
-
session.setHandler("readFile", async (data) => {
|
|
2878
|
-
logger.debug("Read file request:", data.path);
|
|
2879
|
-
try {
|
|
2880
|
-
const buffer = await readFile$1(data.path);
|
|
2881
|
-
const content = buffer.toString("base64");
|
|
2882
|
-
return { success: true, content };
|
|
2883
|
-
} catch (error) {
|
|
2884
|
-
logger.debug("Failed to read file:", error);
|
|
2885
|
-
return { success: false, error: error instanceof Error ? error.message : "Failed to read file" };
|
|
2886
|
-
}
|
|
2887
|
-
});
|
|
2888
|
-
session.setHandler("writeFile", async (data) => {
|
|
2889
|
-
logger.debug("Write file request:", data.path);
|
|
2890
|
-
try {
|
|
2891
|
-
if (data.expectedHash !== null && data.expectedHash !== void 0) {
|
|
2892
|
-
try {
|
|
2893
|
-
const existingBuffer = await readFile$1(data.path);
|
|
2894
|
-
const existingHash = createHash("sha256").update(existingBuffer).digest("hex");
|
|
2895
|
-
if (existingHash !== data.expectedHash) {
|
|
2896
|
-
return {
|
|
2897
|
-
success: false,
|
|
2898
|
-
error: `File hash mismatch. Expected: ${data.expectedHash}, Actual: ${existingHash}`
|
|
2899
|
-
};
|
|
2900
|
-
}
|
|
2901
|
-
} catch (error) {
|
|
2902
|
-
const nodeError = error;
|
|
2903
|
-
if (nodeError.code !== "ENOENT") {
|
|
2904
|
-
throw error;
|
|
2905
|
-
}
|
|
2906
|
-
return {
|
|
2907
|
-
success: false,
|
|
2908
|
-
error: "File does not exist but hash was provided"
|
|
2909
|
-
};
|
|
2910
|
-
}
|
|
2911
|
-
} else {
|
|
2912
|
-
try {
|
|
2913
|
-
await stat(data.path);
|
|
2914
|
-
return {
|
|
2915
|
-
success: false,
|
|
2916
|
-
error: "File already exists but was expected to be new"
|
|
2917
|
-
};
|
|
2918
|
-
} catch (error) {
|
|
2919
|
-
const nodeError = error;
|
|
2920
|
-
if (nodeError.code !== "ENOENT") {
|
|
2921
|
-
throw error;
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
const buffer = Buffer.from(data.content, "base64");
|
|
2926
|
-
await writeFile(data.path, buffer);
|
|
2927
|
-
const hash = createHash("sha256").update(buffer).digest("hex");
|
|
2928
|
-
return { success: true, hash };
|
|
2929
|
-
} catch (error) {
|
|
2930
|
-
logger.debug("Failed to write file:", error);
|
|
2931
|
-
return { success: false, error: error instanceof Error ? error.message : "Failed to write file" };
|
|
2932
|
-
}
|
|
2933
|
-
});
|
|
2934
|
-
session.setHandler("listDirectory", async (data) => {
|
|
2935
|
-
logger.debug("List directory request:", data.path);
|
|
2936
|
-
try {
|
|
2937
|
-
const entries = await readdir(data.path, { withFileTypes: true });
|
|
2938
|
-
const directoryEntries = await Promise.all(
|
|
2939
|
-
entries.map(async (entry) => {
|
|
2940
|
-
const fullPath = join$1(data.path, entry.name);
|
|
2941
|
-
let type = "other";
|
|
2942
|
-
let size;
|
|
2943
|
-
let modified;
|
|
2944
|
-
if (entry.isDirectory()) {
|
|
2945
|
-
type = "directory";
|
|
2946
|
-
} else if (entry.isFile()) {
|
|
2947
|
-
type = "file";
|
|
2948
|
-
}
|
|
2949
|
-
try {
|
|
2950
|
-
const stats = await stat(fullPath);
|
|
2951
|
-
size = stats.size;
|
|
2952
|
-
modified = stats.mtime.getTime();
|
|
2953
|
-
} catch (error) {
|
|
2954
|
-
logger.debug(`Failed to stat ${fullPath}:`, error);
|
|
2955
|
-
}
|
|
2956
|
-
return {
|
|
2957
|
-
name: entry.name,
|
|
2958
|
-
type,
|
|
2959
|
-
size,
|
|
2960
|
-
modified
|
|
2961
|
-
};
|
|
2962
|
-
})
|
|
2963
|
-
);
|
|
2964
|
-
directoryEntries.sort((a, b) => {
|
|
2965
|
-
if (a.type === "directory" && b.type !== "directory") return -1;
|
|
2966
|
-
if (a.type !== "directory" && b.type === "directory") return 1;
|
|
2967
|
-
return a.name.localeCompare(b.name);
|
|
2968
|
-
});
|
|
2969
|
-
return { success: true, entries: directoryEntries };
|
|
2970
|
-
} catch (error) {
|
|
2971
|
-
logger.debug("Failed to list directory:", error);
|
|
2972
|
-
return { success: false, error: error instanceof Error ? error.message : "Failed to list directory" };
|
|
2973
|
-
}
|
|
2974
|
-
});
|
|
2975
|
-
session.setHandler("getDirectoryTree", async (data) => {
|
|
2976
|
-
logger.debug("Get directory tree request:", data.path, "maxDepth:", data.maxDepth);
|
|
2977
|
-
async function buildTree(path, name, currentDepth) {
|
|
2978
|
-
try {
|
|
2979
|
-
const stats = await stat(path);
|
|
2980
|
-
const node = {
|
|
2981
|
-
name,
|
|
2982
|
-
path,
|
|
2983
|
-
type: stats.isDirectory() ? "directory" : "file",
|
|
2984
|
-
size: stats.size,
|
|
2985
|
-
modified: stats.mtime.getTime()
|
|
2986
|
-
};
|
|
2987
|
-
if (stats.isDirectory() && currentDepth < data.maxDepth) {
|
|
2988
|
-
const entries = await readdir(path, { withFileTypes: true });
|
|
2989
|
-
const children = [];
|
|
2990
|
-
await Promise.all(
|
|
2991
|
-
entries.map(async (entry) => {
|
|
2992
|
-
if (entry.isSymbolicLink()) {
|
|
2993
|
-
logger.debug(`Skipping symlink: ${join$1(path, entry.name)}`);
|
|
2994
|
-
return;
|
|
2995
|
-
}
|
|
2996
|
-
const childPath = join$1(path, entry.name);
|
|
2997
|
-
const childNode = await buildTree(childPath, entry.name, currentDepth + 1);
|
|
2998
|
-
if (childNode) {
|
|
2999
|
-
children.push(childNode);
|
|
3000
|
-
}
|
|
3001
|
-
})
|
|
3002
|
-
);
|
|
3003
|
-
children.sort((a, b) => {
|
|
3004
|
-
if (a.type === "directory" && b.type !== "directory") return -1;
|
|
3005
|
-
if (a.type !== "directory" && b.type === "directory") return 1;
|
|
3006
|
-
return a.name.localeCompare(b.name);
|
|
3007
|
-
});
|
|
3008
|
-
node.children = children;
|
|
3009
|
-
}
|
|
3010
|
-
return node;
|
|
3011
|
-
} catch (error) {
|
|
3012
|
-
logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
|
|
3013
|
-
return null;
|
|
3014
|
-
}
|
|
3015
|
-
}
|
|
3016
|
-
try {
|
|
3017
|
-
if (data.maxDepth < 0) {
|
|
3018
|
-
return { success: false, error: "maxDepth must be non-negative" };
|
|
3019
|
-
}
|
|
3020
|
-
const baseName = data.path === "/" ? "/" : data.path.split("/").pop() || data.path;
|
|
3021
|
-
const tree = await buildTree(data.path, baseName, 0);
|
|
3022
|
-
if (!tree) {
|
|
3023
|
-
return { success: false, error: "Failed to access the specified path" };
|
|
3024
|
-
}
|
|
3025
|
-
return { success: true, tree };
|
|
3026
|
-
} catch (error) {
|
|
3027
|
-
logger.debug("Failed to get directory tree:", error);
|
|
3028
|
-
return { success: false, error: error instanceof Error ? error.message : "Failed to get directory tree" };
|
|
3029
|
-
}
|
|
3030
|
-
});
|
|
3031
|
-
session.setHandler("ripgrep", async (data) => {
|
|
3032
|
-
logger.debug("Ripgrep request with args:", data.args, "cwd:", data.cwd);
|
|
3033
|
-
try {
|
|
3034
|
-
const result = await run(data.args, { cwd: data.cwd });
|
|
3035
|
-
return {
|
|
3036
|
-
success: true,
|
|
3037
|
-
exitCode: result.exitCode,
|
|
3038
|
-
stdout: result.stdout.toString(),
|
|
3039
|
-
stderr: result.stderr.toString()
|
|
3040
|
-
};
|
|
3041
|
-
} catch (error) {
|
|
3042
|
-
logger.debug("Failed to run ripgrep:", error);
|
|
3043
|
-
return {
|
|
3044
|
-
success: false,
|
|
3045
|
-
error: error instanceof Error ? error.message : "Failed to run ripgrep"
|
|
3046
|
-
};
|
|
3047
|
-
}
|
|
3048
|
-
});
|
|
3049
|
-
}
|
|
3050
|
-
function registerKillSessionHandler(session, killThisHappy) {
|
|
3051
|
-
session.setHandler("killSession", async () => {
|
|
3052
|
-
logger.debug("Kill session request received");
|
|
3053
|
-
void killThisHappy();
|
|
3054
|
-
return {
|
|
3055
|
-
success: true,
|
|
3056
|
-
message: "Killing happy-cli process"
|
|
3057
|
-
};
|
|
3058
|
-
});
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
2806
|
class MessageQueue2 {
|
|
3062
2807
|
queue = [];
|
|
3063
2808
|
// Made public for testing
|
|
@@ -4621,7 +4366,7 @@ async function startDaemon() {
|
|
|
4621
4366
|
startedAt: Date.now()
|
|
4622
4367
|
};
|
|
4623
4368
|
const api = new ApiClient(credentials.token, credentials.secret);
|
|
4624
|
-
const machine = await api.
|
|
4369
|
+
const machine = await api.getOrCreateMachine({
|
|
4625
4370
|
machineId,
|
|
4626
4371
|
metadata: initialMachineMetadata,
|
|
4627
4372
|
daemonState: initialDaemonState
|
|
@@ -4803,6 +4548,17 @@ async function startHappyServer(client) {
|
|
|
4803
4548
|
};
|
|
4804
4549
|
}
|
|
4805
4550
|
|
|
4551
|
+
function registerKillSessionHandler(rpcHandlerManager, killThisHappy) {
|
|
4552
|
+
rpcHandlerManager.registerHandler("killSession", async () => {
|
|
4553
|
+
logger.debug("Kill session request received");
|
|
4554
|
+
void killThisHappy();
|
|
4555
|
+
return {
|
|
4556
|
+
success: true,
|
|
4557
|
+
message: "Killing happy-cli process"
|
|
4558
|
+
};
|
|
4559
|
+
});
|
|
4560
|
+
}
|
|
4561
|
+
|
|
4806
4562
|
async function start(credentials, options = {}) {
|
|
4807
4563
|
const workingDirectory = process.cwd();
|
|
4808
4564
|
const sessionTag = randomUUID();
|
|
@@ -4821,7 +4577,7 @@ async function start(credentials, options = {}) {
|
|
|
4821
4577
|
process.exit(1);
|
|
4822
4578
|
}
|
|
4823
4579
|
logger.debug(`Using machineId: ${machineId}`);
|
|
4824
|
-
await api.
|
|
4580
|
+
await api.getOrCreateMachine({
|
|
4825
4581
|
machineId,
|
|
4826
4582
|
metadata: initialMachineMetadata
|
|
4827
4583
|
});
|
|
@@ -4889,7 +4645,6 @@ async function start(credentials, options = {}) {
|
|
|
4889
4645
|
allowedTools: mode.allowedTools,
|
|
4890
4646
|
disallowedTools: mode.disallowedTools
|
|
4891
4647
|
}));
|
|
4892
|
-
registerHandlers(session);
|
|
4893
4648
|
let currentPermissionMode = options.permissionMode;
|
|
4894
4649
|
let currentModel = options.model;
|
|
4895
4650
|
let currentFallbackModel = void 0;
|
|
@@ -5036,7 +4791,7 @@ async function start(credentials, options = {}) {
|
|
|
5036
4791
|
logger.debug("[START] Unhandled rejection:", reason);
|
|
5037
4792
|
cleanup();
|
|
5038
4793
|
});
|
|
5039
|
-
registerKillSessionHandler(session, cleanup);
|
|
4794
|
+
registerKillSessionHandler(session.rpcHandlerManager, cleanup);
|
|
5040
4795
|
await loop({
|
|
5041
4796
|
path: workingDirectory,
|
|
5042
4797
|
model: options.model,
|
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-D9P2bndj.cjs');
|
|
4
4
|
require('axios');
|
|
5
5
|
require('chalk');
|
|
6
6
|
require('fs');
|
|
@@ -13,6 +13,12 @@ require('node:crypto');
|
|
|
13
13
|
require('tweetnacl');
|
|
14
14
|
require('node:events');
|
|
15
15
|
require('socket.io-client');
|
|
16
|
+
require('child_process');
|
|
17
|
+
require('util');
|
|
18
|
+
require('fs/promises');
|
|
19
|
+
require('crypto');
|
|
20
|
+
require('path');
|
|
21
|
+
require('url');
|
|
16
22
|
require('expo-server-sdk');
|
|
17
23
|
|
|
18
24
|
|
package/dist/lib.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { Socket } from 'socket.io-client';
|
|
3
4
|
import { ExpoPushMessage } from 'expo-server-sdk';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -287,7 +288,80 @@ declare const RawJSONLinesSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
|
287
288
|
}, z.ZodTypeAny, "passthrough">>]>;
|
|
288
289
|
type RawJSONLines = z.infer<typeof RawJSONLinesSchema>;
|
|
289
290
|
|
|
290
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Common RPC types and interfaces for both session and machine clients
|
|
293
|
+
*/
|
|
294
|
+
/**
|
|
295
|
+
* Generic RPC handler function type
|
|
296
|
+
* @template TRequest - The request data type
|
|
297
|
+
* @template TResponse - The response data type
|
|
298
|
+
*/
|
|
299
|
+
type RpcHandler<TRequest = any, TResponse = any> = (data: TRequest) => TResponse | Promise<TResponse>;
|
|
300
|
+
/**
|
|
301
|
+
* RPC request data from server
|
|
302
|
+
*/
|
|
303
|
+
interface RpcRequest {
|
|
304
|
+
method: string;
|
|
305
|
+
params: string;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Configuration for RPC handler manager
|
|
309
|
+
*/
|
|
310
|
+
interface RpcHandlerConfig {
|
|
311
|
+
/** Prefix to add to all method names (e.g., sessionId or machineId) */
|
|
312
|
+
scopePrefix: string;
|
|
313
|
+
/** Secret key for encryption/decryption */
|
|
314
|
+
secret: Uint8Array;
|
|
315
|
+
/** Logger function for debugging */
|
|
316
|
+
logger?: (message: string, data?: any) => void;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Generic RPC handler manager for session and machine clients
|
|
321
|
+
* Manages RPC method registration, encryption/decryption, and handler execution
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
declare class RpcHandlerManager {
|
|
325
|
+
private handlers;
|
|
326
|
+
private readonly scopePrefix;
|
|
327
|
+
private readonly secret;
|
|
328
|
+
private readonly logger;
|
|
329
|
+
private socket;
|
|
330
|
+
constructor(config: RpcHandlerConfig);
|
|
331
|
+
/**
|
|
332
|
+
* Register an RPC handler for a specific method
|
|
333
|
+
* @param method - The method name (without prefix)
|
|
334
|
+
* @param handler - The handler function
|
|
335
|
+
*/
|
|
336
|
+
registerHandler<TRequest = any, TResponse = any>(method: string, handler: RpcHandler<TRequest, TResponse>): void;
|
|
337
|
+
/**
|
|
338
|
+
* Handle an incoming RPC request
|
|
339
|
+
* @param request - The RPC request data
|
|
340
|
+
* @param callback - The response callback
|
|
341
|
+
*/
|
|
342
|
+
handleRequest(request: RpcRequest): Promise<any>;
|
|
343
|
+
onSocketConnect(socket: Socket): void;
|
|
344
|
+
onSocketDisconnect(): void;
|
|
345
|
+
/**
|
|
346
|
+
* Get the number of registered handlers
|
|
347
|
+
*/
|
|
348
|
+
getHandlerCount(): number;
|
|
349
|
+
/**
|
|
350
|
+
* Check if a handler is registered
|
|
351
|
+
* @param method - The method name (without prefix)
|
|
352
|
+
*/
|
|
353
|
+
hasHandler(method: string): boolean;
|
|
354
|
+
/**
|
|
355
|
+
* Clear all handlers
|
|
356
|
+
*/
|
|
357
|
+
clearHandlers(): void;
|
|
358
|
+
/**
|
|
359
|
+
* Get the prefixed method name
|
|
360
|
+
* @param method - The method name
|
|
361
|
+
*/
|
|
362
|
+
private getPrefixedMethod;
|
|
363
|
+
}
|
|
364
|
+
|
|
291
365
|
declare class ApiSessionClient extends EventEmitter {
|
|
292
366
|
private readonly token;
|
|
293
367
|
private readonly secret;
|
|
@@ -299,7 +373,7 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
299
373
|
private socket;
|
|
300
374
|
private pendingMessages;
|
|
301
375
|
private pendingMessageCallback;
|
|
302
|
-
|
|
376
|
+
readonly rpcHandlerManager: RpcHandlerManager;
|
|
303
377
|
private agentStateLock;
|
|
304
378
|
private metadataLock;
|
|
305
379
|
constructor(token: string, secret: Uint8Array, session: Session);
|
|
@@ -343,16 +417,6 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
343
417
|
* @param handler - Handler function that returns the updated agent state
|
|
344
418
|
*/
|
|
345
419
|
updateAgentState(handler: (metadata: AgentState) => AgentState): void;
|
|
346
|
-
/**
|
|
347
|
-
* Set a custom RPC handler for a specific method with encrypted arguments and responses
|
|
348
|
-
* @param method - The method name to handle
|
|
349
|
-
* @param handler - The handler function to call when the method is invoked
|
|
350
|
-
*/
|
|
351
|
-
setHandler<T = any, R = any>(method: string, handler: RpcHandler<T, R>): void;
|
|
352
|
-
/**
|
|
353
|
-
* Re-register all RPC handlers after reconnection
|
|
354
|
-
*/
|
|
355
|
-
private reregisterHandlers;
|
|
356
420
|
/**
|
|
357
421
|
* Wait for socket buffer to flush
|
|
358
422
|
*/
|
|
@@ -642,11 +706,6 @@ type AgentState = {
|
|
|
642
706
|
};
|
|
643
707
|
};
|
|
644
708
|
|
|
645
|
-
/**
|
|
646
|
-
* RPC handlers for API session communication
|
|
647
|
-
* Handles remote procedure calls from mobile clients
|
|
648
|
-
*/
|
|
649
|
-
|
|
650
709
|
interface SpawnSessionOptions {
|
|
651
710
|
machineId?: string;
|
|
652
711
|
directory: string;
|
|
@@ -680,9 +739,7 @@ declare class ApiMachineClient {
|
|
|
680
739
|
private machine;
|
|
681
740
|
private socket;
|
|
682
741
|
private keepAliveInterval;
|
|
683
|
-
private
|
|
684
|
-
private stopSession?;
|
|
685
|
-
private requestShutdown?;
|
|
742
|
+
private rpcHandlerManager;
|
|
686
743
|
constructor(token: string, secret: Uint8Array, machine: Machine);
|
|
687
744
|
setRPCHandlers({ spawnSession, stopSession, requestShutdown }: MachineRpcHandlers): void;
|
|
688
745
|
/**
|
|
@@ -753,7 +810,7 @@ declare class ApiClient {
|
|
|
753
810
|
* Register or update machine with the server
|
|
754
811
|
* Returns the current machine state from the server with decrypted metadata and daemonState
|
|
755
812
|
*/
|
|
756
|
-
|
|
813
|
+
getOrCreateMachine(opts: {
|
|
757
814
|
machineId: string;
|
|
758
815
|
metadata: MachineMetadata;
|
|
759
816
|
daemonState?: DaemonState;
|