@appchy/jarvis 0.1.105 → 0.1.107
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 +140 -118
- package/dist/bin.js.map +1 -1
- package/harness/harness/check.py +11 -0
- package/harness/test_work.py +20 -0
- package/package.json +4 -4
package/dist/bin.js
CHANGED
|
@@ -1387,65 +1387,10 @@ async function ensureGraphify(options = {}) {
|
|
|
1387
1387
|
);
|
|
1388
1388
|
}
|
|
1389
1389
|
|
|
1390
|
-
// src/graph/hook.ts
|
|
1391
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
1392
|
-
import path7 from "path";
|
|
1393
|
-
var SIGNATURE = "# managed by jarvis";
|
|
1394
|
-
var SCRIPT = `#!/bin/sh
|
|
1395
|
-
${SIGNATURE} \u2014 keeps this repo's map current, so what an agent plans against is what is here.
|
|
1396
|
-
# Detached and silenced: git waits for a hook's output streams to close, so a build left on stdout
|
|
1397
|
-
# would hold up every commit by the length of a build. Never fails a commit.
|
|
1398
|
-
#
|
|
1399
|
-
# Run at the lowest priority the machine offers. A code commit still costs a real extract, and one
|
|
1400
|
-
# arriving at normal priority the instant you commit is felt as the machine going away for half a
|
|
1401
|
-
# minute \u2014 which is how a background job becomes something people turn off. Borrowed from the
|
|
1402
|
-
# docdoc-era hook in crispy, which had this right first.
|
|
1403
|
-
command -v jarvis >/dev/null 2>&1 || exit 0
|
|
1404
|
-
NICE=""
|
|
1405
|
-
command -v nice >/dev/null 2>&1 && NICE="nice -n 19"
|
|
1406
|
-
command -v taskpolicy >/dev/null 2>&1 && NICE="taskpolicy -b $NICE"
|
|
1407
|
-
( $NICE jarvis build graph >/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
1408
|
-
exit 0
|
|
1409
|
-
`;
|
|
1410
|
-
function installCommitHook(repoRoot) {
|
|
1411
|
-
const dir = path7.join(repoRoot, ".git", "hooks");
|
|
1412
|
-
const file = path7.join(dir, "post-commit");
|
|
1413
|
-
if (!existsSync(path7.join(repoRoot, ".git")) || !existsSync(path7.join(repoRoot, ".git", "HEAD"))) {
|
|
1414
|
-
return { installed: false, reason: "not-a-repo" };
|
|
1415
|
-
}
|
|
1416
|
-
if (existsSync(file)) {
|
|
1417
|
-
try {
|
|
1418
|
-
if (!readFileSync(file, "utf8").includes(SIGNATURE))
|
|
1419
|
-
return { installed: false, reason: "foreign-hook", path: file };
|
|
1420
|
-
} catch {
|
|
1421
|
-
return { installed: false, reason: "unwritable", path: file };
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
try {
|
|
1425
|
-
mkdirSync(dir, { recursive: true });
|
|
1426
|
-
writeFileSync(file, SCRIPT, "utf8");
|
|
1427
|
-
chmodSync(file, 493);
|
|
1428
|
-
return { installed: true, path: file };
|
|
1429
|
-
} catch {
|
|
1430
|
-
return { installed: false, reason: "unwritable", path: file };
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
function describeCommitHook(outcome, repoRoot) {
|
|
1434
|
-
if (outcome.installed)
|
|
1435
|
-
return ` the map rebuilds itself on every commit here \u2713 (${path7.relative(repoRoot, outcome.path) || outcome.path})`;
|
|
1436
|
-
if (outcome.reason === "not-a-repo")
|
|
1437
|
-
return ` not a git repo, so there is no commit to rebuild on.
|
|
1438
|
-
Run 'jarvis init' inside one, or rebuild by hand with 'jarvis build graph'.`;
|
|
1439
|
-
if (outcome.reason === "foreign-hook")
|
|
1440
|
-
return ` a post-commit hook is already here and it is not ours \u2014 left untouched.
|
|
1441
|
-
Add this line to it to keep the map current: jarvis build graph >/dev/null 2>&1 &`;
|
|
1442
|
-
return ` could not write the hook \u2014 the map still builds, by hand, with 'jarvis build graph'.`;
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
1390
|
// src/machine.ts
|
|
1446
1391
|
import crypto2 from "crypto";
|
|
1447
1392
|
import fs8 from "fs";
|
|
1448
|
-
import
|
|
1393
|
+
import path7 from "path";
|
|
1449
1394
|
var cached = null;
|
|
1450
1395
|
function getMachine() {
|
|
1451
1396
|
if (cached) return cached;
|
|
@@ -1460,7 +1405,7 @@ function getMachine() {
|
|
|
1460
1405
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1461
1406
|
schemaVersion: 1
|
|
1462
1407
|
};
|
|
1463
|
-
fs8.mkdirSync(
|
|
1408
|
+
fs8.mkdirSync(path7.dirname(file), { recursive: true });
|
|
1464
1409
|
fs8.writeFileSync(file, JSON.stringify(fresh, null, 2));
|
|
1465
1410
|
return cached = fresh;
|
|
1466
1411
|
}
|
|
@@ -1468,13 +1413,13 @@ function getMachine() {
|
|
|
1468
1413
|
// src/service.ts
|
|
1469
1414
|
import { execSync as execSync3, spawn } from "child_process";
|
|
1470
1415
|
import fs9 from "fs";
|
|
1471
|
-
import
|
|
1416
|
+
import path8 from "path";
|
|
1472
1417
|
import os4 from "os";
|
|
1473
1418
|
function serviceSuffix() {
|
|
1474
1419
|
const dir = getConfigDir();
|
|
1475
|
-
const base =
|
|
1420
|
+
const base = path8.join(os4.homedir(), ".jarvis");
|
|
1476
1421
|
if (dir === base) return "";
|
|
1477
|
-
const name = dir.startsWith(base +
|
|
1422
|
+
const name = dir.startsWith(base + path8.sep) ? dir.slice(base.length + 1) : path8.basename(dir);
|
|
1478
1423
|
return name.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1479
1424
|
}
|
|
1480
1425
|
var SERVICE_SUFFIX = serviceSuffix();
|
|
@@ -1485,8 +1430,8 @@ function createServiceManager() {
|
|
|
1485
1430
|
return new FallbackService();
|
|
1486
1431
|
}
|
|
1487
1432
|
var PLIST_LABEL = `com.appchy.jarvis${SERVICE_SUFFIX ? `.${SERVICE_SUFFIX}` : ""}`;
|
|
1488
|
-
var PLIST_DIR =
|
|
1489
|
-
var PLIST_PATH =
|
|
1433
|
+
var PLIST_DIR = path8.join(os4.homedir(), "Library", "LaunchAgents");
|
|
1434
|
+
var PLIST_PATH = path8.join(PLIST_DIR, `${PLIST_LABEL}.plist`);
|
|
1490
1435
|
function escapeXml(s) {
|
|
1491
1436
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1492
1437
|
}
|
|
@@ -1640,7 +1585,7 @@ ${Object.entries(opts.env ?? {}).map(([k, v]) => ` <key>${escapeXml(k)}</key>
|
|
|
1640
1585
|
</plist>
|
|
1641
1586
|
`;
|
|
1642
1587
|
fs9.mkdirSync(PLIST_DIR, { recursive: true });
|
|
1643
|
-
fs9.mkdirSync(
|
|
1588
|
+
fs9.mkdirSync(path8.dirname(logFile), { recursive: true });
|
|
1644
1589
|
unloadAgent();
|
|
1645
1590
|
fs9.writeFileSync(PLIST_PATH, plist);
|
|
1646
1591
|
loadAgent();
|
|
@@ -1742,7 +1687,7 @@ var WindowsService = class {
|
|
|
1742
1687
|
</Task>
|
|
1743
1688
|
`;
|
|
1744
1689
|
const tmpDir = os4.tmpdir();
|
|
1745
|
-
const tmpFile =
|
|
1690
|
+
const tmpFile = path8.join(tmpDir, `jarvis-task-${Date.now()}.xml`);
|
|
1746
1691
|
fs9.writeFileSync(tmpFile, xml, { encoding: "utf-16le" });
|
|
1747
1692
|
try {
|
|
1748
1693
|
execSync3(`schtasks /Create /TN "${TASK_NAME}" /XML "${tmpFile}" /F`, {
|
|
@@ -1788,9 +1733,9 @@ var WindowsService = class {
|
|
|
1788
1733
|
}
|
|
1789
1734
|
}
|
|
1790
1735
|
};
|
|
1791
|
-
var SYSTEMD_DIR =
|
|
1736
|
+
var SYSTEMD_DIR = path8.join(os4.homedir(), ".config", "systemd", "user");
|
|
1792
1737
|
var UNIT_NAME = `jarvis${SERVICE_SUFFIX ? `-${SERVICE_SUFFIX}` : ""}.service`;
|
|
1793
|
-
var UNIT_PATH =
|
|
1738
|
+
var UNIT_PATH = path8.join(SYSTEMD_DIR, UNIT_NAME);
|
|
1794
1739
|
var LinuxService = class {
|
|
1795
1740
|
install(opts) {
|
|
1796
1741
|
const args = [opts.entryPath, "start", "--foreground", "--workspace", opts.workspacePath];
|
|
@@ -1819,7 +1764,7 @@ StandardError=append:${logFile}
|
|
|
1819
1764
|
WantedBy=default.target
|
|
1820
1765
|
`;
|
|
1821
1766
|
fs9.mkdirSync(SYSTEMD_DIR, { recursive: true });
|
|
1822
|
-
fs9.mkdirSync(
|
|
1767
|
+
fs9.mkdirSync(path8.dirname(logFile), { recursive: true });
|
|
1823
1768
|
if (this.isInstalled()) {
|
|
1824
1769
|
try {
|
|
1825
1770
|
execSync3(`systemctl --user stop ${UNIT_NAME}`, { stdio: "ignore" });
|
|
@@ -1899,9 +1844,9 @@ WantedBy=default.target
|
|
|
1899
1844
|
};
|
|
1900
1845
|
var FallbackService = class {
|
|
1901
1846
|
baseDir = getJarvisDir();
|
|
1902
|
-
pidFile =
|
|
1903
|
-
logFile =
|
|
1904
|
-
markerFile =
|
|
1847
|
+
pidFile = path8.join(this.baseDir, "agent.pid");
|
|
1848
|
+
logFile = path8.join(this.baseDir, "agent.log");
|
|
1849
|
+
markerFile = path8.join(this.baseDir, "service-installed");
|
|
1905
1850
|
install(opts) {
|
|
1906
1851
|
fs9.mkdirSync(this.baseDir, { recursive: true });
|
|
1907
1852
|
this.stop();
|
|
@@ -1976,11 +1921,11 @@ var FallbackService = class {
|
|
|
1976
1921
|
};
|
|
1977
1922
|
|
|
1978
1923
|
// src/hooks/install.ts
|
|
1979
|
-
import { existsSync
|
|
1924
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
|
|
1980
1925
|
import os5 from "os";
|
|
1981
|
-
import
|
|
1982
|
-
var SETTINGS_DIR =
|
|
1983
|
-
var SETTINGS_FILE =
|
|
1926
|
+
import path9 from "path";
|
|
1927
|
+
var SETTINGS_DIR = path9.join(os5.homedir(), ".claude");
|
|
1928
|
+
var SETTINGS_FILE = path9.join(SETTINGS_DIR, "settings.json");
|
|
1984
1929
|
var HOOK_STEMS = [
|
|
1985
1930
|
"pre-tool-use",
|
|
1986
1931
|
"session-start",
|
|
@@ -1998,7 +1943,7 @@ function jarvisHooks() {
|
|
|
1998
1943
|
];
|
|
1999
1944
|
}
|
|
2000
1945
|
function isJarvisCommand(command) {
|
|
2001
|
-
const name =
|
|
1946
|
+
const name = path9.basename(command);
|
|
2002
1947
|
return HOOK_STEMS.some((stem) => name === `${stem}.mjs` || name === `${stem}.dev.mjs`);
|
|
2003
1948
|
}
|
|
2004
1949
|
function getCliRoot() {
|
|
@@ -2011,22 +1956,22 @@ function getCliRoot() {
|
|
|
2011
1956
|
entry = realpathSync(binPath);
|
|
2012
1957
|
} catch {
|
|
2013
1958
|
}
|
|
2014
|
-
return
|
|
1959
|
+
return path9.resolve(path9.dirname(entry), "..");
|
|
2015
1960
|
}
|
|
2016
1961
|
function resolveHooks() {
|
|
2017
1962
|
const cliRoot = getCliRoot();
|
|
2018
1963
|
return jarvisHooks().map((h) => ({
|
|
2019
1964
|
...h,
|
|
2020
|
-
binAbsPath:
|
|
1965
|
+
binAbsPath: path9.join(cliRoot, "bin", h.binBasename)
|
|
2021
1966
|
}));
|
|
2022
1967
|
}
|
|
2023
1968
|
function ownsClaudeCode() {
|
|
2024
|
-
return getConfigDir() ===
|
|
1969
|
+
return getConfigDir() === path9.join(os5.homedir(), ".jarvis");
|
|
2025
1970
|
}
|
|
2026
1971
|
function readSettings() {
|
|
2027
|
-
if (!
|
|
1972
|
+
if (!existsSync(SETTINGS_FILE)) return {};
|
|
2028
1973
|
try {
|
|
2029
|
-
const raw =
|
|
1974
|
+
const raw = readFileSync(SETTINGS_FILE, "utf-8");
|
|
2030
1975
|
return raw.trim() ? JSON.parse(raw) : {};
|
|
2031
1976
|
} catch (err) {
|
|
2032
1977
|
logger.sys.warn("[hooks.install] settings.json unreadable", {
|
|
@@ -2037,8 +1982,8 @@ function readSettings() {
|
|
|
2037
1982
|
}
|
|
2038
1983
|
function writeSettings(s) {
|
|
2039
1984
|
try {
|
|
2040
|
-
|
|
2041
|
-
|
|
1985
|
+
mkdirSync(SETTINGS_DIR, { recursive: true });
|
|
1986
|
+
writeFileSync(SETTINGS_FILE, JSON.stringify(s, null, 2) + "\n");
|
|
2042
1987
|
return true;
|
|
2043
1988
|
} catch (err) {
|
|
2044
1989
|
logger.sys.warn("[hooks.install] settings.json unwritable", {
|
|
@@ -2083,7 +2028,7 @@ function claudeCodeHooksState() {
|
|
|
2083
2028
|
return {
|
|
2084
2029
|
type: hook.type,
|
|
2085
2030
|
bin: hook.binAbsPath,
|
|
2086
|
-
exists:
|
|
2031
|
+
exists: existsSync(hook.binAbsPath),
|
|
2087
2032
|
...command ? { command } : {}
|
|
2088
2033
|
};
|
|
2089
2034
|
});
|
|
@@ -2105,10 +2050,10 @@ function installClaudeCodeHooks() {
|
|
|
2105
2050
|
expected: resolved.map((h) => ({
|
|
2106
2051
|
type: h.type,
|
|
2107
2052
|
bin: h.binAbsPath,
|
|
2108
|
-
exists:
|
|
2053
|
+
exists: existsSync(h.binAbsPath)
|
|
2109
2054
|
}))
|
|
2110
2055
|
});
|
|
2111
|
-
const missing = resolved.filter((h) => !
|
|
2056
|
+
const missing = resolved.filter((h) => !existsSync(h.binAbsPath));
|
|
2112
2057
|
if (missing.length === resolved.length) {
|
|
2113
2058
|
logger.sys.warn("[hooks.install] no bin shims found, skipping", {
|
|
2114
2059
|
configDir: configDir2,
|
|
@@ -2119,7 +2064,7 @@ function installClaudeCodeHooks() {
|
|
|
2119
2064
|
let settings = readSettings();
|
|
2120
2065
|
const installed = [];
|
|
2121
2066
|
for (const hook of resolved) {
|
|
2122
|
-
if (!
|
|
2067
|
+
if (!existsSync(hook.binAbsPath)) {
|
|
2123
2068
|
logger.sys.warn("[hooks.install] bin shim missing, skipping hook", {
|
|
2124
2069
|
configDir: configDir2,
|
|
2125
2070
|
type: hook.type,
|
|
@@ -2287,8 +2232,89 @@ Open Claude Code in a repo that has a work/ tree to see them.`);
|
|
|
2287
2232
|
});
|
|
2288
2233
|
}
|
|
2289
2234
|
|
|
2290
|
-
// src/
|
|
2235
|
+
// src/graph/hook.ts
|
|
2236
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, chmodSync } from "fs";
|
|
2237
|
+
import path10 from "path";
|
|
2238
|
+
var SIGNATURE = "# managed by jarvis";
|
|
2239
|
+
var SCRIPT = `#!/bin/sh
|
|
2240
|
+
${SIGNATURE} \u2014 keeps this repo's map current, so what an agent plans against is what is here.
|
|
2241
|
+
# Detached and silenced: git waits for a hook's output streams to close, so a build left on stdout
|
|
2242
|
+
# would hold up every commit by the length of a build. Never fails a commit.
|
|
2243
|
+
#
|
|
2244
|
+
# Run at the lowest priority the machine offers. A code commit still costs a real extract, and one
|
|
2245
|
+
# arriving at normal priority the instant you commit is felt as the machine going away for half a
|
|
2246
|
+
# minute \u2014 which is how a background job becomes something people turn off. Borrowed from the
|
|
2247
|
+
# docdoc-era hook in crispy, which had this right first.
|
|
2248
|
+
command -v jarvis >/dev/null 2>&1 || exit 0
|
|
2249
|
+
NICE=""
|
|
2250
|
+
command -v nice >/dev/null 2>&1 && NICE="nice -n 19"
|
|
2251
|
+
command -v taskpolicy >/dev/null 2>&1 && NICE="taskpolicy -b $NICE"
|
|
2252
|
+
( $NICE jarvis build graph >/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
2253
|
+
exit 0
|
|
2254
|
+
`;
|
|
2255
|
+
function findRepoRoot(from) {
|
|
2256
|
+
let dir = path10.resolve(from);
|
|
2257
|
+
for (; ; ) {
|
|
2258
|
+
if (existsSync2(path10.join(dir, ".git"))) return dir;
|
|
2259
|
+
const parent = path10.dirname(dir);
|
|
2260
|
+
if (parent === dir) return null;
|
|
2261
|
+
dir = parent;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
function installCommitHook(repoRoot) {
|
|
2265
|
+
const dir = path10.join(repoRoot, ".git", "hooks");
|
|
2266
|
+
const file = path10.join(dir, "post-commit");
|
|
2267
|
+
if (!existsSync2(path10.join(repoRoot, ".git")) || !existsSync2(path10.join(repoRoot, ".git", "HEAD"))) {
|
|
2268
|
+
return { installed: false, reason: "not-a-repo" };
|
|
2269
|
+
}
|
|
2270
|
+
if (existsSync2(file)) {
|
|
2271
|
+
try {
|
|
2272
|
+
if (!readFileSync2(file, "utf8").includes(SIGNATURE))
|
|
2273
|
+
return { installed: false, reason: "foreign-hook", path: file };
|
|
2274
|
+
} catch {
|
|
2275
|
+
return { installed: false, reason: "unwritable", path: file };
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
try {
|
|
2279
|
+
mkdirSync2(dir, { recursive: true });
|
|
2280
|
+
writeFileSync2(file, SCRIPT, "utf8");
|
|
2281
|
+
chmodSync(file, 493);
|
|
2282
|
+
return { installed: true, path: file };
|
|
2283
|
+
} catch {
|
|
2284
|
+
return { installed: false, reason: "unwritable", path: file };
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
function describeCommitHook(outcome, repoRoot) {
|
|
2288
|
+
if (outcome.installed)
|
|
2289
|
+
return ` the map rebuilds itself on every commit here \u2713 (${path10.relative(repoRoot, outcome.path) || outcome.path})`;
|
|
2290
|
+
if (outcome.reason === "not-a-repo")
|
|
2291
|
+
return ` not a git repo, so there is no commit to rebuild on.
|
|
2292
|
+
Run this inside one, or rebuild by hand with 'jarvis build graph'.`;
|
|
2293
|
+
if (outcome.reason === "foreign-hook")
|
|
2294
|
+
return ` a post-commit hook is already here and it is not ours \u2014 left untouched.
|
|
2295
|
+
Add this line to it to keep the map current: jarvis build graph >/dev/null 2>&1 &`;
|
|
2296
|
+
return ` could not write the hook \u2014 the map still builds, by hand, with 'jarvis build graph'.`;
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
// src/commands/repo.ts
|
|
2291
2300
|
function register3(program) {
|
|
2301
|
+
const repo = program.command("repo").description("Set up the repo you are standing in \u2014 no pairing, no daemon, no network");
|
|
2302
|
+
repo.command("init").description("Keep this repo's map current by rebuilding it on every commit").action(() => {
|
|
2303
|
+
if (!setUpThisRepo()) process.exit(1);
|
|
2304
|
+
console.log(" It rebuilds from your next commit. To build one now: jarvis build graph\n");
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
function setUpThisRepo() {
|
|
2308
|
+
const root = findRepoRoot(process.cwd()) ?? process.cwd();
|
|
2309
|
+
console.log(" \u25B8 Keeping this repo's map current");
|
|
2310
|
+
const outcome = installCommitHook(root);
|
|
2311
|
+
console.log(`${describeCommitHook(outcome, root)}
|
|
2312
|
+
`);
|
|
2313
|
+
return outcome.installed;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
// src/commands/init.ts
|
|
2317
|
+
function register4(program) {
|
|
2292
2318
|
program.command("init").description("Set this machine up to work in repos, and join an instance if you name one").option("--url <url>", "Also join the jarvis instance at this address").option("--skip-daemon", "Skip the background daemon install step").option("--force", "Re-ask all prompts even when config already has answers").action(async (opts) => {
|
|
2293
2319
|
const ok = await runInit({
|
|
2294
2320
|
url: opts.url,
|
|
@@ -2373,7 +2399,7 @@ async function setUpThisMachine(prompts) {
|
|
|
2373
2399
|
console.log(" \u25B8 Wiring this machine's Claude Code to jarvis");
|
|
2374
2400
|
installHooks();
|
|
2375
2401
|
console.log();
|
|
2376
|
-
|
|
2402
|
+
setUpThisRepo();
|
|
2377
2403
|
await setUpMapTool(prompts);
|
|
2378
2404
|
console.log(" \u25B8 The model key the map embeds with");
|
|
2379
2405
|
const key = loadConfig()?.openaiApiKey;
|
|
@@ -2384,12 +2410,6 @@ async function setUpThisMachine(prompts) {
|
|
|
2384
2410
|
`
|
|
2385
2411
|
);
|
|
2386
2412
|
}
|
|
2387
|
-
function setUpMapRebuild() {
|
|
2388
|
-
const repoRoot = process.cwd();
|
|
2389
|
-
console.log(" \u25B8 Keeping this repo's map current");
|
|
2390
|
-
console.log(`${describeCommitHook(installCommitHook(repoRoot), repoRoot)}
|
|
2391
|
-
`);
|
|
2392
|
-
}
|
|
2393
2413
|
async function setUpMapTool(prompts) {
|
|
2394
2414
|
console.log(" \u25B8 The tool the map's code half is built from");
|
|
2395
2415
|
const state2 = resolveGraphify();
|
|
@@ -2452,7 +2472,8 @@ function reportLocalOnly() {
|
|
|
2452
2472
|
console.log(" \u2714 Done. This machine works in any repo that has a work/ tree:");
|
|
2453
2473
|
console.log(" the board, the map, the session block, the rules that arrive on edit,");
|
|
2454
2474
|
console.log(" and 'jarvis serve' for any agent that speaks MCP.\n");
|
|
2455
|
-
console.log(" In a repo you have cloned: jarvis
|
|
2475
|
+
console.log(" In a repo you have cloned: jarvis repo init");
|
|
2476
|
+
console.log(" jarvis build graph");
|
|
2456
2477
|
console.log(" jarvis work list\n");
|
|
2457
2478
|
console.log(" It has joined no jarvis instance, so it has no web surface and cannot");
|
|
2458
2479
|
console.log(" start sessions on other machines. Both need one:");
|
|
@@ -2664,7 +2685,7 @@ async function promptList(question, fallback) {
|
|
|
2664
2685
|
}
|
|
2665
2686
|
|
|
2666
2687
|
// src/commands/pair.ts
|
|
2667
|
-
function
|
|
2688
|
+
function register5(program) {
|
|
2668
2689
|
program.command("pair").description("Re-pair this machine (when token expired)").action(async () => {
|
|
2669
2690
|
try {
|
|
2670
2691
|
await runPair();
|
|
@@ -2778,7 +2799,7 @@ async function unpair() {
|
|
|
2778
2799
|
clearConfig();
|
|
2779
2800
|
return { attempted: true, serverStatus };
|
|
2780
2801
|
}
|
|
2781
|
-
function
|
|
2802
|
+
function register6(program) {
|
|
2782
2803
|
program.command("unpair").description("Unregister this env from cloud and wipe local config").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
2783
2804
|
try {
|
|
2784
2805
|
const config2 = loadConfig();
|
|
@@ -2833,7 +2854,7 @@ function getRoots() {
|
|
|
2833
2854
|
const cfg = readConfig();
|
|
2834
2855
|
return Array.isArray(cfg.roots) ? cfg.roots : [];
|
|
2835
2856
|
}
|
|
2836
|
-
function
|
|
2857
|
+
function register7(program) {
|
|
2837
2858
|
const cmd = program.command("roots").description("Manage code-root directories");
|
|
2838
2859
|
cmd.command("list", { isDefault: true }).description("List current roots").action(() => {
|
|
2839
2860
|
const roots = getRoots();
|
|
@@ -2878,7 +2899,7 @@ function readLocalConfig() {
|
|
|
2878
2899
|
return {};
|
|
2879
2900
|
}
|
|
2880
2901
|
}
|
|
2881
|
-
function
|
|
2902
|
+
function register8(program) {
|
|
2882
2903
|
program.command("settings").description("Show this env's settings (roots, repos map)").action(async () => {
|
|
2883
2904
|
try {
|
|
2884
2905
|
const config2 = loadConfig();
|
|
@@ -10260,7 +10281,7 @@ import { createRequire as createRequire2 } from "module";
|
|
|
10260
10281
|
var _require = createRequire2(import.meta.url);
|
|
10261
10282
|
var VERSION2 = _require("../package.json").version ?? "0.0.0";
|
|
10262
10283
|
var IS_DEV = String(_require("../package.json").name ?? "").endsWith("-dev");
|
|
10263
|
-
var SHA = "
|
|
10284
|
+
var SHA = "3992b72";
|
|
10264
10285
|
var BUILT = "2026-09-11";
|
|
10265
10286
|
var BUILD = SHA ?? "source";
|
|
10266
10287
|
var BUILD_LABEL = `${SHA ? `${VERSION2} (${SHA}${BUILT ? ` ${BUILT}` : ""})` : `${VERSION2} (source)`}${IS_DEV ? " \u2014 development build" : ""}`;
|
|
@@ -10779,7 +10800,7 @@ async function fetchRoots(hubUrl, envId, token) {
|
|
|
10779
10800
|
}
|
|
10780
10801
|
|
|
10781
10802
|
// src/commands/start.ts
|
|
10782
|
-
function
|
|
10803
|
+
function register9(program) {
|
|
10783
10804
|
program.command("start").description("Start the local agent (authenticates, cleans up stale processes, starts fresh)").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)").option("--force", "Re-ask all prompts even when config has them").action(async (opts) => {
|
|
10784
10805
|
if (refuseWithoutInstance()) process.exit(1);
|
|
10785
10806
|
const config2 = loadConfig();
|
|
@@ -10916,7 +10937,7 @@ function buildUpstreamConfig(req) {
|
|
|
10916
10937
|
}
|
|
10917
10938
|
|
|
10918
10939
|
// src/commands/stop.ts
|
|
10919
|
-
function
|
|
10940
|
+
function register10(program) {
|
|
10920
10941
|
program.command("stop").description("Stop the running agent").action(() => {
|
|
10921
10942
|
uninstallClaudeCodeHooks();
|
|
10922
10943
|
const service = createServiceManager();
|
|
@@ -10943,7 +10964,7 @@ function register9(program) {
|
|
|
10943
10964
|
}
|
|
10944
10965
|
|
|
10945
10966
|
// src/commands/restart.ts
|
|
10946
|
-
function
|
|
10967
|
+
function register11(program) {
|
|
10947
10968
|
program.command("restart").description("Restart the agent (alias for start \u2014 start always does a clean restart)").action(async () => {
|
|
10948
10969
|
await program.parseAsync(["node", "jarvis", "start"]);
|
|
10949
10970
|
});
|
|
@@ -10952,7 +10973,7 @@ function register10(program) {
|
|
|
10952
10973
|
// src/commands/logs.ts
|
|
10953
10974
|
import { spawn as spawn2, execSync as execSync6 } from "child_process";
|
|
10954
10975
|
import fs16 from "fs";
|
|
10955
|
-
function
|
|
10976
|
+
function register12(program) {
|
|
10956
10977
|
program.command("logs").description("View agent logs").option("-f, --follow", "Follow log output (like tail -f)", true).option("-n, --lines <n>", "Number of lines to show", "50").action((opts) => {
|
|
10957
10978
|
const logFile = getLogFile();
|
|
10958
10979
|
if (!fs16.existsSync(logFile)) {
|
|
@@ -11027,7 +11048,7 @@ function portOf(url) {
|
|
|
11027
11048
|
// src/commands/status.ts
|
|
11028
11049
|
var GREEN2 = (text) => `\x1B[32m${text}\x1B[0m`;
|
|
11029
11050
|
var RED2 = (text) => `\x1B[31m${text}\x1B[0m`;
|
|
11030
|
-
function
|
|
11051
|
+
function register13(program) {
|
|
11031
11052
|
program.command("status").description("Show agent configuration and connection status").action(async () => {
|
|
11032
11053
|
const config2 = loadConfig();
|
|
11033
11054
|
const health = await getHealth();
|
|
@@ -11066,7 +11087,7 @@ function endpoint(probed) {
|
|
|
11066
11087
|
}
|
|
11067
11088
|
|
|
11068
11089
|
// src/commands/install.ts
|
|
11069
|
-
function
|
|
11090
|
+
function register14(program) {
|
|
11070
11091
|
program.command("install").description("Install as OS service for auto-start on login and crash recovery").option("-w, --workspace <path>", "Workspace root path").option("--no-upstream", "Don't connect to cloud").action(async (opts) => {
|
|
11071
11092
|
if (refuseWithoutInstance()) process.exit(1);
|
|
11072
11093
|
const config2 = loadConfig();
|
|
@@ -11115,7 +11136,7 @@ function register13(program) {
|
|
|
11115
11136
|
import fs17 from "fs";
|
|
11116
11137
|
import path19 from "path";
|
|
11117
11138
|
import { createInterface as createInterface5 } from "readline";
|
|
11118
|
-
function
|
|
11139
|
+
function register15(program) {
|
|
11119
11140
|
program.command("uninstall").description("Stop the agent, remove the OS service, and wipe local config + identity").option("--keep-data", "Skip the data-wipe prompt; preserve skills/prompts/cache/settings").option("--purge", "Skip the prompt and wipe ALL local data (skills, prompts, cache, settings)").action(async (opts) => {
|
|
11120
11141
|
try {
|
|
11121
11142
|
await runUninstall(opts);
|
|
@@ -11177,7 +11198,7 @@ function confirm2(prompt) {
|
|
|
11177
11198
|
}
|
|
11178
11199
|
|
|
11179
11200
|
// src/commands/logout.ts
|
|
11180
|
-
function
|
|
11201
|
+
function register16(program) {
|
|
11181
11202
|
program.command("logout").description("Clear saved configuration").action(() => {
|
|
11182
11203
|
clearConfig();
|
|
11183
11204
|
console.log("Configuration cleared.");
|
|
@@ -11208,7 +11229,7 @@ async function call(path23, method, body) {
|
|
|
11208
11229
|
}
|
|
11209
11230
|
return await resp.json();
|
|
11210
11231
|
}
|
|
11211
|
-
function
|
|
11232
|
+
function register17(program) {
|
|
11212
11233
|
const mcp = program.command("mcp").description("Connect an agent to this workspace's board");
|
|
11213
11234
|
mcp.command("token").description("Mint a personal token for the Jarvis MCP server").option("--name <name>", "Which machine this token is for, e.g. 'laptop'").option("--scopes <list>", "read | write | read,write", "read,write").option("--show", "Show the current token's details instead of minting").option("--revoke", "Revoke the current token").action(async (opts) => {
|
|
11214
11235
|
try {
|
|
@@ -11262,7 +11283,7 @@ function register16(program) {
|
|
|
11262
11283
|
}
|
|
11263
11284
|
|
|
11264
11285
|
// src/commands/model.ts
|
|
11265
|
-
function
|
|
11286
|
+
function register18(program) {
|
|
11266
11287
|
const model = program.command("model").description("Model access for the map's semantic search, on this machine");
|
|
11267
11288
|
model.command("key").argument("[key]", "The OpenAI key to store. Omit it to see what is set.").option("--show", "Say whether a key is set, without printing it").option("--clear", "Forget the stored key").description("Set the OpenAI key the map embeds with").action((key, opts) => {
|
|
11268
11289
|
const config2 = loadConfig();
|
|
@@ -11521,7 +11542,7 @@ function isStale(lockPath, staleMs) {
|
|
|
11521
11542
|
}
|
|
11522
11543
|
|
|
11523
11544
|
// src/commands/build.ts
|
|
11524
|
-
function
|
|
11545
|
+
function register19(program) {
|
|
11525
11546
|
const build2 = program.command("build").description("Build an artifact from this repo");
|
|
11526
11547
|
build2.command("graph").description("Read the repo's jarvis.config.ts, build the graph, and say what is wrong with it").option("--repo <path>", "The repo to map. Default: the working directory").option("--rebuild", "LAST RESORT: throw the graph away and re-extract from scratch").option("--label", "Re-name the detected communities through the configured labeler").option("--gate", "Fail when a governance class has more findings than this repo carries").action(async (opts) => {
|
|
11527
11548
|
const argv = [
|
|
@@ -11581,7 +11602,7 @@ function isRedirected(req) {
|
|
|
11581
11602
|
}
|
|
11582
11603
|
|
|
11583
11604
|
// src/commands/dev.ts
|
|
11584
|
-
function
|
|
11605
|
+
function register20(program) {
|
|
11585
11606
|
const dev = program.command("dev").description("Run a development build in a repo, without replacing the installed jarvis");
|
|
11586
11607
|
dev.command("use").argument("[where]", "'here' for the working directory, 'all' for every repo", "here").option("--root <path>", "The checkout to run. Default: the one already recorded").description("Point a repo at the development build").action((where, opts) => {
|
|
11587
11608
|
const current = readDevRedirect();
|
|
@@ -12298,7 +12319,7 @@ async function brief2(repo) {
|
|
|
12298
12319
|
}
|
|
12299
12320
|
|
|
12300
12321
|
// src/commands/serve.ts
|
|
12301
|
-
function
|
|
12322
|
+
function register21(program) {
|
|
12302
12323
|
program.command("serve").description("Serve this repo to an agent over stdio \u2014 what an .mcp.json launches").option("--repo <path>", "The repo to serve. Default: the working directory").action(async (opts) => {
|
|
12303
12324
|
const repo = resolveRepo(opts.repo);
|
|
12304
12325
|
const problem = harnessProblem();
|
|
@@ -12603,7 +12624,7 @@ function whenRebuilt(dir, reload) {
|
|
|
12603
12624
|
}
|
|
12604
12625
|
|
|
12605
12626
|
// src/commands/ui.ts
|
|
12606
|
-
function
|
|
12627
|
+
function register22(program) {
|
|
12607
12628
|
program.command("ui").description("Open this repo's board in a browser \u2014 nothing to configure, nothing to join").option("--repo <path>", "The repo to show. Default: the working directory").option("--port <number>", "The port to listen on. Default: 3402").option("--no-open", "Print the address instead of opening a browser").option("--packaged", "Serve the page this build shipped with, never a checkout's").action(async (opts) => {
|
|
12608
12629
|
const repo = resolveRepo(opts.repo);
|
|
12609
12630
|
const port = opts.port ? Number.parseInt(opts.port, 10) : 3402;
|
|
@@ -12673,7 +12694,7 @@ async function openWhenUp(port) {
|
|
|
12673
12694
|
|
|
12674
12695
|
// src/commands/work.ts
|
|
12675
12696
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
12676
|
-
function
|
|
12697
|
+
function register23(program) {
|
|
12677
12698
|
program.command("work").description("The board \u2014 take work, prove it, finish it").argument("[args...]", "Passed to the harness untouched").allowUnknownOption().passThroughOptions().helpOption(false).action((passed) => {
|
|
12678
12699
|
const problem = harnessProblem();
|
|
12679
12700
|
if (problem) {
|
|
@@ -12696,11 +12717,11 @@ function register22(program) {
|
|
|
12696
12717
|
// src/cli.ts
|
|
12697
12718
|
function createCli() {
|
|
12698
12719
|
const program = new Command().enablePositionalOptions().name("jarvis").description("Jarvis local agent \u2014 watches Claude Code sessions on your machine").version(BUILD_LABEL);
|
|
12699
|
-
register3(program);
|
|
12700
12720
|
register4(program);
|
|
12721
|
+
register3(program);
|
|
12701
12722
|
register5(program);
|
|
12702
|
-
register(program);
|
|
12703
12723
|
register6(program);
|
|
12724
|
+
register(program);
|
|
12704
12725
|
register7(program);
|
|
12705
12726
|
register8(program);
|
|
12706
12727
|
register9(program);
|
|
@@ -12715,9 +12736,10 @@ function createCli() {
|
|
|
12715
12736
|
register18(program);
|
|
12716
12737
|
register19(program);
|
|
12717
12738
|
register20(program);
|
|
12718
|
-
register2(program);
|
|
12719
12739
|
register21(program);
|
|
12740
|
+
register2(program);
|
|
12720
12741
|
register22(program);
|
|
12742
|
+
register23(program);
|
|
12721
12743
|
return program;
|
|
12722
12744
|
}
|
|
12723
12745
|
|