@oxagen/cli 2.1.5-76 → 2.1.5-88
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 +207 -42
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -6276,7 +6276,11 @@ var init_wire = __esm({
|
|
|
6276
6276
|
* first model call, by digesting its remote and looking for the digest
|
|
6277
6277
|
* in `bound_remote_digests`: every repository the organization bound,
|
|
6278
6278
|
* in any workspace, each as its canonical digest and its folded digest
|
|
6279
|
-
* (`canonicalRemote` and `foldedRemote` in `remote.ts`).
|
|
6279
|
+
* (`canonicalRemote` and `foldedRemote` in `remote.ts`). An organisation
|
|
6280
|
+
* with more than fit under the cap gets a list cut to it, the host
|
|
6281
|
+
* workspace's repositories first, and a repository the cut left out is
|
|
6282
|
+
* asked about like an unbound one (#4439). The list is never dropped,
|
|
6283
|
+
* because an absent clause asks nothing.
|
|
6280
6284
|
*
|
|
6281
6285
|
* `link` carries what the link path would apply, for the question the
|
|
6282
6286
|
* host shows. `timeout_ms` is how long the host waits before it answers
|
|
@@ -12118,6 +12122,48 @@ var init_frame_body = __esm({
|
|
|
12118
12122
|
}
|
|
12119
12123
|
});
|
|
12120
12124
|
|
|
12125
|
+
// ../../packages/tacho/src/claude-code/prompt-issue-refs.ts
|
|
12126
|
+
function issueNumber(text5) {
|
|
12127
|
+
const n2 = Number(text5);
|
|
12128
|
+
return Number.isSafeInteger(n2) && n2 > 0 ? n2 : void 0;
|
|
12129
|
+
}
|
|
12130
|
+
function promptIssueRefs(prompt) {
|
|
12131
|
+
const found = [];
|
|
12132
|
+
const rest = prompt.replace(ISSUE_URL2, (whole, owner, repo, num, at2) => {
|
|
12133
|
+
const n2 = issueNumber(num);
|
|
12134
|
+
if (n2 !== void 0) found.push({ at: at2, ref: `${owner}/${repo}#${n2}` });
|
|
12135
|
+
return " ".repeat(whole.length);
|
|
12136
|
+
});
|
|
12137
|
+
for (const match of rest.matchAll(REPO_REF)) {
|
|
12138
|
+
const n2 = issueNumber(match[3]);
|
|
12139
|
+
if (n2 !== void 0)
|
|
12140
|
+
found.push({ at: match.index, ref: `${match[1]}/${match[2]}#${n2}` });
|
|
12141
|
+
}
|
|
12142
|
+
for (const match of rest.matchAll(BARE_REF)) {
|
|
12143
|
+
const n2 = issueNumber(match[1]);
|
|
12144
|
+
if (n2 !== void 0) found.push({ at: match.index, ref: `#${n2}` });
|
|
12145
|
+
}
|
|
12146
|
+
found.sort((a, b3) => a.at - b3.at);
|
|
12147
|
+
const refs = [];
|
|
12148
|
+
for (const { ref: ref2 } of found) {
|
|
12149
|
+
if (refs.length === PROMPT_ISSUE_REFS_MAX) break;
|
|
12150
|
+
if (!refs.some((seen) => seen.toLowerCase() === ref2.toLowerCase()))
|
|
12151
|
+
refs.push(ref2);
|
|
12152
|
+
}
|
|
12153
|
+
return refs;
|
|
12154
|
+
}
|
|
12155
|
+
var PROMPT_ISSUE_REFS_ATTR, PROMPT_ISSUE_REFS_MAX, ISSUE_URL2, REPO_REF, BARE_REF;
|
|
12156
|
+
var init_prompt_issue_refs = __esm({
|
|
12157
|
+
"../../packages/tacho/src/claude-code/prompt-issue-refs.ts"() {
|
|
12158
|
+
"use strict";
|
|
12159
|
+
PROMPT_ISSUE_REFS_ATTR = "prompt.issue_refs";
|
|
12160
|
+
PROMPT_ISSUE_REFS_MAX = 10;
|
|
12161
|
+
ISSUE_URL2 = /https?:\/\/(?:www\.)?github\.com\/([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)\/issues\/(\d+)(?![\w-])/gi;
|
|
12162
|
+
REPO_REF = /(?<![\w./-])([A-Za-z0-9][A-Za-z0-9-]*)\/([A-Za-z0-9_.-]+)#(\d+)(?![\w-])/g;
|
|
12163
|
+
BARE_REF = /(?<![\w/&#-])#(\d+)(?![\w-])/g;
|
|
12164
|
+
}
|
|
12165
|
+
});
|
|
12166
|
+
|
|
12121
12167
|
// ../../packages/tacho/src/claude-code/hooks.ts
|
|
12122
12168
|
function kindOf(value) {
|
|
12123
12169
|
if (value === null) return "null";
|
|
@@ -12320,14 +12366,17 @@ function normalizeHook(raw, env, options) {
|
|
|
12320
12366
|
} : {}
|
|
12321
12367
|
};
|
|
12322
12368
|
const kind = input.hook_event_name === "UserPromptSubmit" ? "turn_start" : "oxagen:message";
|
|
12369
|
+
const issueRefs = kind === "turn_start" && prompt !== void 0 && workOrderIdOf(env[WORK_ORDER_ENV]) === void 0 ? promptIssueRefs(prompt) : [];
|
|
12323
12370
|
return [
|
|
12324
|
-
draft(
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12371
|
+
draft(kind, body2, {
|
|
12372
|
+
...prompt !== void 0 ? { content: textContent(prompt) } : {},
|
|
12373
|
+
...issueRefs.length > 0 ? {
|
|
12374
|
+
attrs: {
|
|
12375
|
+
...base2.attrs,
|
|
12376
|
+
[PROMPT_ISSUE_REFS_ATTR]: issueRefs.join(" ")
|
|
12377
|
+
}
|
|
12329
12378
|
} : {}
|
|
12330
|
-
)
|
|
12379
|
+
})
|
|
12331
12380
|
];
|
|
12332
12381
|
}
|
|
12333
12382
|
case "PreToolUse": {
|
|
@@ -12711,6 +12760,7 @@ var init_hooks = __esm({
|
|
|
12711
12760
|
init_ids();
|
|
12712
12761
|
init_frame_body();
|
|
12713
12762
|
init_wire();
|
|
12763
|
+
init_prompt_issue_refs();
|
|
12714
12764
|
init_context();
|
|
12715
12765
|
init_payload_members();
|
|
12716
12766
|
init_github_text();
|
|
@@ -26672,7 +26722,7 @@ import { readFileSync as readFileSync10 } from "node:fs";
|
|
|
26672
26722
|
import { dirname as dirname9, resolve as resolve3 } from "node:path";
|
|
26673
26723
|
import { fileURLToPath } from "node:url";
|
|
26674
26724
|
function readVersion() {
|
|
26675
|
-
if (true) return "2.1.5-
|
|
26725
|
+
if (true) return "2.1.5-88";
|
|
26676
26726
|
try {
|
|
26677
26727
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
26678
26728
|
const pkg = JSON.parse(
|
|
@@ -46233,7 +46283,7 @@ function createGitLane(deps) {
|
|
|
46233
46283
|
reconciledHeads.delete(sessionUuid2);
|
|
46234
46284
|
}
|
|
46235
46285
|
}
|
|
46236
|
-
function
|
|
46286
|
+
function putBack2(read2) {
|
|
46237
46287
|
const sessionUuid2 = read2.session.recorder.sessionUuid;
|
|
46238
46288
|
if (read2.priorReconcileAt === void 0)
|
|
46239
46289
|
lastReconcileAt.delete(sessionUuid2);
|
|
@@ -46269,7 +46319,7 @@ function createGitLane(deps) {
|
|
|
46269
46319
|
force: true,
|
|
46270
46320
|
reconcile: item.due
|
|
46271
46321
|
});
|
|
46272
|
-
for (const rest of found.slice(index + 1))
|
|
46322
|
+
for (const rest of found.slice(index + 1)) putBack2(rest);
|
|
46273
46323
|
throw error;
|
|
46274
46324
|
}
|
|
46275
46325
|
}
|
|
@@ -46310,7 +46360,7 @@ function createGitLane(deps) {
|
|
|
46310
46360
|
priorReconcileAt: last
|
|
46311
46361
|
});
|
|
46312
46362
|
} catch (error) {
|
|
46313
|
-
|
|
46363
|
+
putBack2({ session, due, priorReconcileAt: last });
|
|
46314
46364
|
throw error;
|
|
46315
46365
|
}
|
|
46316
46366
|
}
|
|
@@ -46745,7 +46795,7 @@ var init_reflection_ask = __esm({
|
|
|
46745
46795
|
});
|
|
46746
46796
|
|
|
46747
46797
|
// ../../packages/tacho/src/interjection.ts
|
|
46748
|
-
var digest3, timestamp, count5, configVersion, workspaceSlug, interjectionKeySchema, INTERJECTION_RECEIPT_ID_PATTERN, INTERJECTION_QUESTION_MAX, INTERJECTION_PATHS, INTERJECTION_ANSWER_SOURCES, SKILLS_RESOLVED_REASONS, repoUnknownBodySchema, interjectLinkPathSchema, interjectCreatePathSchema, interjectBodySchema, answerBodySchema, repoBoundBodySchema, workspaceCreatedBodySchema, skillsResolvedBodySchema, interjectionAnswerPayloadSchema;
|
|
46798
|
+
var digest3, timestamp, count5, configVersion, workspaceSlug, interjectionKeySchema, INTERJECTION_RECEIPT_ID_PATTERN, INTERJECTION_QUESTION_MAX, INTERJECTION_PATHS, INTERJECTION_ANSWER_SOURCES, SKILLS_RESOLVED_REASONS, repoUnknownBodySchema, interjectLinkPathSchema, interjectCreatePathSchema, INTERJECT_PROVIDERS, interjectBodySchema, answerBodySchema, repoBoundBodySchema, workspaceCreatedBodySchema, skillsResolvedBodySchema, interjectionAnswerPayloadSchema;
|
|
46749
46799
|
var init_interjection = __esm({
|
|
46750
46800
|
"../../packages/tacho/src/interjection.ts"() {
|
|
46751
46801
|
"use strict";
|
|
@@ -46796,6 +46846,7 @@ var init_interjection = __esm({
|
|
|
46796
46846
|
proposed_slug: workspaceSlug.nullable(),
|
|
46797
46847
|
skills_enabled: external_exports.literal(false)
|
|
46798
46848
|
}).strict();
|
|
46849
|
+
INTERJECT_PROVIDERS = ["github", "gitlab"];
|
|
46799
46850
|
interjectBodySchema = external_exports.object({
|
|
46800
46851
|
interjection_key: interjectionKeySchema,
|
|
46801
46852
|
reason: external_exports.literal("repo_unknown"),
|
|
@@ -46809,7 +46860,16 @@ var init_interjection = __esm({
|
|
|
46809
46860
|
/** What the timeout answers. */
|
|
46810
46861
|
on_timeout: external_exports.literal("deny"),
|
|
46811
46862
|
/** The two paths a person can take, link first. Deny needs no path. */
|
|
46812
|
-
paths: external_exports.tuple([interjectLinkPathSchema, interjectCreatePathSchema])
|
|
46863
|
+
paths: external_exports.tuple([interjectLinkPathSchema, interjectCreatePathSchema]),
|
|
46864
|
+
/**
|
|
46865
|
+
* The forge the remote's host names (#4439): `github` for github.com and
|
|
46866
|
+
* `gitlab` for gitlab.com. Absent for any other host, and from a host
|
|
46867
|
+
* built before the field, which the control plane reads as GitHub. The
|
|
46868
|
+
* host string itself stays on the machine. A GitLab project binds through
|
|
46869
|
+
* its own project access token, so the control plane offers no link for
|
|
46870
|
+
* a `gitlab` question.
|
|
46871
|
+
*/
|
|
46872
|
+
provider: external_exports.enum(INTERJECT_PROVIDERS).optional()
|
|
46813
46873
|
}).strict();
|
|
46814
46874
|
answerBodySchema = external_exports.object({
|
|
46815
46875
|
interjection_key: interjectionKeySchema,
|
|
@@ -46898,6 +46958,12 @@ function proposedSlug(name) {
|
|
|
46898
46958
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").slice(0, SLUG_MAX).replace(/-+$/, "");
|
|
46899
46959
|
return slug.length >= SLUG_MIN && SLUG_PATTERN.test(slug) ? slug : null;
|
|
46900
46960
|
}
|
|
46961
|
+
function providerOf(canonical3) {
|
|
46962
|
+
const host = canonical3.slice(0, canonical3.indexOf("/")).toLowerCase();
|
|
46963
|
+
if (host === "github.com") return "github";
|
|
46964
|
+
if (host === "gitlab.com") return "gitlab";
|
|
46965
|
+
return void 0;
|
|
46966
|
+
}
|
|
46901
46967
|
function prepareInterjection(record, clause, remote, now) {
|
|
46902
46968
|
const key = ulid(now);
|
|
46903
46969
|
const question = interjectionQuestion(clause, record.harness);
|
|
@@ -46934,7 +47000,8 @@ function prepareInterjection(record, clause, remote, now) {
|
|
|
46934
47000
|
proposed_slug: name === null ? null : proposedSlug(name),
|
|
46935
47001
|
skills_enabled: false
|
|
46936
47002
|
}
|
|
46937
|
-
]
|
|
47003
|
+
],
|
|
47004
|
+
...providerOf(remote.canonical) === void 0 ? {} : { provider: providerOf(remote.canonical) }
|
|
46938
47005
|
});
|
|
46939
47006
|
if (!unknown2.success || !interject.success) return void 0;
|
|
46940
47007
|
return {
|
|
@@ -46964,6 +47031,8 @@ function sealInterjection(record, pending, fields) {
|
|
|
46964
47031
|
function expireInterjection(record, now, fields) {
|
|
46965
47032
|
const held = record.control.interjection;
|
|
46966
47033
|
if (held === void 0 || Date.parse(held.expiresAt) > now) return void 0;
|
|
47034
|
+
expiredByHook.set(record, held);
|
|
47035
|
+
putBack.delete(held);
|
|
46967
47036
|
return settle(
|
|
46968
47037
|
record,
|
|
46969
47038
|
held,
|
|
@@ -46972,6 +47041,18 @@ function expireInterjection(record, now, fields) {
|
|
|
46972
47041
|
fields
|
|
46973
47042
|
);
|
|
46974
47043
|
}
|
|
47044
|
+
function restoreExpiredInterjection(record, held) {
|
|
47045
|
+
if (held === void 0 || record.control.interjection !== void 0 || expiredByHook.get(record) !== held)
|
|
47046
|
+
return false;
|
|
47047
|
+
record.control.interjection = held;
|
|
47048
|
+
expiredByHook.delete(record);
|
|
47049
|
+
putBack.add(held);
|
|
47050
|
+
return true;
|
|
47051
|
+
}
|
|
47052
|
+
function heldQuestionWasPutBack(record) {
|
|
47053
|
+
const held = record.control.interjection;
|
|
47054
|
+
return held !== void 0 && putBack.has(held);
|
|
47055
|
+
}
|
|
46975
47056
|
function interjectionAnswerOf(payload) {
|
|
46976
47057
|
const parsed2 = interjectionAnswerPayloadSchema.safeParse(
|
|
46977
47058
|
payload["interjection"]
|
|
@@ -47045,7 +47126,7 @@ function settle(record, held, answer, payload, fields) {
|
|
|
47045
47126
|
record.control.interjection = void 0;
|
|
47046
47127
|
return events;
|
|
47047
47128
|
}
|
|
47048
|
-
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_OPEN, INTERJECTION_TIMED_OUT_TEXT;
|
|
47129
|
+
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_OPEN, INTERJECTION_TIMED_OUT_TEXT, expiredByHook, putBack;
|
|
47049
47130
|
var init_interjection2 = __esm({
|
|
47050
47131
|
"../../packages/tacho/src/collector/interjection.ts"() {
|
|
47051
47132
|
"use strict";
|
|
@@ -47058,6 +47139,8 @@ var init_interjection2 = __esm({
|
|
|
47058
47139
|
NAME_MAX2 = 120;
|
|
47059
47140
|
INTERJECTION_OPEN = "interjection_open";
|
|
47060
47141
|
INTERJECTION_TIMED_OUT_TEXT = "Oxagen asked a person whether to bind this repository to a workspace, and nobody answered in time. This session goes on without skills.";
|
|
47142
|
+
expiredByHook = /* @__PURE__ */ new WeakMap();
|
|
47143
|
+
putBack = /* @__PURE__ */ new WeakSet();
|
|
47061
47144
|
}
|
|
47062
47145
|
});
|
|
47063
47146
|
|
|
@@ -47882,7 +47965,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47882
47965
|
hook_event_name: "UserPromptSubmit",
|
|
47883
47966
|
attrs: replayed
|
|
47884
47967
|
};
|
|
47885
|
-
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), questionFields) : void 0;
|
|
47968
|
+
const timedOut = replay === void 0 || heldQuestionWasPutBack(record) ? expireInterjection(record, deps.now(), questionFields) : void 0;
|
|
47886
47969
|
if (timedOut !== void 0) events.push(...timedOut);
|
|
47887
47970
|
const asked = await repositoryQuestion(
|
|
47888
47971
|
record,
|
|
@@ -47970,7 +48053,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47970
48053
|
const toolInput = input.tool_input;
|
|
47971
48054
|
noteToolCall(record, toolName3, toolInput);
|
|
47972
48055
|
noteRecallHints(record, input.tool_name, toolInput);
|
|
47973
|
-
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), {
|
|
48056
|
+
const timedOut = replay === void 0 || heldQuestionWasPutBack(record) ? expireInterjection(record, deps.now(), {
|
|
47974
48057
|
hook_event_name: "PreToolUse",
|
|
47975
48058
|
attrs: replayed
|
|
47976
48059
|
}) : void 0;
|
|
@@ -52513,21 +52596,26 @@ ${tools}---
|
|
|
52513
52596
|
|
|
52514
52597
|
${skill.body.replace(/^\n+/, "")}`;
|
|
52515
52598
|
}
|
|
52599
|
+
function updateFramed(hash3, part2) {
|
|
52600
|
+
const bytes = typeof part2 === "string" ? Buffer.from(part2, "utf8") : part2;
|
|
52601
|
+
const length = Buffer.alloc(8);
|
|
52602
|
+
length.writeBigUInt64BE(BigInt(bytes.byteLength));
|
|
52603
|
+
hash3.update(length);
|
|
52604
|
+
hash3.update(bytes);
|
|
52605
|
+
}
|
|
52516
52606
|
function skillDigest(skill) {
|
|
52517
52607
|
const hash3 = createHash11("sha256");
|
|
52518
|
-
hash3
|
|
52608
|
+
updateFramed(hash3, skillMarkdown(skill));
|
|
52519
52609
|
for (const file of skill.files) {
|
|
52520
|
-
hash3.
|
|
52521
|
-
hash3
|
|
52522
|
-
hash3.update("\0");
|
|
52523
|
-
hash3.update(file.content);
|
|
52610
|
+
updateFramed(hash3, file.path);
|
|
52611
|
+
updateFramed(hash3, file.content);
|
|
52524
52612
|
}
|
|
52525
52613
|
return `sha256:${hash3.digest("hex")}`;
|
|
52526
52614
|
}
|
|
52527
52615
|
function isMarker(value) {
|
|
52528
52616
|
if (typeof value !== "object" || value === null) return false;
|
|
52529
|
-
const { digest: digest6, sessions } = value;
|
|
52530
|
-
return typeof digest6 === "string" && typeof sessions === "object" && sessions !== null && Object.values(sessions).every((at2) => typeof at2 === "string");
|
|
52617
|
+
const { digest: digest6, lineage, sessions } = value;
|
|
52618
|
+
return typeof digest6 === "string" && (lineage === void 0 || typeof lineage === "string") && typeof sessions === "object" && sessions !== null && Object.values(sessions).every((at2) => typeof at2 === "string");
|
|
52531
52619
|
}
|
|
52532
52620
|
async function readMarker(folder) {
|
|
52533
52621
|
let entries2;
|
|
@@ -52624,21 +52712,38 @@ async function placeSkills(root, sessionId, skills, now = /* @__PURE__ */ new Da
|
|
|
52624
52712
|
if (found.state === "absent") {
|
|
52625
52713
|
await writeSkill(root, skill, {
|
|
52626
52714
|
digest: digest6,
|
|
52715
|
+
lineage: skill.lineage,
|
|
52627
52716
|
sessions: { [sessionId]: now.toISOString() }
|
|
52628
52717
|
});
|
|
52629
52718
|
result2.placed.push(skill.name);
|
|
52630
52719
|
continue;
|
|
52631
52720
|
}
|
|
52632
52721
|
const live = liveSessions(found.marker, now);
|
|
52722
|
+
const othersLive = Object.keys(live).some(
|
|
52723
|
+
(session) => session !== sessionId
|
|
52724
|
+
);
|
|
52725
|
+
const held = found.marker.lineage;
|
|
52726
|
+
if (held !== void 0 && held !== skill.lineage && othersLive) {
|
|
52727
|
+
result2.skipped.push(skill.name);
|
|
52728
|
+
result2.warnings.push(
|
|
52729
|
+
`${folder} holds ${held} for another running session, so ${skill.lineage} was not placed.`
|
|
52730
|
+
);
|
|
52731
|
+
continue;
|
|
52732
|
+
}
|
|
52633
52733
|
const joined = { ...live, [sessionId]: now.toISOString() };
|
|
52634
|
-
if (found.marker.digest === digest6) {
|
|
52635
|
-
await writeMarker(folder, {
|
|
52734
|
+
if (found.marker.digest === digest6 && (held === void 0 || held === skill.lineage)) {
|
|
52735
|
+
await writeMarker(folder, {
|
|
52736
|
+
digest: digest6,
|
|
52737
|
+
lineage: skill.lineage,
|
|
52738
|
+
sessions: joined
|
|
52739
|
+
});
|
|
52636
52740
|
result2.placed.push(skill.name);
|
|
52637
52741
|
continue;
|
|
52638
52742
|
}
|
|
52639
|
-
if (
|
|
52743
|
+
if (othersLive) {
|
|
52640
52744
|
await writeMarker(folder, {
|
|
52641
52745
|
digest: found.marker.digest,
|
|
52746
|
+
...held === void 0 ? {} : { lineage: held },
|
|
52642
52747
|
sessions: joined
|
|
52643
52748
|
});
|
|
52644
52749
|
result2.skipped.push(skill.name);
|
|
@@ -52649,6 +52754,7 @@ async function placeSkills(root, sessionId, skills, now = /* @__PURE__ */ new Da
|
|
|
52649
52754
|
}
|
|
52650
52755
|
await writeSkill(root, skill, {
|
|
52651
52756
|
digest: digest6,
|
|
52757
|
+
lineage: skill.lineage,
|
|
52652
52758
|
sessions: { [sessionId]: now.toISOString() }
|
|
52653
52759
|
});
|
|
52654
52760
|
result2.placed.push(skill.name);
|
|
@@ -52682,7 +52788,7 @@ async function removeSkills(root, sessionId, now = /* @__PURE__ */ new Date()) {
|
|
|
52682
52788
|
await rm2(folder, { recursive: true, force: true });
|
|
52683
52789
|
result2.removed.push(name);
|
|
52684
52790
|
} else if (held) {
|
|
52685
|
-
await writeMarker(folder, {
|
|
52791
|
+
await writeMarker(folder, { ...found.marker, sessions });
|
|
52686
52792
|
result2.kept.push(name);
|
|
52687
52793
|
}
|
|
52688
52794
|
}
|
|
@@ -55068,6 +55174,7 @@ function createModelProxy(deps) {
|
|
|
55068
55174
|
attrs: attrs2
|
|
55069
55175
|
};
|
|
55070
55176
|
const metered = route.api !== "other";
|
|
55177
|
+
await deps.daySpendSeeded?.();
|
|
55071
55178
|
const { model: askedModel, ambiguous: modelAmbiguous } = modelOf(
|
|
55072
55179
|
readable,
|
|
55073
55180
|
json2
|
|
@@ -58292,6 +58399,7 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
58292
58399
|
if (session.sealed && !sealed) session.sealed = false;
|
|
58293
58400
|
session.control.repoChecked = repoChecked;
|
|
58294
58401
|
if (interjection === void 0) session.control.interjection = void 0;
|
|
58402
|
+
else restoreExpiredInterjection(session, interjection);
|
|
58295
58403
|
const held = new Set(messages.map((message) => message.id));
|
|
58296
58404
|
const arrived = session.control.messages.filter(
|
|
58297
58405
|
(message) => !held.has(message.id)
|
|
@@ -59957,16 +60065,29 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
59957
60065
|
}
|
|
59958
60066
|
await refreshUpstreams();
|
|
59959
60067
|
function walDaySpendMicros(day) {
|
|
60068
|
+
let total2 = 0;
|
|
60069
|
+
for (const session of wal.sessions())
|
|
60070
|
+
total2 += sessionDaySpendMicros(session, day);
|
|
60071
|
+
return total2;
|
|
60072
|
+
}
|
|
60073
|
+
function sessionDaySpendMicros(session, day) {
|
|
59960
60074
|
const start = Date.parse(`${day}T00:00:00.000Z`);
|
|
59961
60075
|
const end = Date.parse(nextUtcDayStart(day));
|
|
60076
|
+
return observedSpendMicros(wal.eventsSince(session, start), (event) => {
|
|
60077
|
+
const at2 = Date.parse(event.ts);
|
|
60078
|
+
return at2 >= start && at2 < end;
|
|
60079
|
+
});
|
|
60080
|
+
}
|
|
60081
|
+
async function walDaySpendMicrosYielding(day) {
|
|
60082
|
+
const yieldToLoop = () => new Promise((resolve26) => setImmediate(resolve26));
|
|
60083
|
+
await yieldToLoop();
|
|
59962
60084
|
let total2 = 0;
|
|
59963
60085
|
for (const session of wal.sessions()) {
|
|
59964
|
-
|
|
59965
|
-
|
|
59966
|
-
|
|
59967
|
-
});
|
|
60086
|
+
if (stopped2) return void 0;
|
|
60087
|
+
total2 += sessionDaySpendMicros(session, day);
|
|
60088
|
+
await yieldToLoop();
|
|
59968
60089
|
}
|
|
59969
|
-
return total2;
|
|
60090
|
+
return stopped2 ? void 0 : total2;
|
|
59970
60091
|
}
|
|
59971
60092
|
function observedSpendMicros(events, within4 = () => true) {
|
|
59972
60093
|
let total2 = 0;
|
|
@@ -59993,6 +60114,7 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
59993
60114
|
};
|
|
59994
60115
|
}
|
|
59995
60116
|
let startupDaySpend;
|
|
60117
|
+
let daySpendSeed = Promise.resolve();
|
|
59996
60118
|
const modelProxy = createModelProxy({
|
|
59997
60119
|
registry: registry2,
|
|
59998
60120
|
hostRecorder: () => hostRecorder,
|
|
@@ -60011,6 +60133,7 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
60011
60133
|
// counter asks this once per process (`createDaySpend`), so the figure
|
|
60012
60134
|
// read at startup is used once. A first call on a later day than
|
|
60013
60135
|
// startup's reads the WAL for that day.
|
|
60136
|
+
daySpendSeeded: () => daySpendSeed,
|
|
60014
60137
|
priorDaySpendMicros: spendRead("the day's spend", (day) => {
|
|
60015
60138
|
const seeded = startupDaySpend;
|
|
60016
60139
|
startupDaySpend = void 0;
|
|
@@ -60463,17 +60586,26 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
60463
60586
|
}
|
|
60464
60587
|
}
|
|
60465
60588
|
clock2.phase("restart gaps");
|
|
60466
|
-
|
|
60589
|
+
ready(api);
|
|
60590
|
+
clock2.ready();
|
|
60591
|
+
{
|
|
60467
60592
|
const day = utcDay(now());
|
|
60468
|
-
|
|
60469
|
-
|
|
60470
|
-
|
|
60471
|
-
|
|
60593
|
+
const began = performance.now();
|
|
60594
|
+
daySpendSeed = walDaySpendMicrosYielding(day).then(
|
|
60595
|
+
(micros) => {
|
|
60596
|
+
if (micros === void 0) return;
|
|
60597
|
+
startupDaySpend = { day, micros };
|
|
60598
|
+
log(
|
|
60599
|
+
`day spend read took ${Math.round(performance.now() - began)}ms after ready`
|
|
60600
|
+
);
|
|
60601
|
+
},
|
|
60602
|
+
(error) => {
|
|
60603
|
+
log(
|
|
60604
|
+
`day spend not read from the WAL at startup: ${error instanceof Error ? error.message : String(error)}`
|
|
60605
|
+
);
|
|
60606
|
+
}
|
|
60472
60607
|
);
|
|
60473
60608
|
}
|
|
60474
|
-
clock2.phase("day spend");
|
|
60475
|
-
ready(api);
|
|
60476
|
-
clock2.ready();
|
|
60477
60609
|
servingSince = now();
|
|
60478
60610
|
if (options.listen ?? true) {
|
|
60479
60611
|
const unixSocket = (options.platform ?? process.platform) !== "win32";
|
|
@@ -60924,6 +61056,7 @@ async function initializeDaemon(options, server, port, ready, clock2) {
|
|
|
60924
61056
|
bodyPurgeIdle: async () => {
|
|
60925
61057
|
while (bodyPurge !== void 0) await bodyPurge;
|
|
60926
61058
|
},
|
|
61059
|
+
daySpendSeeded: () => daySpendSeed,
|
|
60927
61060
|
workOrdersIdle: () => workOrderAutostart.idle(),
|
|
60928
61061
|
stop: async () => {
|
|
60929
61062
|
if (stopped2) return;
|
|
@@ -61057,6 +61190,7 @@ var init_daemon = __esm({
|
|
|
61057
61190
|
init_registry();
|
|
61058
61191
|
init_server();
|
|
61059
61192
|
init_spool();
|
|
61193
|
+
init_interjection2();
|
|
61060
61194
|
init_refused();
|
|
61061
61195
|
init_session_heads();
|
|
61062
61196
|
init_transcript_tailer();
|
|
@@ -63376,7 +63510,7 @@ var init_package = __esm({
|
|
|
63376
63510
|
"package.json"() {
|
|
63377
63511
|
package_default = {
|
|
63378
63512
|
name: "@oxagen/cli",
|
|
63379
|
-
version: "2.1.5-
|
|
63513
|
+
version: "2.1.5-88",
|
|
63380
63514
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
63381
63515
|
type: "module",
|
|
63382
63516
|
main: "./dist/index.js",
|
|
@@ -79174,9 +79308,40 @@ var init_digest3 = __esm({
|
|
|
79174
79308
|
});
|
|
79175
79309
|
|
|
79176
79310
|
// ../../packages/run-evidence/src/limits.ts
|
|
79311
|
+
function countCapFor(collection) {
|
|
79312
|
+
const shareBytes = Math.floor(
|
|
79313
|
+
ENVELOPE_ITEM_BUDGET_JCS_BYTES * ENVELOPE_COLLECTION_SHARES[collection] / 100
|
|
79314
|
+
);
|
|
79315
|
+
return Math.floor(shareBytes / MAX_ENVELOPE_ITEM_JCS_BYTES);
|
|
79316
|
+
}
|
|
79317
|
+
var MAX_ENVELOPE_JCS_BYTES, ENVELOPE_RESERVED_JCS_BYTES, MAX_ENVELOPE_ITEM_JCS_BYTES, ENVELOPE_COLLECTION_SHARES, ENVELOPE_ITEM_BUDGET_JCS_BYTES, MAX_CONTEXT_FRAMES, MAX_MODEL_CALLS, MAX_CHANGES, MAX_TOOL_CALLS, MAX_APPROVALS, MAX_VERIFICATIONS, MAX_COMMITS, MAX_PULL_REQUESTS, MAX_ARTIFACTS;
|
|
79177
79318
|
var init_limits = __esm({
|
|
79178
79319
|
"../../packages/run-evidence/src/limits.ts"() {
|
|
79179
79320
|
"use strict";
|
|
79321
|
+
MAX_ENVELOPE_JCS_BYTES = 1048576;
|
|
79322
|
+
ENVELOPE_RESERVED_JCS_BYTES = 65536;
|
|
79323
|
+
MAX_ENVELOPE_ITEM_JCS_BYTES = 512;
|
|
79324
|
+
ENVELOPE_COLLECTION_SHARES = {
|
|
79325
|
+
contextFrames: 10,
|
|
79326
|
+
modelCalls: 15,
|
|
79327
|
+
changes: 20,
|
|
79328
|
+
toolCalls: 30,
|
|
79329
|
+
approvals: 3,
|
|
79330
|
+
verifications: 5,
|
|
79331
|
+
commits: 7,
|
|
79332
|
+
pullRequests: 2,
|
|
79333
|
+
artifacts: 8
|
|
79334
|
+
};
|
|
79335
|
+
ENVELOPE_ITEM_BUDGET_JCS_BYTES = MAX_ENVELOPE_JCS_BYTES - ENVELOPE_RESERVED_JCS_BYTES;
|
|
79336
|
+
MAX_CONTEXT_FRAMES = countCapFor("contextFrames");
|
|
79337
|
+
MAX_MODEL_CALLS = countCapFor("modelCalls");
|
|
79338
|
+
MAX_CHANGES = countCapFor("changes");
|
|
79339
|
+
MAX_TOOL_CALLS = countCapFor("toolCalls");
|
|
79340
|
+
MAX_APPROVALS = countCapFor("approvals");
|
|
79341
|
+
MAX_VERIFICATIONS = countCapFor("verifications");
|
|
79342
|
+
MAX_COMMITS = countCapFor("commits");
|
|
79343
|
+
MAX_PULL_REQUESTS = countCapFor("pullRequests");
|
|
79344
|
+
MAX_ARTIFACTS = countCapFor("artifacts");
|
|
79180
79345
|
}
|
|
79181
79346
|
});
|
|
79182
79347
|
|
package/package.json
CHANGED