@appchy/jarvis 0.1.4 → 0.1.6
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 +190 -39
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
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";
|
|
@@ -384,7 +388,7 @@ function claudeCodeProvider(config = {}) {
|
|
|
384
388
|
options: {
|
|
385
389
|
model: req.model,
|
|
386
390
|
systemPrompt: systemPromptOption,
|
|
387
|
-
maxTurns: config.maxTurns
|
|
391
|
+
...config.maxTurns ? { maxTurns: config.maxTurns } : {},
|
|
388
392
|
...permissionOptions,
|
|
389
393
|
...config.mcpServers ? { mcpServers: config.mcpServers } : {},
|
|
390
394
|
...config.workingDirectory ? { cwd: config.workingDirectory } : {},
|
|
@@ -553,7 +557,7 @@ function claudeCodeProvider(config = {}) {
|
|
|
553
557
|
options: {
|
|
554
558
|
model: req.model,
|
|
555
559
|
systemPrompt: streamSystemPromptOption,
|
|
556
|
-
maxTurns: config.maxTurns
|
|
560
|
+
...config.maxTurns ? { maxTurns: config.maxTurns } : {},
|
|
557
561
|
...permissionOptions,
|
|
558
562
|
...config.mcpServers ? { mcpServers: config.mcpServers } : {},
|
|
559
563
|
...config.workingDirectory ? { cwd: config.workingDirectory } : {},
|
|
@@ -2052,7 +2056,7 @@ function createWsProgressHandlers(deps) {
|
|
|
2052
2056
|
id: `status-plan-${crypto2.randomUUID()}`,
|
|
2053
2057
|
role: "assistant",
|
|
2054
2058
|
type: "status",
|
|
2055
|
-
content: "Planning
|
|
2059
|
+
content: "Planning",
|
|
2056
2060
|
isPartial: true,
|
|
2057
2061
|
createdAt: now
|
|
2058
2062
|
});
|
|
@@ -2234,7 +2238,7 @@ function createAgent(deps) {
|
|
|
2234
2238
|
systemPrompt: systemMsg?.content ?? "",
|
|
2235
2239
|
workingDirectory: wsPath,
|
|
2236
2240
|
tools: claudeCodeTools,
|
|
2237
|
-
maxTurns: msg.maxTurns
|
|
2241
|
+
...msg.maxTurns ? { maxTurns: msg.maxTurns } : {},
|
|
2238
2242
|
userId: deps.userId,
|
|
2239
2243
|
abortController,
|
|
2240
2244
|
heartbeat: () => {
|
|
@@ -2262,7 +2266,7 @@ function createAgent(deps) {
|
|
|
2262
2266
|
...deps.useSubscription ? { useSubscription: true } : { apiKey: deps.anthropicApiKey },
|
|
2263
2267
|
workingDirectory: wsPath,
|
|
2264
2268
|
tools: claudeCodeTools,
|
|
2265
|
-
maxTurns: msg.maxTurns
|
|
2269
|
+
...msg.maxTurns ? { maxTurns: msg.maxTurns } : {},
|
|
2266
2270
|
userId: deps.userId,
|
|
2267
2271
|
abortController,
|
|
2268
2272
|
heartbeat: () => {
|
|
@@ -4660,8 +4664,39 @@ async function waitForAgent(port, maxAttempts = 30) {
|
|
|
4660
4664
|
}
|
|
4661
4665
|
|
|
4662
4666
|
// src/cli.ts
|
|
4667
|
+
import { createRequire } from "module";
|
|
4668
|
+
var _require = createRequire(import.meta.url);
|
|
4669
|
+
var PKG_VERSION = _require("../package.json").version ?? "dev";
|
|
4670
|
+
var LOG_DIR = path7.join(os4.homedir(), ".jarvis");
|
|
4671
|
+
var LOG_FILE = path7.join(LOG_DIR, "agent.log");
|
|
4672
|
+
var PID_FILE = path7.join(LOG_DIR, "agent.pid");
|
|
4673
|
+
function savePid(pid) {
|
|
4674
|
+
fs7.mkdirSync(LOG_DIR, { recursive: true });
|
|
4675
|
+
fs7.writeFileSync(PID_FILE, String(pid));
|
|
4676
|
+
}
|
|
4677
|
+
function readPid() {
|
|
4678
|
+
try {
|
|
4679
|
+
const pid = parseInt(fs7.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
4680
|
+
if (isNaN(pid)) return null;
|
|
4681
|
+
try {
|
|
4682
|
+
process.kill(pid, 0);
|
|
4683
|
+
return pid;
|
|
4684
|
+
} catch {
|
|
4685
|
+
fs7.unlinkSync(PID_FILE);
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
} catch {
|
|
4689
|
+
return null;
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
function clearPid() {
|
|
4693
|
+
try {
|
|
4694
|
+
fs7.unlinkSync(PID_FILE);
|
|
4695
|
+
} catch {
|
|
4696
|
+
}
|
|
4697
|
+
}
|
|
4663
4698
|
function createCli() {
|
|
4664
|
-
const program = new Command().name("jarvis").description("Jarvis local agent \u2014 runs Claude Code on your machine").version(
|
|
4699
|
+
const program = new Command().name("jarvis").description("Jarvis local agent \u2014 runs Claude Code on your machine").version(PKG_VERSION);
|
|
4665
4700
|
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) => {
|
|
4666
4701
|
try {
|
|
4667
4702
|
const parsed = parseConnectToken(token);
|
|
@@ -4687,15 +4722,13 @@ function createCli() {
|
|
|
4687
4722
|
process.exit(1);
|
|
4688
4723
|
}
|
|
4689
4724
|
});
|
|
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) => {
|
|
4725
|
+
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
4726
|
const config = loadConfig();
|
|
4692
4727
|
const port = parseInt(opts.port, 10);
|
|
4693
4728
|
const alreadyRunning = await isPortInUse(port);
|
|
4694
4729
|
if (alreadyRunning) {
|
|
4695
|
-
console.log(`
|
|
4696
|
-
|
|
4697
|
-
console.log(`Clients (jarvis chat, VSCode) can connect to it.
|
|
4698
|
-
`);
|
|
4730
|
+
console.log(`Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
4731
|
+
console.log(`Use 'jarvis restart' to restart, or 'jarvis logs' to view logs.`);
|
|
4699
4732
|
return;
|
|
4700
4733
|
}
|
|
4701
4734
|
const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();
|
|
@@ -4704,35 +4737,153 @@ Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
|
4704
4737
|
if (!anthropicApiKey && !config?.useSubscription) {
|
|
4705
4738
|
console.warn("Warning: No Anthropic API key set. Using subscription mode.");
|
|
4706
4739
|
}
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4740
|
+
if (opts.foreground) {
|
|
4741
|
+
await startAgent({
|
|
4742
|
+
port,
|
|
4743
|
+
workspacePath,
|
|
4744
|
+
anthropicApiKey,
|
|
4745
|
+
useSubscription: !anthropicApiKey,
|
|
4746
|
+
userId,
|
|
4747
|
+
upstream: opts.upstream && config?.apiUrl && config?.token ? { apiUrl: config.apiUrl, token: config.token } : void 0
|
|
4748
|
+
});
|
|
4749
|
+
return;
|
|
4750
|
+
}
|
|
4751
|
+
fs7.mkdirSync(LOG_DIR, { recursive: true });
|
|
4752
|
+
const logFd = fs7.openSync(LOG_FILE, "a");
|
|
4753
|
+
const args = [
|
|
4754
|
+
"start",
|
|
4755
|
+
"--foreground",
|
|
4756
|
+
"--port",
|
|
4757
|
+
String(port),
|
|
4758
|
+
"--workspace",
|
|
4759
|
+
workspacePath
|
|
4760
|
+
];
|
|
4761
|
+
if (!opts.upstream) {
|
|
4762
|
+
args.push("--no-upstream");
|
|
4763
|
+
}
|
|
4764
|
+
if (anthropicApiKey) {
|
|
4765
|
+
args.push("--api-key", anthropicApiKey);
|
|
4766
|
+
}
|
|
4767
|
+
const binPath = process.argv[1];
|
|
4768
|
+
const cliRoot = path7.resolve(path7.dirname(binPath), "..");
|
|
4769
|
+
const distEntry = path7.join(cliRoot, "dist", "bin.js");
|
|
4770
|
+
const useDistEntry = fs7.existsSync(distEntry);
|
|
4771
|
+
const child = spawn2(
|
|
4772
|
+
process.execPath,
|
|
4773
|
+
useDistEntry ? [distEntry, ...args] : [binPath, ...args],
|
|
4774
|
+
{
|
|
4775
|
+
detached: true,
|
|
4776
|
+
stdio: ["ignore", logFd, logFd],
|
|
4777
|
+
cwd: workspacePath,
|
|
4778
|
+
env: { ...process.env, NODE_NO_WARNINGS: "1" }
|
|
4779
|
+
}
|
|
4780
|
+
);
|
|
4781
|
+
child.unref();
|
|
4782
|
+
fs7.closeSync(logFd);
|
|
4783
|
+
savePid(child.pid);
|
|
4784
|
+
console.log(`Jarvis agent started (PID: ${child.pid})`);
|
|
4785
|
+
console.log(` Local: ws://127.0.0.1:${port}`);
|
|
4786
|
+
console.log(` Workspace: ${workspacePath}`);
|
|
4787
|
+
console.log(` Logs: ${LOG_FILE}`);
|
|
4788
|
+
if (config?.apiUrl) {
|
|
4789
|
+
console.log(` Cloud: ${config.apiUrl}`);
|
|
4790
|
+
}
|
|
4791
|
+
console.log();
|
|
4792
|
+
console.log(`Commands:`);
|
|
4793
|
+
console.log(` jarvis logs \u2014 View agent logs`);
|
|
4794
|
+
console.log(` jarvis stop \u2014 Stop the agent`);
|
|
4795
|
+
console.log(` jarvis restart \u2014 Restart the agent`);
|
|
4796
|
+
});
|
|
4797
|
+
program.command("stop").description("Stop the running agent").action(async () => {
|
|
4798
|
+
const pid = readPid();
|
|
4799
|
+
if (pid) {
|
|
4800
|
+
try {
|
|
4801
|
+
process.kill(pid, "SIGTERM");
|
|
4802
|
+
clearPid();
|
|
4803
|
+
console.log(`Agent stopped (PID: ${pid})`);
|
|
4804
|
+
} catch {
|
|
4805
|
+
clearPid();
|
|
4806
|
+
console.log("Agent process not found. Cleaned up PID file.");
|
|
4807
|
+
}
|
|
4808
|
+
return;
|
|
4809
|
+
}
|
|
4810
|
+
const running = await isPortInUse(7862);
|
|
4811
|
+
if (running) {
|
|
4812
|
+
try {
|
|
4813
|
+
const output = execSync("lsof -ti :7862", { encoding: "utf-8" }).trim();
|
|
4814
|
+
if (output) {
|
|
4815
|
+
const pids = output.split("\n");
|
|
4816
|
+
for (const p of pids) {
|
|
4817
|
+
try {
|
|
4818
|
+
process.kill(parseInt(p, 10), "SIGTERM");
|
|
4819
|
+
} catch {
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
console.log("Agent stopped.");
|
|
4823
|
+
return;
|
|
4824
|
+
}
|
|
4825
|
+
} catch {
|
|
4826
|
+
}
|
|
4827
|
+
}
|
|
4828
|
+
console.log("No agent is running.");
|
|
4829
|
+
});
|
|
4830
|
+
program.command("restart").description("Restart the agent").action(async () => {
|
|
4831
|
+
const pid = readPid();
|
|
4832
|
+
if (pid) {
|
|
4833
|
+
try {
|
|
4834
|
+
process.kill(pid, "SIGTERM");
|
|
4835
|
+
} catch {
|
|
4836
|
+
}
|
|
4837
|
+
clearPid();
|
|
4838
|
+
console.log(`Stopped agent (PID: ${pid})`);
|
|
4839
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
4840
|
+
}
|
|
4841
|
+
console.log("Starting agent...");
|
|
4842
|
+
await program.parseAsync(["node", "jarvis", "start"]);
|
|
4843
|
+
});
|
|
4844
|
+
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) => {
|
|
4845
|
+
if (!fs7.existsSync(LOG_FILE)) {
|
|
4846
|
+
console.log("No log file found. Start the agent first: jarvis start");
|
|
4847
|
+
return;
|
|
4848
|
+
}
|
|
4849
|
+
if (opts.follow) {
|
|
4850
|
+
const tail = spawn2("tail", ["-f", "-n", opts.lines, LOG_FILE], {
|
|
4851
|
+
stdio: "inherit"
|
|
4852
|
+
});
|
|
4853
|
+
process.on("SIGINT", () => {
|
|
4854
|
+
tail.kill();
|
|
4855
|
+
process.exit(0);
|
|
4856
|
+
});
|
|
4857
|
+
tail.on("exit", () => process.exit(0));
|
|
4858
|
+
} else {
|
|
4859
|
+
const content = execSync(`tail -n ${opts.lines} "${LOG_FILE}"`, { encoding: "utf-8" });
|
|
4860
|
+
process.stdout.write(content);
|
|
4861
|
+
}
|
|
4715
4862
|
});
|
|
4716
4863
|
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
4864
|
await launchChat(opts);
|
|
4718
4865
|
});
|
|
4719
|
-
program.command("status").description("Show agent configuration and connection status").action(() => {
|
|
4866
|
+
program.command("status").description("Show agent configuration and connection status").action(async () => {
|
|
4720
4867
|
const config = loadConfig();
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
}
|
|
4726
|
-
console.log(
|
|
4868
|
+
const pid = readPid();
|
|
4869
|
+
const port = config?.port ?? 7862;
|
|
4870
|
+
const running = await isPortInUse(port);
|
|
4871
|
+
console.log(`Jarvis Agent v${PKG_VERSION}:`);
|
|
4872
|
+
console.log(` Status: ${running ? `\x1B[32mrunning\x1B[0m` : `\x1B[31mstopped\x1B[0m`}${pid ? ` (PID: ${pid})` : ""}`);
|
|
4873
|
+
console.log(` Port: ${port}`);
|
|
4727
4874
|
console.log(` Config: ${getConfigPath()}`);
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4875
|
+
if (config) {
|
|
4876
|
+
console.log(` User: ${config.userId}`);
|
|
4877
|
+
console.log(` Env: ${config.envId ?? "local"}`);
|
|
4878
|
+
console.log(` Workspace: ${config.workspacePath ?? "(cwd)"}`);
|
|
4879
|
+
console.log(` Cloud: ${config.apiUrl ?? "(not connected)"}`);
|
|
4880
|
+
if (config.connectedAt) {
|
|
4881
|
+
console.log(` Connected: ${config.connectedAt}`);
|
|
4882
|
+
}
|
|
4883
|
+
} else {
|
|
4884
|
+
console.log(` Config: Not set up. Run 'jarvis connect <token>'`);
|
|
4735
4885
|
}
|
|
4886
|
+
console.log(` Logs: ${LOG_FILE}`);
|
|
4736
4887
|
});
|
|
4737
4888
|
program.command("logout").description("Clear saved configuration").action(() => {
|
|
4738
4889
|
clearConfig();
|
|
@@ -4744,10 +4895,10 @@ Jarvis agent is already running on ws://127.0.0.1:${port}`);
|
|
|
4744
4895
|
// src/bin.ts
|
|
4745
4896
|
function findEnv() {
|
|
4746
4897
|
let dir = process.cwd();
|
|
4747
|
-
while (dir !==
|
|
4748
|
-
const envPath =
|
|
4749
|
-
if (
|
|
4750
|
-
dir =
|
|
4898
|
+
while (dir !== path8.dirname(dir)) {
|
|
4899
|
+
const envPath = path8.join(dir, ".env");
|
|
4900
|
+
if (fs8.existsSync(envPath)) return envPath;
|
|
4901
|
+
dir = path8.dirname(dir);
|
|
4751
4902
|
}
|
|
4752
4903
|
return void 0;
|
|
4753
4904
|
}
|