@primitive.ai/prim 0.1.0-alpha.62 → 0.1.0-alpha.64
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/{chunk-QGVHLP5J.js → chunk-7X7SFOPJ.js} +54 -5
- package/dist/{chunk-I3HIPAIR.js → chunk-CPX3BUOC.js} +7 -4
- package/dist/chunk-G5D3FF3D.js +853 -0
- package/dist/{chunk-S4LFRVGD.js → chunk-HIMWM526.js} +1 -1
- package/dist/{chunk-R4CUX6FY.js → chunk-KHZNYEUV.js} +1 -1
- package/dist/{chunk-KBFFVYBC.js → chunk-LNU44OJV.js} +3 -5
- package/dist/{chunk-LOGW54W5.js → chunk-MCPHIB4W.js} +18 -7
- package/dist/{chunk-DA4BMHEB.js → chunk-VYGY3OOX.js} +2 -2
- package/dist/{chunk-YITJ2H3B.js → chunk-WS3MCNFD.js} +1 -1
- package/dist/daemon/server.js +343 -44
- package/dist/hooks/post-commit.js +30 -6
- package/dist/hooks/post-tool-use.js +32 -20
- package/dist/hooks/pre-commit.js +2 -2
- package/dist/hooks/pre-tool-use.js +11 -3
- package/dist/hooks/prim-hook.js +7 -7
- package/dist/hooks/session-start.js +15 -14
- package/dist/index.js +236 -139
- package/dist/statusline-main.js +50 -40
- package/package.json +1 -1
- package/dist/chunk-GF5QII7T.js +0 -411
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
checkAffectedDecisions,
|
|
14
14
|
daemonOrDirectGet,
|
|
15
15
|
formatDecisionsWarning
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WS3MCNFD.js";
|
|
17
17
|
import {
|
|
18
18
|
JOURNAL_DIR,
|
|
19
19
|
SESSIONS_DIR,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
listFlushing,
|
|
23
23
|
pendingJournalStats,
|
|
24
24
|
readMovesFromPath
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-HIMWM526.js";
|
|
26
26
|
import {
|
|
27
27
|
bindRepository,
|
|
28
28
|
compareSemver,
|
|
@@ -32,12 +32,13 @@ import {
|
|
|
32
32
|
postCommitHookBlock,
|
|
33
33
|
printJson,
|
|
34
34
|
registerSkillCommands,
|
|
35
|
+
resolveRepositoryBinding,
|
|
35
36
|
uninstallPostCommitHookAtPath,
|
|
36
37
|
uninstallProjectPostCommitHook
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-MCPHIB4W.js";
|
|
38
39
|
import {
|
|
39
40
|
fetchFeedbackCapability
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-KHZNYEUV.js";
|
|
41
42
|
import {
|
|
42
43
|
inspectWorkspaceId
|
|
43
44
|
} from "./chunk-UVIWZWM6.js";
|
|
@@ -48,7 +49,7 @@ import {
|
|
|
48
49
|
packageVersion,
|
|
49
50
|
pinnedHookCommand,
|
|
50
51
|
warmBinCache
|
|
51
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-LNU44OJV.js";
|
|
52
53
|
import {
|
|
53
54
|
canonicalGitRoot,
|
|
54
55
|
canonicalRepositoryPath,
|
|
@@ -73,7 +74,7 @@ import {
|
|
|
73
74
|
resolveAuthCredential,
|
|
74
75
|
setStoredToken,
|
|
75
76
|
withFileLock
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-CPX3BUOC.js";
|
|
77
78
|
import {
|
|
78
79
|
daemonIsLive,
|
|
79
80
|
daemonRequest
|
|
@@ -104,6 +105,7 @@ async function applyActivation(active) {
|
|
|
104
105
|
bound = await bindRepository(root);
|
|
105
106
|
}
|
|
106
107
|
setRepoActive(root, active);
|
|
108
|
+
await daemonRequest("statusline_invalidate", {}, { timeoutMs: 250 });
|
|
107
109
|
process.stderr.write(`[prim] prim ${active ? "enabled" : "disabled"} in ${root}
|
|
108
110
|
`);
|
|
109
111
|
printJson({ active, repo: root, ...bound, ...postCommitHook ? { postCommitHook } : {} });
|
|
@@ -671,7 +673,7 @@ function normalizeApiUrl(url) {
|
|
|
671
673
|
|
|
672
674
|
// src/daemon/launchd.ts
|
|
673
675
|
var LAUNCHD_LABEL = "ai.getprimitive.prim-daemon";
|
|
674
|
-
var RUNTIME_SCHEMA_VERSION =
|
|
676
|
+
var RUNTIME_SCHEMA_VERSION = 3;
|
|
675
677
|
var RUNTIME_DIR_MODE = 448;
|
|
676
678
|
var RUNTIME_FILE_MODE = 384;
|
|
677
679
|
var RUNTIME_LAUNCHER_MODE = 448;
|
|
@@ -751,7 +753,7 @@ function findPackageVersion(entryFile) {
|
|
|
751
753
|
function readRuntimeManifest(path) {
|
|
752
754
|
try {
|
|
753
755
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
754
|
-
if (parsed.schemaVersion !== RUNTIME_SCHEMA_VERSION || typeof parsed.version !== "string" || typeof parsed.nodePath !== "string" || parsed.daemonFile !== "prim-daemon-server" || typeof parsed.daemonSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(parsed.daemonSha256)
|
|
756
|
+
if (parsed.schemaVersion !== RUNTIME_SCHEMA_VERSION || typeof parsed.version !== "string" || typeof parsed.nodePath !== "string" || parsed.daemonFile !== "prim-daemon-server" || typeof parsed.daemonSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(parsed.daemonSha256)) {
|
|
755
757
|
return null;
|
|
756
758
|
}
|
|
757
759
|
return parsed;
|
|
@@ -759,12 +761,12 @@ function readRuntimeManifest(path) {
|
|
|
759
761
|
return null;
|
|
760
762
|
}
|
|
761
763
|
}
|
|
762
|
-
function sameRuntime(current, desired, daemonPath
|
|
763
|
-
if (!current || current.version !== desired.version || current.nodePath !== desired.nodePath || current.daemonSha256 !== desired.daemonSha256
|
|
764
|
+
function sameRuntime(current, desired, daemonPath) {
|
|
765
|
+
if (!current || current.version !== desired.version || current.nodePath !== desired.nodePath || current.daemonSha256 !== desired.daemonSha256) {
|
|
764
766
|
return false;
|
|
765
767
|
}
|
|
766
768
|
try {
|
|
767
|
-
return sha256File(daemonPath) === desired.daemonSha256
|
|
769
|
+
return sha256File(daemonPath) === desired.daemonSha256;
|
|
768
770
|
} catch {
|
|
769
771
|
return false;
|
|
770
772
|
}
|
|
@@ -788,8 +790,6 @@ function stageRuntime(options = {}) {
|
|
|
788
790
|
if (!daemonSource || !existsSync2(daemonSource)) {
|
|
789
791
|
throw new Error("cannot stage runtime: prim-daemon-server bundle is unavailable");
|
|
790
792
|
}
|
|
791
|
-
const configuredStatusline = options.statuslineSource === void 0 ? binFile("prim-statusline") : options.statuslineSource;
|
|
792
|
-
const statuslineSource = configuredStatusline && existsSync2(configuredStatusline) ? configuredStatusline : null;
|
|
793
793
|
const nodePath = resolve(options.nodePath ?? process.execPath);
|
|
794
794
|
const version = options.version ?? findPackageVersion(daemonSource);
|
|
795
795
|
const desired = {
|
|
@@ -798,10 +798,6 @@ function stageRuntime(options = {}) {
|
|
|
798
798
|
nodePath,
|
|
799
799
|
daemonFile: "prim-daemon-server",
|
|
800
800
|
daemonSha256: sha256File(daemonSource),
|
|
801
|
-
...statuslineSource ? {
|
|
802
|
-
statuslineFile: "prim-statusline",
|
|
803
|
-
statuslineSha256: sha256File(statuslineSource)
|
|
804
|
-
} : {},
|
|
805
801
|
stagedAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
806
802
|
};
|
|
807
803
|
let currentRelease = null;
|
|
@@ -811,19 +807,13 @@ function stageRuntime(options = {}) {
|
|
|
811
807
|
}
|
|
812
808
|
const current = currentRelease ? readRuntimeManifest(join(currentRelease, "manifest.json")) : null;
|
|
813
809
|
const currentDaemon = currentRelease ? join(currentRelease, desired.daemonFile) : "";
|
|
814
|
-
|
|
815
|
-
if (currentRelease && sameRuntime(current, desired, currentDaemon, currentStatusline)) {
|
|
810
|
+
if (currentRelease && sameRuntime(current, desired, currentDaemon)) {
|
|
816
811
|
const manifest = current;
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
RUNTIME_LAUNCHER_MODE
|
|
823
|
-
);
|
|
824
|
-
} else {
|
|
825
|
-
rmSync(paths.statuslineLauncher, { force: true });
|
|
826
|
-
}
|
|
812
|
+
atomicWrite(
|
|
813
|
+
paths.statuslineLauncher,
|
|
814
|
+
statuslineLauncherContent(manifest.version, options.homeDir),
|
|
815
|
+
RUNTIME_LAUNCHER_MODE
|
|
816
|
+
);
|
|
827
817
|
return {
|
|
828
818
|
changed: false,
|
|
829
819
|
manifest,
|
|
@@ -844,14 +834,6 @@ function stageRuntime(options = {}) {
|
|
|
844
834
|
if (sha256File(daemonTarget) !== desired.daemonSha256) {
|
|
845
835
|
throw new Error("cannot stage runtime: daemon bundle changed while it was copied");
|
|
846
836
|
}
|
|
847
|
-
if (statuslineSource && desired.statuslineFile) {
|
|
848
|
-
const statuslineTarget = join(stagingDir, desired.statuslineFile);
|
|
849
|
-
copyFileSync(statuslineSource, statuslineTarget);
|
|
850
|
-
chmodSync(statuslineTarget, RUNTIME_FILE_MODE);
|
|
851
|
-
if (sha256File(statuslineTarget) !== desired.statuslineSha256) {
|
|
852
|
-
throw new Error("cannot stage runtime: statusline bundle changed while it was copied");
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
837
|
const manifestTarget = join(stagingDir, "manifest.json");
|
|
856
838
|
writeFileSync(manifestTarget, `${JSON.stringify(desired, null, 2)}
|
|
857
839
|
`, {
|
|
@@ -859,23 +841,16 @@ function stageRuntime(options = {}) {
|
|
|
859
841
|
mode: RUNTIME_FILE_MODE,
|
|
860
842
|
flag: "wx"
|
|
861
843
|
});
|
|
862
|
-
const releaseName = `release-${createHash2("sha256").update(
|
|
863
|
-
`${version}\0${nodePath}\0${desired.statuslineFile ?? ""}\0${desired.stagedAt}\0${process.pid}\0${Math.random()}`
|
|
864
|
-
).digest("hex").slice(0, 16)}`;
|
|
844
|
+
const releaseName = `release-${createHash2("sha256").update(`${version}\0${nodePath}\0${desired.stagedAt}\0${process.pid}\0${Math.random()}`).digest("hex").slice(0, 16)}`;
|
|
865
845
|
releaseDir = join(paths.releasesDir, releaseName);
|
|
866
846
|
renameSync(stagingDir, releaseDir);
|
|
867
847
|
releaseDir = realpathSync(releaseDir);
|
|
868
848
|
atomicSymlink(join("releases", releaseName), paths.currentLink);
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
RUNTIME_LAUNCHER_MODE
|
|
875
|
-
);
|
|
876
|
-
} else {
|
|
877
|
-
rmSync(paths.statuslineLauncher, { force: true });
|
|
878
|
-
}
|
|
849
|
+
atomicWrite(
|
|
850
|
+
paths.statuslineLauncher,
|
|
851
|
+
statuslineLauncherContent(desired.version, options.homeDir),
|
|
852
|
+
RUNTIME_LAUNCHER_MODE
|
|
853
|
+
);
|
|
879
854
|
} catch (error) {
|
|
880
855
|
rmSync(stagingDir, { recursive: true, force: true });
|
|
881
856
|
throw error;
|
|
@@ -890,9 +865,20 @@ function stageRuntime(options = {}) {
|
|
|
890
865
|
function shellQuote(value) {
|
|
891
866
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
892
867
|
}
|
|
893
|
-
function statuslineLauncherContent(
|
|
868
|
+
function statuslineLauncherContent(version, homeDir = homedir()) {
|
|
869
|
+
const socketPath = join(homeDir, ".config", "prim", "sock");
|
|
870
|
+
const fallback = `primitive ${version} (daemon: down)`;
|
|
894
871
|
return `#!/bin/sh
|
|
895
|
-
|
|
872
|
+
response=$(
|
|
873
|
+
printf 'prim-statusline-v1\\000%s\\000%s\\000' "\${PWD:-/}" "\${PRIM_API_URL:-}" |
|
|
874
|
+
/usr/bin/nc -U -w 1 ${shellQuote(socketPath)} 2>/dev/null
|
|
875
|
+
)
|
|
876
|
+
status=$?
|
|
877
|
+
if [ "$status" -eq 0 ] && [ -n "$response" ]; then
|
|
878
|
+
printf '%s' "$response"
|
|
879
|
+
else
|
|
880
|
+
printf '%s' ${shellQuote(fallback)}
|
|
881
|
+
fi
|
|
896
882
|
`;
|
|
897
883
|
}
|
|
898
884
|
function runtimeStatuslineCommand(options = {}) {
|
|
@@ -1488,6 +1474,7 @@ var CAPTURE_EVENTS = [
|
|
|
1488
1474
|
"UserPromptSubmit",
|
|
1489
1475
|
"PreToolUse",
|
|
1490
1476
|
"PostToolUse",
|
|
1477
|
+
"PostToolUseFailure",
|
|
1491
1478
|
"Stop",
|
|
1492
1479
|
"SessionEnd",
|
|
1493
1480
|
"SubagentStop"
|
|
@@ -1509,6 +1496,11 @@ var REGISTRATIONS = [
|
|
|
1509
1496
|
),
|
|
1510
1497
|
makeRegistration("PreToolUse", "Edit|Write|MultiEdit|NotebookEdit|Bash", GATE_BIN),
|
|
1511
1498
|
makeRegistration("PostToolUse", "Edit|Write|MultiEdit|NotebookEdit|Bash", POST_TOOL_USE_BIN),
|
|
1499
|
+
makeRegistration(
|
|
1500
|
+
"PostToolUseFailure",
|
|
1501
|
+
"Edit|Write|MultiEdit|NotebookEdit|Bash",
|
|
1502
|
+
POST_TOOL_USE_BIN
|
|
1503
|
+
),
|
|
1512
1504
|
makeRegistration("SessionStart", "*", SESSION_START_BIN),
|
|
1513
1505
|
makeDetachedRegistration("SessionEnd", "*", SESSION_END_BIN)
|
|
1514
1506
|
];
|
|
@@ -1728,10 +1720,7 @@ function performInstall(scope, force) {
|
|
|
1728
1720
|
let statuslineCommand = STATUSLINE_COMMAND;
|
|
1729
1721
|
if (!blockedByUserStatusline && process.platform === "darwin" && (!before.statusLine || isPrimStatusLine(before))) {
|
|
1730
1722
|
try {
|
|
1731
|
-
|
|
1732
|
-
if (!runtime.manifest.statuslineFile) {
|
|
1733
|
-
throw new Error("standalone prim-statusline entry is unavailable");
|
|
1734
|
-
}
|
|
1723
|
+
stageRuntime();
|
|
1735
1724
|
statuslineCommand = runtimeStatuslineCommand();
|
|
1736
1725
|
} catch (error) {
|
|
1737
1726
|
const detail = error instanceof Error ? error.message : String(error);
|
|
@@ -1893,6 +1882,8 @@ var GATE_BIN2 = "prim-pre-tool-use";
|
|
|
1893
1882
|
var POST_TOOL_USE_BIN2 = "prim-post-tool-use";
|
|
1894
1883
|
var SESSION_START_BIN2 = "prim-session-start";
|
|
1895
1884
|
var CODEX_ARGS = "--agent codex";
|
|
1885
|
+
var CODEX_EDIT_MATCHER = "apply_patch";
|
|
1886
|
+
var CODEX_POST_TOOL_MATCHER = "apply_patch|Bash";
|
|
1896
1887
|
var JSON_INDENT2 = 2;
|
|
1897
1888
|
var CODEX_CAPTURE_EVENTS = [
|
|
1898
1889
|
"SessionStart",
|
|
@@ -1905,8 +1896,8 @@ var CODEX_CAPTURE_EVENTS = [
|
|
|
1905
1896
|
var PRIM_BINS2 = [CAPTURE_BIN2, GATE_BIN2, POST_TOOL_USE_BIN2, SESSION_START_BIN2];
|
|
1906
1897
|
var CODEX_REGISTRATIONS = [
|
|
1907
1898
|
...CODEX_CAPTURE_EVENTS.map((event) => makeRegistration(event, "*", CAPTURE_BIN2, CODEX_ARGS)),
|
|
1908
|
-
makeRegistration("PreToolUse",
|
|
1909
|
-
makeRegistration("PostToolUse",
|
|
1899
|
+
makeRegistration("PreToolUse", CODEX_EDIT_MATCHER, GATE_BIN2, CODEX_ARGS),
|
|
1900
|
+
makeRegistration("PostToolUse", CODEX_POST_TOOL_MATCHER, POST_TOOL_USE_BIN2, CODEX_ARGS),
|
|
1910
1901
|
makeRegistration("SessionStart", "*", SESSION_START_BIN2, CODEX_ARGS)
|
|
1911
1902
|
];
|
|
1912
1903
|
var USER_SCOPE_PATH2 = join3(homedir3(), ".codex", "hooks.json");
|
|
@@ -2030,10 +2021,74 @@ ${line("project", result.project)}`);
|
|
|
2030
2021
|
}
|
|
2031
2022
|
|
|
2032
2023
|
// src/commands/daemon.ts
|
|
2033
|
-
import { spawn } from "child_process";
|
|
2024
|
+
import { spawn as spawn2 } from "child_process";
|
|
2034
2025
|
import { closeSync as closeSync2, existsSync as existsSync4, mkdirSync as mkdirSync3, openSync as openSync2, readFileSync as readFileSync4, unlinkSync } from "fs";
|
|
2026
|
+
import { homedir as homedir5 } from "os";
|
|
2027
|
+
import { join as join5 } from "path";
|
|
2028
|
+
import { Option } from "commander";
|
|
2029
|
+
|
|
2030
|
+
// src/daemon/latest-bootstrap.ts
|
|
2031
|
+
import { spawn } from "child_process";
|
|
2035
2032
|
import { homedir as homedir4 } from "os";
|
|
2036
2033
|
import { join as join4 } from "path";
|
|
2034
|
+
var LATEST_BOOTSTRAP_TIMEOUT_MS = 45e3;
|
|
2035
|
+
var LATEST_BOOTSTRAP_LOCK_NAME = "daemon-latest.lock";
|
|
2036
|
+
async function runLatestEnsure(options) {
|
|
2037
|
+
const env = {
|
|
2038
|
+
...options.env ?? process.env,
|
|
2039
|
+
npm_config_prefer_online: "true",
|
|
2040
|
+
npm_config_fetch_retries: "1",
|
|
2041
|
+
npm_config_fetch_retry_mintimeout: "1000",
|
|
2042
|
+
npm_config_fetch_retry_maxtimeout: "5000",
|
|
2043
|
+
npm_config_fetch_timeout: "15000"
|
|
2044
|
+
};
|
|
2045
|
+
return await new Promise((resolve5) => {
|
|
2046
|
+
let settled = false;
|
|
2047
|
+
let child;
|
|
2048
|
+
try {
|
|
2049
|
+
child = (options.spawnProcess ?? spawn)(
|
|
2050
|
+
"npx",
|
|
2051
|
+
["--yes", "--prefer-online", "-p", "@primitive.ai/prim@latest", "prim", "daemon", "ensure"],
|
|
2052
|
+
{ env, stdio: "ignore" }
|
|
2053
|
+
);
|
|
2054
|
+
} catch {
|
|
2055
|
+
resolve5(false);
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
2058
|
+
const timer = setTimeout(() => {
|
|
2059
|
+
child.kill("SIGTERM");
|
|
2060
|
+
finish(false);
|
|
2061
|
+
}, options.timeoutMs ?? LATEST_BOOTSTRAP_TIMEOUT_MS);
|
|
2062
|
+
const finish = (result) => {
|
|
2063
|
+
if (settled) return;
|
|
2064
|
+
settled = true;
|
|
2065
|
+
clearTimeout(timer);
|
|
2066
|
+
resolve5(result);
|
|
2067
|
+
};
|
|
2068
|
+
timer.unref();
|
|
2069
|
+
child.once("error", () => finish(false));
|
|
2070
|
+
child.once("exit", (code) => finish(code === 0));
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
async function runLatestDaemonBootstrap(ensureCurrent, options = {}) {
|
|
2074
|
+
const lockPath = options.lockPath ?? join4(options.homeDir ?? homedir4(), ".config", "prim", LATEST_BOOTSTRAP_LOCK_NAME);
|
|
2075
|
+
try {
|
|
2076
|
+
return await withFileLock(
|
|
2077
|
+
lockPath,
|
|
2078
|
+
async () => {
|
|
2079
|
+
const current = await ensureCurrent();
|
|
2080
|
+
if (current.disabled) return true;
|
|
2081
|
+
return await runLatestEnsure(options);
|
|
2082
|
+
},
|
|
2083
|
+
// A concurrent SessionStart already owns the complete bootstrap. Do not
|
|
2084
|
+
// queue another npm lookup behind it; the short window only permits one
|
|
2085
|
+
// retry after recovering a stale lock.
|
|
2086
|
+
{ timeoutMs: 100, pollMs: 25 }
|
|
2087
|
+
);
|
|
2088
|
+
} catch {
|
|
2089
|
+
return false;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2037
2092
|
|
|
2038
2093
|
// src/lib/presence.ts
|
|
2039
2094
|
var DECISION_ORIGIN = "https://app.getprimitive.ai";
|
|
@@ -2084,10 +2139,10 @@ function formatTeammatesWithArea(teammates, cap) {
|
|
|
2084
2139
|
|
|
2085
2140
|
// src/commands/daemon.ts
|
|
2086
2141
|
var DAEMON_BIN = "prim-daemon-server";
|
|
2087
|
-
var CONFIG_DIR =
|
|
2088
|
-
var PID_PATH =
|
|
2089
|
-
var SOCK_PATH =
|
|
2090
|
-
var LOG_PATH =
|
|
2142
|
+
var CONFIG_DIR = join5(homedir5(), ".config", "prim");
|
|
2143
|
+
var PID_PATH = join5(CONFIG_DIR, "daemon.pid");
|
|
2144
|
+
var SOCK_PATH = join5(CONFIG_DIR, "sock");
|
|
2145
|
+
var LOG_PATH = join5(CONFIG_DIR, "daemon.log");
|
|
2091
2146
|
var CONFIG_DIR_MODE = 448;
|
|
2092
2147
|
var LOG_FILE_MODE = 384;
|
|
2093
2148
|
var STOP_TIMEOUT_MS = 5e3;
|
|
@@ -2158,13 +2213,13 @@ function sleep(ms) {
|
|
|
2158
2213
|
}
|
|
2159
2214
|
function spawnDaemon(options) {
|
|
2160
2215
|
const file = binFile(DAEMON_BIN);
|
|
2161
|
-
return file ?
|
|
2216
|
+
return file ? spawn2(process.execPath, [file], options) : spawn2(DAEMON_BIN, [], options);
|
|
2162
2217
|
}
|
|
2163
2218
|
function openDaemonLog(configDir = CONFIG_DIR) {
|
|
2164
2219
|
if (!existsSync4(configDir)) {
|
|
2165
2220
|
mkdirSync3(configDir, { recursive: true, mode: CONFIG_DIR_MODE });
|
|
2166
2221
|
}
|
|
2167
|
-
return openSync2(
|
|
2222
|
+
return openSync2(join5(configDir, "daemon.log"), "a", LOG_FILE_MODE);
|
|
2168
2223
|
}
|
|
2169
2224
|
async function waitForReady() {
|
|
2170
2225
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
@@ -2676,7 +2731,7 @@ async function daemonEnsure() {
|
|
|
2676
2731
|
process.stderr.write("[prim] daemon remains explicitly disabled\n");
|
|
2677
2732
|
console.log(JSON.stringify({ ensured: false, disabled: true, supervised: false }, null, 2));
|
|
2678
2733
|
}
|
|
2679
|
-
return;
|
|
2734
|
+
return { disabled };
|
|
2680
2735
|
}
|
|
2681
2736
|
const result = await ensureMacDaemon();
|
|
2682
2737
|
if (result.state === "disabled") {
|
|
@@ -2703,6 +2758,7 @@ async function daemonEnsure() {
|
|
|
2703
2758
|
2
|
|
2704
2759
|
)
|
|
2705
2760
|
);
|
|
2761
|
+
return { disabled: result.state === "disabled" };
|
|
2706
2762
|
}
|
|
2707
2763
|
function registerDaemonCommands(program2) {
|
|
2708
2764
|
const daemon = program2.command("daemon").description("Manage the prim companion daemon (latency unlock + presence + broadcast)");
|
|
@@ -2718,13 +2774,17 @@ function registerDaemonCommands(program2) {
|
|
|
2718
2774
|
daemon.command("restart").description("Restart the daemon and clear any explicit disable marker").option("--foreground", "Restart in the foreground").action(async (opts) => {
|
|
2719
2775
|
await daemonRestart(opts);
|
|
2720
2776
|
});
|
|
2721
|
-
daemon.command("ensure").description("Idempotently install, upgrade, and heal the daemon unless explicitly disabled").action(async () => {
|
|
2777
|
+
daemon.command("ensure").description("Idempotently install, upgrade, and heal the daemon unless explicitly disabled").addOption(new Option("--latest-bootstrap").hideHelp()).action(async (opts) => {
|
|
2778
|
+
if (opts.latestBootstrap) {
|
|
2779
|
+
await runLatestDaemonBootstrap(daemonEnsure);
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2722
2782
|
await daemonEnsure();
|
|
2723
2783
|
});
|
|
2724
2784
|
}
|
|
2725
2785
|
|
|
2726
2786
|
// src/commands/decisions.ts
|
|
2727
|
-
import { Option } from "commander";
|
|
2787
|
+
import { Option as Option2 } from "commander";
|
|
2728
2788
|
|
|
2729
2789
|
// src/decisions/cascade-renderer.ts
|
|
2730
2790
|
var DEPENDENTS_INLINE_LIMIT = 5;
|
|
@@ -3526,7 +3586,7 @@ function registerDecisionsCommands(program2) {
|
|
|
3526
3586
|
}
|
|
3527
3587
|
});
|
|
3528
3588
|
decisions.command("create").description("Record a decision directly with its explicit user or agent origin").requiredOption("--intent <text>", "What was decided (required)").addOption(
|
|
3529
|
-
new
|
|
3589
|
+
new Option2(
|
|
3530
3590
|
"--attribution <origin>",
|
|
3531
3591
|
"Who originated the exact choice: user | agent (required)"
|
|
3532
3592
|
).choices(["user", "agent"]).makeOptionMandatory()
|
|
@@ -3857,19 +3917,46 @@ function checkWorkspaceIdentity() {
|
|
|
3857
3917
|
};
|
|
3858
3918
|
}
|
|
3859
3919
|
}
|
|
3860
|
-
function classifyRepositoryBinding(value) {
|
|
3861
|
-
|
|
3920
|
+
function classifyRepositoryBinding(value, currentServerValue) {
|
|
3921
|
+
if (!isValidRepoSyncId(value)) {
|
|
3922
|
+
return {
|
|
3923
|
+
name: "repo-binding",
|
|
3924
|
+
status: "fail",
|
|
3925
|
+
detail: "missing or invalid local prim.repoSyncId \u2014 run `prim enable`"
|
|
3926
|
+
};
|
|
3927
|
+
}
|
|
3928
|
+
if (currentServerValue !== void 0 && value !== currentServerValue) {
|
|
3929
|
+
return {
|
|
3930
|
+
name: "repo-binding",
|
|
3931
|
+
status: "fail",
|
|
3932
|
+
detail: "local repository binding is stale for the current origin \u2014 run `prim enable`"
|
|
3933
|
+
};
|
|
3934
|
+
}
|
|
3935
|
+
return {
|
|
3862
3936
|
name: "repo-binding",
|
|
3863
3937
|
status: "ok",
|
|
3864
|
-
detail: "valid local repository binding ready"
|
|
3865
|
-
} : {
|
|
3866
|
-
name: "repo-binding",
|
|
3867
|
-
status: "fail",
|
|
3868
|
-
detail: "missing or invalid local prim.repoSyncId \u2014 run `prim enable`"
|
|
3938
|
+
detail: currentServerValue === void 0 ? "valid local repository binding ready" : "local repository binding matches the current server binding"
|
|
3869
3939
|
};
|
|
3870
3940
|
}
|
|
3871
|
-
function checkRepositoryBinding() {
|
|
3872
|
-
|
|
3941
|
+
async function checkRepositoryBinding() {
|
|
3942
|
+
const root = process.cwd();
|
|
3943
|
+
const local = repoSyncId(root);
|
|
3944
|
+
const localCheck = classifyRepositoryBinding(local);
|
|
3945
|
+
if (localCheck.status === "fail") return localCheck;
|
|
3946
|
+
try {
|
|
3947
|
+
const current = await resolveRepositoryBinding(root, {
|
|
3948
|
+
signal: AbortSignal.timeout(CONNECTIVITY_TIMEOUT_MS),
|
|
3949
|
+
quietRefresh: true
|
|
3950
|
+
});
|
|
3951
|
+
return classifyRepositoryBinding(local, current.repoSyncId);
|
|
3952
|
+
} catch (error) {
|
|
3953
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
3954
|
+
return {
|
|
3955
|
+
name: "repo-binding",
|
|
3956
|
+
status: "fail",
|
|
3957
|
+
detail: `could not verify the current repository binding \u2014 ${detail.slice(0, 80)}`
|
|
3958
|
+
};
|
|
3959
|
+
}
|
|
3873
3960
|
}
|
|
3874
3961
|
function classifyPostCommitHook(inspection) {
|
|
3875
3962
|
if (inspection.covered) {
|
|
@@ -4016,7 +4103,7 @@ async function collectChecks() {
|
|
|
4016
4103
|
checkStranded(),
|
|
4017
4104
|
checkFeedbackHooks(),
|
|
4018
4105
|
checkWorkspaceIdentity(),
|
|
4019
|
-
checkRepositoryBinding(),
|
|
4106
|
+
await checkRepositoryBinding(),
|
|
4020
4107
|
checkPostCommitHook(),
|
|
4021
4108
|
...backend,
|
|
4022
4109
|
await checkFeedbackCapability()
|
|
@@ -4061,8 +4148,8 @@ import {
|
|
|
4061
4148
|
rmSync as rmSync2,
|
|
4062
4149
|
writeFileSync as writeFileSync3
|
|
4063
4150
|
} from "fs";
|
|
4064
|
-
import { homedir as
|
|
4065
|
-
import { dirname as dirname3, join as
|
|
4151
|
+
import { homedir as homedir6 } from "os";
|
|
4152
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
4066
4153
|
import { Document, parseDocument, stringify } from "yaml";
|
|
4067
4154
|
var CAPTURE_BIN3 = "prim-hook";
|
|
4068
4155
|
var GATE_BIN3 = "prim-pre-tool-use";
|
|
@@ -4087,13 +4174,13 @@ var PINNED_CASES = PRIM_BINS3.map((bin) => {
|
|
|
4087
4174
|
;;`;
|
|
4088
4175
|
}).join("\n");
|
|
4089
4176
|
function hermesHome() {
|
|
4090
|
-
return process.env.HERMES_HOME ??
|
|
4177
|
+
return process.env.HERMES_HOME ?? join6(homedir6(), ".hermes");
|
|
4091
4178
|
}
|
|
4092
4179
|
function configPath() {
|
|
4093
|
-
return
|
|
4180
|
+
return join6(hermesHome(), "config.yaml");
|
|
4094
4181
|
}
|
|
4095
4182
|
function shimPath() {
|
|
4096
|
-
return
|
|
4183
|
+
return join6(hermesHome(), "agent-hooks", "prim-shim.sh");
|
|
4097
4184
|
}
|
|
4098
4185
|
var SHIM_SCRIPT = `#!/bin/sh
|
|
4099
4186
|
# prim Hermes hook shim \u2014 managed by \`prim hermes install\`. Hermes runs hooks
|
|
@@ -4125,6 +4212,7 @@ var REGISTRATIONS2 = [
|
|
|
4125
4212
|
...CAPTURE_EVENTS2.map((event) => ({ event, bin: CAPTURE_BIN3 })),
|
|
4126
4213
|
{ event: "pre_tool_call", matcher: EDIT_MATCHER, bin: GATE_BIN3, timeout: GATE_TIMEOUT_SECONDS },
|
|
4127
4214
|
{ event: "post_tool_call", matcher: EDIT_MATCHER, bin: POST_TOOL_USE_BIN3 },
|
|
4215
|
+
{ event: "post_approval_response", bin: POST_TOOL_USE_BIN3 },
|
|
4128
4216
|
{ event: "on_session_start", bin: SESSION_START_BIN3 },
|
|
4129
4217
|
{ event: "on_session_end", bin: SESSION_END_BIN2 }
|
|
4130
4218
|
];
|
|
@@ -4395,9 +4483,9 @@ function registerHermesCommands(program2) {
|
|
|
4395
4483
|
// src/commands/hooks.ts
|
|
4396
4484
|
import { execFileSync } from "child_process";
|
|
4397
4485
|
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
4398
|
-
import { homedir as
|
|
4399
|
-
import { dirname as dirname4, join as
|
|
4400
|
-
import { Option as
|
|
4486
|
+
import { homedir as homedir7 } from "os";
|
|
4487
|
+
import { dirname as dirname4, join as join7, resolve as resolve2 } from "path";
|
|
4488
|
+
import { Option as Option3 } from "commander";
|
|
4401
4489
|
var PRE_COMMIT = { hookName: "pre-commit", binName: "prim-pre-commit" };
|
|
4402
4490
|
var POST_COMMIT = { hookName: "post-commit", binName: "prim-post-commit" };
|
|
4403
4491
|
var HOOKS = [PRE_COMMIT, POST_COMMIT];
|
|
@@ -4544,9 +4632,9 @@ function projectHooksDir(gitRoot) {
|
|
|
4544
4632
|
}
|
|
4545
4633
|
return resolve2(gitRoot, commonDir, "hooks");
|
|
4546
4634
|
}
|
|
4547
|
-
var PRIM_GIT_HOOKS_DIR =
|
|
4635
|
+
var PRIM_GIT_HOOKS_DIR = join7(homedir7(), ".config", "prim", "git-hooks");
|
|
4548
4636
|
function expandTilde(p) {
|
|
4549
|
-
return p.startsWith("~/") ?
|
|
4637
|
+
return p.startsWith("~/") ? join7(homedir7(), p.slice(2)) : p;
|
|
4550
4638
|
}
|
|
4551
4639
|
function isOurHooksDir(value) {
|
|
4552
4640
|
return value !== "" && expandTilde(value) === PRIM_GIT_HOOKS_DIR;
|
|
@@ -4739,12 +4827,12 @@ function registerHooksCommands(program2) {
|
|
|
4739
4827
|
hooks.command("install").description(
|
|
4740
4828
|
"Install the prim git hooks \u2014 pre-commit + post-commit (auto-detects Husky; use --target to override)"
|
|
4741
4829
|
).addOption(
|
|
4742
|
-
new
|
|
4830
|
+
new Option3("--target <where>", "install destination; bypasses Husky detection").choices([
|
|
4743
4831
|
"husky",
|
|
4744
4832
|
"git-hooks"
|
|
4745
4833
|
])
|
|
4746
4834
|
).addOption(
|
|
4747
|
-
new
|
|
4835
|
+
new Option3(
|
|
4748
4836
|
"--scope <scope>",
|
|
4749
4837
|
"project (default, this repo) or user (a global core.hooksPath capturing every repo)"
|
|
4750
4838
|
).choices(["project", "user"])
|
|
@@ -4784,7 +4872,7 @@ function registerHooksCommands(program2) {
|
|
|
4784
4872
|
hooks.command("uninstall").description(
|
|
4785
4873
|
"Remove the prim git hooks (.git/hooks, or the global core.hooksPath with --scope user)"
|
|
4786
4874
|
).addOption(
|
|
4787
|
-
new
|
|
4875
|
+
new Option3(
|
|
4788
4876
|
"--scope <scope>",
|
|
4789
4877
|
"project (default, this repo) or user (global core.hooksPath)"
|
|
4790
4878
|
).choices(["project", "user"])
|
|
@@ -4821,11 +4909,11 @@ function registerHooksCommands(program2) {
|
|
|
4821
4909
|
|
|
4822
4910
|
// src/commands/moves.ts
|
|
4823
4911
|
import { existsSync as existsSync8, mkdirSync as mkdirSync6, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
4824
|
-
import { join as
|
|
4912
|
+
import { join as join9 } from "path";
|
|
4825
4913
|
|
|
4826
4914
|
// src/flusher.ts
|
|
4827
4915
|
import { createReadStream, renameSync as renameSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
4828
|
-
import { dirname as dirname5, join as
|
|
4916
|
+
import { dirname as dirname5, join as join8 } from "path";
|
|
4829
4917
|
import { createInterface } from "readline";
|
|
4830
4918
|
var BATCH_SIZE = 500;
|
|
4831
4919
|
var HTTP_TIMEOUT_MS = 1e4;
|
|
@@ -4949,7 +5037,7 @@ async function flushOnce() {
|
|
|
4949
5037
|
return { flushed: total };
|
|
4950
5038
|
}
|
|
4951
5039
|
var flushInFlight;
|
|
4952
|
-
var FLUSH_LOCK_PATH =
|
|
5040
|
+
var FLUSH_LOCK_PATH = join8(dirname5(JOURNAL_DIR), ".flush.lock");
|
|
4953
5041
|
var FLUSH_LOCK_TIMEOUT_MS = 250;
|
|
4954
5042
|
function isFlushLockContended(error) {
|
|
4955
5043
|
return error instanceof Error && error.message.startsWith("timed out waiting for file lock");
|
|
@@ -5066,18 +5154,18 @@ function registerMovesCommands(program2) {
|
|
|
5066
5154
|
}
|
|
5067
5155
|
});
|
|
5068
5156
|
moves.command("bind").description("Pin the current directory to an org via .prim/workspace.json").requiredOption("--orgId <orgId>", "Convex organization id").action((opts) => {
|
|
5069
|
-
const dir =
|
|
5157
|
+
const dir = join9(process.cwd(), ".prim");
|
|
5070
5158
|
if (!existsSync8(dir)) {
|
|
5071
5159
|
mkdirSync6(dir, { recursive: true, mode: DIR_MODE });
|
|
5072
5160
|
}
|
|
5073
|
-
const file =
|
|
5161
|
+
const file = join9(process.cwd(), WORKSPACE_FILE);
|
|
5074
5162
|
writeFileSync5(file, JSON.stringify({ orgId: opts.orgId, boundAt: Date.now() }, null, 2), {
|
|
5075
5163
|
mode: FILE_MODE
|
|
5076
5164
|
});
|
|
5077
5165
|
console.log(`[prim] bound ${process.cwd()} to org ${opts.orgId}`);
|
|
5078
5166
|
});
|
|
5079
5167
|
moves.command("drop").description("Remove the .prim/workspace.json binding from the cwd").action(() => {
|
|
5080
|
-
const file =
|
|
5168
|
+
const file = join9(process.cwd(), WORKSPACE_FILE);
|
|
5081
5169
|
if (!existsSync8(file)) {
|
|
5082
5170
|
console.log("[prim] no workspace binding in cwd");
|
|
5083
5171
|
return;
|
|
@@ -5176,7 +5264,7 @@ import {
|
|
|
5176
5264
|
unlinkSync as unlinkSync5,
|
|
5177
5265
|
writeFileSync as writeFileSync6
|
|
5178
5266
|
} from "fs";
|
|
5179
|
-
import { join as
|
|
5267
|
+
import { join as join10 } from "path";
|
|
5180
5268
|
var DIR_MODE2 = 448;
|
|
5181
5269
|
var FILE_MODE2 = 384;
|
|
5182
5270
|
function ensureDir() {
|
|
@@ -5185,7 +5273,7 @@ function ensureDir() {
|
|
|
5185
5273
|
}
|
|
5186
5274
|
}
|
|
5187
5275
|
function markerPath(sessionId) {
|
|
5188
|
-
return
|
|
5276
|
+
return join10(SESSIONS_DIR, `${sessionId}.json`);
|
|
5189
5277
|
}
|
|
5190
5278
|
function registerSessionCommands(program2) {
|
|
5191
5279
|
const session = program2.command("session").description("Decision Event Pipeline \u2014 session binding markers");
|
|
@@ -5213,7 +5301,7 @@ function registerSessionCommands(program2) {
|
|
|
5213
5301
|
for (const f of files) {
|
|
5214
5302
|
const sessionId = f.replace(/\.json$/, "");
|
|
5215
5303
|
try {
|
|
5216
|
-
const m = JSON.parse(readFileSync7(
|
|
5304
|
+
const m = JSON.parse(readFileSync7(join10(SESSIONS_DIR, f), "utf-8"));
|
|
5217
5305
|
console.log(`${sessionId} org=${m.orgId}`);
|
|
5218
5306
|
} catch {
|
|
5219
5307
|
}
|
|
@@ -5233,7 +5321,7 @@ function registerSessionCommands(program2) {
|
|
|
5233
5321
|
// src/commands/setup.ts
|
|
5234
5322
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
5235
5323
|
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
5236
|
-
import { join as
|
|
5324
|
+
import { join as join11 } from "path";
|
|
5237
5325
|
var EXIT_INCOMPLETE = 1;
|
|
5238
5326
|
var EXIT_USAGE3 = 2;
|
|
5239
5327
|
var SESSION_LABELS = {
|
|
@@ -5314,7 +5402,7 @@ function detectProjectConflicts(agent, run) {
|
|
|
5314
5402
|
}
|
|
5315
5403
|
try {
|
|
5316
5404
|
const root = gitToplevel();
|
|
5317
|
-
const preCommit = root &&
|
|
5405
|
+
const preCommit = root && join11(root, ".git", "hooks", "pre-commit");
|
|
5318
5406
|
if (preCommit && existsSync10(preCommit) && readFileSync8(preCommit, "utf-8").includes("prim-pre-commit")) {
|
|
5319
5407
|
conflicts.push(CONFLICT_HOOKS);
|
|
5320
5408
|
}
|
|
@@ -5473,14 +5561,55 @@ function registerSetupCommand(program2, dependencies = {}) {
|
|
|
5473
5561
|
import { readFileSync as readFileSync9 } from "fs";
|
|
5474
5562
|
import { dirname as dirname6, resolve as resolve3 } from "path";
|
|
5475
5563
|
import { fileURLToPath } from "url";
|
|
5476
|
-
|
|
5564
|
+
|
|
5565
|
+
// src/lib/statusline-render.ts
|
|
5477
5566
|
var STATUSLINE_NAME_CAP = 3;
|
|
5567
|
+
function formatStatusline(version, snapshot, resolveIngestionStatus) {
|
|
5568
|
+
if (!snapshot) {
|
|
5569
|
+
return `primitive ${version} (daemon: down)`;
|
|
5570
|
+
}
|
|
5571
|
+
if (snapshot.healthy === false) {
|
|
5572
|
+
if (snapshot.needsReauth) {
|
|
5573
|
+
return `primitive ${version} (daemon: paused \xB7 run \`prim auth login\`)`;
|
|
5574
|
+
}
|
|
5575
|
+
if (snapshot.ingestion?.healthy === false) {
|
|
5576
|
+
const pending = snapshot.ingestion.pendingCount;
|
|
5577
|
+
const qualifier = snapshot.ingestion.pendingSampled ? "at least " : "";
|
|
5578
|
+
return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""})`;
|
|
5579
|
+
}
|
|
5580
|
+
if (snapshot.heartbeat?.healthy === false) {
|
|
5581
|
+
return `primitive ${version} (daemon: degraded \xB7 presence: unavailable)`;
|
|
5582
|
+
}
|
|
5583
|
+
return `primitive ${version} (daemon: starting)`;
|
|
5584
|
+
}
|
|
5585
|
+
const ingestionStatus = resolveIngestionStatus();
|
|
5586
|
+
if (snapshot.envMismatch) {
|
|
5587
|
+
return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 presence: other env)`;
|
|
5588
|
+
}
|
|
5589
|
+
if (snapshot.presenceStale) {
|
|
5590
|
+
return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 presence: stale)`;
|
|
5591
|
+
}
|
|
5592
|
+
let team;
|
|
5593
|
+
if (snapshot.onlineTeammates !== void 0) {
|
|
5594
|
+
team = `team: ${formatTeammatesWithArea(snapshot.onlineTeammates, STATUSLINE_NAME_CAP)}`;
|
|
5595
|
+
} else if (snapshot.onlineNames !== void 0) {
|
|
5596
|
+
team = `team: ${formatTeammates(snapshot.onlineNames, STATUSLINE_NAME_CAP)}`;
|
|
5597
|
+
} else if (typeof snapshot.onlineCount === "number") {
|
|
5598
|
+
team = `team: ${String(snapshot.onlineCount)} online`;
|
|
5599
|
+
} else {
|
|
5600
|
+
team = "team: \u2014";
|
|
5601
|
+
}
|
|
5602
|
+
return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 ${team})`;
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
// src/commands/statusline.ts
|
|
5606
|
+
var STATUSLINE_TIMEOUT_MS = 200;
|
|
5478
5607
|
function readPackageVersion() {
|
|
5479
5608
|
try {
|
|
5480
5609
|
const here = dirname6(fileURLToPath(import.meta.url));
|
|
5481
5610
|
const candidates = [
|
|
5482
|
-
//
|
|
5483
|
-
//
|
|
5611
|
+
// Schema-v2 runtimes staged a manifest beside this standalone bundle.
|
|
5612
|
+
// Keep resolving it while those legacy launchers transition to schema v3.
|
|
5484
5613
|
resolve3(here, "manifest.json"),
|
|
5485
5614
|
resolve3(here, "../../package.json"),
|
|
5486
5615
|
resolve3(here, "../package.json")
|
|
@@ -5515,40 +5644,8 @@ async function renderStatusline() {
|
|
|
5515
5644
|
);
|
|
5516
5645
|
if (!snapshot) {
|
|
5517
5646
|
debug("daemon snapshot missing");
|
|
5518
|
-
return `primitive ${version} (daemon: down)`;
|
|
5519
|
-
}
|
|
5520
|
-
if (snapshot.healthy === false) {
|
|
5521
|
-
if (snapshot.needsReauth) {
|
|
5522
|
-
return `primitive ${version} (daemon: paused \xB7 run \`prim auth login\`)`;
|
|
5523
|
-
}
|
|
5524
|
-
if (snapshot.ingestion?.healthy === false) {
|
|
5525
|
-
const pending = snapshot.ingestion.pendingCount;
|
|
5526
|
-
const qualifier = snapshot.ingestion.pendingSampled ? "at least " : "";
|
|
5527
|
-
return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""})`;
|
|
5528
|
-
}
|
|
5529
|
-
if (snapshot.heartbeat?.healthy === false) {
|
|
5530
|
-
return `primitive ${version} (daemon: degraded \xB7 presence: unavailable)`;
|
|
5531
|
-
}
|
|
5532
|
-
return `primitive ${version} (daemon: starting)`;
|
|
5533
|
-
}
|
|
5534
|
-
const ingestionStatus = decisionIngestionStatus(process.cwd());
|
|
5535
|
-
if (snapshot.envMismatch) {
|
|
5536
|
-
return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 presence: other env)`;
|
|
5537
|
-
}
|
|
5538
|
-
if (snapshot.presenceStale) {
|
|
5539
|
-
return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 presence: stale)`;
|
|
5540
|
-
}
|
|
5541
|
-
let team;
|
|
5542
|
-
if (snapshot.onlineTeammates !== void 0) {
|
|
5543
|
-
team = `team: ${formatTeammatesWithArea(snapshot.onlineTeammates, STATUSLINE_NAME_CAP)}`;
|
|
5544
|
-
} else if (snapshot.onlineNames !== void 0) {
|
|
5545
|
-
team = `team: ${formatTeammates(snapshot.onlineNames, STATUSLINE_NAME_CAP)}`;
|
|
5546
|
-
} else if (typeof snapshot.onlineCount === "number") {
|
|
5547
|
-
team = `team: ${String(snapshot.onlineCount)} online`;
|
|
5548
|
-
} else {
|
|
5549
|
-
team = "team: \u2014";
|
|
5550
5647
|
}
|
|
5551
|
-
return
|
|
5648
|
+
return formatStatusline(version, snapshot, () => decisionIngestionStatus(process.cwd()));
|
|
5552
5649
|
}
|
|
5553
5650
|
function registerStatuslineCommands(program2) {
|
|
5554
5651
|
program2.command("statusline").description("Render the Claude Code statusLine for the prim companion daemon").action(async () => {
|