@appchy/jarvis 0.1.4 → 0.1.5
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/bin.js +173 -32
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
// src/bin.ts
|
|
2
2
|
import dotenv from "dotenv";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import fs8 from "fs";
|
|
4
|
+
import path8 from "path";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
+
import { spawn as spawn2, execSync } from "child_process";
|
|
9
|
+
import fs7 from "fs";
|
|
10
|
+
import path7 from "path";
|
|
11
|
+
import os4 from "os";
|
|
8
12
|
|
|
9
13
|
// src/config.ts
|
|
10
14
|
import fs from "fs";
|
|
@@ -4660,6 +4664,34 @@ async function waitForAgent(port, maxAttempts = 30) {
|
|
|
4660
4664
|
}
|
|
4661
4665
|
|
|
4662
4666
|
// src/cli.ts
|
|
4667
|
+
var LOG_DIR = path7.join(os4.homedir(), ".jarvis");
|
|
4668
|
+
var LOG_FILE = path7.join(LOG_DIR, "agent.log");
|
|
4669
|
+
var PID_FILE = path7.join(LOG_DIR, "agent.pid");
|
|
4670
|
+
function savePid(pid) {
|
|
4671
|
+
fs7.mkdirSync(LOG_DIR, { recursive: true });
|
|
4672
|
+
fs7.writeFileSync(PID_FILE, String(pid));
|
|
4673
|
+
}
|
|
4674
|
+
function readPid() {
|
|
4675
|
+
try {
|
|
4676
|
+
const pid = parseInt(fs7.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
4677
|
+
if (isNaN(pid)) return null;
|
|
4678
|
+
try {
|
|
4679
|
+
process.kill(pid, 0);
|
|
4680
|
+
return pid;
|
|
4681
|
+
} catch {
|
|
4682
|
+
fs7.unlinkSync(PID_FILE);
|
|
4683
|
+
return null;
|
|
4684
|
+
}
|
|
4685
|
+
} catch {
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
function clearPid() {
|
|
4690
|
+
try {
|
|
4691
|
+
fs7.unlinkSync(PID_FILE);
|
|
4692
|
+
} catch {
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4663
4695
|
function createCli() {
|
|
4664
4696
|
const program = new Command().name("jarvis").description("Jarvis local agent \u2014 runs Claude Code on your machine").version("0.0.0");
|
|
4665
4697
|
program.command("connect <token>").description("Connect to Jarvis cloud using a token from the web UI").option("-w, --workspace <path>", "Workspace root path for repo operations").action((token, opts) => {
|
|
@@ -4687,15 +4719,13 @@ function createCli() {
|
|
|
4687
4719
|
process.exit(1);
|
|
4688
4720
|
}
|
|
4689
4721
|
});
|
|
4690
|
-
program.command("start").description("Start the local agent").option("-p, --port <port>", "Local WS server port", "7862").option("-w, --workspace <path>", "Workspace root path").option("--api-key <key>", "Anthropic API key (for local-only use)").option("--no-upstream", "Don't connect to cloud (local-only mode)").action(async (opts) => {
|
|
4722
|
+
program.command("start").description("Start the local agent (runs as background daemon)").option("-p, --port <port>", "Local WS server port", "7862").option("-w, --workspace <path>", "Workspace root path").option("--api-key <key>", "Anthropic API key (for local-only use)").option("--no-upstream", "Don't connect to cloud (local-only mode)").option("--foreground", "Run in foreground (don't daemonize)").action(async (opts) => {
|
|
4691
4723
|
const config = loadConfig();
|
|
4692
4724
|
const port = parseInt(opts.port, 10);
|
|
4693
4725
|
const alreadyRunning = await isPortInUse(port);
|
|
4694
4726
|
if (alreadyRunning) {
|
|
4695
|
-
console.log(`
|
|
4696
|
-
|
|
4697
|
-
console.log(`Clients (jarvis chat, VSCode) can connect to it.
|
|
4698
|
-
`);
|
|
4727
|
+
console.log(`Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
4728
|
+
console.log(`Use 'jarvis restart' to restart, or 'jarvis logs' to view logs.`);
|
|
4699
4729
|
return;
|
|
4700
4730
|
}
|
|
4701
4731
|
const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();
|
|
@@ -4704,35 +4734,146 @@ Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
|
4704
4734
|
if (!anthropicApiKey && !config?.useSubscription) {
|
|
4705
4735
|
console.warn("Warning: No Anthropic API key set. Using subscription mode.");
|
|
4706
4736
|
}
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4737
|
+
if (opts.foreground) {
|
|
4738
|
+
await startAgent({
|
|
4739
|
+
port,
|
|
4740
|
+
workspacePath,
|
|
4741
|
+
anthropicApiKey,
|
|
4742
|
+
useSubscription: !anthropicApiKey,
|
|
4743
|
+
userId,
|
|
4744
|
+
upstream: opts.upstream && config?.apiUrl && config?.token ? { apiUrl: config.apiUrl, token: config.token } : void 0
|
|
4745
|
+
});
|
|
4746
|
+
return;
|
|
4747
|
+
}
|
|
4748
|
+
fs7.mkdirSync(LOG_DIR, { recursive: true });
|
|
4749
|
+
const logFd = fs7.openSync(LOG_FILE, "a");
|
|
4750
|
+
const args = [
|
|
4751
|
+
"start",
|
|
4752
|
+
"--foreground",
|
|
4753
|
+
"--port",
|
|
4754
|
+
String(port),
|
|
4755
|
+
"--workspace",
|
|
4756
|
+
workspacePath
|
|
4757
|
+
];
|
|
4758
|
+
if (!opts.upstream) {
|
|
4759
|
+
args.push("--no-upstream");
|
|
4760
|
+
}
|
|
4761
|
+
if (anthropicApiKey) {
|
|
4762
|
+
args.push("--api-key", anthropicApiKey);
|
|
4763
|
+
}
|
|
4764
|
+
const binPath = process.argv[1];
|
|
4765
|
+
const child = spawn2(process.execPath, [binPath, ...args], {
|
|
4766
|
+
detached: true,
|
|
4767
|
+
stdio: ["ignore", logFd, logFd],
|
|
4768
|
+
cwd: workspacePath,
|
|
4769
|
+
env: { ...process.env, NODE_NO_WARNINGS: "1" }
|
|
4714
4770
|
});
|
|
4771
|
+
child.unref();
|
|
4772
|
+
fs7.closeSync(logFd);
|
|
4773
|
+
savePid(child.pid);
|
|
4774
|
+
console.log(`Jarvis agent started (PID: ${child.pid})`);
|
|
4775
|
+
console.log(` Local: ws://127.0.0.1:${port}`);
|
|
4776
|
+
console.log(` Workspace: ${workspacePath}`);
|
|
4777
|
+
console.log(` Logs: ${LOG_FILE}`);
|
|
4778
|
+
if (config?.apiUrl) {
|
|
4779
|
+
console.log(` Cloud: ${config.apiUrl}`);
|
|
4780
|
+
}
|
|
4781
|
+
console.log();
|
|
4782
|
+
console.log(`Commands:`);
|
|
4783
|
+
console.log(` jarvis logs \u2014 View agent logs`);
|
|
4784
|
+
console.log(` jarvis stop \u2014 Stop the agent`);
|
|
4785
|
+
console.log(` jarvis restart \u2014 Restart the agent`);
|
|
4786
|
+
});
|
|
4787
|
+
program.command("stop").description("Stop the running agent").action(async () => {
|
|
4788
|
+
const pid = readPid();
|
|
4789
|
+
if (pid) {
|
|
4790
|
+
try {
|
|
4791
|
+
process.kill(pid, "SIGTERM");
|
|
4792
|
+
clearPid();
|
|
4793
|
+
console.log(`Agent stopped (PID: ${pid})`);
|
|
4794
|
+
} catch {
|
|
4795
|
+
clearPid();
|
|
4796
|
+
console.log("Agent process not found. Cleaned up PID file.");
|
|
4797
|
+
}
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
const running = await isPortInUse(7862);
|
|
4801
|
+
if (running) {
|
|
4802
|
+
try {
|
|
4803
|
+
const output = execSync("lsof -ti :7862", { encoding: "utf-8" }).trim();
|
|
4804
|
+
if (output) {
|
|
4805
|
+
const pids = output.split("\n");
|
|
4806
|
+
for (const p of pids) {
|
|
4807
|
+
try {
|
|
4808
|
+
process.kill(parseInt(p, 10), "SIGTERM");
|
|
4809
|
+
} catch {
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
console.log("Agent stopped.");
|
|
4813
|
+
return;
|
|
4814
|
+
}
|
|
4815
|
+
} catch {
|
|
4816
|
+
}
|
|
4817
|
+
}
|
|
4818
|
+
console.log("No agent is running.");
|
|
4819
|
+
});
|
|
4820
|
+
program.command("restart").description("Restart the agent").action(async () => {
|
|
4821
|
+
const pid = readPid();
|
|
4822
|
+
if (pid) {
|
|
4823
|
+
try {
|
|
4824
|
+
process.kill(pid, "SIGTERM");
|
|
4825
|
+
} catch {
|
|
4826
|
+
}
|
|
4827
|
+
clearPid();
|
|
4828
|
+
console.log(`Stopped agent (PID: ${pid})`);
|
|
4829
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
4830
|
+
}
|
|
4831
|
+
console.log("Starting agent...");
|
|
4832
|
+
await program.parseAsync(["node", "jarvis", "start"]);
|
|
4833
|
+
});
|
|
4834
|
+
program.command("logs").description("View agent logs").option("-f, --follow", "Follow log output (like tail -f)").option("-n, --lines <n>", "Number of lines to show", "50").action((opts) => {
|
|
4835
|
+
if (!fs7.existsSync(LOG_FILE)) {
|
|
4836
|
+
console.log("No log file found. Start the agent first: jarvis start");
|
|
4837
|
+
return;
|
|
4838
|
+
}
|
|
4839
|
+
if (opts.follow) {
|
|
4840
|
+
const tail = spawn2("tail", ["-f", "-n", opts.lines, LOG_FILE], {
|
|
4841
|
+
stdio: "inherit"
|
|
4842
|
+
});
|
|
4843
|
+
process.on("SIGINT", () => {
|
|
4844
|
+
tail.kill();
|
|
4845
|
+
process.exit(0);
|
|
4846
|
+
});
|
|
4847
|
+
tail.on("exit", () => process.exit(0));
|
|
4848
|
+
} else {
|
|
4849
|
+
const content = execSync(`tail -n ${opts.lines} "${LOG_FILE}"`, { encoding: "utf-8" });
|
|
4850
|
+
process.stdout.write(content);
|
|
4851
|
+
}
|
|
4715
4852
|
});
|
|
4716
4853
|
program.command("chat").description("Interactive TUI \u2014 chat with Jarvis in your terminal").option("--model <id>", "Model (e.g., claude-opus-4-20250514)").option("--mode <mode>", "Permission mode: supervised|auto|plan|yolo").option("--thinking <config>", "Thinking: adaptive|enabled|disabled").option("--thinking-budget <n>", "Token budget when thinking=enabled").option("--max-turns <n>", "Max turns per task").option("-p, --port <port>", "Agent server port", "7862").option("-w, --workspace <path>", "Workspace root path").option("--no-server", "Connect to existing server, don't auto-start").action(async (opts) => {
|
|
4717
4854
|
await launchChat(opts);
|
|
4718
4855
|
});
|
|
4719
|
-
program.command("status").description("Show agent configuration and connection status").action(() => {
|
|
4856
|
+
program.command("status").description("Show agent configuration and connection status").action(async () => {
|
|
4720
4857
|
const config = loadConfig();
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
}
|
|
4726
|
-
console.log(
|
|
4858
|
+
const pid = readPid();
|
|
4859
|
+
const port = config?.port ?? 7862;
|
|
4860
|
+
const running = await isPortInUse(port);
|
|
4861
|
+
console.log("Jarvis Agent:");
|
|
4862
|
+
console.log(` Status: ${running ? `\x1B[32mrunning\x1B[0m` : `\x1B[31mstopped\x1B[0m`}${pid ? ` (PID: ${pid})` : ""}`);
|
|
4863
|
+
console.log(` Port: ${port}`);
|
|
4727
4864
|
console.log(` Config: ${getConfigPath()}`);
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4865
|
+
if (config) {
|
|
4866
|
+
console.log(` User: ${config.userId}`);
|
|
4867
|
+
console.log(` Env: ${config.envId ?? "local"}`);
|
|
4868
|
+
console.log(` Workspace: ${config.workspacePath ?? "(cwd)"}`);
|
|
4869
|
+
console.log(` Cloud: ${config.apiUrl ?? "(not connected)"}`);
|
|
4870
|
+
if (config.connectedAt) {
|
|
4871
|
+
console.log(` Connected: ${config.connectedAt}`);
|
|
4872
|
+
}
|
|
4873
|
+
} else {
|
|
4874
|
+
console.log(` Config: Not set up. Run 'jarvis connect <token>'`);
|
|
4735
4875
|
}
|
|
4876
|
+
console.log(` Logs: ${LOG_FILE}`);
|
|
4736
4877
|
});
|
|
4737
4878
|
program.command("logout").description("Clear saved configuration").action(() => {
|
|
4738
4879
|
clearConfig();
|
|
@@ -4744,10 +4885,10 @@ Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
|
4744
4885
|
// src/bin.ts
|
|
4745
4886
|
function findEnv() {
|
|
4746
4887
|
let dir = process.cwd();
|
|
4747
|
-
while (dir !==
|
|
4748
|
-
const envPath =
|
|
4749
|
-
if (
|
|
4750
|
-
dir =
|
|
4888
|
+
while (dir !== path8.dirname(dir)) {
|
|
4889
|
+
const envPath = path8.join(dir, ".env");
|
|
4890
|
+
if (fs8.existsSync(envPath)) return envPath;
|
|
4891
|
+
dir = path8.dirname(dir);
|
|
4751
4892
|
}
|
|
4752
4893
|
return void 0;
|
|
4753
4894
|
}
|