@oxagen/cli 2.1.4-501 → 2.1.4-504
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/oxagen.mjs +251 -164
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -8747,6 +8747,95 @@ var init_claude_desktop_writer = __esm({
|
|
|
8747
8747
|
}
|
|
8748
8748
|
});
|
|
8749
8749
|
|
|
8750
|
+
// ../../packages/tacho/src/claude-code/context.ts
|
|
8751
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
8752
|
+
function digestText(value) {
|
|
8753
|
+
return `sha256:${createHash3("sha256").update(value, "utf8").digest("hex")}`;
|
|
8754
|
+
}
|
|
8755
|
+
function deliveredContext(text4, bundleEtag) {
|
|
8756
|
+
return text4 === null ? { chars: 0, bundle_etag: bundleEtag } : { digest: digestText(text4), chars: text4.length, bundle_etag: bundleEtag };
|
|
8757
|
+
}
|
|
8758
|
+
function readDeliveredContext(value) {
|
|
8759
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
8760
|
+
const { digest: digest6, chars, bundle_etag } = value;
|
|
8761
|
+
if (typeof chars !== "number" || !Number.isSafeInteger(chars) || chars < 0)
|
|
8762
|
+
return void 0;
|
|
8763
|
+
if (digest6 !== void 0 && !isSha256Digest(digest6)) return void 0;
|
|
8764
|
+
if (bundle_etag !== void 0 && (typeof bundle_etag !== "string" || bundle_etag.length === 0 || bundle_etag.length > 128))
|
|
8765
|
+
return void 0;
|
|
8766
|
+
return {
|
|
8767
|
+
...digest6 !== void 0 ? { digest: digest6 } : {},
|
|
8768
|
+
chars,
|
|
8769
|
+
...bundle_etag !== void 0 ? { bundle_etag } : {}
|
|
8770
|
+
};
|
|
8771
|
+
}
|
|
8772
|
+
function snapshotEnv(env, secretPattern = DEFAULT_SECRET_ENV_PATTERN) {
|
|
8773
|
+
const out = {};
|
|
8774
|
+
for (const [key, value] of Object.entries(env)) {
|
|
8775
|
+
if (value === void 0) {
|
|
8776
|
+
continue;
|
|
8777
|
+
}
|
|
8778
|
+
if (!/^(CLAUDE|OTEL|ANTHROPIC|TERM_PROGRAM$|SHELL$|CI$|GITHUB_ACTIONS$)/.test(
|
|
8779
|
+
key
|
|
8780
|
+
)) {
|
|
8781
|
+
continue;
|
|
8782
|
+
}
|
|
8783
|
+
if (secretPattern.test(key)) {
|
|
8784
|
+
continue;
|
|
8785
|
+
}
|
|
8786
|
+
out[key] = value.length > 1024 ? `${value.slice(0, 1024)}...` : value;
|
|
8787
|
+
}
|
|
8788
|
+
return out;
|
|
8789
|
+
}
|
|
8790
|
+
function hostFactsFromEnv(env) {
|
|
8791
|
+
const facts = {};
|
|
8792
|
+
const pid = env["CLAUDE_PID"];
|
|
8793
|
+
if (pid !== void 0 && /^\d+$/.test(pid)) {
|
|
8794
|
+
facts.claude_pid = Number(pid);
|
|
8795
|
+
}
|
|
8796
|
+
if (env["CLAUDE_CODE_EXECPATH"] !== void 0) {
|
|
8797
|
+
facts.claude_execpath = env["CLAUDE_CODE_EXECPATH"];
|
|
8798
|
+
}
|
|
8799
|
+
if (env["CLAUDE_CODE_CHILD_SESSION"] !== void 0) {
|
|
8800
|
+
facts.is_child_session = env["CLAUDE_CODE_CHILD_SESSION"] === "1";
|
|
8801
|
+
}
|
|
8802
|
+
if (env["CLAUDE_CODE_BRIDGE_SESSION_ID"] !== void 0) {
|
|
8803
|
+
facts.bridge_session_id = env["CLAUDE_CODE_BRIDGE_SESSION_ID"];
|
|
8804
|
+
}
|
|
8805
|
+
return facts;
|
|
8806
|
+
}
|
|
8807
|
+
function contextFactsFromEnv(env) {
|
|
8808
|
+
const facts = {};
|
|
8809
|
+
if (env["CLAUDE_CODE_ENTRYPOINT"] !== void 0) {
|
|
8810
|
+
facts.entrypoint = env["CLAUDE_CODE_ENTRYPOINT"];
|
|
8811
|
+
}
|
|
8812
|
+
if (env["CLAUDE_EFFORT"] !== void 0) {
|
|
8813
|
+
facts.effort = env["CLAUDE_EFFORT"];
|
|
8814
|
+
}
|
|
8815
|
+
if (env["CLAUDE_PROJECT_DIR"] !== void 0) {
|
|
8816
|
+
facts.project_dir = env["CLAUDE_PROJECT_DIR"];
|
|
8817
|
+
}
|
|
8818
|
+
if (env["TERM_PROGRAM"] !== void 0) {
|
|
8819
|
+
facts.terminal_type = env["TERM_PROGRAM"];
|
|
8820
|
+
}
|
|
8821
|
+
return facts;
|
|
8822
|
+
}
|
|
8823
|
+
function harnessVersionFromExecPath(execPath) {
|
|
8824
|
+
if (execPath === void 0) {
|
|
8825
|
+
return void 0;
|
|
8826
|
+
}
|
|
8827
|
+
const match = /\/versions\/(\d+\.\d+\.\d+)(?:\/|$)/.exec(execPath);
|
|
8828
|
+
return match?.[1];
|
|
8829
|
+
}
|
|
8830
|
+
var DEFAULT_SECRET_ENV_PATTERN;
|
|
8831
|
+
var init_context2 = __esm({
|
|
8832
|
+
"../../packages/tacho/src/claude-code/context.ts"() {
|
|
8833
|
+
"use strict";
|
|
8834
|
+
init_digest();
|
|
8835
|
+
DEFAULT_SECRET_ENV_PATTERN = /KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|PRIVATE|HEADERS|AUTH/i;
|
|
8836
|
+
}
|
|
8837
|
+
});
|
|
8838
|
+
|
|
8750
8839
|
// ../../packages/tacho/src/claude-code/cursor-adapter.ts
|
|
8751
8840
|
function isRecord(value) {
|
|
8752
8841
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -8780,6 +8869,10 @@ function translateCursorPayload(raw) {
|
|
|
8780
8869
|
subagent_id: subagentId,
|
|
8781
8870
|
subagent_type: subagentType,
|
|
8782
8871
|
duration,
|
|
8872
|
+
task,
|
|
8873
|
+
description,
|
|
8874
|
+
summary,
|
|
8875
|
+
error_message: errorMessage2,
|
|
8783
8876
|
...rest
|
|
8784
8877
|
} = raw;
|
|
8785
8878
|
const id = str2(conversationId) ?? str2(cursorSessionId);
|
|
@@ -8815,6 +8908,19 @@ function translateCursorPayload(raw) {
|
|
|
8815
8908
|
if (typeof duration === "number") out["duration_ms"] = duration;
|
|
8816
8909
|
if (typeof subagentId === "string") out["agent_id"] = subagentId;
|
|
8817
8910
|
if (typeof subagentType === "string") out["agent_type"] = subagentType;
|
|
8911
|
+
const digestOnly = [
|
|
8912
|
+
["task", task],
|
|
8913
|
+
["description", description],
|
|
8914
|
+
["summary", summary]
|
|
8915
|
+
];
|
|
8916
|
+
if (event === "postToolUseFailure" && errorMessage2 !== void 0)
|
|
8917
|
+
out["error"] = errorMessage2;
|
|
8918
|
+
else digestOnly.push(["error_message", errorMessage2]);
|
|
8919
|
+
for (const [name, value] of digestOnly) {
|
|
8920
|
+
if (typeof value !== "string") continue;
|
|
8921
|
+
out[`${name}_digest`] = digestText(value);
|
|
8922
|
+
out[`${name}_length`] = value.length;
|
|
8923
|
+
}
|
|
8818
8924
|
return out;
|
|
8819
8925
|
}
|
|
8820
8926
|
function reasonOf(value, fallback) {
|
|
@@ -8881,6 +8987,7 @@ var CURSOR_TO_CLAUDE_EVENT, CURSOR_HOOK_EVENTS, CURSOR_ENFORCEMENT_EVENTS, CURSO
|
|
|
8881
8987
|
var init_cursor_adapter = __esm({
|
|
8882
8988
|
"../../packages/tacho/src/claude-code/cursor-adapter.ts"() {
|
|
8883
8989
|
"use strict";
|
|
8990
|
+
init_context2();
|
|
8884
8991
|
CURSOR_TO_CLAUDE_EVENT = {
|
|
8885
8992
|
sessionStart: "SessionStart",
|
|
8886
8993
|
sessionEnd: "SessionEnd",
|
|
@@ -9349,7 +9456,7 @@ var init_agents = __esm({
|
|
|
9349
9456
|
});
|
|
9350
9457
|
|
|
9351
9458
|
// ../../packages/tacho/src/ids.ts
|
|
9352
|
-
import { createHash as
|
|
9459
|
+
import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
|
|
9353
9460
|
function uuidBytes(uuid) {
|
|
9354
9461
|
const hex = uuid.replace(/-/g, "");
|
|
9355
9462
|
if (!/^[0-9a-f]{32}$/i.test(hex)) {
|
|
@@ -9362,7 +9469,7 @@ function formatUuid(bytes) {
|
|
|
9362
9469
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
9363
9470
|
}
|
|
9364
9471
|
function uuidv5(namespace, name) {
|
|
9365
|
-
const hash3 =
|
|
9472
|
+
const hash3 = createHash4("sha1").update(uuidBytes(namespace)).update(Buffer.from(name, "utf8")).digest();
|
|
9366
9473
|
const bytes = Buffer.from(hash3.subarray(0, 16));
|
|
9367
9474
|
bytes[6] = (bytes[6] ?? 0) & 15 | 80;
|
|
9368
9475
|
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
@@ -9375,11 +9482,11 @@ function eventIdIdem(sessionUuidValue, seq) {
|
|
|
9375
9482
|
if (!Number.isInteger(seq) || seq < 0) {
|
|
9376
9483
|
throw new TypeError(`seq must be a non-negative integer, got ${seq}`);
|
|
9377
9484
|
}
|
|
9378
|
-
const hash3 =
|
|
9485
|
+
const hash3 = createHash4("sha256").update(sessionUuidValue).update(" ").update(String(seq)).digest("hex");
|
|
9379
9486
|
return `evt_${hash3}`;
|
|
9380
9487
|
}
|
|
9381
9488
|
function effectId(sessionUuidValue, toolUseId, target2) {
|
|
9382
|
-
return `eff_${
|
|
9489
|
+
return `eff_${createHash4("sha256").update(sessionUuidValue).update(" ").update(toolUseId).update(" ").update(target2).digest("hex")}`;
|
|
9383
9490
|
}
|
|
9384
9491
|
function ulid(now = Date.now()) {
|
|
9385
9492
|
let time = now;
|
|
@@ -9405,7 +9512,7 @@ function backfillEventId(sessionUuidValue, seq, rawSourceDigest, tsMs) {
|
|
|
9405
9512
|
timePart = CROCKFORD[time % 32] + timePart;
|
|
9406
9513
|
time = Math.floor(time / 32);
|
|
9407
9514
|
}
|
|
9408
|
-
const hash3 =
|
|
9515
|
+
const hash3 = createHash4("sha256").update(sessionUuidValue).update(" ").update(String(seq)).update(" ").update(rawSourceDigest).digest();
|
|
9409
9516
|
let bits2 = 0n;
|
|
9410
9517
|
for (let index = 0; index < 10; index += 1)
|
|
9411
9518
|
bits2 = bits2 << 8n | BigInt(hash3[index] ?? 0);
|
|
@@ -9882,95 +9989,6 @@ var init_stella_writer = __esm({
|
|
|
9882
9989
|
}
|
|
9883
9990
|
});
|
|
9884
9991
|
|
|
9885
|
-
// ../../packages/tacho/src/claude-code/context.ts
|
|
9886
|
-
import { createHash as createHash4 } from "node:crypto";
|
|
9887
|
-
function digestText(value) {
|
|
9888
|
-
return `sha256:${createHash4("sha256").update(value, "utf8").digest("hex")}`;
|
|
9889
|
-
}
|
|
9890
|
-
function deliveredContext(text4, bundleEtag) {
|
|
9891
|
-
return text4 === null ? { chars: 0, bundle_etag: bundleEtag } : { digest: digestText(text4), chars: text4.length, bundle_etag: bundleEtag };
|
|
9892
|
-
}
|
|
9893
|
-
function readDeliveredContext(value) {
|
|
9894
|
-
if (typeof value !== "object" || value === null) return void 0;
|
|
9895
|
-
const { digest: digest6, chars, bundle_etag } = value;
|
|
9896
|
-
if (typeof chars !== "number" || !Number.isSafeInteger(chars) || chars < 0)
|
|
9897
|
-
return void 0;
|
|
9898
|
-
if (digest6 !== void 0 && !isSha256Digest(digest6)) return void 0;
|
|
9899
|
-
if (bundle_etag !== void 0 && (typeof bundle_etag !== "string" || bundle_etag.length === 0 || bundle_etag.length > 128))
|
|
9900
|
-
return void 0;
|
|
9901
|
-
return {
|
|
9902
|
-
...digest6 !== void 0 ? { digest: digest6 } : {},
|
|
9903
|
-
chars,
|
|
9904
|
-
...bundle_etag !== void 0 ? { bundle_etag } : {}
|
|
9905
|
-
};
|
|
9906
|
-
}
|
|
9907
|
-
function snapshotEnv(env, secretPattern = DEFAULT_SECRET_ENV_PATTERN) {
|
|
9908
|
-
const out = {};
|
|
9909
|
-
for (const [key, value] of Object.entries(env)) {
|
|
9910
|
-
if (value === void 0) {
|
|
9911
|
-
continue;
|
|
9912
|
-
}
|
|
9913
|
-
if (!/^(CLAUDE|OTEL|ANTHROPIC|TERM_PROGRAM$|SHELL$|CI$|GITHUB_ACTIONS$)/.test(
|
|
9914
|
-
key
|
|
9915
|
-
)) {
|
|
9916
|
-
continue;
|
|
9917
|
-
}
|
|
9918
|
-
if (secretPattern.test(key)) {
|
|
9919
|
-
continue;
|
|
9920
|
-
}
|
|
9921
|
-
out[key] = value.length > 1024 ? `${value.slice(0, 1024)}...` : value;
|
|
9922
|
-
}
|
|
9923
|
-
return out;
|
|
9924
|
-
}
|
|
9925
|
-
function hostFactsFromEnv(env) {
|
|
9926
|
-
const facts = {};
|
|
9927
|
-
const pid = env["CLAUDE_PID"];
|
|
9928
|
-
if (pid !== void 0 && /^\d+$/.test(pid)) {
|
|
9929
|
-
facts.claude_pid = Number(pid);
|
|
9930
|
-
}
|
|
9931
|
-
if (env["CLAUDE_CODE_EXECPATH"] !== void 0) {
|
|
9932
|
-
facts.claude_execpath = env["CLAUDE_CODE_EXECPATH"];
|
|
9933
|
-
}
|
|
9934
|
-
if (env["CLAUDE_CODE_CHILD_SESSION"] !== void 0) {
|
|
9935
|
-
facts.is_child_session = env["CLAUDE_CODE_CHILD_SESSION"] === "1";
|
|
9936
|
-
}
|
|
9937
|
-
if (env["CLAUDE_CODE_BRIDGE_SESSION_ID"] !== void 0) {
|
|
9938
|
-
facts.bridge_session_id = env["CLAUDE_CODE_BRIDGE_SESSION_ID"];
|
|
9939
|
-
}
|
|
9940
|
-
return facts;
|
|
9941
|
-
}
|
|
9942
|
-
function contextFactsFromEnv(env) {
|
|
9943
|
-
const facts = {};
|
|
9944
|
-
if (env["CLAUDE_CODE_ENTRYPOINT"] !== void 0) {
|
|
9945
|
-
facts.entrypoint = env["CLAUDE_CODE_ENTRYPOINT"];
|
|
9946
|
-
}
|
|
9947
|
-
if (env["CLAUDE_EFFORT"] !== void 0) {
|
|
9948
|
-
facts.effort = env["CLAUDE_EFFORT"];
|
|
9949
|
-
}
|
|
9950
|
-
if (env["CLAUDE_PROJECT_DIR"] !== void 0) {
|
|
9951
|
-
facts.project_dir = env["CLAUDE_PROJECT_DIR"];
|
|
9952
|
-
}
|
|
9953
|
-
if (env["TERM_PROGRAM"] !== void 0) {
|
|
9954
|
-
facts.terminal_type = env["TERM_PROGRAM"];
|
|
9955
|
-
}
|
|
9956
|
-
return facts;
|
|
9957
|
-
}
|
|
9958
|
-
function harnessVersionFromExecPath(execPath) {
|
|
9959
|
-
if (execPath === void 0) {
|
|
9960
|
-
return void 0;
|
|
9961
|
-
}
|
|
9962
|
-
const match = /\/versions\/(\d+\.\d+\.\d+)(?:\/|$)/.exec(execPath);
|
|
9963
|
-
return match?.[1];
|
|
9964
|
-
}
|
|
9965
|
-
var DEFAULT_SECRET_ENV_PATTERN;
|
|
9966
|
-
var init_context2 = __esm({
|
|
9967
|
-
"../../packages/tacho/src/claude-code/context.ts"() {
|
|
9968
|
-
"use strict";
|
|
9969
|
-
init_digest();
|
|
9970
|
-
DEFAULT_SECRET_ENV_PATTERN = /KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|PRIVATE|HEADERS|AUTH/i;
|
|
9971
|
-
}
|
|
9972
|
-
});
|
|
9973
|
-
|
|
9974
9992
|
// ../../packages/tacho/src/host/process-scan.ts
|
|
9975
9993
|
import { execFile, spawnSync } from "node:child_process";
|
|
9976
9994
|
import { readFileSync as readFileSync4, readlinkSync as readlinkSync2 } from "node:fs";
|
|
@@ -10923,11 +10941,18 @@ async function loadCedarRuntimeFrom(sources) {
|
|
|
10923
10941
|
return null;
|
|
10924
10942
|
}
|
|
10925
10943
|
}
|
|
10926
|
-
function loadCedarRuntime() {
|
|
10927
|
-
|
|
10944
|
+
function loadCedarRuntime(now = Date.now) {
|
|
10945
|
+
if (failedAt !== void 0 && now() - failedAt >= CEDAR_RETRY_AFTER_MS) {
|
|
10946
|
+
cached = void 0;
|
|
10947
|
+
failedAt = void 0;
|
|
10948
|
+
}
|
|
10949
|
+
cached ??= loadCedarRuntimeFrom(DEFAULT_SOURCES).then((runtime) => {
|
|
10950
|
+
if (runtime === null) failedAt = now();
|
|
10951
|
+
return runtime;
|
|
10952
|
+
});
|
|
10928
10953
|
return cached;
|
|
10929
10954
|
}
|
|
10930
|
-
var CEDAR_WASM_ASSET, SPECIFIER, DEFAULT_SOURCES, cached;
|
|
10955
|
+
var CEDAR_WASM_ASSET, SPECIFIER, DEFAULT_SOURCES, CEDAR_RETRY_AFTER_MS, cached, failedAt;
|
|
10931
10956
|
var init_runtime = __esm({
|
|
10932
10957
|
"../../packages/tacho/src/policy/runtime.ts"() {
|
|
10933
10958
|
"use strict";
|
|
@@ -10948,6 +10973,7 @@ var init_runtime = __esm({
|
|
|
10948
10973
|
SPECIFIER
|
|
10949
10974
|
)
|
|
10950
10975
|
};
|
|
10976
|
+
CEDAR_RETRY_AFTER_MS = 6e4;
|
|
10951
10977
|
}
|
|
10952
10978
|
});
|
|
10953
10979
|
|
|
@@ -11818,9 +11844,18 @@ function normalizeHook(raw, env, options) {
|
|
|
11818
11844
|
}
|
|
11819
11845
|
case "SessionEnd": {
|
|
11820
11846
|
const reason3 = str3(input["reason"]) ?? str3(input["end_reason"]) ?? "other";
|
|
11847
|
+
const completed = [
|
|
11848
|
+
"prompt_input_exit",
|
|
11849
|
+
"clear",
|
|
11850
|
+
"other",
|
|
11851
|
+
"resume",
|
|
11852
|
+
"completed",
|
|
11853
|
+
"window_close",
|
|
11854
|
+
"user_close"
|
|
11855
|
+
].includes(reason3);
|
|
11821
11856
|
const body2 = {
|
|
11822
11857
|
session_end_reason: reason3,
|
|
11823
|
-
session_outcome:
|
|
11858
|
+
session_outcome: completed ? "completed" : "aborted"
|
|
11824
11859
|
};
|
|
11825
11860
|
return [draft("agent_stop", body2, { hook_source_kind: reason3 })];
|
|
11826
11861
|
}
|
|
@@ -22025,33 +22060,35 @@ function restoreClaude(options, released) {
|
|
|
22025
22060
|
else delete settings[HELPER_KEY];
|
|
22026
22061
|
touched = true;
|
|
22027
22062
|
}
|
|
22063
|
+
const current = envOf2(settings);
|
|
22064
|
+
const foreignKey = current !== void 0 && (isSecret(current[CLAUDE_API_KEY]) || isSecret(current[CLAUDE_AUTH_TOKEN]));
|
|
22065
|
+
const why = foreignKey ? { reason: "foreign_key_present" } : {};
|
|
22028
22066
|
let secretRestored = false;
|
|
22029
|
-
if (released !== void 0) {
|
|
22067
|
+
if (released !== void 0 && !foreignKey) {
|
|
22030
22068
|
const member2 = sidecar?.taken.find((t) => t.kind === released.kind)?.member ?? (released.kind === "bearer" ? CLAUDE_AUTH_TOKEN : CLAUDE_API_KEY);
|
|
22031
|
-
const env = { ...
|
|
22069
|
+
const env = { ...current ?? {} };
|
|
22032
22070
|
env[member2] = released.secret;
|
|
22033
22071
|
settings["env"] = env;
|
|
22034
22072
|
touched = true;
|
|
22035
22073
|
secretRestored = true;
|
|
22036
22074
|
} else if (sidecar?.created_env === true) {
|
|
22037
|
-
|
|
22038
|
-
if (env !== void 0 && Object.keys(env).length === 0) {
|
|
22075
|
+
if (current !== void 0 && Object.keys(current).length === 0) {
|
|
22039
22076
|
delete settings["env"];
|
|
22040
22077
|
touched = true;
|
|
22041
22078
|
}
|
|
22042
22079
|
}
|
|
22043
22080
|
if (!touched) {
|
|
22044
22081
|
dropSidecar();
|
|
22045
|
-
return { changed: false, secretRestored };
|
|
22082
|
+
return { changed: false, secretRestored, ...why };
|
|
22046
22083
|
}
|
|
22047
22084
|
const next = serializeLike2(text4, settings);
|
|
22048
22085
|
if (next === text4) {
|
|
22049
22086
|
dropSidecar();
|
|
22050
|
-
return { changed: false, secretRestored };
|
|
22087
|
+
return { changed: false, secretRestored, ...why };
|
|
22051
22088
|
}
|
|
22052
22089
|
writeAtomicPreserving2(file, next);
|
|
22053
22090
|
dropSidecar();
|
|
22054
|
-
return { changed: true, secretRestored };
|
|
22091
|
+
return { changed: true, secretRestored, ...why };
|
|
22055
22092
|
}
|
|
22056
22093
|
function restoreCodex(options, released) {
|
|
22057
22094
|
const file = fileFor2("codex", options);
|
|
@@ -23497,7 +23534,7 @@ import { readFileSync as readFileSync11 } from "node:fs";
|
|
|
23497
23534
|
import { dirname as dirname8, resolve as resolve2 } from "node:path";
|
|
23498
23535
|
import { fileURLToPath } from "node:url";
|
|
23499
23536
|
function readVersion() {
|
|
23500
|
-
if (true) return "2.1.4-
|
|
23537
|
+
if (true) return "2.1.4-504";
|
|
23501
23538
|
try {
|
|
23502
23539
|
const here = dirname8(fileURLToPath(import.meta.url));
|
|
23503
23540
|
const pkg = JSON.parse(
|
|
@@ -23644,13 +23681,14 @@ function runtimeCommands(entry2 = process.argv[1], env = process.env, nodePath =
|
|
|
23644
23681
|
}
|
|
23645
23682
|
const transient = transientBinDir(binDir, env);
|
|
23646
23683
|
const flagged = transient !== void 0 ? { transient } : {};
|
|
23684
|
+
const node2 = stableExecutablePath(nodePath, platform, exists);
|
|
23647
23685
|
return {
|
|
23648
|
-
hookCommand: `${shellQuote(
|
|
23686
|
+
hookCommand: `${shellQuote(node2, platform)} ${shellQuote(P.join(binDir, "tacho-hook.mjs"), platform)}`,
|
|
23649
23687
|
credentialHelperCommand: helperCommandFor(
|
|
23650
|
-
`${shellQuote(
|
|
23688
|
+
`${shellQuote(node2, platform)} ${shellQuote(P.join(binDir, "tacho.mjs"), platform)}`
|
|
23651
23689
|
),
|
|
23652
|
-
daemonCommand: [
|
|
23653
|
-
mcpStdioCommand: [
|
|
23690
|
+
daemonCommand: [node2, P.join(binDir, "tachod.mjs")],
|
|
23691
|
+
mcpStdioCommand: [node2, P.join(binDir, "tacho.mjs"), "mcp-stdio"],
|
|
23654
23692
|
binDir,
|
|
23655
23693
|
...flagged
|
|
23656
23694
|
};
|
|
@@ -23668,7 +23706,10 @@ function oxagenRuntimeCommands(entry2 = process.argv[1], env = process.env, node
|
|
|
23668
23706
|
} else if (native) {
|
|
23669
23707
|
prefix = [stableExecutablePath(nodePath, platform, exists)];
|
|
23670
23708
|
} else if (entry2 !== void 0 && !/\.[cm]?tsx?$/.test(entry2)) {
|
|
23671
|
-
prefix = [
|
|
23709
|
+
prefix = [
|
|
23710
|
+
stableExecutablePath(nodePath, platform, exists),
|
|
23711
|
+
P.resolve(entry2)
|
|
23712
|
+
];
|
|
23672
23713
|
} else {
|
|
23673
23714
|
return runtimeCommands(void 0, env, nodePath, platform, false, exists);
|
|
23674
23715
|
}
|
|
@@ -25561,9 +25602,9 @@ ${lines.join("\n")}
|
|
|
25561
25602
|
* one torn write (a crash mid-append, before `repairTail` runs at the next
|
|
25562
25603
|
* startup) must not stop every reader of this session. The retention
|
|
25563
25604
|
* sweep reads through here. `unshipped` and `stats` read through
|
|
25564
|
-
* `eventsAfterShipped`, and `head`, `compact`, `lastSeqOf`,
|
|
25565
|
-
* `appendRecovered` read back from the tail through `eventsBackward`.
|
|
25566
|
-
* skip a bad line the same way.
|
|
25605
|
+
* `eventsAfterShipped`, and `head`, `eventsSince`, `compact`, `lastSeqOf`,
|
|
25606
|
+
* and `appendRecovered` read back from the tail through `eventsBackward`.
|
|
25607
|
+
* Both skip a bad line the same way.
|
|
25567
25608
|
*/
|
|
25568
25609
|
read(sessionUuid2) {
|
|
25569
25610
|
const path2 = this.fileFor(sessionUuid2);
|
|
@@ -26036,6 +26077,26 @@ ${lines.join("\n")}
|
|
|
26036
26077
|
const suffix = ".bodies.jsonl";
|
|
26037
26078
|
return readdirSync7(this.dir).filter((name) => name.endsWith(suffix)).map((name) => name.slice(0, -suffix.length));
|
|
26038
26079
|
}
|
|
26080
|
+
/**
|
|
26081
|
+
* A session's latest events, in seq order: read back from the tail, and
|
|
26082
|
+
* stopped at the first event whose `ts` is before `since` (epoch ms). That
|
|
26083
|
+
* event is left out, and so is everything written before it. An event
|
|
26084
|
+
* whose `ts` does not parse cannot be placed in time, so it is kept and the
|
|
26085
|
+
* walk goes on past it.
|
|
26086
|
+
*
|
|
26087
|
+
* The read costs the lines it walks, not the file. It takes the file's seq
|
|
26088
|
+
* order for time order, and a caller has to accept that: an event written
|
|
26089
|
+
* late with an earlier `ts` ends the walk, so an event written before it
|
|
26090
|
+
* is not returned, whatever its own `ts`.
|
|
26091
|
+
*/
|
|
26092
|
+
eventsSince(sessionUuid2, since) {
|
|
26093
|
+
const out = [];
|
|
26094
|
+
for (const event of this.eventsBackward(sessionUuid2)) {
|
|
26095
|
+
if (Date.parse(event.ts) < since) break;
|
|
26096
|
+
out.push(event);
|
|
26097
|
+
}
|
|
26098
|
+
return out.reverse();
|
|
26099
|
+
}
|
|
26039
26100
|
/**
|
|
26040
26101
|
* The last sealed event of a session, if any: the last line of its file
|
|
26041
26102
|
* that parses, read back from the tail.
|
|
@@ -37730,34 +37791,33 @@ function createGitLane(deps) {
|
|
|
37730
37791
|
function recordReconciliation(session, reading, snapshot) {
|
|
37731
37792
|
const mark = session.recorder.markChain();
|
|
37732
37793
|
try {
|
|
37733
|
-
|
|
37734
|
-
|
|
37735
|
-
|
|
37736
|
-
|
|
37737
|
-
{
|
|
37738
|
-
|
|
37739
|
-
|
|
37740
|
-
|
|
37741
|
-
|
|
37742
|
-
|
|
37743
|
-
|
|
37744
|
-
|
|
37745
|
-
|
|
37746
|
-
|
|
37747
|
-
|
|
37748
|
-
|
|
37749
|
-
|
|
37750
|
-
|
|
37751
|
-
|
|
37752
|
-
|
|
37753
|
-
|
|
37754
|
-
|
|
37755
|
-
|
|
37756
|
-
|
|
37757
|
-
|
|
37758
|
-
|
|
37759
|
-
|
|
37760
|
-
]);
|
|
37794
|
+
const reconciled = session.recorder.sealCollectorEvent(
|
|
37795
|
+
"oxagen:worktree_reconciled",
|
|
37796
|
+
worktreeReconciledBody(reading.changes),
|
|
37797
|
+
{
|
|
37798
|
+
attrs: {
|
|
37799
|
+
// What the list measures, so a reader can tell a list that
|
|
37800
|
+
// leaves out pulled commits and earlier edits from one that
|
|
37801
|
+
// does not (ADR-188).
|
|
37802
|
+
changes_basis: reading.basis,
|
|
37803
|
+
pre_session_changes: PRE_SESSION_CHANGES[reading.preexisting],
|
|
37804
|
+
// Whether the rows of files that held edits before the session
|
|
37805
|
+
// count the session's lines alone, or the whole file against
|
|
37806
|
+
// `HEAD` for want of a copy.
|
|
37807
|
+
...reading.preSessionCounts !== void 0 ? { pre_session_edit_counts: reading.preSessionCounts } : {},
|
|
37808
|
+
...snapshot ? {
|
|
37809
|
+
worktree_root: snapshot.root,
|
|
37810
|
+
...snapshot.repository ? { repository_url: snapshot.repository } : {},
|
|
37811
|
+
...snapshot.baseline ? { diff_base_sha: snapshot.baseline } : {},
|
|
37812
|
+
...snapshot.head ? { diff_head_sha: snapshot.head } : {},
|
|
37813
|
+
diff_complete: String(snapshot.complete),
|
|
37814
|
+
diff_limitations: snapshot.limitations.join(",")
|
|
37815
|
+
} : {}
|
|
37816
|
+
},
|
|
37817
|
+
...snapshot ? { content: jsonContent(JSON.stringify(snapshot)) } : {}
|
|
37818
|
+
}
|
|
37819
|
+
);
|
|
37820
|
+
record([reconciled], session.recorder.takeBodies());
|
|
37761
37821
|
} catch (error) {
|
|
37762
37822
|
session.recorder.rollbackChain(mark);
|
|
37763
37823
|
requestGitRead(session.recorder.sessionUuid, {
|
|
@@ -43563,6 +43623,10 @@ function createDaySpend(deps) {
|
|
|
43563
43623
|
let held;
|
|
43564
43624
|
function own(day) {
|
|
43565
43625
|
if (held !== void 0 && held.day >= day) return held.ownMicros;
|
|
43626
|
+
if (held !== void 0) {
|
|
43627
|
+
held = { day, ownMicros: 0 };
|
|
43628
|
+
return 0;
|
|
43629
|
+
}
|
|
43566
43630
|
let seeded = 0;
|
|
43567
43631
|
try {
|
|
43568
43632
|
seeded = nonNegative2(deps.priorDaySpendMicros?.(day) ?? 0);
|
|
@@ -47729,7 +47793,15 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
47729
47793
|
});
|
|
47730
47794
|
}
|
|
47731
47795
|
function record(events, bodies = []) {
|
|
47732
|
-
if (events.length === 0)
|
|
47796
|
+
if (events.length === 0) {
|
|
47797
|
+
if (bodies.length > 0) {
|
|
47798
|
+
const where = bodies.map((body2) => `session ${body2.session_uuid} seq ${body2.seq}`).join(", ");
|
|
47799
|
+
log(
|
|
47800
|
+
`dropped ${bodies.length} frame ${bodies.length === 1 ? "body" : "bodies"} handed over without an event (${where}). A body ships only with its own event, so this content will not ship.`
|
|
47801
|
+
);
|
|
47802
|
+
}
|
|
47803
|
+
return;
|
|
47804
|
+
}
|
|
47733
47805
|
const retention = retentionInForce();
|
|
47734
47806
|
wal.append(
|
|
47735
47807
|
events,
|
|
@@ -49178,6 +49250,24 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
49178
49250
|
}
|
|
49179
49251
|
}
|
|
49180
49252
|
await refreshUpstreams();
|
|
49253
|
+
function walDaySpendMicros(day) {
|
|
49254
|
+
const start = Date.parse(`${day}T00:00:00.000Z`);
|
|
49255
|
+
const end = Date.parse(nextUtcDayStart(day));
|
|
49256
|
+
let total2 = 0;
|
|
49257
|
+
for (const session of wal.sessions()) {
|
|
49258
|
+
for (const event of wal.eventsSince(session, start)) {
|
|
49259
|
+
if (event.kind !== "llm_call") continue;
|
|
49260
|
+
if (event.attrs[TACHO_METERING_ATTR] !== TACHO_METERING_OBSERVED)
|
|
49261
|
+
continue;
|
|
49262
|
+
const at = Date.parse(event.ts);
|
|
49263
|
+
if (!(at >= start && at < end)) continue;
|
|
49264
|
+
const cost = event.body.cost_usd_micros;
|
|
49265
|
+
if (typeof cost === "number") total2 += cost;
|
|
49266
|
+
}
|
|
49267
|
+
}
|
|
49268
|
+
return total2;
|
|
49269
|
+
}
|
|
49270
|
+
let startupDaySpend;
|
|
49181
49271
|
const modelProxy = createModelProxy({
|
|
49182
49272
|
registry: registry2,
|
|
49183
49273
|
hostRecorder: () => hostRecorder,
|
|
@@ -49191,25 +49281,14 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
49191
49281
|
...displacedUpstreams,
|
|
49192
49282
|
...options.modelUpstreams
|
|
49193
49283
|
}),
|
|
49194
|
-
// A restart must not hand the agent's day back either (ADR-160).
|
|
49195
|
-
//
|
|
49196
|
-
//
|
|
49284
|
+
// A restart must not hand the agent's day back either (ADR-160). The day
|
|
49285
|
+
// counter asks this once per process (`createDaySpend`), so the figure
|
|
49286
|
+
// read at startup is used once. A first call on a later day than
|
|
49287
|
+
// startup's reads the WAL for that day.
|
|
49197
49288
|
priorDaySpendMicros: (day) => {
|
|
49198
|
-
const
|
|
49199
|
-
|
|
49200
|
-
|
|
49201
|
-
const last = wal.lastEvent(session);
|
|
49202
|
-
if (last !== void 0 && Date.parse(last.ts) < start) continue;
|
|
49203
|
-
for (const event of wal.read(session)) {
|
|
49204
|
-
if (event.kind !== "llm_call") continue;
|
|
49205
|
-
if (event.attrs[TACHO_METERING_ATTR] !== TACHO_METERING_OBSERVED)
|
|
49206
|
-
continue;
|
|
49207
|
-
if (utcDay(Date.parse(event.ts)) !== day) continue;
|
|
49208
|
-
const cost = event.body.cost_usd_micros;
|
|
49209
|
-
if (typeof cost === "number") total2 += cost;
|
|
49210
|
-
}
|
|
49211
|
-
}
|
|
49212
|
-
return total2;
|
|
49289
|
+
const seeded = startupDaySpend;
|
|
49290
|
+
startupDaySpend = void 0;
|
|
49291
|
+
return seeded?.day === day ? seeded.micros : walDaySpendMicros(day);
|
|
49213
49292
|
},
|
|
49214
49293
|
recordedDaySpend: () => recordedDaySpend === void 0 ? void 0 : {
|
|
49215
49294
|
day: recordedDaySpend.day,
|
|
@@ -49587,6 +49666,14 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
49587
49666
|
);
|
|
49588
49667
|
}
|
|
49589
49668
|
}
|
|
49669
|
+
try {
|
|
49670
|
+
const day = utcDay(now());
|
|
49671
|
+
startupDaySpend = { day, micros: walDaySpendMicros(day) };
|
|
49672
|
+
} catch (error) {
|
|
49673
|
+
log(
|
|
49674
|
+
`day spend not read from the WAL at startup: ${error instanceof Error ? error.message : String(error)}`
|
|
49675
|
+
);
|
|
49676
|
+
}
|
|
49590
49677
|
ready(api);
|
|
49591
49678
|
servingSince = now();
|
|
49592
49679
|
if (options.listen ?? true) {
|
|
@@ -52268,7 +52355,7 @@ var init_package = __esm({
|
|
|
52268
52355
|
"package.json"() {
|
|
52269
52356
|
package_default = {
|
|
52270
52357
|
name: "@oxagen/cli",
|
|
52271
|
-
version: "2.1.4-
|
|
52358
|
+
version: "2.1.4-504",
|
|
52272
52359
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
52273
52360
|
type: "module",
|
|
52274
52361
|
main: "./dist/index.js",
|
|
@@ -52320,11 +52407,11 @@ var init_package = __esm({
|
|
|
52320
52407
|
devDependencies: {
|
|
52321
52408
|
"@oxagen/telemetry": "workspace:*",
|
|
52322
52409
|
"@types/node": "25.9.8",
|
|
52323
|
-
"@vitest/coverage-v8": "2.
|
|
52410
|
+
"@vitest/coverage-v8": "3.2.6",
|
|
52324
52411
|
esbuild: "0.28.2",
|
|
52325
52412
|
tsx: "4.23.5",
|
|
52326
52413
|
typescript: "6.0.3",
|
|
52327
|
-
vitest: "2.
|
|
52414
|
+
vitest: "3.2.6"
|
|
52328
52415
|
}
|
|
52329
52416
|
};
|
|
52330
52417
|
}
|
package/package.json
CHANGED