@oxagen/cli 2.1.4-489 → 2.1.4-495
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 +304 -71
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -4839,6 +4839,16 @@ var init_envelope = __esm({
|
|
|
4839
4839
|
]).optional(),
|
|
4840
4840
|
tool_denial_kind: short.optional(),
|
|
4841
4841
|
tool_result_tokens: u32.optional(),
|
|
4842
|
+
/**
|
|
4843
|
+
* How `tool_result_tokens` is known (#5339). `reported` is Claude Code's own
|
|
4844
|
+
* count on its OTel tool span. `estimated` is the recorder's: the result's
|
|
4845
|
+
* UTF-8 bytes over four, from the hook that saw the result. A count with no
|
|
4846
|
+
* basis was written before the member existed, and only the OTel span wrote
|
|
4847
|
+
* a count then, so a reader takes it as `reported`. The recorder writes the
|
|
4848
|
+
* two together. The envelope does not require the pair, so a frame from a
|
|
4849
|
+
* host older than the member still parses.
|
|
4850
|
+
*/
|
|
4851
|
+
tool_result_tokens_basis: external_exports.enum(TOKEN_SOURCE_BASES).optional(),
|
|
4842
4852
|
batch_size: u8.optional(),
|
|
4843
4853
|
batch_index: u8.optional(),
|
|
4844
4854
|
attribution_skill: short.optional(),
|
|
@@ -5615,7 +5625,7 @@ function bundleSkillChars(skill) {
|
|
|
5615
5625
|
for (const file of skill.files) chars += file.path.length + file.content.length;
|
|
5616
5626
|
return chars;
|
|
5617
5627
|
}
|
|
5618
|
-
var TACHO_BATCH_SCHEMA, TACHO_BUNDLE_SCHEMA, TACHO_COMMANDS_SCHEMA, TACHO_ENROLLMENT_CLAIMS_SCHEMA, TACHO_ENFORCEMENT_TIER_ATTR, TACHO_GATEWAY_TIER, TACHO_GATEWAY_SESSION_HEADER, TACHO_GATEWAY_GENESIS_HEADER, TACHO_METERING_ATTR, TACHO_METERING_OBSERVED, TACHO_MODEL_SESSION_HEADER, TACHO_CREDENTIAL_BASIS_ATTR, TACHO_CREDENTIAL_GATEWAY_BROKERED, TACHO_CREDENTIAL_HARNESS_HELD, TACHO_CREDENTIAL_BASES, TACHO_RUN_TOKEN_ATTR, BUNDLE_FEATURE_GATEWAY_TOOLS, BUNDLE_FEATURE_MODEL_PRICES, BUNDLE_FEATURE_MODEL_ALLOWLIST, BUNDLE_FEATURE_INDEPENDENT_MODELS, BUNDLE_FEATURE_HOOK_FAIL_OPEN, BUNDLE_FEATURE_STEERING_MANIFEST, BUNDLE_FEATURE_CONTAINMENT, BUNDLE_FEATURE_DAILY_BUDGET, BUNDLE_FEATURE_STEER_NEXT_STEP, BUNDLE_FEATURE_UNBOUND_REPO, BUNDLE_FEATURE_CEDAR, BUNDLE_FEATURE_SKILLS, BUNDLE_FEATURE_CACHE_KEEP_ALIVE, BUNDLE_FEATURE_WORK_ORDERS, TACHO_BUNDLE_FEATURES, bundleFeaturesSchema, hostEnrollmentIdSchema, tachoPlatformSchema, tachoHarnessSchema, TACHO_HARNESS_LABELS, TACHO_HARNESS_TIERS, WRAPPED_HARNESSES, CONNECTED_HARNESSES, HARNESS_BINARY, MODEL_HARNESS_ROUTES, MODEL_ROUTED_HARNESSES, BROKERABLE_HARNESSES, BROKERABLE_HARNESS_PROVIDER, TACHO_TIER_SUMMARY, CUSTOM_AGENT_NAME_PATTERN, RESERVED_AGENT_NAMES, customAgentNameSchema, tachoHostStatusSchema, tachoBundleModeSchema, tachoCommandSchema, tachoCommandStatusSchema, tachoCommandAckStatusSchema, tachoDeliveryModeSchema, denyGenerationSchema, deliveredCommandSchema, deliveredCommandResponseSchema, WORK_ORDER_ID_PATTERN, WORK_ITEM_ID_PATTERN, workOrderCommandPayloadSchema, WORK_ORDER_CLAIM_PATH, WORK_ORDER_REJECT_PATH, workOrderClaimResponseSchema, workOrderRejectResponseSchema, WORK_ORDER_ENV, WORK_ORDER_ATTR, steeringForceSchema, steeringItemKindSchema, steeringCutReasonSchema, steeringManifestItemSchema, STEERING_MANIFEST_SCHEMA, steeringManifestSchema, steeringManifestFrameSchema, cedarIdSchema, cedarPrincipalSchema, cedarToolSchema, cedarBundleSchema, BUNDLE_SKILLS_MAX, BUNDLE_SKILL_FILES_MAX, BUNDLE_SKILLS_CHARS_MAX, BASE64_PATTERN, bundleSkillFileSchema, bundleSkillSchema, policyBundleSchema, enrollmentClaimsSchema, tachoEventWireSchema, daemonHealthSchema, TACHO_MAX_BATCH, TACHO_MAX_BODY_BYTES, TACHO_MAX_REQUEST_BYTES, TACHO_REQUEST_ENVELOPE_BYTES, tachoBodySchema, tachoBatchSchema, agentDaySpendSchema, controlEnvelopeSchema, ingestResponseSchema, bundleResponseSchema, commandAcknowledgementSchema, commandsResponseSchema, enrollmentResponseSchema, tokenEnrollmentResponseSchema;
|
|
5628
|
+
var TACHO_BATCH_SCHEMA, TACHO_BUNDLE_SCHEMA, TACHO_COMMANDS_SCHEMA, TACHO_ENROLLMENT_CLAIMS_SCHEMA, TACHO_ENFORCEMENT_TIER_ATTR, TACHO_GATEWAY_TIER, TACHO_GATEWAY_SESSION_HEADER, TACHO_GATEWAY_GENESIS_HEADER, MCP_STREAMABLE_HTTP_ACCEPT, TACHO_METERING_ATTR, TACHO_METERING_OBSERVED, TACHO_MODEL_SESSION_HEADER, TACHO_CREDENTIAL_BASIS_ATTR, TACHO_CREDENTIAL_GATEWAY_BROKERED, TACHO_CREDENTIAL_HARNESS_HELD, TACHO_CREDENTIAL_BASES, TACHO_RUN_TOKEN_ATTR, BUNDLE_FEATURE_GATEWAY_TOOLS, BUNDLE_FEATURE_MODEL_PRICES, BUNDLE_FEATURE_MODEL_ALLOWLIST, BUNDLE_FEATURE_INDEPENDENT_MODELS, BUNDLE_FEATURE_HOOK_FAIL_OPEN, BUNDLE_FEATURE_STEERING_MANIFEST, BUNDLE_FEATURE_CONTAINMENT, BUNDLE_FEATURE_DAILY_BUDGET, BUNDLE_FEATURE_STEER_NEXT_STEP, BUNDLE_FEATURE_UNBOUND_REPO, BUNDLE_FEATURE_CEDAR, BUNDLE_FEATURE_SKILLS, BUNDLE_FEATURE_CACHE_KEEP_ALIVE, BUNDLE_FEATURE_WORK_ORDERS, TACHO_BUNDLE_FEATURES, bundleFeaturesSchema, hostEnrollmentIdSchema, tachoPlatformSchema, tachoHarnessSchema, TACHO_HARNESS_LABELS, TACHO_HARNESS_TIERS, WRAPPED_HARNESSES, CONNECTED_HARNESSES, HARNESS_BINARY, MODEL_HARNESS_ROUTES, MODEL_ROUTED_HARNESSES, BROKERABLE_HARNESSES, BROKERABLE_HARNESS_PROVIDER, TACHO_TIER_SUMMARY, CUSTOM_AGENT_NAME_PATTERN, RESERVED_AGENT_NAMES, customAgentNameSchema, tachoHostStatusSchema, tachoBundleModeSchema, tachoCommandSchema, tachoCommandStatusSchema, tachoCommandAckStatusSchema, tachoDeliveryModeSchema, denyGenerationSchema, deliveredCommandSchema, deliveredCommandResponseSchema, WORK_ORDER_ID_PATTERN, WORK_ITEM_ID_PATTERN, workOrderCommandPayloadSchema, WORK_ORDER_CLAIM_PATH, WORK_ORDER_REJECT_PATH, workOrderClaimResponseSchema, workOrderRejectResponseSchema, WORK_ORDER_ENV, WORK_ORDER_ATTR, steeringForceSchema, steeringItemKindSchema, steeringCutReasonSchema, steeringManifestItemSchema, STEERING_MANIFEST_SCHEMA, steeringManifestSchema, steeringManifestFrameSchema, cedarIdSchema, cedarPrincipalSchema, cedarToolSchema, cedarBundleSchema, BUNDLE_SKILLS_MAX, BUNDLE_SKILL_FILES_MAX, BUNDLE_SKILLS_CHARS_MAX, BASE64_PATTERN, bundleSkillFileSchema, bundleSkillSchema, policyBundleSchema, enrollmentClaimsSchema, tachoEventWireSchema, daemonHealthSchema, TACHO_MAX_BATCH, TACHO_MAX_BODY_BYTES, TACHO_MAX_REQUEST_BYTES, TACHO_REQUEST_ENVELOPE_BYTES, tachoBodySchema, tachoBatchSchema, agentDaySpendSchema, controlEnvelopeSchema, ingestResponseSchema, bundleResponseSchema, commandAcknowledgementSchema, commandsResponseSchema, enrollmentResponseSchema, tokenEnrollmentResponseSchema;
|
|
5619
5629
|
var init_wire = __esm({
|
|
5620
5630
|
"../../packages/tacho/src/wire.ts"() {
|
|
5621
5631
|
"use strict";
|
|
@@ -5631,6 +5641,7 @@ var init_wire = __esm({
|
|
|
5631
5641
|
TACHO_GATEWAY_TIER = "gateway";
|
|
5632
5642
|
TACHO_GATEWAY_SESSION_HEADER = "x-tacho-gateway-session";
|
|
5633
5643
|
TACHO_GATEWAY_GENESIS_HEADER = "x-tacho-gateway-genesis";
|
|
5644
|
+
MCP_STREAMABLE_HTTP_ACCEPT = "application/json, text/event-stream";
|
|
5634
5645
|
TACHO_METERING_ATTR = "oxagen.metering";
|
|
5635
5646
|
TACHO_METERING_OBSERVED = "observed";
|
|
5636
5647
|
TACHO_MODEL_SESSION_HEADER = "x-oxagen-session";
|
|
@@ -11528,7 +11539,10 @@ function normalizeHook(raw, env, options) {
|
|
|
11528
11539
|
body2["tool_output_digest"] = digestJcs(
|
|
11529
11540
|
input.tool_response
|
|
11530
11541
|
);
|
|
11531
|
-
|
|
11542
|
+
const bytes = jsonByteLength(input.tool_response);
|
|
11543
|
+
body2["tool_output_bytes"] = bytes;
|
|
11544
|
+
body2["tool_result_tokens"] = Math.ceil(bytes / 4);
|
|
11545
|
+
body2["tool_result_tokens_basis"] = "estimated";
|
|
11532
11546
|
}
|
|
11533
11547
|
if (failed3) {
|
|
11534
11548
|
const error = input.error ?? input["error_type"];
|
|
@@ -14512,7 +14526,24 @@ function steeringFactsOf(steering) {
|
|
|
14512
14526
|
steering_tokens_basis: "estimated"
|
|
14513
14527
|
};
|
|
14514
14528
|
}
|
|
14515
|
-
|
|
14529
|
+
function contextFactsOf(tokens) {
|
|
14530
|
+
if (tokens <= 0) return {};
|
|
14531
|
+
return {
|
|
14532
|
+
context_frame_tokens: tokens,
|
|
14533
|
+
context_frame_tokens_basis: "estimated"
|
|
14534
|
+
};
|
|
14535
|
+
}
|
|
14536
|
+
function injectedMarksOf(value) {
|
|
14537
|
+
if (!Array.isArray(value)) return [];
|
|
14538
|
+
return value.flatMap((mark) => {
|
|
14539
|
+
if (typeof mark !== "object" || mark === null) return [];
|
|
14540
|
+
const { at, tokens } = mark;
|
|
14541
|
+
if (typeof at !== "string" || typeof tokens !== "number") return [];
|
|
14542
|
+
if (!Number.isFinite(tokens)) return [];
|
|
14543
|
+
return [{ at, tokens: clampU32(tokens) }];
|
|
14544
|
+
});
|
|
14545
|
+
}
|
|
14546
|
+
var REQUEST_FULL_DIGEST_ATTR, SYSTEM_CONTEXT_PARTS_OMITTED_ATTR, MEMORY_REQUESTS, LISTED_PER_TURN, INJECTED_MARKS_MAX, U32_MAX, NAME_MAX, tokenSourceFacts, SystemContextMemory, SHARED_SYSTEM_CONTEXT_MEMORY, CONVERSATION_FIELDS2, STEERING_ASSEMBLY_PART, SystemContextTracker;
|
|
14516
14547
|
var init_system_context = __esm({
|
|
14517
14548
|
"../../packages/tacho/src/claude-code/system-context.ts"() {
|
|
14518
14549
|
"use strict";
|
|
@@ -14524,6 +14555,7 @@ var init_system_context = __esm({
|
|
|
14524
14555
|
SYSTEM_CONTEXT_PARTS_OMITTED_ATTR = "oxagen.system_context_parts_omitted";
|
|
14525
14556
|
MEMORY_REQUESTS = 512;
|
|
14526
14557
|
LISTED_PER_TURN = 16;
|
|
14558
|
+
INJECTED_MARKS_MAX = 32;
|
|
14527
14559
|
U32_MAX = 4294967295;
|
|
14528
14560
|
NAME_MAX = 512;
|
|
14529
14561
|
tokenSourceFacts = modelFacts.pick({
|
|
@@ -14580,11 +14612,16 @@ var init_system_context = __esm({
|
|
|
14580
14612
|
this.steering = parts === void 0 ? void 0 : { parts, tokens: state?.steeringTokens ?? sum(parts) };
|
|
14581
14613
|
this.listedTurn = state?.listedTurn;
|
|
14582
14614
|
this.listed = [...state?.listed ?? []];
|
|
14615
|
+
this.injected = injectedMarksOf(state?.injected);
|
|
14616
|
+
const floor = state?.injectedFloor;
|
|
14617
|
+
this.injectedFloor = typeof floor === "number" && Number.isFinite(floor) ? clampU32(floor) : 0;
|
|
14583
14618
|
}
|
|
14584
14619
|
memory;
|
|
14585
14620
|
steering;
|
|
14586
14621
|
listedTurn;
|
|
14587
14622
|
listed;
|
|
14623
|
+
injected;
|
|
14624
|
+
injectedFloor;
|
|
14588
14625
|
state() {
|
|
14589
14626
|
const state = {};
|
|
14590
14627
|
if (this.steering !== void 0) {
|
|
@@ -14593,6 +14630,9 @@ var init_system_context = __esm({
|
|
|
14593
14630
|
}
|
|
14594
14631
|
if (this.listedTurn !== void 0) state.listedTurn = this.listedTurn;
|
|
14595
14632
|
if (this.listed.length > 0) state.listed = [...this.listed];
|
|
14633
|
+
if (this.injected.length > 0)
|
|
14634
|
+
state.injected = this.injected.map((mark) => ({ ...mark }));
|
|
14635
|
+
if (this.injectedFloor > 0) state.injectedFloor = this.injectedFloor;
|
|
14596
14636
|
return state;
|
|
14597
14637
|
}
|
|
14598
14638
|
/** Take the steering a sealed `steering.manifest` frame names. */
|
|
@@ -14600,21 +14640,84 @@ var init_system_context = __esm({
|
|
|
14600
14640
|
const steering = steeringContext(body2);
|
|
14601
14641
|
if (steering !== void 0) this.steering = steering;
|
|
14602
14642
|
}
|
|
14643
|
+
/**
|
|
14644
|
+
* Note text an Oxagen hook answer handed the agent after its start, at
|
|
14645
|
+
* `at`, when the answer left (#5339). The text joins the conversation, so
|
|
14646
|
+
* every call made from `at` on carries it. Empty text notes nothing.
|
|
14647
|
+
*
|
|
14648
|
+
* The caller passes only text the session's own conversation reads. The
|
|
14649
|
+
* start's text is the steering manifest's to count, and a subagent's text
|
|
14650
|
+
* stays in the subagent's conversation.
|
|
14651
|
+
*/
|
|
14652
|
+
noteInjectedContext(text4, at) {
|
|
14653
|
+
const tokens = clampU32(budgetTokens(text4));
|
|
14654
|
+
if (tokens === 0) return;
|
|
14655
|
+
this.markInjected(at, this.injectedTotal() + tokens);
|
|
14656
|
+
}
|
|
14657
|
+
/**
|
|
14658
|
+
* Empty the running total at `at`: a compaction or a `/clear` took the
|
|
14659
|
+
* text out of the conversation. A call made before `at` still reads the
|
|
14660
|
+
* total it was made with.
|
|
14661
|
+
*/
|
|
14662
|
+
clearInjectedContext(at) {
|
|
14663
|
+
if (this.injected.length === 0 && this.injectedFloor === 0) return;
|
|
14664
|
+
this.markInjected(at, 0);
|
|
14665
|
+
}
|
|
14666
|
+
injectedTotal() {
|
|
14667
|
+
return this.injected.at(-1)?.tokens ?? this.injectedFloor;
|
|
14668
|
+
}
|
|
14669
|
+
markInjected(at, tokens) {
|
|
14670
|
+
this.injected.push({ at, tokens: clampU32(tokens) });
|
|
14671
|
+
while (this.injected.length > INJECTED_MARKS_MAX) {
|
|
14672
|
+
const oldest = this.injected.shift();
|
|
14673
|
+
if (oldest !== void 0) this.injectedFloor = oldest.tokens;
|
|
14674
|
+
}
|
|
14675
|
+
}
|
|
14676
|
+
/**
|
|
14677
|
+
* The context Oxagen's hooks had handed the session when a call was made
|
|
14678
|
+
* at `at`: the latest mark at or before it. A record can arrive after
|
|
14679
|
+
* later answers left, since OTel exports in batches and the transcript is
|
|
14680
|
+
* read behind the session. A call with no readable time reads the latest
|
|
14681
|
+
* total. A call older than every mark kept reads the total before them.
|
|
14682
|
+
*/
|
|
14683
|
+
injectedAt(at) {
|
|
14684
|
+
const when = at === void 0 ? Number.NaN : Date.parse(at);
|
|
14685
|
+
if (Number.isNaN(when)) return this.injectedTotal();
|
|
14686
|
+
for (let index = this.injected.length - 1; index >= 0; index -= 1) {
|
|
14687
|
+
const mark = this.injected[index];
|
|
14688
|
+
if (mark === void 0) continue;
|
|
14689
|
+
const markAt = Date.parse(mark.at);
|
|
14690
|
+
if (Number.isNaN(markAt) || markAt <= when) return mark.tokens;
|
|
14691
|
+
}
|
|
14692
|
+
return this.injectedFloor;
|
|
14693
|
+
}
|
|
14603
14694
|
/**
|
|
14604
14695
|
* Measure one model call. `content` is the proxy's exchange body, `attrs`
|
|
14605
|
-
* the frame's attrs,
|
|
14696
|
+
* the frame's attrs, `turn` a key that changes when the turn does, and
|
|
14697
|
+
* `at` when the call was made.
|
|
14606
14698
|
*/
|
|
14607
|
-
measure(content, attrs2, turn) {
|
|
14699
|
+
measure(content, attrs2, turn, at) {
|
|
14608
14700
|
const recorded = requestOf(content);
|
|
14609
14701
|
const resolved = recorded === void 0 ? void 0 : resolveRequest(recorded.request, this.memory);
|
|
14610
14702
|
if (recorded === void 0 || resolved === void 0)
|
|
14611
|
-
return this.checked(
|
|
14612
|
-
|
|
14703
|
+
return this.checked(
|
|
14704
|
+
{
|
|
14705
|
+
...steeringFactsOf(this.steering),
|
|
14706
|
+
...contextFactsOf(this.injectedAt(at))
|
|
14707
|
+
},
|
|
14708
|
+
{},
|
|
14709
|
+
() => {
|
|
14710
|
+
}
|
|
14711
|
+
);
|
|
14613
14712
|
const fullDigest = attrs2?.[REQUEST_FULL_DIGEST_ATTR];
|
|
14614
14713
|
const key = isSha256Digest(fullDigest) ? fullDigest : recorded.request[PRIOR_MEMBER] === void 0 ? digestBytes(recorded.text) : void 0;
|
|
14615
14714
|
if (key !== void 0) this.memory.set(key, resolved);
|
|
14616
|
-
const
|
|
14617
|
-
const
|
|
14715
|
+
const main3 = resolved.tools.length > 0;
|
|
14716
|
+
const steering = main3 ? this.steering : void 0;
|
|
14717
|
+
const facts = {
|
|
14718
|
+
...steeringFactsOf(steering),
|
|
14719
|
+
...main3 ? contextFactsOf(this.injectedAt(at)) : {}
|
|
14720
|
+
};
|
|
14618
14721
|
const parts = [
|
|
14619
14722
|
...resolved.system,
|
|
14620
14723
|
...resolved.instructions,
|
|
@@ -14647,15 +14750,23 @@ var init_system_context = __esm({
|
|
|
14647
14750
|
/**
|
|
14648
14751
|
* The token sources of a model call whose request the recorder never saw:
|
|
14649
14752
|
* the counted OTel or transcript row of a call the proxy did not carry
|
|
14650
|
-
* (#4493).
|
|
14651
|
-
*
|
|
14652
|
-
*
|
|
14653
|
-
*
|
|
14654
|
-
*
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14753
|
+
* (#4493). Two counts are known without the request: the steering, from
|
|
14754
|
+
* the manifest, and the context frames, from the hook answers noted before
|
|
14755
|
+
* `at`, when the call was made (#5339). The tool definition count and the
|
|
14756
|
+
* system context stay absent, never zero. Nothing changes on the tracker,
|
|
14757
|
+
* so there is nothing to commit. The caller asks only for a call that
|
|
14758
|
+
* carries the session's conversation, since a side call carries neither.
|
|
14759
|
+
*/
|
|
14760
|
+
measureUnseen(at) {
|
|
14761
|
+
return this.checked(
|
|
14762
|
+
{
|
|
14763
|
+
...steeringFactsOf(this.steering),
|
|
14764
|
+
...contextFactsOf(this.injectedAt(at))
|
|
14765
|
+
},
|
|
14766
|
+
{},
|
|
14767
|
+
() => {
|
|
14768
|
+
}
|
|
14769
|
+
).facts;
|
|
14659
14770
|
}
|
|
14660
14771
|
/**
|
|
14661
14772
|
* Hand back facts the envelope accepts, or none. A body the envelope
|
|
@@ -15295,7 +15406,12 @@ function spanDraft(span, resource) {
|
|
|
15295
15406
|
...s(attrs2, "tool_name") !== void 0 ? { tool_name: s(attrs2, "tool_name") } : {},
|
|
15296
15407
|
...s(attrs2, "tool_use_id") !== void 0 ? { tool_use_id: s(attrs2, "tool_use_id") } : {},
|
|
15297
15408
|
...n(attrs2, "duration_ms") !== void 0 ? { tool_duration_ms: n(attrs2, "duration_ms") } : {},
|
|
15298
|
-
|
|
15409
|
+
// Claude Code's own count, so it is `reported`. A reader prefers it
|
|
15410
|
+
// to the hook's estimate of the same call (#5339).
|
|
15411
|
+
...n(attrs2, "result_tokens") !== void 0 ? {
|
|
15412
|
+
tool_result_tokens: n(attrs2, "result_tokens"),
|
|
15413
|
+
tool_result_tokens_basis: "reported"
|
|
15414
|
+
} : {},
|
|
15299
15415
|
...s(attrs2, "file_path") !== void 0 ? { tool_target: s(attrs2, "file_path") } : {},
|
|
15300
15416
|
...s(attrs2, "full_command") !== void 0 ? { tool_target: (s(attrs2, "full_command") ?? "").slice(0, 512) } : {},
|
|
15301
15417
|
...s(attrs2, "skill_name") !== void 0 ? { attribution_skill: s(attrs2, "skill_name") } : {},
|
|
@@ -16543,16 +16659,18 @@ var init_recorder = __esm({
|
|
|
16543
16659
|
if (kind === "agent_stop") this.turnOpen = false;
|
|
16544
16660
|
const sighting = kind === "llm_call" ? this.llmCallSighting(body2, fields.source ?? "collector") : NO_SIGHTING;
|
|
16545
16661
|
const duplicate = sighting.attrs ?? {};
|
|
16662
|
+
const ts2 = fields.ts ?? this.now();
|
|
16546
16663
|
const measured = kind === "llm_call" ? this.systemContext.measure(
|
|
16547
16664
|
fields.content,
|
|
16548
16665
|
fields.attrs,
|
|
16549
|
-
this.turnOpen ? `turn:${this.turnSeq}` : `idle:${this.turnSeq}
|
|
16666
|
+
this.turnOpen ? `turn:${this.turnSeq}` : `idle:${this.turnSeq}`,
|
|
16667
|
+
ts2
|
|
16550
16668
|
) : void 0;
|
|
16551
16669
|
const event = this.seal(
|
|
16552
16670
|
kind,
|
|
16553
16671
|
measured !== void 0 ? { ...measured.facts, ...body2 } : body2,
|
|
16554
16672
|
{
|
|
16555
|
-
ts:
|
|
16673
|
+
ts: ts2,
|
|
16556
16674
|
source: fields.source ?? "collector",
|
|
16557
16675
|
...fields.hook_event_name !== void 0 ? { hook_event_name: fields.hook_event_name } : {},
|
|
16558
16676
|
attrs: { ...fields.attrs, ...measured?.attrs, ...duplicate },
|
|
@@ -16966,19 +17084,32 @@ var init_recorder = __esm({
|
|
|
16966
17084
|
* recorder knows without the call's request (#4493). Only the counted row,
|
|
16967
17085
|
* the first sighting of its call, takes them. A stamped duplicate is never
|
|
16968
17086
|
* summed, and the rollup joins a stamped proxy row back for the members the
|
|
16969
|
-
* counted row lacks.
|
|
16970
|
-
*
|
|
16971
|
-
*
|
|
16972
|
-
*
|
|
16973
|
-
*
|
|
16974
|
-
*
|
|
16975
|
-
*
|
|
16976
|
-
|
|
16977
|
-
|
|
17087
|
+
* counted row lacks. Two sources are known without the request: the
|
|
17088
|
+
* steering count, and the context frames Oxagen's hooks handed the session
|
|
17089
|
+
* before `ts`, when the call was made (#5339). The tool definitions and the
|
|
17090
|
+
* system context stay absent (ADR-062, amendments of 2026-10-02 and
|
|
17091
|
+
* 2026-10-03). A member the producer set itself wins, as on a proxied call.
|
|
17092
|
+
* Only a call on the session's own conversation comes here: an OTel record
|
|
17093
|
+
* whose `query_source` says so ({@link onSessionConversation}), or a
|
|
17094
|
+
* transcript `assistant` record, since Claude Code writes no side call to
|
|
17095
|
+
* the transcript.
|
|
17096
|
+
*/
|
|
17097
|
+
withUnseenRequestSources(body2, attrs2, ts2) {
|
|
16978
17098
|
if (attrs2[LLM_CALL_DUPLICATE_OF_ATTR] !== void 0) return body2;
|
|
16979
|
-
const facts = this.systemContext.measureUnseen();
|
|
17099
|
+
const facts = this.systemContext.measureUnseen(ts2);
|
|
16980
17100
|
return Object.keys(facts).length === 0 ? body2 : { ...facts, ...body2 };
|
|
16981
17101
|
}
|
|
17102
|
+
/**
|
|
17103
|
+
* Note text an Oxagen hook answer handed this session's agent after its
|
|
17104
|
+
* start, at `at`, when the answer left (#5339). Every model call on the
|
|
17105
|
+
* session's own conversation from then on carries the running total as
|
|
17106
|
+
* `context_frame_tokens`. The hook handler calls this only for a live
|
|
17107
|
+
* answer, since a replay's answer reaches no harness. A rollback of the
|
|
17108
|
+
* chain takes the note back with everything else the hook changed.
|
|
17109
|
+
*/
|
|
17110
|
+
noteInjectedContext(text4, at) {
|
|
17111
|
+
this.systemContext.noteInjectedContext(text4, at);
|
|
17112
|
+
}
|
|
16982
17113
|
/**
|
|
16983
17114
|
* The attrs a `tool_call` carries, or undefined when the chain already
|
|
16984
17115
|
* holds this call and the row must not be sealed at all.
|
|
@@ -17112,6 +17243,9 @@ var init_recorder = __esm({
|
|
|
17112
17243
|
this.started = true;
|
|
17113
17244
|
this.stopped = false;
|
|
17114
17245
|
body2 = { ...body2, env_snapshot: this.envSnapshot };
|
|
17246
|
+
const source = body2["session_start_source"];
|
|
17247
|
+
if (source === "compact" || source === "clear")
|
|
17248
|
+
this.systemContext.clearInjectedContext(ts2);
|
|
17115
17249
|
}
|
|
17116
17250
|
if (draft.kind === "turn_start") {
|
|
17117
17251
|
if (this.turnOpen) {
|
|
@@ -17388,7 +17522,7 @@ var init_recorder = __esm({
|
|
|
17388
17522
|
}
|
|
17389
17523
|
const event = this.seal(
|
|
17390
17524
|
draft.kind,
|
|
17391
|
-
draft.kind === "llm_call" && draft.source === "otel_log" && onSessionConversation(draft.standard.context.query_source) ? this.withUnseenRequestSources(draft.body, duplicate) : draft.body,
|
|
17525
|
+
draft.kind === "llm_call" && draft.source === "otel_log" && onSessionConversation(draft.standard.context.query_source) ? this.withUnseenRequestSources(draft.body, duplicate, draft.ts) : draft.body,
|
|
17392
17526
|
{
|
|
17393
17527
|
ts: draft.ts,
|
|
17394
17528
|
source: draft.source,
|
|
@@ -17471,7 +17605,7 @@ var init_recorder = __esm({
|
|
|
17471
17605
|
duplicate = { [LLM_CALL_DUPLICATE_OF_ATTR]: "transcript" };
|
|
17472
17606
|
}
|
|
17473
17607
|
if (draft.kind === "llm_call")
|
|
17474
|
-
body2 = this.withUnseenRequestSources(body2, duplicate);
|
|
17608
|
+
body2 = this.withUnseenRequestSources(body2, duplicate, draft.ts);
|
|
17475
17609
|
let content = draft.content;
|
|
17476
17610
|
if (this.isSealedPrompt(draft.kind, body2)) {
|
|
17477
17611
|
content = void 0;
|
|
@@ -23363,7 +23497,7 @@ import { readFileSync as readFileSync11 } from "node:fs";
|
|
|
23363
23497
|
import { dirname as dirname8, resolve as resolve2 } from "node:path";
|
|
23364
23498
|
import { fileURLToPath } from "node:url";
|
|
23365
23499
|
function readVersion() {
|
|
23366
|
-
if (true) return "2.1.4-
|
|
23500
|
+
if (true) return "2.1.4-495";
|
|
23367
23501
|
try {
|
|
23368
23502
|
const here = dirname8(fileURLToPath(import.meta.url));
|
|
23369
23503
|
const pkg = JSON.parse(
|
|
@@ -28339,16 +28473,20 @@ function requestedMcpEndpoint(deps, warnings) {
|
|
|
28339
28473
|
}
|
|
28340
28474
|
return request3.pinned;
|
|
28341
28475
|
}
|
|
28342
|
-
function repointCommands(host, runtime) {
|
|
28343
|
-
|
|
28344
|
-
|
|
28476
|
+
function repointCommands(host, runtime, wrapperVersion) {
|
|
28477
|
+
if (sameCommands(host, runtime) && host.wrapper_version === wrapperVersion)
|
|
28478
|
+
return void 0;
|
|
28345
28479
|
return {
|
|
28346
28480
|
...host,
|
|
28347
28481
|
hook_command: runtime.hookCommand,
|
|
28348
28482
|
daemon_command: runtime.daemonCommand,
|
|
28349
|
-
mcp_stdio_command: runtime.mcpStdioCommand
|
|
28483
|
+
mcp_stdio_command: runtime.mcpStdioCommand,
|
|
28484
|
+
wrapper_version: wrapperVersion
|
|
28350
28485
|
};
|
|
28351
28486
|
}
|
|
28487
|
+
function sameCommands(host, runtime) {
|
|
28488
|
+
return host.hook_command === runtime.hookCommand && sameArgv(host.daemon_command, runtime.daemonCommand) && sameArgv(host.mcp_stdio_command ?? [], runtime.mcpStdioCommand);
|
|
28489
|
+
}
|
|
28352
28490
|
function sameArgv(a, b5) {
|
|
28353
28491
|
return a.length === b5.length && a.every((part2, i2) => part2 === b5[i2]);
|
|
28354
28492
|
}
|
|
@@ -28557,7 +28695,7 @@ ${problems.map((problem) => ` ${problem}`).join("\n")}`
|
|
|
28557
28695
|
writeHostFile(deps.paths.hostFile, host);
|
|
28558
28696
|
deps.out(` MCP endpoint pinned to ${pinned} (TACHO_MCP_ENDPOINT)`);
|
|
28559
28697
|
}
|
|
28560
|
-
const repointed = repointCommands(host, deps.runtime);
|
|
28698
|
+
const repointed = repointCommands(host, deps.runtime, deps.wrapperVersion);
|
|
28561
28699
|
if (repointed !== void 0) {
|
|
28562
28700
|
if (deps.runtime.transient !== void 0) {
|
|
28563
28701
|
warnings.push(
|
|
@@ -28570,9 +28708,14 @@ ${problems.map((problem) => ` ${problem}`).join("\n")}`
|
|
|
28570
28708
|
} else {
|
|
28571
28709
|
host = { ...repointed, harness_files: harnessFilesRecord(deps.paths) };
|
|
28572
28710
|
writeHostFile(deps.paths.hostFile, host);
|
|
28573
|
-
deps.
|
|
28574
|
-
|
|
28575
|
-
|
|
28711
|
+
if (!sameCommands(existing, deps.runtime))
|
|
28712
|
+
deps.out(
|
|
28713
|
+
` service and hooks now run from ${deps.runtime.binDir} (was ${existing.hook_command})`
|
|
28714
|
+
);
|
|
28715
|
+
if (existing.wrapper_version !== deps.wrapperVersion)
|
|
28716
|
+
deps.out(
|
|
28717
|
+
` host.json now records version ${deps.wrapperVersion} (was ${existing.wrapper_version})`
|
|
28718
|
+
);
|
|
28576
28719
|
}
|
|
28577
28720
|
}
|
|
28578
28721
|
} else {
|
|
@@ -29906,6 +30049,11 @@ function shimError(id, message) {
|
|
|
29906
30049
|
error: { code: -32002, message }
|
|
29907
30050
|
};
|
|
29908
30051
|
}
|
|
30052
|
+
function answersNoRequest(message) {
|
|
30053
|
+
if (Array.isArray(message) || !("error" in message)) return false;
|
|
30054
|
+
const id = message.id;
|
|
30055
|
+
return id === null || id === void 0;
|
|
30056
|
+
}
|
|
29909
30057
|
function resolveTarget(options, deps) {
|
|
29910
30058
|
const paths = agentPathsForEnrollment(
|
|
29911
30059
|
tachoHome(deps.env, deps.home),
|
|
@@ -29937,8 +30085,9 @@ async function runMcpStdio(options, deps) {
|
|
|
29937
30085
|
const text4 = line.trim();
|
|
29938
30086
|
if (text4.length === 0) continue;
|
|
29939
30087
|
let id;
|
|
30088
|
+
let method;
|
|
29940
30089
|
try {
|
|
29941
|
-
id = JSON.parse(text4)
|
|
30090
|
+
({ id, method } = JSON.parse(text4));
|
|
29942
30091
|
} catch {
|
|
29943
30092
|
deps.stdout.write(
|
|
29944
30093
|
`${JSON.stringify(shimError(null, "the shim received a line that is not JSON"))}
|
|
@@ -29946,7 +30095,7 @@ async function runMcpStdio(options, deps) {
|
|
|
29946
30095
|
);
|
|
29947
30096
|
continue;
|
|
29948
30097
|
}
|
|
29949
|
-
const expectsReply = id !== void 0;
|
|
30098
|
+
const expectsReply = id !== void 0 && typeof method === "string";
|
|
29950
30099
|
const reply2 = (document) => {
|
|
29951
30100
|
if (expectsReply) deps.stdout.write(`${JSON.stringify(document)}
|
|
29952
30101
|
`);
|
|
@@ -29961,7 +30110,9 @@ async function runMcpStdio(options, deps) {
|
|
|
29961
30110
|
headers: {
|
|
29962
30111
|
Authorization: `Bearer ${target2.token}`,
|
|
29963
30112
|
"Content-Type": "application/json",
|
|
29964
|
-
|
|
30113
|
+
// The two media types the MCP transport requires of a client. The
|
|
30114
|
+
// local gateway always answers with JSON, which this accepts.
|
|
30115
|
+
Accept: MCP_STREAMABLE_HTTP_ACCEPT,
|
|
29965
30116
|
// Loopback, so this is not a real origin check — it is here so the
|
|
29966
30117
|
// gateway's guard sees a Host it recognises even behind a proxy
|
|
29967
30118
|
// that rewrites one.
|
|
@@ -29983,8 +30134,12 @@ async function runMcpStdio(options, deps) {
|
|
|
29983
30134
|
parsed = void 0;
|
|
29984
30135
|
}
|
|
29985
30136
|
if (typeof parsed === "object" && parsed !== null) {
|
|
29986
|
-
if (expectsReply
|
|
30137
|
+
if (expectsReply && answersNoRequest(parsed)) {
|
|
30138
|
+
reply2({ ...parsed, id });
|
|
30139
|
+
} else if (expectsReply) {
|
|
30140
|
+
deps.stdout.write(`${body2}
|
|
29987
30141
|
`);
|
|
30142
|
+
}
|
|
29988
30143
|
} else if (!response.ok || expectsReply && body2.length > 0) {
|
|
29989
30144
|
deps.stderr.write(
|
|
29990
30145
|
`oxagen mcp-stdio: the gateway answered ${response.status}: ${body2.slice(0, 200)}
|
|
@@ -30018,6 +30173,7 @@ var init_mcp_stdio = __esm({
|
|
|
30018
30173
|
init_agents();
|
|
30019
30174
|
init_host_file();
|
|
30020
30175
|
init_paths();
|
|
30176
|
+
init_wire();
|
|
30021
30177
|
GATEWAY_TIMEOUT_MS = 5 * 6e4;
|
|
30022
30178
|
}
|
|
30023
30179
|
});
|
|
@@ -34674,12 +34830,45 @@ function readRpcBody(text4) {
|
|
|
34674
34830
|
return JSON.parse(trimmed);
|
|
34675
34831
|
}
|
|
34676
34832
|
let last;
|
|
34677
|
-
for (const
|
|
34678
|
-
|
|
34833
|
+
for (const event of trimmed.split(/\r?\n\r?\n/)) {
|
|
34834
|
+
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(line.startsWith("data: ") ? 6 : 5));
|
|
34835
|
+
const payload = data.join("\n");
|
|
34836
|
+
if (payload.trim().length > 0) last = payload;
|
|
34679
34837
|
}
|
|
34680
34838
|
if (last === void 0) return void 0;
|
|
34681
34839
|
return JSON.parse(last);
|
|
34682
34840
|
}
|
|
34841
|
+
function isRpcErrorObject(value) {
|
|
34842
|
+
if (value === null || typeof value !== "object") return false;
|
|
34843
|
+
const error = value;
|
|
34844
|
+
return typeof error["code"] === "number" && typeof error["message"] === "string";
|
|
34845
|
+
}
|
|
34846
|
+
function answerFor(id, upstream) {
|
|
34847
|
+
const { status: status2, body: body2 } = upstream;
|
|
34848
|
+
const ok = status2 >= 200 && status2 < 300;
|
|
34849
|
+
const message = body2 !== null && typeof body2 === "object" && !Array.isArray(body2) ? body2 : void 0;
|
|
34850
|
+
const error = message?.["error"];
|
|
34851
|
+
if (isRpcErrorObject(error)) {
|
|
34852
|
+
if (message?.["id"] === id) return { status: status2, body: body2 };
|
|
34853
|
+
return {
|
|
34854
|
+
status: status2,
|
|
34855
|
+
body: { jsonrpc: "2.0", id, error }
|
|
34856
|
+
};
|
|
34857
|
+
}
|
|
34858
|
+
if (ok && message !== void 0 && "result" in message) {
|
|
34859
|
+
if (message["id"] === id) return { status: status2, body: body2 };
|
|
34860
|
+
}
|
|
34861
|
+
const flat = upstream.text.replace(/\s+/g, " ").trim();
|
|
34862
|
+
const what = flat.length === 0 ? "with no body" : `with a body that is not a JSON-RPC answer to this request: ${flat.slice(0, UPSTREAM_EXCERPT_MAX)}`;
|
|
34863
|
+
return {
|
|
34864
|
+
status: ok ? 502 : status2,
|
|
34865
|
+
body: rpcError(
|
|
34866
|
+
id,
|
|
34867
|
+
RPC_INTERNAL_ERROR,
|
|
34868
|
+
`the Oxagen control plane answered HTTP ${status2} ${what}`
|
|
34869
|
+
)
|
|
34870
|
+
};
|
|
34871
|
+
}
|
|
34683
34872
|
function outcomeOf(status2, rpc) {
|
|
34684
34873
|
if (rpc?.error !== void 0)
|
|
34685
34874
|
return rpc.error.code === RPC_REFUSED ? "rejected" : "error";
|
|
@@ -34733,10 +34922,11 @@ function createMcpGateway(deps) {
|
|
|
34733
34922
|
headers: {
|
|
34734
34923
|
Authorization: `Bearer ${attribution2.apiKey}`,
|
|
34735
34924
|
"Content-Type": "application/json",
|
|
34736
|
-
//
|
|
34737
|
-
//
|
|
34738
|
-
//
|
|
34739
|
-
|
|
34925
|
+
// Both media types, as the MCP transport requires. The hosted
|
|
34926
|
+
// server refuses any other Accept with a 406 (#5356). It answers
|
|
34927
|
+
// with an event stream, and `readRpcBody` reads the response out of
|
|
34928
|
+
// it, so the client still gets one JSON answer.
|
|
34929
|
+
Accept: MCP_STREAMABLE_HTTP_ACCEPT,
|
|
34740
34930
|
"User-Agent": "oxagen-local-gateway",
|
|
34741
34931
|
"X-Tacho-Host": attribution2.hostEnrollmentId,
|
|
34742
34932
|
// Which chain this call belongs to. The control plane takes the
|
|
@@ -34756,7 +34946,13 @@ function createMcpGateway(deps) {
|
|
|
34756
34946
|
signal: controller.signal
|
|
34757
34947
|
});
|
|
34758
34948
|
const text4 = await response.text();
|
|
34759
|
-
|
|
34949
|
+
let body2;
|
|
34950
|
+
try {
|
|
34951
|
+
body2 = readRpcBody(text4);
|
|
34952
|
+
} catch {
|
|
34953
|
+
body2 = void 0;
|
|
34954
|
+
}
|
|
34955
|
+
return { status: response.status, body: body2, text: text4 };
|
|
34760
34956
|
} finally {
|
|
34761
34957
|
clearTimeout(timer);
|
|
34762
34958
|
}
|
|
@@ -34809,9 +35005,9 @@ function createMcpGateway(deps) {
|
|
|
34809
35005
|
if (name !== void 0) clients.set(context.sessionId, name);
|
|
34810
35006
|
}
|
|
34811
35007
|
const startedAt = now();
|
|
34812
|
-
let
|
|
35008
|
+
let upstream;
|
|
34813
35009
|
try {
|
|
34814
|
-
|
|
35010
|
+
upstream = await forward(request3, attribution2);
|
|
34815
35011
|
} catch (error) {
|
|
34816
35012
|
const message = error instanceof Error ? error.message : String(error);
|
|
34817
35013
|
log(`mcp gateway forward failed: ${message}`);
|
|
@@ -34825,6 +35021,17 @@ function createMcpGateway(deps) {
|
|
|
34825
35021
|
)
|
|
34826
35022
|
};
|
|
34827
35023
|
}
|
|
35024
|
+
let response = typeof request3.id === "string" || typeof request3.id === "number" ? answerFor(request3.id, upstream) : { status: upstream.status, body: upstream.body };
|
|
35025
|
+
if (response.body !== upstream.body) {
|
|
35026
|
+
const said = response.body.error?.message;
|
|
35027
|
+
log(
|
|
35028
|
+
`mcp gateway gave ${request3.method} an error with the request's id after HTTP ${upstream.status}: ${said ?? "no message"}`
|
|
35029
|
+
);
|
|
35030
|
+
} else if (upstream.status < 200 || upstream.status >= 300) {
|
|
35031
|
+
log(
|
|
35032
|
+
`mcp gateway: the control plane answered ${request3.method} with HTTP ${upstream.status}`
|
|
35033
|
+
);
|
|
35034
|
+
}
|
|
34828
35035
|
const rpc = response.body;
|
|
34829
35036
|
if (request3.method === "tools/list" && rpc?.result !== void 0) {
|
|
34830
35037
|
const bundle2 = deps.bundle?.();
|
|
@@ -34944,7 +35151,7 @@ function toolNameOf(params) {
|
|
|
34944
35151
|
const name = params?.["name"];
|
|
34945
35152
|
return typeof name === "string" && name.length > 0 ? name : "unknown";
|
|
34946
35153
|
}
|
|
34947
|
-
var RPC_INVALID_REQUEST, RPC_INTERNAL_ERROR, RPC_REFUSED, CLAUDE_CODE_TOOL_USE_ID_META, MAX_TOOL_USE_ID_LENGTH, DEFAULT_TIMEOUT_MS3, REFUSAL_RULES_MAX, REFUSAL_RULE_MAX;
|
|
35154
|
+
var RPC_INVALID_REQUEST, RPC_INTERNAL_ERROR, RPC_REFUSED, CLAUDE_CODE_TOOL_USE_ID_META, MAX_TOOL_USE_ID_LENGTH, DEFAULT_TIMEOUT_MS3, UPSTREAM_EXCERPT_MAX, REFUSAL_RULES_MAX, REFUSAL_RULE_MAX;
|
|
34948
35155
|
var init_mcp_gateway = __esm({
|
|
34949
35156
|
"../../packages/tacho/src/collector/mcp-gateway.ts"() {
|
|
34950
35157
|
"use strict";
|
|
@@ -34958,6 +35165,7 @@ var init_mcp_gateway = __esm({
|
|
|
34958
35165
|
CLAUDE_CODE_TOOL_USE_ID_META = "claudecode/toolUseId";
|
|
34959
35166
|
MAX_TOOL_USE_ID_LENGTH = 512;
|
|
34960
35167
|
DEFAULT_TIMEOUT_MS3 = 3e4;
|
|
35168
|
+
UPSTREAM_EXCERPT_MAX = 200;
|
|
34961
35169
|
REFUSAL_RULES_MAX = 64;
|
|
34962
35170
|
REFUSAL_RULE_MAX = 512;
|
|
34963
35171
|
}
|
|
@@ -38383,6 +38591,11 @@ function drainMidTurn(input, record, deps, events, replay, used = 0) {
|
|
|
38383
38591
|
if (continuation !== void 0) texts.push(continuation);
|
|
38384
38592
|
return texts;
|
|
38385
38593
|
}
|
|
38594
|
+
function noteHandedContext(record, input, replay, text4, at) {
|
|
38595
|
+
if (replay !== void 0 || input.agent_id !== void 0) return;
|
|
38596
|
+
if (text4.length === 0) return;
|
|
38597
|
+
record.recorder.noteInjectedContext(text4, at);
|
|
38598
|
+
}
|
|
38386
38599
|
function hookLedgerKey(raw, harness, hookId) {
|
|
38387
38600
|
if (hookId !== void 0) return hookId;
|
|
38388
38601
|
if (harness === "stella" || typeof raw !== "object" || raw === null)
|
|
@@ -38685,6 +38898,11 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
38685
38898
|
) : void 0;
|
|
38686
38899
|
if (block === void 0) record.control.resumeOwed = void 0;
|
|
38687
38900
|
if (block === void 0) notePrompt(record, promptText(input));
|
|
38901
|
+
const handed = [
|
|
38902
|
+
...delivered,
|
|
38903
|
+
...recalled !== void 0 ? [recalled.text] : []
|
|
38904
|
+
];
|
|
38905
|
+
const context = handed.join(CONTEXT_JOINER);
|
|
38688
38906
|
events.push(
|
|
38689
38907
|
...record.recorder.ingestHook(
|
|
38690
38908
|
payload,
|
|
@@ -38692,11 +38910,16 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
38692
38910
|
at,
|
|
38693
38911
|
(draft) => withReplay({
|
|
38694
38912
|
...draft,
|
|
38695
|
-
...recalled !== void 0 ? {
|
|
38913
|
+
...recalled !== void 0 || handed.length > 0 ? {
|
|
38696
38914
|
attrs: {
|
|
38697
38915
|
...draft.attrs,
|
|
38698
|
-
|
|
38699
|
-
|
|
38916
|
+
...recalled !== void 0 ? {
|
|
38917
|
+
"oxagen.recall_digest": digestText(recalled.text),
|
|
38918
|
+
"oxagen.recalled_memories": String(recalled.count)
|
|
38919
|
+
} : {},
|
|
38920
|
+
// How much text the answer hands the agent, as the start
|
|
38921
|
+
// records it (#5339).
|
|
38922
|
+
...handed.length > 0 ? { "oxagen.delivered_chars": String(context.length) } : {}
|
|
38700
38923
|
}
|
|
38701
38924
|
} : {},
|
|
38702
38925
|
body: {
|
|
@@ -38717,16 +38940,13 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
38717
38940
|
record
|
|
38718
38941
|
};
|
|
38719
38942
|
}
|
|
38720
|
-
|
|
38721
|
-
...delivered,
|
|
38722
|
-
...recalled !== void 0 ? [recalled.text] : []
|
|
38723
|
-
];
|
|
38943
|
+
noteHandedContext(record, input, replay, context, at);
|
|
38724
38944
|
return {
|
|
38725
38945
|
events,
|
|
38726
|
-
response:
|
|
38946
|
+
response: handed.length > 0 ? {
|
|
38727
38947
|
hookSpecificOutput: {
|
|
38728
38948
|
hookEventName: "UserPromptSubmit",
|
|
38729
|
-
additionalContext: context
|
|
38949
|
+
additionalContext: context
|
|
38730
38950
|
}
|
|
38731
38951
|
} : {},
|
|
38732
38952
|
record
|
|
@@ -38995,6 +39215,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
38995
39215
|
if (operatorBlock(view, record) !== void 0)
|
|
38996
39216
|
return { events, response: {}, record };
|
|
38997
39217
|
const texts = drainMidTurn(input, record, deps, events, replay);
|
|
39218
|
+
noteHandedContext(record, input, replay, texts.join(CONTEXT_JOINER), at);
|
|
38998
39219
|
return {
|
|
38999
39220
|
events,
|
|
39000
39221
|
response: texts.length > 0 ? {
|
|
@@ -39029,6 +39250,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
39029
39250
|
...drainMidTurn(input, record, deps, events, replay, ask?.length ?? 0),
|
|
39030
39251
|
...ask !== void 0 ? [ask] : []
|
|
39031
39252
|
];
|
|
39253
|
+
noteHandedContext(record, input, replay, texts.join(CONTEXT_JOINER), at);
|
|
39032
39254
|
return {
|
|
39033
39255
|
events,
|
|
39034
39256
|
response: texts.length > 0 ? { decision: "block", reason: texts.join(CONTEXT_JOINER) } : {},
|
|
@@ -47228,7 +47450,17 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
47228
47450
|
`no enrollment at ${paths.hostFile}; run \`oxagen agent enroll\` first`
|
|
47229
47451
|
);
|
|
47230
47452
|
}
|
|
47231
|
-
let host = loaded;
|
|
47453
|
+
let host = loaded.wrapper_version === TACHO_VERSION ? loaded : { ...loaded, wrapper_version: TACHO_VERSION };
|
|
47454
|
+
const onDisk = readHostFileLenient(paths.hostFile).host;
|
|
47455
|
+
if (onDisk !== void 0 && onDisk.host_enrollment_id === host.host_enrollment_id && onDisk.wrapper_version !== TACHO_VERSION) {
|
|
47456
|
+
log(
|
|
47457
|
+
`host.json now records version ${TACHO_VERSION} (was ${onDisk.wrapper_version})`
|
|
47458
|
+
);
|
|
47459
|
+
writeHostFile(paths.hostFile, {
|
|
47460
|
+
...onDisk,
|
|
47461
|
+
wrapper_version: TACHO_VERSION
|
|
47462
|
+
});
|
|
47463
|
+
}
|
|
47232
47464
|
for (const dir of [paths.dir, paths.wal, paths.spool, paths.quarantine])
|
|
47233
47465
|
ensureDir(dir);
|
|
47234
47466
|
const recallMemories = options.memoryRecall ?? options.listen ?? true ? createMemoryRecall({
|
|
@@ -47517,10 +47749,10 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
47517
47749
|
const marked = new Set(marks.map(({ session }) => session));
|
|
47518
47750
|
const unmarked = registry2.list().filter((session) => within4(session) && !marked.has(session));
|
|
47519
47751
|
if (unmarked.length > 0) {
|
|
47520
|
-
const
|
|
47752
|
+
const onDisk2 = new Set(wal.sessions());
|
|
47521
47753
|
for (const session of unmarked) {
|
|
47522
47754
|
const recorder = session.recorder;
|
|
47523
|
-
if (!
|
|
47755
|
+
if (!onDisk2.has(recorder.sessionUuid)) {
|
|
47524
47756
|
recorder.rollbackToBirth();
|
|
47525
47757
|
continue;
|
|
47526
47758
|
}
|
|
@@ -47612,8 +47844,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
47612
47844
|
bundle_etag: host.bundle.etag,
|
|
47613
47845
|
// What this daemon's `policyBundleSchema` names, so the control plane
|
|
47614
47846
|
// can send a gated bundle field without breaking hosts that predate it.
|
|
47615
|
-
// Reported from the running code rather than
|
|
47616
|
-
//
|
|
47847
|
+
// Reported from the running code rather than read off `version`, which
|
|
47848
|
+
// a daemon older than #5365 took from the enrollment, not the upgrade.
|
|
47617
47849
|
bundle_features: [...TACHO_BUNDLE_FEATURES],
|
|
47618
47850
|
// Omitted until a read succeeds: absent means nothing was said, and a
|
|
47619
47851
|
// daemon that could not read the files has nothing to say.
|
|
@@ -49811,6 +50043,7 @@ var init_daemon = __esm({
|
|
|
49811
50043
|
init_work_orders();
|
|
49812
50044
|
init_ids();
|
|
49813
50045
|
init_timestamp();
|
|
50046
|
+
init_version();
|
|
49814
50047
|
init_wire();
|
|
49815
50048
|
init_backfill2();
|
|
49816
50049
|
init_detector();
|
|
@@ -52035,7 +52268,7 @@ var init_package = __esm({
|
|
|
52035
52268
|
"package.json"() {
|
|
52036
52269
|
package_default = {
|
|
52037
52270
|
name: "@oxagen/cli",
|
|
52038
|
-
version: "2.1.4-
|
|
52271
|
+
version: "2.1.4-495",
|
|
52039
52272
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
52040
52273
|
type: "module",
|
|
52041
52274
|
main: "./dist/index.js",
|
package/package.json
CHANGED