@jentrix/cli 0.5.17 → 0.5.19
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.
|
@@ -22,8 +22,8 @@ description: End a connected Jentrix session after preserving approved outputs,
|
|
|
22
22
|
Declining never blocks closure.
|
|
23
23
|
5. Run `jentrix session end <session-id>` and relay all output, including the exact
|
|
24
24
|
telemetry line and any capture gap.
|
|
25
|
-
6.
|
|
26
|
-
|
|
25
|
+
6. Report provider-reported Codex token receipts when the hook supplied a rollout
|
|
26
|
+
path. If none were observed, keep token fields null; never report estimates.
|
|
27
27
|
7. A final-response artifact exists only when a prior `Stop` hook observed assistant
|
|
28
28
|
text before closure. The assistant text produced by this closing turn occurs after
|
|
29
29
|
the command and must not be claimed as captured.
|
package/dist/main.js
CHANGED
|
@@ -20966,7 +20966,7 @@ function refreshAccessToken(input) {
|
|
|
20966
20966
|
|
|
20967
20967
|
// src/client.ts
|
|
20968
20968
|
var CLI_NAME = "stacks-cli";
|
|
20969
|
-
var CLI_VERSION = "0.5.
|
|
20969
|
+
var CLI_VERSION = "0.5.19";
|
|
20970
20970
|
var DEAD_TOKEN_MESSAGE = "authentication failed (HTTP 401): the token is dead or expired \u2014 mint a new PAT at /account/tokens on your Jentrix server and update STACKS_TOKEN (or --token / the config file).";
|
|
20971
20971
|
var RELOGIN_MESSAGE = "OAuth session expired and could not be refreshed \u2014 run `jentrix login` to sign in again.";
|
|
20972
20972
|
function originOf2(url2) {
|
|
@@ -22620,6 +22620,7 @@ function readTranscriptHead(path) {
|
|
|
22620
22620
|
function parseHookLedger(body) {
|
|
22621
22621
|
const starts = [];
|
|
22622
22622
|
const endedAt = /* @__PURE__ */ new Map();
|
|
22623
|
+
const transcriptBySession = /* @__PURE__ */ new Map();
|
|
22623
22624
|
for (const line of body.split("\n").filter(Boolean)) {
|
|
22624
22625
|
let parsed;
|
|
22625
22626
|
try {
|
|
@@ -22629,6 +22630,10 @@ function parseHookLedger(body) {
|
|
|
22629
22630
|
}
|
|
22630
22631
|
const sessionId = parsed.payload?.session_id;
|
|
22631
22632
|
if (typeof sessionId !== "string") continue;
|
|
22633
|
+
const transcriptPath = parsed.payload?.transcript_path?.trim();
|
|
22634
|
+
if (transcriptPath) {
|
|
22635
|
+
transcriptBySession.set(sessionId, transcriptPath);
|
|
22636
|
+
}
|
|
22632
22637
|
const stamped = parsed.at ? Date.parse(parsed.at) : NaN;
|
|
22633
22638
|
const ms = Number.isNaN(stamped) ? 0 : stamped;
|
|
22634
22639
|
if (parsed.event === "SessionEnd") {
|
|
@@ -22643,16 +22648,10 @@ function parseHookLedger(body) {
|
|
|
22643
22648
|
});
|
|
22644
22649
|
}
|
|
22645
22650
|
}
|
|
22646
|
-
return { starts, endedAt };
|
|
22651
|
+
return { starts, endedAt, transcriptBySession };
|
|
22647
22652
|
}
|
|
22648
22653
|
function transcriptForSessionIn(ledger, sessionId) {
|
|
22649
|
-
|
|
22650
|
-
const start = ledger.starts[i];
|
|
22651
|
-
if (start.sessionId === sessionId && start.transcriptPath) {
|
|
22652
|
-
return start.transcriptPath;
|
|
22653
|
-
}
|
|
22654
|
-
}
|
|
22655
|
-
return null;
|
|
22654
|
+
return ledger.transcriptBySession.get(sessionId) ?? null;
|
|
22656
22655
|
}
|
|
22657
22656
|
var CLAUDE_SESSION_ENV = "CLAUDE_CODE_SESSION_ID";
|
|
22658
22657
|
var CODEX_THREAD_ENV = "CODEX_THREAD_ID";
|
|
@@ -22676,9 +22675,10 @@ function readClaudeHookContext(deps2, readFile = (path) => readFileSync2(path, "
|
|
|
22676
22675
|
} catch {
|
|
22677
22676
|
}
|
|
22678
22677
|
}
|
|
22679
|
-
const
|
|
22678
|
+
const ledger = parseHookLedger(body);
|
|
22679
|
+
const { starts, endedAt } = ledger;
|
|
22680
22680
|
if (own) {
|
|
22681
|
-
const transcriptPath = transcriptForSessionIn(
|
|
22681
|
+
const transcriptPath = transcriptForSessionIn(ledger, own);
|
|
22682
22682
|
return {
|
|
22683
22683
|
sessionId: own,
|
|
22684
22684
|
transcriptPath,
|
|
@@ -22740,13 +22740,15 @@ function readCodexHookContext(deps2, readFile = (path) => readFileSync2(path, "u
|
|
|
22740
22740
|
} catch {
|
|
22741
22741
|
}
|
|
22742
22742
|
}
|
|
22743
|
-
const
|
|
22743
|
+
const ledger = parseHookLedger(body);
|
|
22744
|
+
const { starts, endedAt } = ledger;
|
|
22744
22745
|
if (own) {
|
|
22745
22746
|
const source = threadId ? CODEX_THREAD_ENV : CODEX_SESSION_ENV;
|
|
22747
|
+
const transcriptPath = transcriptForSessionIn(ledger, own);
|
|
22746
22748
|
return {
|
|
22747
22749
|
sessionId: own,
|
|
22748
|
-
transcriptPath
|
|
22749
|
-
basis: `${source}=${own} \u2014 this Codex task's own id`,
|
|
22750
|
+
transcriptPath,
|
|
22751
|
+
basis: `${source}=${own} \u2014 this Codex task's own id${transcriptPath ? " (rollout from its hook record)" : ""}`,
|
|
22750
22752
|
newerElsewhere: null
|
|
22751
22753
|
};
|
|
22752
22754
|
}
|
|
@@ -22769,7 +22771,7 @@ function readCodexHookContext(deps2, readFile = (path) => readFileSync2(path, "u
|
|
|
22769
22771
|
const match = matches[0];
|
|
22770
22772
|
return match ? {
|
|
22771
22773
|
sessionId: match.sessionId,
|
|
22772
|
-
transcriptPath:
|
|
22774
|
+
transcriptPath: transcriptForSessionIn(ledger, match.sessionId),
|
|
22773
22775
|
basis: `unambiguous SessionStart${match.at ? ` at ${match.at}` : ""} in ${match.cwd}`,
|
|
22774
22776
|
newerElsewhere: null
|
|
22775
22777
|
} : null;
|
|
@@ -22851,7 +22853,12 @@ async function runSessionAttach(flags, deps2) {
|
|
|
22851
22853
|
}
|
|
22852
22854
|
} else if (!flags.providerSession && flags.provider === "codex") {
|
|
22853
22855
|
const hookContext = readCodexHookContext(deps2);
|
|
22854
|
-
if (hookContext)
|
|
22856
|
+
if (hookContext) {
|
|
22857
|
+
flags.providerSession = hookContext.sessionId;
|
|
22858
|
+
if (!flags.transcriptPath && hookContext.transcriptPath) {
|
|
22859
|
+
flags.transcriptPath = hookContext.transcriptPath;
|
|
22860
|
+
}
|
|
22861
|
+
}
|
|
22855
22862
|
} else if (flags.provider === "claude" && flags.providerSession && !flags.transcriptPath) {
|
|
22856
22863
|
flags.transcriptPath = readClaudeHookTranscript(deps2, flags.providerSession) ?? void 0;
|
|
22857
22864
|
}
|
|
@@ -23076,7 +23083,7 @@ function telemetryVerdict(sessionId, usage, hostRan, provider = "claude") {
|
|
|
23076
23083
|
if (provider === "codex" && hostRan) {
|
|
23077
23084
|
return {
|
|
23078
23085
|
state: "unavailable",
|
|
23079
|
-
line: `Telemetry: token usage unavailable \u2014 Codex
|
|
23086
|
+
line: `Telemetry: token usage unavailable \u2014 no Codex rollout receipt was observed${wallPart} (coverage ${coverage})`,
|
|
23080
23087
|
warning: null
|
|
23081
23088
|
};
|
|
23082
23089
|
}
|
|
@@ -23858,7 +23865,7 @@ function sessionBindingCheck(detected) {
|
|
|
23858
23865
|
return detected.hookDir ? {
|
|
23859
23866
|
name: "session",
|
|
23860
23867
|
status: "ok",
|
|
23861
|
-
detail: `${detected.providerSessionId} \xB7 ${detected.basis ?? "resolved"} \xB7 host watches trusted Codex lifecycle hooks
|
|
23868
|
+
detail: `${detected.providerSessionId} \xB7 ${detected.basis ?? "resolved"} \xB7 host watches trusted Codex lifecycle hooks and provider-reported rollout usage`
|
|
23862
23869
|
} : {
|
|
23863
23870
|
name: "session",
|
|
23864
23871
|
status: "warn",
|
|
@@ -23886,7 +23893,7 @@ function detectProvider(flags, deps2) {
|
|
|
23886
23893
|
return {
|
|
23887
23894
|
provider: "codex",
|
|
23888
23895
|
providerSessionId: flags.providerSession ?? hook2?.sessionId ?? null,
|
|
23889
|
-
transcriptPath: null,
|
|
23896
|
+
transcriptPath: flags.transcriptPath ?? hook2?.transcriptPath ?? null,
|
|
23890
23897
|
basis: flags.providerSession ? `codex thread ${flags.providerSession} (explicit)` : hook2?.basis ?? null,
|
|
23891
23898
|
newerElsewhere: null,
|
|
23892
23899
|
transcriptGap: null,
|
|
@@ -23898,7 +23905,7 @@ function detectProvider(flags, deps2) {
|
|
|
23898
23905
|
return {
|
|
23899
23906
|
provider: "codex",
|
|
23900
23907
|
providerSessionId: current.sessionId,
|
|
23901
|
-
transcriptPath:
|
|
23908
|
+
transcriptPath: flags.transcriptPath ?? current.transcriptPath,
|
|
23902
23909
|
basis: current.basis,
|
|
23903
23910
|
newerElsewhere: null,
|
|
23904
23911
|
transcriptGap: null,
|
|
@@ -24332,7 +24339,7 @@ ${JSON.stringify(session.alignment, null, 2)}`
|
|
|
24332
24339
|
});
|
|
24333
24340
|
if (pid !== null) {
|
|
24334
24341
|
deps2.writeOut(
|
|
24335
|
-
captureMode === "on" ? `Capture host running (pid ${pid}) \u2014 TRACE capture ON for this session.` : detected.provider === "codex" ? `Session host running (pid ${pid}) \u2014 heartbeats + Codex
|
|
24342
|
+
captureMode === "on" ? `Capture host running (pid ${pid}) \u2014 TRACE capture ON for this session.` : detected.provider === "codex" ? `Session host running (pid ${pid}) \u2014 heartbeats + Codex rollout telemetry; TRACE capture is OFF.` : `Session host running (pid ${pid}) \u2014 heartbeats + telemetry only; TRACE capture is OFF (MVP default; a NEW session aligned with --capture records one \u2014 it cannot start mid-session).`
|
|
24336
24343
|
);
|
|
24337
24344
|
}
|
|
24338
24345
|
} else if (!liveHost) {
|
|
@@ -27496,7 +27503,7 @@ function registerLogoutCommand(program3, deps2, onExit2) {
|
|
|
27496
27503
|
|
|
27497
27504
|
// src/commands/plugin.ts
|
|
27498
27505
|
import { existsSync as existsSync4 } from "node:fs";
|
|
27499
|
-
import { join as join4, resolve as resolve2 } from "node:path";
|
|
27506
|
+
import { join as join4, resolve as resolve2, win32 } from "node:path";
|
|
27500
27507
|
var MARKETPLACE_NAME = "jentrix";
|
|
27501
27508
|
var PLUGIN_REF = "jentrix@jentrix";
|
|
27502
27509
|
var LEGACY_MARKETPLACE = "stacks";
|
|
@@ -27536,6 +27543,14 @@ function persistentPluginRoot(globalNodeModules, ownRoot, exists) {
|
|
|
27536
27543
|
function isPluginMarketplaceDir(dir) {
|
|
27537
27544
|
return existsSync4(join4(dir, ".claude-plugin", "marketplace.json"));
|
|
27538
27545
|
}
|
|
27546
|
+
function samePluginPath(a, b, win = process.platform === "win32") {
|
|
27547
|
+
const normalize = (raw) => {
|
|
27548
|
+
const bare = raw.replace(/^\\\\\?\\UNC\\/i, "\\\\").replace(/^\\\\\?\\/, "");
|
|
27549
|
+
const abs = win ? win32.resolve(bare) : resolve2(bare);
|
|
27550
|
+
return win ? abs.toLowerCase() : abs;
|
|
27551
|
+
};
|
|
27552
|
+
return normalize(a) === normalize(b);
|
|
27553
|
+
}
|
|
27539
27554
|
function isCodexPluginMarketplaceDir(dir) {
|
|
27540
27555
|
return existsSync4(join4(dir, ".agents", "plugins", "marketplace.json"));
|
|
27541
27556
|
}
|
|
@@ -27582,7 +27597,7 @@ async function installCodexPlugin(deps2, codex, pluginDir) {
|
|
|
27582
27597
|
const existing = marketplaces.find((row) => row.name === MARKETPLACE_NAME);
|
|
27583
27598
|
if (existing) {
|
|
27584
27599
|
const source = existing.marketplaceSource;
|
|
27585
|
-
if (source?.sourceType !== "local" || typeof source.source !== "string" ||
|
|
27600
|
+
if (source?.sourceType !== "local" || typeof source.source !== "string" || !samePluginPath(source.source, pluginDir)) {
|
|
27586
27601
|
deps2.writeErr(
|
|
27587
27602
|
`PLUGIN_MARKETPLACE_CONFLICT: Codex marketplace "${MARKETPLACE_NAME}" points somewhere else \u2014 inspect with \`codex plugin marketplace list\`; if intentional, run \`codex plugin marketplace remove ${MARKETPLACE_NAME}\` and retry`
|
|
27588
27603
|
);
|
|
@@ -27627,7 +27642,7 @@ async function installCodexPlugin(deps2, codex, pluginDir) {
|
|
|
27627
27642
|
}
|
|
27628
27643
|
return finishInstall(
|
|
27629
27644
|
deps2,
|
|
27630
|
-
"Jentrix Codex plugin ready: $jentrix-connect, $jentrix-align, $jentrix-plan, $jentrix-checkpoint, $jentrix-status, and $jentrix-end are available in NEW Codex tasks. Open `/hooks` and trust the Jentrix hooks before use." + await removeLegacyPlugin(deps2, codex, "codex")
|
|
27645
|
+
"Jentrix Codex plugin ready: $jentrix-connect, $jentrix-align, $jentrix-plan, $jentrix-checkpoint, $jentrix-status, $jentrix-review, and $jentrix-end are available in NEW Codex tasks. Open `/hooks` and trust the Jentrix hooks before use." + await removeLegacyPlugin(deps2, codex, "codex")
|
|
27631
27646
|
);
|
|
27632
27647
|
}
|
|
27633
27648
|
async function runPluginInstall(deps2, provider = "claude") {
|
|
@@ -27718,7 +27733,7 @@ ${update.stderr}`.match(
|
|
|
27718
27733
|
);
|
|
27719
27734
|
return finishInstall(
|
|
27720
27735
|
deps2,
|
|
27721
|
-
`Jentrix plugin ready: /jentrix-connect, /jentrix-align, /jentrix-plan, /jentrix-checkpoint, /jentrix-status, /jentrix-end are available in NEW Claude Code sessions (running sessions pick it up on restart).${await removeLegacyPlugin(deps2, claude, "claude")}`
|
|
27736
|
+
`Jentrix plugin ready: /jentrix-connect, /jentrix-align, /jentrix-plan, /jentrix-checkpoint, /jentrix-status, /jentrix-review, /jentrix-end are available in NEW Claude Code sessions (running sessions pick it up on restart).${await removeLegacyPlugin(deps2, claude, "claude")}`
|
|
27722
27737
|
);
|
|
27723
27738
|
}
|
|
27724
27739
|
function registerPluginCommand(program3, deps2, onExit2) {
|