@oxagen/cli 2.1.5-63 → 2.1.5-73
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 +1168 -386
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -3589,15 +3589,15 @@ var init_types = __esm({
|
|
|
3589
3589
|
}
|
|
3590
3590
|
const valueType = this._def.valueType;
|
|
3591
3591
|
function finalizeSet(elements2) {
|
|
3592
|
-
const
|
|
3592
|
+
const parsedSet2 = /* @__PURE__ */ new Set();
|
|
3593
3593
|
for (const element of elements2) {
|
|
3594
3594
|
if (element.status === "aborted")
|
|
3595
3595
|
return INVALID;
|
|
3596
3596
|
if (element.status === "dirty")
|
|
3597
3597
|
status2.dirty();
|
|
3598
|
-
|
|
3598
|
+
parsedSet2.add(element.value);
|
|
3599
3599
|
}
|
|
3600
|
-
return { status: status2.value, value:
|
|
3600
|
+
return { status: status2.value, value: parsedSet2 };
|
|
3601
3601
|
}
|
|
3602
3602
|
const elements = [...ctx.data.values()].map((item, i2) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i2)));
|
|
3603
3603
|
if (ctx.common.async) {
|
|
@@ -5656,7 +5656,7 @@ function bundleSkillChars(skill) {
|
|
|
5656
5656
|
chars += file.path.length + file.content.length;
|
|
5657
5657
|
return chars;
|
|
5658
5658
|
}
|
|
5659
|
-
var protocolTimestampSchema, machineGroupSchema, 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, REFUSAL_META_KEY, 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_STEERING_INCOMPLETE, BUNDLE_FEATURE_CONTAINMENT, BUNDLE_FEATURE_DAILY_BUDGET, BUNDLE_FEATURE_STEER_NEXT_STEP, BUNDLE_FEATURE_UNBOUND_REPO, BUNDLE_FEATURE_CEDAR, BUNDLE_FEATURE_CEDAR_TOOLBELT, BUNDLE_FEATURE_SKILLS, BUNDLE_FEATURE_CACHE_KEEP_ALIVE, BUNDLE_FEATURE_WORK_ORDERS, BUNDLE_FEATURE_WORK_ORDER_START, BUNDLE_FEATURE_GATEWAY_POLICY, GATEWAY_MIN_TIERS, SENSITIVE_SCREEN_ACTIONS, PROMPT_REDACTION_PATTERNS_MAX, PROMPT_REDACTION_PATTERN_MAX, gatewayPolicySchema, 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, 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_CRITERION_CLAIM_PATH, WORK_CRITERION_ID_PATTERN, WORK_HEAD_SHA_PATTERN, WORK_CRITERION_CLAIM_TEXT_MAX, workCriterionClaimResponseSchema, 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;
|
|
5659
|
+
var protocolTimestampSchema, machineGroupSchema, 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, REFUSAL_META_KEY, 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_STEERING_INCOMPLETE, BUNDLE_FEATURE_CONTAINMENT, BUNDLE_FEATURE_DAILY_BUDGET, BUNDLE_FEATURE_STEER_NEXT_STEP, BUNDLE_FEATURE_UNBOUND_REPO, BUNDLE_FEATURE_CEDAR, BUNDLE_FEATURE_CEDAR_TOOLBELT, BUNDLE_FEATURE_SKILLS, BUNDLE_FEATURE_CACHE_KEEP_ALIVE, BUNDLE_FEATURE_WORK_ORDERS, BUNDLE_FEATURE_WORK_ORDER_START, BUNDLE_FEATURE_MCP_RULE_SETS, BUNDLE_FEATURE_GATEWAY_POLICY, GATEWAY_MIN_TIERS, SENSITIVE_SCREEN_ACTIONS, PROMPT_REDACTION_PATTERNS_MAX, PROMPT_REDACTION_PATTERN_MAX, gatewayPolicySchema, 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, 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_CRITERION_CLAIM_PATH, WORK_CRITERION_ID_PATTERN, WORK_HEAD_SHA_PATTERN, WORK_CRITERION_CLAIM_TEXT_MAX, workCriterionClaimResponseSchema, 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;
|
|
5660
5660
|
var init_wire = __esm({
|
|
5661
5661
|
"../../packages/tacho/src/wire.ts"() {
|
|
5662
5662
|
"use strict";
|
|
@@ -5709,6 +5709,7 @@ var init_wire = __esm({
|
|
|
5709
5709
|
BUNDLE_FEATURE_CACHE_KEEP_ALIVE = "cache_keep_alive";
|
|
5710
5710
|
BUNDLE_FEATURE_WORK_ORDERS = "work_orders";
|
|
5711
5711
|
BUNDLE_FEATURE_WORK_ORDER_START = "work_order_start";
|
|
5712
|
+
BUNDLE_FEATURE_MCP_RULE_SETS = "mcp_rule_sets";
|
|
5712
5713
|
BUNDLE_FEATURE_GATEWAY_POLICY = "gateway_policy";
|
|
5713
5714
|
GATEWAY_MIN_TIERS = ["harness", "gateway", "contained"];
|
|
5714
5715
|
SENSITIVE_SCREEN_ACTIONS = ["flag", "strip", "reject"];
|
|
@@ -5755,6 +5756,7 @@ var init_wire = __esm({
|
|
|
5755
5756
|
BUNDLE_FEATURE_WORK_ORDERS,
|
|
5756
5757
|
BUNDLE_FEATURE_WORK_ORDER_START,
|
|
5757
5758
|
BUNDLE_FEATURE_STEERING_INCOMPLETE,
|
|
5759
|
+
BUNDLE_FEATURE_MCP_RULE_SETS,
|
|
5758
5760
|
BUNDLE_FEATURE_GATEWAY_POLICY
|
|
5759
5761
|
];
|
|
5760
5762
|
bundleFeaturesSchema = external_exports.array(external_exports.string().max(64)).max(32);
|
|
@@ -6072,6 +6074,25 @@ var init_wire = __esm({
|
|
|
6072
6074
|
deny: external_exports.array(external_exports.string().max(512)).max(1024),
|
|
6073
6075
|
ask: external_exports.array(external_exports.string().max(512)).max(1024)
|
|
6074
6076
|
}).strict(),
|
|
6077
|
+
/**
|
|
6078
|
+
* The agent's MCP tool rules as the app holds them (#5398): one list per
|
|
6079
|
+
* rule set, each rule in its set's order. The host takes the first rule
|
|
6080
|
+
* that matches in each set and the most restrictive answer across the
|
|
6081
|
+
* sets (deny, then ask, then allow), and a set with no matching rule says
|
|
6082
|
+
* nothing. These rules are not also in `permissions`, whose fixed
|
|
6083
|
+
* deny-before-allow order would undo theirs.
|
|
6084
|
+
*
|
|
6085
|
+
* Emitted only to a host that advertised `BUNDLE_FEATURE_MCP_RULE_SETS`.
|
|
6086
|
+
* When it is absent, the same rules are sorted into `permissions`.
|
|
6087
|
+
*/
|
|
6088
|
+
mcp_rule_sets: external_exports.array(
|
|
6089
|
+
external_exports.array(
|
|
6090
|
+
external_exports.object({
|
|
6091
|
+
rule: external_exports.string().max(512),
|
|
6092
|
+
effect: external_exports.enum(["allow", "deny", "ask"])
|
|
6093
|
+
}).strict()
|
|
6094
|
+
).max(1024)
|
|
6095
|
+
).max(256).optional(),
|
|
6075
6096
|
tools: external_exports.record(
|
|
6076
6097
|
external_exports.string().max(256),
|
|
6077
6098
|
external_exports.object({
|
|
@@ -8121,12 +8142,12 @@ function cacheKeepAliveFinding(bundle2) {
|
|
|
8121
8142
|
}
|
|
8122
8143
|
function parseRule(raw) {
|
|
8123
8144
|
const rule = raw.trim();
|
|
8124
|
-
const
|
|
8125
|
-
if (
|
|
8145
|
+
const open7 = rule.indexOf("(");
|
|
8146
|
+
if (open7 === -1 || !rule.endsWith(")")) return { raw, tool: rule };
|
|
8126
8147
|
return {
|
|
8127
8148
|
raw,
|
|
8128
|
-
tool: rule.slice(0,
|
|
8129
|
-
spec: rule.slice(
|
|
8149
|
+
tool: rule.slice(0, open7).trim(),
|
|
8150
|
+
spec: rule.slice(open7 + 1, -1)
|
|
8130
8151
|
};
|
|
8131
8152
|
}
|
|
8132
8153
|
function escapeRegex(value) {
|
|
@@ -8427,6 +8448,29 @@ function firstMatch(rules, call2, context, effect) {
|
|
|
8427
8448
|
}
|
|
8428
8449
|
return void 0;
|
|
8429
8450
|
}
|
|
8451
|
+
function parsedSet(set) {
|
|
8452
|
+
const cached3 = parsedSetCache.get(set);
|
|
8453
|
+
if (cached3 !== void 0 && cached3.length === set.length && cached3.every((rule, index) => rule.raw === set[index]?.rule))
|
|
8454
|
+
return cached3;
|
|
8455
|
+
const parsed2 = set.map((entry2) => parseRule(entry2.rule));
|
|
8456
|
+
parsedSetCache.set(set, parsed2);
|
|
8457
|
+
return parsed2;
|
|
8458
|
+
}
|
|
8459
|
+
function ruleSetsMatch(sets, call2, context) {
|
|
8460
|
+
if (sets === void 0) return void 0;
|
|
8461
|
+
let result2;
|
|
8462
|
+
for (const set of sets) {
|
|
8463
|
+
const parsed2 = parsedSet(set);
|
|
8464
|
+
for (const [index, rule] of parsed2.entries()) {
|
|
8465
|
+
const effect = set[index].effect;
|
|
8466
|
+
if (!callMatches(rule, call2, context ?? {}, effect)) continue;
|
|
8467
|
+
if (result2 === void 0 || EFFECT_RANK[effect] > EFFECT_RANK[result2.effect])
|
|
8468
|
+
result2 = { effect, rule: rule.raw };
|
|
8469
|
+
break;
|
|
8470
|
+
}
|
|
8471
|
+
}
|
|
8472
|
+
return result2;
|
|
8473
|
+
}
|
|
8430
8474
|
function allowMatch(rules, call2, context) {
|
|
8431
8475
|
const single = firstMatch(rules, call2, context, "allow");
|
|
8432
8476
|
if (single !== void 0) return [single];
|
|
@@ -8559,12 +8603,8 @@ function evaluatePreToolUse(input) {
|
|
|
8559
8603
|
};
|
|
8560
8604
|
}
|
|
8561
8605
|
const call2 = toolCallOf(toolName3, toolInput);
|
|
8562
|
-
const
|
|
8563
|
-
|
|
8564
|
-
call2,
|
|
8565
|
-
input.context,
|
|
8566
|
-
"deny"
|
|
8567
|
-
);
|
|
8606
|
+
const ordered = ruleSetsMatch(bundle2.mcp_rule_sets, call2, input.context);
|
|
8607
|
+
const denied = firstMatch(bundle2.permissions.deny, call2, input.context, "deny") ?? (ordered?.effect === "deny" ? ordered.rule : void 0);
|
|
8568
8608
|
if (denied !== void 0) {
|
|
8569
8609
|
return {
|
|
8570
8610
|
decision: bundle2.mode === "observe" ? "allow" : "deny",
|
|
@@ -8588,7 +8628,7 @@ function evaluatePreToolUse(input) {
|
|
|
8588
8628
|
stale
|
|
8589
8629
|
};
|
|
8590
8630
|
}
|
|
8591
|
-
const ask = firstMatch(bundle2.permissions.ask, call2, input.context, "ask");
|
|
8631
|
+
const ask = firstMatch(bundle2.permissions.ask, call2, input.context, "ask") ?? (ordered?.effect === "ask" ? ordered.rule : void 0);
|
|
8592
8632
|
if (ask !== void 0) {
|
|
8593
8633
|
return {
|
|
8594
8634
|
decision: bundle2.mode === "observe" ? "allow" : "ask",
|
|
@@ -8603,7 +8643,7 @@ function evaluatePreToolUse(input) {
|
|
|
8603
8643
|
stale
|
|
8604
8644
|
};
|
|
8605
8645
|
}
|
|
8606
|
-
const allowed = allowMatch(bundle2.permissions.allow, call2, input.context);
|
|
8646
|
+
const allowed = allowMatch(bundle2.permissions.allow, call2, input.context) ?? (ordered?.effect === "allow" ? [ordered.rule] : void 0);
|
|
8607
8647
|
if (allowed !== void 0) {
|
|
8608
8648
|
const rule = allowed.join(" and ");
|
|
8609
8649
|
return {
|
|
@@ -8753,7 +8793,7 @@ function decideWithCedar(input) {
|
|
|
8753
8793
|
};
|
|
8754
8794
|
}
|
|
8755
8795
|
}
|
|
8756
|
-
var SHELL_OPERATORS, SHELL_LEADING_WORDS, WINDOWS_PATH, SHELL_TOOLS2, DECLARATION_SYNONYMS, GLOB_CACHE_LIMIT, globCache, parsedRuleCache, WRITE_EFFECTS;
|
|
8796
|
+
var SHELL_OPERATORS, SHELL_LEADING_WORDS, WINDOWS_PATH, SHELL_TOOLS2, DECLARATION_SYNONYMS, GLOB_CACHE_LIMIT, globCache, parsedRuleCache, EFFECT_RANK, parsedSetCache, WRITE_EFFECTS;
|
|
8757
8797
|
var init_bundle = __esm({
|
|
8758
8798
|
"../../packages/tacho/src/host/bundle.ts"() {
|
|
8759
8799
|
"use strict";
|
|
@@ -8795,6 +8835,8 @@ var init_bundle = __esm({
|
|
|
8795
8835
|
GLOB_CACHE_LIMIT = 1024;
|
|
8796
8836
|
globCache = /* @__PURE__ */ new Map();
|
|
8797
8837
|
parsedRuleCache = /* @__PURE__ */ new WeakMap();
|
|
8838
|
+
EFFECT_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
8839
|
+
parsedSetCache = /* @__PURE__ */ new WeakMap();
|
|
8798
8840
|
WRITE_EFFECTS = /* @__PURE__ */ new Set([
|
|
8799
8841
|
"file_write",
|
|
8800
8842
|
"file_edit",
|
|
@@ -8853,6 +8895,13 @@ function withRecordedHarnessFiles(paths, host) {
|
|
|
8853
8895
|
claudeDesktopConfig: record.claude_desktop_config !== void 0 ? record.claude_desktop_config ?? void 0 : paths.claudeDesktopConfig
|
|
8854
8896
|
};
|
|
8855
8897
|
}
|
|
8898
|
+
function recordedHarnessHomes(host) {
|
|
8899
|
+
const record = host?.harness_files;
|
|
8900
|
+
return {
|
|
8901
|
+
...record?.claude_settings !== void 0 ? { claudeConfigDir: dirname2(record.claude_settings) } : {},
|
|
8902
|
+
...record?.codex_hooks !== void 0 ? { codexHome: dirname2(record.codex_hooks) } : {}
|
|
8903
|
+
};
|
|
8904
|
+
}
|
|
8856
8905
|
function mcpEndpointOverrideRequestFrom(env) {
|
|
8857
8906
|
const raw = env["TACHO_MCP_ENDPOINT"];
|
|
8858
8907
|
if (typeof raw !== "string" || raw.length === 0)
|
|
@@ -9578,7 +9627,7 @@ var init_settings_writer = __esm({
|
|
|
9578
9627
|
"Stop"
|
|
9579
9628
|
];
|
|
9580
9629
|
STEER_WAIT_FLAG = "--await-steer";
|
|
9581
|
-
STEER_WAIT_TIMEOUT_S =
|
|
9630
|
+
STEER_WAIT_TIMEOUT_S = 1814400;
|
|
9582
9631
|
COMMAND_HOOK_TIMEOUTS_S = {
|
|
9583
9632
|
SessionStart: 10,
|
|
9584
9633
|
UserPromptSubmit: 10,
|
|
@@ -10917,12 +10966,12 @@ function procStartTicks(stat7) {
|
|
|
10917
10966
|
return ticks !== void 0 && /^\d+$/.test(ticks) ? ticks : void 0;
|
|
10918
10967
|
}
|
|
10919
10968
|
function procParent(stat7) {
|
|
10920
|
-
const
|
|
10969
|
+
const open7 = stat7.indexOf("(");
|
|
10921
10970
|
const close = stat7.lastIndexOf(")");
|
|
10922
|
-
if (
|
|
10971
|
+
if (open7 < 0 || close < open7) return void 0;
|
|
10923
10972
|
const ppid = stat7.slice(close + 1).trim().split(/\s+/)[1];
|
|
10924
10973
|
if (ppid === void 0 || !/^\d+$/.test(ppid)) return void 0;
|
|
10925
|
-
return { ppid: Number(ppid), comm: stat7.slice(
|
|
10974
|
+
return { ppid: Number(ppid), comm: stat7.slice(open7 + 1, close) };
|
|
10926
10975
|
}
|
|
10927
10976
|
function readProcParent(pid, read2 = readText) {
|
|
10928
10977
|
const stat7 = read2(`/proc/${pid}/stat`);
|
|
@@ -23229,7 +23278,7 @@ function openCredentialStore(paths) {
|
|
|
23229
23278
|
entriesSeen = { version: version2, entries: parsed2.data.entries };
|
|
23230
23279
|
return parsed2.data.entries;
|
|
23231
23280
|
}
|
|
23232
|
-
function
|
|
23281
|
+
function writeAll3(entries2) {
|
|
23233
23282
|
if (entries2.length === 0) {
|
|
23234
23283
|
if (existsSync5(paths.file)) unlinkSync4(paths.file);
|
|
23235
23284
|
return;
|
|
@@ -23273,7 +23322,7 @@ function openCredentialStore(paths) {
|
|
|
23273
23322
|
prefix: kind === "chatgpt" ? "login" : credentialPrefix(secret),
|
|
23274
23323
|
sealed: seal(keyForWrite(), secret, sealingContext(provider, owner))
|
|
23275
23324
|
};
|
|
23276
|
-
|
|
23325
|
+
writeAll3([
|
|
23277
23326
|
...readAll().filter((e) => !matches(e, provider, owner)),
|
|
23278
23327
|
entry2
|
|
23279
23328
|
]);
|
|
@@ -23289,7 +23338,7 @@ function openCredentialStore(paths) {
|
|
|
23289
23338
|
entry2.sealed,
|
|
23290
23339
|
sealingContext(provider, owner)
|
|
23291
23340
|
);
|
|
23292
|
-
|
|
23341
|
+
writeAll3(entries2.filter((e) => !matches(e, provider, owner)));
|
|
23293
23342
|
return { kind: entry2.kind, secret };
|
|
23294
23343
|
},
|
|
23295
23344
|
status: () => readAll().map(custodyOf),
|
|
@@ -26623,7 +26672,7 @@ import { readFileSync as readFileSync10 } from "node:fs";
|
|
|
26623
26672
|
import { dirname as dirname9, resolve as resolve3 } from "node:path";
|
|
26624
26673
|
import { fileURLToPath } from "node:url";
|
|
26625
26674
|
function readVersion() {
|
|
26626
|
-
if (true) return "2.1.5-
|
|
26675
|
+
if (true) return "2.1.5-73";
|
|
26627
26676
|
try {
|
|
26628
26677
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
26629
26678
|
const pkg = JSON.parse(
|
|
@@ -28176,6 +28225,73 @@ function readTailLine(path2, size = statSync5(path2).size, window2 = SCAN_CHUNK_
|
|
|
28176
28225
|
closeSync5(fd2);
|
|
28177
28226
|
}
|
|
28178
28227
|
}
|
|
28228
|
+
function* readLinesBackward(path2, size = statSync5(path2).size, window2 = SCAN_CHUNK_BYTES) {
|
|
28229
|
+
if (size === 0) return;
|
|
28230
|
+
const fd2 = openSync5(path2, "r");
|
|
28231
|
+
try {
|
|
28232
|
+
let buffer = Buffer.alloc(0);
|
|
28233
|
+
let start = size;
|
|
28234
|
+
let chunk2 = Math.max(1, window2);
|
|
28235
|
+
const largest = Math.max(chunk2, SCAN_CHUNK_BYTES);
|
|
28236
|
+
let cut = false;
|
|
28237
|
+
const readEarlier = (end2) => {
|
|
28238
|
+
if (start === 0) return false;
|
|
28239
|
+
const from = Math.max(0, start - chunk2);
|
|
28240
|
+
const length = start - from;
|
|
28241
|
+
const earlier = Buffer.allocUnsafe(length);
|
|
28242
|
+
let filled = 0;
|
|
28243
|
+
while (filled < length) {
|
|
28244
|
+
const read2 = readSync2(
|
|
28245
|
+
fd2,
|
|
28246
|
+
earlier,
|
|
28247
|
+
filled,
|
|
28248
|
+
length - filled,
|
|
28249
|
+
from + filled
|
|
28250
|
+
);
|
|
28251
|
+
if (read2 <= 0) break;
|
|
28252
|
+
filled += read2;
|
|
28253
|
+
}
|
|
28254
|
+
if (filled < length) {
|
|
28255
|
+
cut = true;
|
|
28256
|
+
return false;
|
|
28257
|
+
}
|
|
28258
|
+
buffer = Buffer.concat([earlier, buffer.subarray(0, end2 - start)]);
|
|
28259
|
+
start = from;
|
|
28260
|
+
chunk2 = Math.min(chunk2 * 2, largest);
|
|
28261
|
+
return true;
|
|
28262
|
+
};
|
|
28263
|
+
let end = size;
|
|
28264
|
+
while (end > 0) {
|
|
28265
|
+
if (end - 1 < start && !readEarlier(end)) return;
|
|
28266
|
+
let terminated = false;
|
|
28267
|
+
let lineEnd = end;
|
|
28268
|
+
if (buffer[end - 1 - start] === 10) {
|
|
28269
|
+
terminated = true;
|
|
28270
|
+
lineEnd = end - 1;
|
|
28271
|
+
}
|
|
28272
|
+
if (lineEnd === 0) return;
|
|
28273
|
+
let offset = 0;
|
|
28274
|
+
for (; ; ) {
|
|
28275
|
+
const at2 = lineEnd > start ? buffer.lastIndexOf(10, lineEnd - start - 1) : -1;
|
|
28276
|
+
if (at2 !== -1) {
|
|
28277
|
+
offset = start + at2 + 1;
|
|
28278
|
+
break;
|
|
28279
|
+
}
|
|
28280
|
+
if (!readEarlier(end)) break;
|
|
28281
|
+
}
|
|
28282
|
+
if (cut) return;
|
|
28283
|
+
yield {
|
|
28284
|
+
text: buffer.subarray(offset - start, lineEnd - start).toString("utf8"),
|
|
28285
|
+
offset,
|
|
28286
|
+
end: terminated ? lineEnd + 1 : lineEnd,
|
|
28287
|
+
terminated
|
|
28288
|
+
};
|
|
28289
|
+
end = offset;
|
|
28290
|
+
}
|
|
28291
|
+
} finally {
|
|
28292
|
+
closeSync5(fd2);
|
|
28293
|
+
}
|
|
28294
|
+
}
|
|
28179
28295
|
function* readLinesFrom(path2, from = 0, chunkBytes = SCAN_CHUNK_BYTES) {
|
|
28180
28296
|
const fd2 = openSync5(path2, "r");
|
|
28181
28297
|
try {
|
|
@@ -28194,13 +28310,15 @@ function* readLinesFrom(path2, from = 0, chunkBytes = SCAN_CHUNK_BYTES) {
|
|
|
28194
28310
|
closeSync5(fd2);
|
|
28195
28311
|
}
|
|
28196
28312
|
}
|
|
28197
|
-
async function* readLinesFromAsync(path2, from = 0) {
|
|
28313
|
+
async function* readLinesFromAsync(path2, from = 0, to = Number.POSITIVE_INFINITY) {
|
|
28198
28314
|
const handle = await open2(path2, "r");
|
|
28199
28315
|
try {
|
|
28200
28316
|
const splitter = new LineSplitter(from);
|
|
28201
28317
|
let position = from;
|
|
28202
|
-
|
|
28203
|
-
const chunk2 = Buffer.allocUnsafe(
|
|
28318
|
+
while (position < to) {
|
|
28319
|
+
const chunk2 = Buffer.allocUnsafe(
|
|
28320
|
+
Math.min(SCAN_CHUNK_BYTES, to - position)
|
|
28321
|
+
);
|
|
28204
28322
|
const { bytesRead } = await handle.read(chunk2, 0, chunk2.length, position);
|
|
28205
28323
|
if (bytesRead <= 0) break;
|
|
28206
28324
|
position += bytesRead;
|
|
@@ -28542,6 +28660,7 @@ import {
|
|
|
28542
28660
|
writeSync as writeSync4
|
|
28543
28661
|
} from "node:fs";
|
|
28544
28662
|
import { randomUUID } from "node:crypto";
|
|
28663
|
+
import { open as open3 } from "node:fs/promises";
|
|
28545
28664
|
import { join as join18 } from "node:path";
|
|
28546
28665
|
function activityAt(event) {
|
|
28547
28666
|
const at2 = Date.parse(event.ts);
|
|
@@ -28576,7 +28695,66 @@ function isResumeMark(value) {
|
|
|
28576
28695
|
function sizeOf(path2) {
|
|
28577
28696
|
return statSync6(path2, { throwIfNoEntry: false })?.size ?? 0;
|
|
28578
28697
|
}
|
|
28579
|
-
|
|
28698
|
+
function statIfExists2(path2) {
|
|
28699
|
+
return statSync6(path2, { throwIfNoEntry: false });
|
|
28700
|
+
}
|
|
28701
|
+
async function writeAll2(out, bytes) {
|
|
28702
|
+
let written2 = 0;
|
|
28703
|
+
while (written2 < bytes.length) {
|
|
28704
|
+
const { bytesWritten } = await out.write(
|
|
28705
|
+
bytes,
|
|
28706
|
+
written2,
|
|
28707
|
+
bytes.length - written2
|
|
28708
|
+
);
|
|
28709
|
+
written2 += bytesWritten;
|
|
28710
|
+
}
|
|
28711
|
+
}
|
|
28712
|
+
async function copyRange(path2, out, from, to, signal) {
|
|
28713
|
+
if (to <= from) return;
|
|
28714
|
+
const source = await open3(path2, "r");
|
|
28715
|
+
try {
|
|
28716
|
+
const buffer = Buffer.allocUnsafe(
|
|
28717
|
+
Math.min(BODY_PURGE_SLICE_BYTES, to - from)
|
|
28718
|
+
);
|
|
28719
|
+
for (let at2 = from; at2 < to; ) {
|
|
28720
|
+
signal?.throwIfAborted();
|
|
28721
|
+
const { bytesRead } = await source.read(
|
|
28722
|
+
buffer,
|
|
28723
|
+
0,
|
|
28724
|
+
Math.min(buffer.length, to - at2),
|
|
28725
|
+
at2
|
|
28726
|
+
);
|
|
28727
|
+
if (bytesRead <= 0) return;
|
|
28728
|
+
await writeAll2(out, buffer.subarray(0, bytesRead));
|
|
28729
|
+
at2 += bytesRead;
|
|
28730
|
+
}
|
|
28731
|
+
} finally {
|
|
28732
|
+
await source.close();
|
|
28733
|
+
}
|
|
28734
|
+
}
|
|
28735
|
+
function readRangeSync(path2, from, to) {
|
|
28736
|
+
const buffer = Buffer.alloc(Math.max(0, to - from));
|
|
28737
|
+
if (buffer.length === 0) return buffer;
|
|
28738
|
+
const fd2 = openSync6(path2, "r");
|
|
28739
|
+
try {
|
|
28740
|
+
let filled = 0;
|
|
28741
|
+
while (filled < buffer.length) {
|
|
28742
|
+
const read2 = readSync3(
|
|
28743
|
+
fd2,
|
|
28744
|
+
buffer,
|
|
28745
|
+
filled,
|
|
28746
|
+
buffer.length - filled,
|
|
28747
|
+
from + filled
|
|
28748
|
+
);
|
|
28749
|
+
if (read2 <= 0) break;
|
|
28750
|
+
filled += read2;
|
|
28751
|
+
}
|
|
28752
|
+
return buffer.subarray(0, filled);
|
|
28753
|
+
} finally {
|
|
28754
|
+
closeSync6(fd2);
|
|
28755
|
+
}
|
|
28756
|
+
}
|
|
28757
|
+
var BODY_READ_SLICE, BODY_DROP_SLICE_BYTES, BODY_DROP_SCANS, BODY_PURGE_SLICE_BYTES, BODY_PURGE_SCANS, BODY_PURGE_CATCH_UPS, NEWLINE, EVENT_TAIL_WINDOW, WalRecoveryConflict, Wal;
|
|
28580
28758
|
var init_wal = __esm({
|
|
28581
28759
|
"../../packages/tacho/src/host/wal.ts"() {
|
|
28582
28760
|
"use strict";
|
|
@@ -28586,6 +28764,9 @@ var init_wal = __esm({
|
|
|
28586
28764
|
BODY_READ_SLICE = 32;
|
|
28587
28765
|
BODY_DROP_SLICE_BYTES = 1024 * 1024;
|
|
28588
28766
|
BODY_DROP_SCANS = 3;
|
|
28767
|
+
BODY_PURGE_SLICE_BYTES = 1024 * 1024;
|
|
28768
|
+
BODY_PURGE_SCANS = 3;
|
|
28769
|
+
BODY_PURGE_CATCH_UPS = 3;
|
|
28589
28770
|
NEWLINE = 10;
|
|
28590
28771
|
EVENT_TAIL_WINDOW = 16 * 1024;
|
|
28591
28772
|
WalRecoveryConflict = class extends Error {
|
|
@@ -28685,6 +28866,18 @@ var init_wal = __esm({
|
|
|
28685
28866
|
* WAL has ever opened. See `flush` for why this exists.
|
|
28686
28867
|
*/
|
|
28687
28868
|
dirtyPaths = /* @__PURE__ */ new Set();
|
|
28869
|
+
/**
|
|
28870
|
+
* The awaited body sweeps running now, one entry per session scan
|
|
28871
|
+
* (`purgeBodiesOutsideMandateAsync`). Every write to a body file other than
|
|
28872
|
+
* an append marks the entries for its session, so a scan whose bytes moved
|
|
28873
|
+
* under it does not rename its copy over the file.
|
|
28874
|
+
*/
|
|
28875
|
+
bodyWatches = /* @__PURE__ */ new Set();
|
|
28876
|
+
/**
|
|
28877
|
+
* The temporary files those sweeps are writing. `compact` removes a
|
|
28878
|
+
* temporary file a crashed rewrite left, and must not remove one of these.
|
|
28879
|
+
*/
|
|
28880
|
+
liveTemps = /* @__PURE__ */ new Set();
|
|
28688
28881
|
fileFor(sessionUuid2) {
|
|
28689
28882
|
return join18(this.dir, `${sessionUuid2}.ndjson`);
|
|
28690
28883
|
}
|
|
@@ -29407,6 +29600,7 @@ ${lines.join("\n")}
|
|
|
29407
29600
|
if (next > 0) await new Promise((resolve26) => setImmediate(resolve26));
|
|
29408
29601
|
const slice = this.blankSlice(path2, found, next, idems);
|
|
29409
29602
|
if (slice === void 0) break;
|
|
29603
|
+
if (slice.blanked > 0) this.bodyRewritten(session);
|
|
29410
29604
|
blanked += slice.blanked;
|
|
29411
29605
|
moved ||= slice.moved;
|
|
29412
29606
|
next = slice.next;
|
|
@@ -29663,6 +29857,7 @@ ${lines.join("\n")}
|
|
|
29663
29857
|
this.dirtyPaths.add(path2);
|
|
29664
29858
|
}
|
|
29665
29859
|
this.bodyIndexes.invalidate(sessionUuid2);
|
|
29860
|
+
this.bodyRewritten(sessionUuid2);
|
|
29666
29861
|
return cut;
|
|
29667
29862
|
}
|
|
29668
29863
|
/**
|
|
@@ -29703,11 +29898,11 @@ ${lines.join("\n")}
|
|
|
29703
29898
|
*eventsBackward(sessionUuid2) {
|
|
29704
29899
|
const path2 = this.fileFor(sessionUuid2);
|
|
29705
29900
|
if (!existsSync12(path2)) return;
|
|
29706
|
-
|
|
29707
|
-
|
|
29708
|
-
|
|
29709
|
-
|
|
29710
|
-
|
|
29901
|
+
for (const line of readLinesBackward(
|
|
29902
|
+
path2,
|
|
29903
|
+
statSync6(path2).size,
|
|
29904
|
+
EVENT_TAIL_WINDOW
|
|
29905
|
+
)) {
|
|
29711
29906
|
if (line.text.trim().length === 0) continue;
|
|
29712
29907
|
let event;
|
|
29713
29908
|
try {
|
|
@@ -29849,6 +30044,17 @@ ${lines.join("\n")}
|
|
|
29849
30044
|
firstUnshippedAt(sessionUuid2, through) {
|
|
29850
30045
|
const known = this.firstUnshipped.get(sessionUuid2);
|
|
29851
30046
|
if (known?.through === through) return known.ts;
|
|
30047
|
+
const waiting = this.lastSeqOf(sessionUuid2) - through;
|
|
30048
|
+
if (!this.resume.has(sessionUuid2) && waiting > 0 && waiting <= through) {
|
|
30049
|
+
let first;
|
|
30050
|
+
for (const event of this.eventsBackward(sessionUuid2)) {
|
|
30051
|
+
if (event.seq <= through) break;
|
|
30052
|
+
first = event;
|
|
30053
|
+
}
|
|
30054
|
+
if (first === void 0) return void 0;
|
|
30055
|
+
this.firstUnshipped.set(sessionUuid2, { through, ts: first.ts });
|
|
30056
|
+
return first.ts;
|
|
30057
|
+
}
|
|
29852
30058
|
for (const first of this.eventsAfterShipped(
|
|
29853
30059
|
sessionUuid2,
|
|
29854
30060
|
EVENT_TAIL_WINDOW
|
|
@@ -29989,27 +30195,241 @@ ${lines.join("\n")}
|
|
|
29989
30195
|
* that withholds a body from a shipment. See `purgeBodiesNarrowedOut` in
|
|
29990
30196
|
* the daemon, which calls this when a replacement bundle verifies and
|
|
29991
30197
|
* narrows the clause.
|
|
30198
|
+
*
|
|
30199
|
+
* This reads every event file and every body file on the synchronous path,
|
|
30200
|
+
* which ADR-231 rules out on the daemon's thread. The daemon calls
|
|
30201
|
+
* `purgeBodiesOutsideMandateAsync`. It calls this only when it cannot record
|
|
30202
|
+
* the purge it owes, the one case where the erase has to finish before the
|
|
30203
|
+
* narrowed bundle is cached.
|
|
29992
30204
|
*/
|
|
29993
30205
|
purgeBodiesOutsideMandate(retention) {
|
|
29994
30206
|
let purged = 0;
|
|
29995
|
-
const
|
|
29996
|
-
|
|
29997
|
-
|
|
29998
|
-
|
|
29999
|
-
|
|
30207
|
+
for (const session of this.sessionsToPurge())
|
|
30208
|
+
purged += this.purgeSessionSync(session, retention);
|
|
30209
|
+
return purged;
|
|
30210
|
+
}
|
|
30211
|
+
/**
|
|
30212
|
+
* The same sweep, without holding the daemon's thread (#5176, ADR-231).
|
|
30213
|
+
* Every read is awaited, and a turn of the event loop separates two
|
|
30214
|
+
* sessions, so a hook or a proxied model call waits for one read and not
|
|
30215
|
+
* for the sweep.
|
|
30216
|
+
*
|
|
30217
|
+
* Each session is rewritten the way `rewriteBodies` rewrites it: the lines
|
|
30218
|
+
* kept go to a temporary file, and a rename puts it over the body file. A
|
|
30219
|
+
* crash part way leaves the old file whole, and the caller's record of the
|
|
30220
|
+
* purge it owes runs the sweep again. Hooks append to the file while the
|
|
30221
|
+
* scan awaits its reads, and three rules keep those appends:
|
|
30222
|
+
*
|
|
30223
|
+
* - The scan measures the body file and the event file in one synchronous
|
|
30224
|
+
* stretch, and reads each only up to that size. `append` writes a body
|
|
30225
|
+
* and then its event in one synchronous stretch too, so every body the
|
|
30226
|
+
* scan reads has its event in the part of the event file the scan reads,
|
|
30227
|
+
* or is a crash orphan. A body appended later is never judged an orphan.
|
|
30228
|
+
* - Bytes appended after that moment go to the new file as they are. They
|
|
30229
|
+
* were recorded under the mandate in force when they were appended, and
|
|
30230
|
+
* the daemon caches the narrowed mandate before it starts this sweep.
|
|
30231
|
+
* - The rename happens in one synchronous stretch, after a last check. When
|
|
30232
|
+
* the file was replaced, cut short, or written other than by an append
|
|
30233
|
+
* while the scan read it (`dropBodiesAsync` blanks lines in place), the
|
|
30234
|
+
* copy is thrown away and the session is scanned again. After
|
|
30235
|
+
* `BODY_PURGE_SCANS` scans the session goes through the synchronous sweep.
|
|
30236
|
+
*
|
|
30237
|
+
* The copy is synced to disk with an awaited call before that stretch, so
|
|
30238
|
+
* the stretch copies and syncs only what was appended since, about
|
|
30239
|
+
* `BODY_PURGE_SLICE_BYTES` at most.
|
|
30240
|
+
*/
|
|
30241
|
+
async purgeBodiesOutsideMandateAsync(retention, options = {}) {
|
|
30242
|
+
const { signal } = options;
|
|
30243
|
+
let purged = 0;
|
|
30244
|
+
for (const session of this.sessionsToPurge()) {
|
|
30245
|
+
await new Promise((resolve26) => setImmediate(resolve26));
|
|
30246
|
+
signal?.throwIfAborted();
|
|
30247
|
+
await options.beforeSession?.(session);
|
|
30248
|
+
signal?.throwIfAborted();
|
|
30000
30249
|
if (!existsSync12(this.bodyFileFor(session))) continue;
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
|
|
30005
|
-
);
|
|
30006
|
-
purged += this.rewriteBodies(
|
|
30007
|
-
session,
|
|
30008
|
-
(stored) => this.keeps(stored, kindOf2, retention)
|
|
30009
|
-
);
|
|
30250
|
+
let swept = "moved";
|
|
30251
|
+
for (let scan = 0; scan < BODY_PURGE_SCANS && swept === "moved"; scan++)
|
|
30252
|
+
swept = await this.purgeSessionAsync(session, retention, signal);
|
|
30253
|
+
purged += swept === "moved" ? this.purgeSessionSync(session, retention) : swept;
|
|
30010
30254
|
}
|
|
30011
30255
|
return purged;
|
|
30012
30256
|
}
|
|
30257
|
+
/**
|
|
30258
|
+
* Every session that has an event file OR a body file. `sessions()` lists
|
|
30259
|
+
* `.ndjson` only, so a crash between `append`'s body write and its first
|
|
30260
|
+
* event write leaves a `<uuid>.bodies.jsonl` with no `.ndjson` beside it,
|
|
30261
|
+
* invisible to a sweep that walked `sessions()` and to `compact`, which
|
|
30262
|
+
* does. Those bytes would outlive every mechanism meant to remove them.
|
|
30263
|
+
*/
|
|
30264
|
+
sessionsToPurge() {
|
|
30265
|
+
return /* @__PURE__ */ new Set([...this.sessions(), ...this.sessionsWithBodies()]);
|
|
30266
|
+
}
|
|
30267
|
+
/** One session of `purgeBodiesOutsideMandate`, read and rewritten at once. */
|
|
30268
|
+
purgeSessionSync(session, retention) {
|
|
30269
|
+
if (!existsSync12(this.bodyFileFor(session))) return 0;
|
|
30270
|
+
const kindOf2 = new Map(
|
|
30271
|
+
this.read(session).map(
|
|
30272
|
+
(event) => [event.event_id_idem, event.kind]
|
|
30273
|
+
)
|
|
30274
|
+
);
|
|
30275
|
+
return this.rewriteBodies(
|
|
30276
|
+
session,
|
|
30277
|
+
(stored) => this.keeps(stored, kindOf2, retention)
|
|
30278
|
+
);
|
|
30279
|
+
}
|
|
30280
|
+
/**
|
|
30281
|
+
* One scan of `purgeBodiesOutsideMandateAsync` over one session. Answers
|
|
30282
|
+
* how many lines went, or `moved` when the file changed under the scan
|
|
30283
|
+
* other than by an append, in which case nothing was renamed.
|
|
30284
|
+
*/
|
|
30285
|
+
async purgeSessionAsync(session, retention, signal) {
|
|
30286
|
+
const path2 = this.bodyFileFor(session);
|
|
30287
|
+
const start = statIfExists2(path2);
|
|
30288
|
+
if (start === void 0) return 0;
|
|
30289
|
+
const eventEnd = statIfExists2(this.fileFor(session))?.size ?? 0;
|
|
30290
|
+
const watch2 = { session, moved: false };
|
|
30291
|
+
this.bodyWatches.add(watch2);
|
|
30292
|
+
const tmp = `${path2}.${randomUUID()}.tmp`;
|
|
30293
|
+
let out;
|
|
30294
|
+
try {
|
|
30295
|
+
const kindOf2 = await this.eventKindsUpTo(session, eventEnd, signal);
|
|
30296
|
+
let cut = 0;
|
|
30297
|
+
let kept = 0;
|
|
30298
|
+
let held = [];
|
|
30299
|
+
let heldBytes = 0;
|
|
30300
|
+
const writeHeld = async (to) => {
|
|
30301
|
+
if (heldBytes === 0) return;
|
|
30302
|
+
await writeAll2(to, Buffer.concat(held, heldBytes));
|
|
30303
|
+
held = [];
|
|
30304
|
+
heldBytes = 0;
|
|
30305
|
+
};
|
|
30306
|
+
for await (const line of readLinesFromAsync(path2, 0, start.size)) {
|
|
30307
|
+
signal?.throwIfAborted();
|
|
30308
|
+
if (line.text.trim().length === 0) continue;
|
|
30309
|
+
if (this.keeps(parseStoredBody(line.text), kindOf2, retention)) {
|
|
30310
|
+
kept += 1;
|
|
30311
|
+
if (out === void 0) continue;
|
|
30312
|
+
const bytes = Buffer.from(`${line.text}
|
|
30313
|
+
`);
|
|
30314
|
+
held.push(bytes);
|
|
30315
|
+
heldBytes += bytes.length;
|
|
30316
|
+
if (heldBytes >= BODY_PURGE_SLICE_BYTES) await writeHeld(out);
|
|
30317
|
+
continue;
|
|
30318
|
+
}
|
|
30319
|
+
cut += 1;
|
|
30320
|
+
if (out === void 0) {
|
|
30321
|
+
this.liveTemps.add(tmp);
|
|
30322
|
+
out = await open3(tmp, "wx", 384);
|
|
30323
|
+
await copyRange(path2, out, 0, line.offset, signal);
|
|
30324
|
+
}
|
|
30325
|
+
}
|
|
30326
|
+
if (out === void 0) return watch2.moved ? "moved" : 0;
|
|
30327
|
+
await writeHeld(out);
|
|
30328
|
+
let copied = start.size;
|
|
30329
|
+
for (let round = 0; round < BODY_PURGE_CATCH_UPS; round += 1) {
|
|
30330
|
+
const size = statIfExists2(path2)?.size;
|
|
30331
|
+
if (size === void 0 || size - copied <= BODY_PURGE_SLICE_BYTES)
|
|
30332
|
+
break;
|
|
30333
|
+
await copyRange(path2, out, copied, size, signal);
|
|
30334
|
+
copied = size;
|
|
30335
|
+
}
|
|
30336
|
+
await out.sync();
|
|
30337
|
+
await out.close();
|
|
30338
|
+
out = void 0;
|
|
30339
|
+
signal?.throwIfAborted();
|
|
30340
|
+
if (watch2.moved) return "moved";
|
|
30341
|
+
return this.commitPurge(session, tmp, {
|
|
30342
|
+
start,
|
|
30343
|
+
copied,
|
|
30344
|
+
keptAny: kept > 0 || copied > start.size,
|
|
30345
|
+
cut
|
|
30346
|
+
});
|
|
30347
|
+
} catch (error) {
|
|
30348
|
+
if (error.code === "ENOENT" && !existsSync12(path2))
|
|
30349
|
+
return 0;
|
|
30350
|
+
throw error;
|
|
30351
|
+
} finally {
|
|
30352
|
+
this.bodyWatches.delete(watch2);
|
|
30353
|
+
if (out !== void 0) await out.close().catch(() => void 0);
|
|
30354
|
+
if (existsSync12(tmp)) unlinkSync9(tmp);
|
|
30355
|
+
this.liveTemps.delete(tmp);
|
|
30356
|
+
}
|
|
30357
|
+
}
|
|
30358
|
+
/**
|
|
30359
|
+
* The kind of every event in the first `end` bytes of a session's event
|
|
30360
|
+
* file, by event id, read with awaited reads. A line that does not parse is
|
|
30361
|
+
* reported and skipped, as `read` does. A line cut off at `end` was torn by
|
|
30362
|
+
* a crash, since `append` ends every write with a newline, and is skipped.
|
|
30363
|
+
*/
|
|
30364
|
+
async eventKindsUpTo(session, end, signal) {
|
|
30365
|
+
const kindOf2 = /* @__PURE__ */ new Map();
|
|
30366
|
+
if (end === 0) return kindOf2;
|
|
30367
|
+
for await (const line of readLinesFromAsync(
|
|
30368
|
+
this.fileFor(session),
|
|
30369
|
+
0,
|
|
30370
|
+
end
|
|
30371
|
+
)) {
|
|
30372
|
+
signal?.throwIfAborted();
|
|
30373
|
+
if (!line.terminated || line.text.trim().length === 0) continue;
|
|
30374
|
+
try {
|
|
30375
|
+
const event = parseEventLine(line.text);
|
|
30376
|
+
kindOf2.set(event.event_id_idem, event.kind);
|
|
30377
|
+
} catch (error) {
|
|
30378
|
+
this.reportEventParseFailure({
|
|
30379
|
+
session_uuid: session,
|
|
30380
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
30381
|
+
});
|
|
30382
|
+
}
|
|
30383
|
+
}
|
|
30384
|
+
return kindOf2;
|
|
30385
|
+
}
|
|
30386
|
+
/**
|
|
30387
|
+
* The rename of `purgeSessionAsync`, in one synchronous stretch, so nothing
|
|
30388
|
+
* else can write the body file between the check and the rename. Copies
|
|
30389
|
+
* what was appended since `copied`, syncs it, and puts the copy over the
|
|
30390
|
+
* file, or removes the file when nothing in it is left.
|
|
30391
|
+
*/
|
|
30392
|
+
commitPurge(session, tmp, scan) {
|
|
30393
|
+
const path2 = this.bodyFileFor(session);
|
|
30394
|
+
const now = statIfExists2(path2);
|
|
30395
|
+
if (now === void 0) return 0;
|
|
30396
|
+
if (now.ino !== scan.start.ino || now.dev !== scan.start.dev || now.size < scan.copied)
|
|
30397
|
+
return "moved";
|
|
30398
|
+
const tail = readRangeSync(path2, scan.copied, now.size);
|
|
30399
|
+
if (!scan.keptAny && tail.toString("utf8").trim().length === 0) {
|
|
30400
|
+
unlinkSync9(path2);
|
|
30401
|
+
} else {
|
|
30402
|
+
const fd2 = openSync6(tmp, "r+");
|
|
30403
|
+
try {
|
|
30404
|
+
let written2 = 0;
|
|
30405
|
+
const at2 = fstatSync(fd2).size;
|
|
30406
|
+
while (written2 < tail.length)
|
|
30407
|
+
written2 += writeSync4(
|
|
30408
|
+
fd2,
|
|
30409
|
+
tail,
|
|
30410
|
+
written2,
|
|
30411
|
+
tail.length - written2,
|
|
30412
|
+
at2 + written2
|
|
30413
|
+
);
|
|
30414
|
+
fdatasyncSync(fd2);
|
|
30415
|
+
} finally {
|
|
30416
|
+
closeSync6(fd2);
|
|
30417
|
+
}
|
|
30418
|
+
renameSync3(tmp, path2);
|
|
30419
|
+
}
|
|
30420
|
+
this.bodyIndexes.invalidate(session);
|
|
30421
|
+
this.bodyRewritten(session);
|
|
30422
|
+
return scan.cut;
|
|
30423
|
+
}
|
|
30424
|
+
/**
|
|
30425
|
+
* Tell every awaited sweep of this session that its body file changed
|
|
30426
|
+
* other than by an append. Each write that cuts, blanks, or replaces body
|
|
30427
|
+
* bytes calls this in the same synchronous stretch as the write.
|
|
30428
|
+
*/
|
|
30429
|
+
bodyRewritten(session) {
|
|
30430
|
+
for (const watch2 of this.bodyWatches)
|
|
30431
|
+
if (watch2.session === session) watch2.moved = true;
|
|
30432
|
+
}
|
|
30013
30433
|
/**
|
|
30014
30434
|
* Whether one stored body survives this mandate. Three answers, each for a
|
|
30015
30435
|
* reason:
|
|
@@ -30027,7 +30447,9 @@ ${lines.join("\n")}
|
|
|
30027
30447
|
* the two writes and no event will ever arrive for it. Keeping it kept
|
|
30028
30448
|
* prompt or tool bytes that no mandate covers and that nothing would
|
|
30029
30449
|
* ever ship, delete or compact, because every one of those paths starts
|
|
30030
|
-
* from the event.
|
|
30450
|
+
* from the event. The awaited sweep does let appends land while it reads,
|
|
30451
|
+
* so it judges only the bodies written before it measured the files, and
|
|
30452
|
+
* their events are all in the part of the event file it reads.
|
|
30031
30453
|
* - Otherwise the class comes from the event's kind and the one retention
|
|
30032
30454
|
* gate answers. A kind the table does not name has no class, so no mandate
|
|
30033
30455
|
* can cover it and the body goes.
|
|
@@ -30089,6 +30511,7 @@ ${lines.join("\n")}
|
|
|
30089
30511
|
if (kept === 0) unlinkSync9(path2);
|
|
30090
30512
|
else renameSync3(tmp, path2);
|
|
30091
30513
|
this.bodyIndexes.invalidate(sessionUuid2);
|
|
30514
|
+
this.bodyRewritten(sessionUuid2);
|
|
30092
30515
|
return cut;
|
|
30093
30516
|
} finally {
|
|
30094
30517
|
if (existsSync12(tmp)) unlinkSync9(tmp);
|
|
@@ -30116,6 +30539,7 @@ ${lines.join("\n")}
|
|
|
30116
30539
|
`^${uuid}\\.bodies\\.jsonl\\.${uuid}\\.tmp$`
|
|
30117
30540
|
);
|
|
30118
30541
|
for (const name of readdirSync7(this.dir)) {
|
|
30542
|
+
if (this.liveTemps.has(join18(this.dir, name))) continue;
|
|
30119
30543
|
if (abandonedRewrite.test(name)) {
|
|
30120
30544
|
try {
|
|
30121
30545
|
unlinkSync9(join18(this.dir, name));
|
|
@@ -30199,6 +30623,7 @@ ${lines.join("\n")}
|
|
|
30199
30623
|
const path2 = this.bodyFileFor(session);
|
|
30200
30624
|
if (existsSync12(path2)) unlinkSync9(path2);
|
|
30201
30625
|
this.bodyIndexes.invalidate(session);
|
|
30626
|
+
this.bodyRewritten(session);
|
|
30202
30627
|
return true;
|
|
30203
30628
|
} catch (error) {
|
|
30204
30629
|
this.bodyFailure(session, "cleanup", error);
|
|
@@ -30551,8 +30976,12 @@ function daemonServiceSpec(daemonCommand, deps) {
|
|
|
30551
30976
|
command: daemonCommand,
|
|
30552
30977
|
env: {
|
|
30553
30978
|
...deps.env["TACHO_HOME"] !== void 0 ? { TACHO_HOME: deps.env["TACHO_HOME"] } : {},
|
|
30554
|
-
// The harness homes
|
|
30555
|
-
//
|
|
30979
|
+
// The harness homes this shell moved. Each collector reads its agent's
|
|
30980
|
+
// harness files where that agent's host.json recorded them at enroll
|
|
30981
|
+
// (`harness_files`), so these decide nothing for an agent with a
|
|
30982
|
+
// record. They stay for an agent enrolled before the record existed.
|
|
30983
|
+
// One service serves every agent, so they come from whichever shell
|
|
30984
|
+
// installed it last (#5409).
|
|
30556
30985
|
...Object.fromEntries(
|
|
30557
30986
|
HARNESS_HOME_VARS.flatMap((key) => {
|
|
30558
30987
|
const value = deps.env[key];
|
|
@@ -43081,7 +43510,11 @@ async function renewStaticToken(harness, deps) {
|
|
|
43081
43510
|
const label2 = TACHO_HARNESS_LABELS[harness];
|
|
43082
43511
|
if (deps.host.host_status !== "active" || !deps.inCustody(provider, harness))
|
|
43083
43512
|
return "skipped";
|
|
43084
|
-
const dirs =
|
|
43513
|
+
const dirs = {
|
|
43514
|
+
...deps.stellaHome !== void 0 ? { stellaHome: deps.stellaHome } : {},
|
|
43515
|
+
...deps.codexHome !== void 0 ? { codexHome: deps.codexHome } : {},
|
|
43516
|
+
...deps.claudeConfigDir !== void 0 ? { claudeConfigDir: deps.claudeConfigDir } : {}
|
|
43517
|
+
};
|
|
43085
43518
|
let brokered = false;
|
|
43086
43519
|
try {
|
|
43087
43520
|
brokered = (await readModelCredentialState({
|
|
@@ -44021,8 +44454,33 @@ var init_git_facts = __esm({
|
|
|
44021
44454
|
|
|
44022
44455
|
// ../../packages/tacho/src/collector/work-order-autostart.ts
|
|
44023
44456
|
import { spawn as spawn7 } from "node:child_process";
|
|
44024
|
-
import { closeSync as closeSync7, existsSync as existsSync21, openSync as openSync7 } from "node:fs";
|
|
44457
|
+
import { closeSync as closeSync7, existsSync as existsSync21, openSync as openSync7, readSync as readSync4, statSync as statSync12 } from "node:fs";
|
|
44025
44458
|
import { dirname as dirname20, join as join36 } from "node:path";
|
|
44459
|
+
function lastLogLine(path2) {
|
|
44460
|
+
let fd2;
|
|
44461
|
+
try {
|
|
44462
|
+
const size = statSync12(path2).size;
|
|
44463
|
+
const length = Math.min(size, 4096);
|
|
44464
|
+
const buffer = Buffer.alloc(length);
|
|
44465
|
+
fd2 = openSync7(path2, "r");
|
|
44466
|
+
readSync4(fd2, buffer, 0, length, size - length);
|
|
44467
|
+
const line = buffer.toString("utf8").replace(TERMINAL_CODE, "").split(/\r?\n/).map((text5) => text5.trim()).filter((text5) => text5.length > 0).pop();
|
|
44468
|
+
if (line === void 0) return void 0;
|
|
44469
|
+
return line.length > EXIT_REPORT_QUOTE ? `${line.slice(0, EXIT_REPORT_QUOTE - 1)}\u2026` : line;
|
|
44470
|
+
} catch {
|
|
44471
|
+
return void 0;
|
|
44472
|
+
} finally {
|
|
44473
|
+
if (fd2 !== void 0) {
|
|
44474
|
+
try {
|
|
44475
|
+
closeSync7(fd2);
|
|
44476
|
+
} catch {
|
|
44477
|
+
}
|
|
44478
|
+
}
|
|
44479
|
+
}
|
|
44480
|
+
}
|
|
44481
|
+
function exitPhrase(exit) {
|
|
44482
|
+
return exit.signal !== null ? `ended on ${exit.signal}` : `exited with code ${String(exit.code)}`;
|
|
44483
|
+
}
|
|
44026
44484
|
function asError(error) {
|
|
44027
44485
|
return error instanceof Error ? error : new Error(String(error));
|
|
44028
44486
|
}
|
|
@@ -44037,6 +44495,10 @@ function isPlainBranchName(name) {
|
|
|
44037
44495
|
function createWorkOrderAutostart(deps) {
|
|
44038
44496
|
const { paths, log } = deps;
|
|
44039
44497
|
const isAlive = deps.isAlive ?? processIsAlive;
|
|
44498
|
+
const wait = deps.wait ?? ((ms) => new Promise((done) => {
|
|
44499
|
+
setTimeout(done, ms).unref();
|
|
44500
|
+
}));
|
|
44501
|
+
const sessions = /* @__PURE__ */ new Set();
|
|
44040
44502
|
const spawnHarness = deps.spawn ?? spawnDetached;
|
|
44041
44503
|
let searchPath;
|
|
44042
44504
|
const pathForHarness = () => {
|
|
@@ -44222,7 +44684,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44222
44684
|
`work order ${id2}: could not clear its running mark: ${asError(error).message}`
|
|
44223
44685
|
);
|
|
44224
44686
|
}
|
|
44225
|
-
const ended = exit === void 0 ? "ended while the daemon was stopped" : "never" in exit ? `never started (${exit.never})` :
|
|
44687
|
+
const ended = exit === void 0 ? "ended while the daemon was stopped" : "never" in exit ? `never started (${exit.never})` : exitPhrase(exit);
|
|
44226
44688
|
const { worktree, root, branch, base_sha: base2 } = mark;
|
|
44227
44689
|
if (worktree === void 0 || !existsSync21(worktree)) {
|
|
44228
44690
|
log(`work order ${id2}: the harness ${ended}`);
|
|
@@ -44276,13 +44738,28 @@ function createWorkOrderAutostart(deps) {
|
|
|
44276
44738
|
`work order ${id2}: the harness ${ended} and left nothing that is not on a remote, so its worktree is removed${mark.log !== void 0 ? `. Its output is in ${mark.log}` : ""}.`
|
|
44277
44739
|
);
|
|
44278
44740
|
}
|
|
44279
|
-
function
|
|
44741
|
+
async function reportExit(id2, binary, exit, logPath) {
|
|
44742
|
+
if (sessions.has(id2)) return;
|
|
44743
|
+
await wait(EXIT_REPORT_GRACE_MS);
|
|
44744
|
+
if (sessions.has(id2)) return;
|
|
44745
|
+
const said = lastLogLine(logPath);
|
|
44746
|
+
const reason3 = `${binary} ${exitPhrase(exit)} before it opened a run.${said !== void 0 ? ` Its last output: ${said}` : ""} The full output is in ${logPath} on this machine.`;
|
|
44747
|
+
const failed3 = await refuseWorkOrder(deps.client, id2, reason3.slice(0, 512));
|
|
44748
|
+
log(
|
|
44749
|
+
failed3 === void 0 ? `work order ${id2}: ${reason3} Oxagen ended the send.` : `work order ${id2}: ${reason3} Oxagen kept the send (${failed3}).`
|
|
44750
|
+
);
|
|
44751
|
+
}
|
|
44752
|
+
function watch2(id2, binary, workspace, exited) {
|
|
44280
44753
|
void exited.then((exit) => {
|
|
44281
|
-
const done =
|
|
44754
|
+
const done = Promise.all([
|
|
44755
|
+
cleanUp({ work_order: id2, ...workspace }, exit),
|
|
44756
|
+
reportExit(id2, binary, exit, workspace.log)
|
|
44757
|
+
]).then(() => void 0).catch((error) => {
|
|
44282
44758
|
log(
|
|
44283
44759
|
`work order ${id2}: cleanup after the harness failed: ${asError(error).message}`
|
|
44284
44760
|
);
|
|
44285
44761
|
}).finally(() => {
|
|
44762
|
+
sessions.delete(id2);
|
|
44286
44763
|
cleanups.delete(done);
|
|
44287
44764
|
});
|
|
44288
44765
|
cleanups.add(done);
|
|
@@ -44292,8 +44769,8 @@ function createWorkOrderAutostart(deps) {
|
|
|
44292
44769
|
const id2 = order.work_order;
|
|
44293
44770
|
const running = runningWorkOrder(paths, id2, isAlive);
|
|
44294
44771
|
if (running !== void 0) return;
|
|
44295
|
-
const
|
|
44296
|
-
if (
|
|
44772
|
+
const wait2 = retry.get(id2);
|
|
44773
|
+
if (wait2 !== void 0 && deps.now() < wait2.at) return;
|
|
44297
44774
|
const outcome = await claimForStart(deps.client, deps.host(), id2);
|
|
44298
44775
|
if (outcome.kind === "refused" && outcome.final) {
|
|
44299
44776
|
log(
|
|
@@ -44389,7 +44866,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44389
44866
|
log(
|
|
44390
44867
|
`work order ${id2} for ${claim.work_order.item_number} started ${binary} (process ${started.pid}) in ${workspace.worktree}; output goes to ${workspace.log}`
|
|
44391
44868
|
);
|
|
44392
|
-
watch2(id2, workspace, started.exited);
|
|
44869
|
+
watch2(id2, binary, workspace, started.exited);
|
|
44393
44870
|
}
|
|
44394
44871
|
async function runPass() {
|
|
44395
44872
|
let orders;
|
|
@@ -44438,6 +44915,9 @@ function createWorkOrderAutostart(deps) {
|
|
|
44438
44915
|
}
|
|
44439
44916
|
}
|
|
44440
44917
|
},
|
|
44918
|
+
noteSession: (workOrder) => {
|
|
44919
|
+
sessions.add(workOrder);
|
|
44920
|
+
},
|
|
44441
44921
|
idle: async () => {
|
|
44442
44922
|
while (pass2 !== void 0 || cleanups.size > 0) {
|
|
44443
44923
|
await Promise.allSettled([pass2, ...cleanups]);
|
|
@@ -44445,7 +44925,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44445
44925
|
}
|
|
44446
44926
|
};
|
|
44447
44927
|
}
|
|
44448
|
-
var SLOW_GIT_MS, RETRY_MIN_MS, RETRY_MAX_MS, spawnDetached;
|
|
44928
|
+
var SLOW_GIT_MS, RETRY_MIN_MS, RETRY_MAX_MS, EXIT_REPORT_GRACE_MS, TERMINAL_CODE, EXIT_REPORT_QUOTE, spawnDetached;
|
|
44449
44929
|
var init_work_order_autostart = __esm({
|
|
44450
44930
|
"../../packages/tacho/src/collector/work-order-autostart.ts"() {
|
|
44451
44931
|
"use strict";
|
|
@@ -44459,6 +44939,12 @@ var init_work_order_autostart = __esm({
|
|
|
44459
44939
|
SLOW_GIT_MS = 12e4;
|
|
44460
44940
|
RETRY_MIN_MS = 15e3;
|
|
44461
44941
|
RETRY_MAX_MS = 5 * 6e4;
|
|
44942
|
+
EXIT_REPORT_GRACE_MS = 6e4;
|
|
44943
|
+
TERMINAL_CODE = new RegExp(
|
|
44944
|
+
`${String.fromCharCode(27)}\\[[0-9;?]*[A-Za-z]`,
|
|
44945
|
+
"g"
|
|
44946
|
+
);
|
|
44947
|
+
EXIT_REPORT_QUOTE = 240;
|
|
44462
44948
|
spawnDetached = (command2, args, options) => new Promise((resolve26) => {
|
|
44463
44949
|
let fd2;
|
|
44464
44950
|
try {
|
|
@@ -44468,10 +44954,10 @@ var init_work_order_autostart = __esm({
|
|
|
44468
44954
|
resolve26({ ok: false, error: asError(error) });
|
|
44469
44955
|
return;
|
|
44470
44956
|
}
|
|
44471
|
-
let
|
|
44957
|
+
let open7 = true;
|
|
44472
44958
|
const close = () => {
|
|
44473
|
-
if (!
|
|
44474
|
-
|
|
44959
|
+
if (!open7) return;
|
|
44960
|
+
open7 = false;
|
|
44475
44961
|
try {
|
|
44476
44962
|
closeSync7(fd2);
|
|
44477
44963
|
} catch {
|
|
@@ -44559,7 +45045,7 @@ import { createReadStream } from "node:fs";
|
|
|
44559
45045
|
import {
|
|
44560
45046
|
lstat,
|
|
44561
45047
|
mkdir,
|
|
44562
|
-
open as
|
|
45048
|
+
open as open4,
|
|
44563
45049
|
readdir,
|
|
44564
45050
|
readlink,
|
|
44565
45051
|
rename,
|
|
@@ -44612,7 +45098,7 @@ async function contentHash(absolutePath, kind, keep) {
|
|
|
44612
45098
|
const temp2 = join37(keep.dir, `.partial-${randomUUID3()}`);
|
|
44613
45099
|
copy = {
|
|
44614
45100
|
temp: temp2,
|
|
44615
|
-
handle: await
|
|
45101
|
+
handle: await open4(temp2, "wx", keep.executable ? 448 : 384)
|
|
44616
45102
|
};
|
|
44617
45103
|
} catch {
|
|
44618
45104
|
copy = null;
|
|
@@ -46380,22 +46866,41 @@ var init_interjection = __esm({
|
|
|
46380
46866
|
function showsRefusedPrompt(harness) {
|
|
46381
46867
|
return harness !== "stella";
|
|
46382
46868
|
}
|
|
46869
|
+
function questionBoundary(harness) {
|
|
46870
|
+
return showsRefusedPrompt(harness) ? "UserPromptSubmit" : "SessionStart";
|
|
46871
|
+
}
|
|
46872
|
+
function holdToolCall(evaluation, record) {
|
|
46873
|
+
const held = record.control.interjection;
|
|
46874
|
+
if (held === void 0 || evaluation.decision === "deny") return evaluation;
|
|
46875
|
+
const refused2 = {
|
|
46876
|
+
...evaluation,
|
|
46877
|
+
decision: "deny",
|
|
46878
|
+
evaluated: "deny",
|
|
46879
|
+
source: "bundle",
|
|
46880
|
+
reason_code: INTERJECTION_OPEN,
|
|
46881
|
+
reason: held.question
|
|
46882
|
+
};
|
|
46883
|
+
delete refused2.rule;
|
|
46884
|
+
delete refused2.rules;
|
|
46885
|
+
return refused2;
|
|
46886
|
+
}
|
|
46383
46887
|
function isBound(clause, remote) {
|
|
46384
46888
|
const bound = new Set(clause.bound_remote_digests);
|
|
46385
46889
|
return bound.has(remote.remote_digest) || bound.has(remote.remote_digest_folded);
|
|
46386
46890
|
}
|
|
46387
|
-
function interjectionQuestion(clause) {
|
|
46891
|
+
function interjectionQuestion(clause, harness) {
|
|
46388
46892
|
const minutes = Math.max(1, Math.round(clause.timeout_ms / 6e4));
|
|
46389
46893
|
const slug = clause.workspace_slug;
|
|
46390
|
-
|
|
46894
|
+
const hold = showsRefusedPrompt(harness) ? `Oxagen is holding this session before its first model call. ` : `Oxagen is refusing this session's tool calls until a person answers. `;
|
|
46895
|
+
return hold + `It started in a repository that no workspace in your organization has bound, and skills are on for workspace ${slug}. Should Oxagen link this repository to ${slug}, or create a new workspace for it with skills off? A person with access answers on this run's page in Oxagen. With no answer in ${minutes} minutes, the session goes on without skills.`;
|
|
46391
46896
|
}
|
|
46392
46897
|
function proposedSlug(name) {
|
|
46393
46898
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").slice(0, SLUG_MAX).replace(/-+$/, "");
|
|
46394
46899
|
return slug.length >= SLUG_MIN && SLUG_PATTERN.test(slug) ? slug : null;
|
|
46395
46900
|
}
|
|
46396
|
-
function
|
|
46901
|
+
function prepareInterjection(record, clause, remote, now) {
|
|
46397
46902
|
const key = ulid(now);
|
|
46398
|
-
const question = interjectionQuestion(clause);
|
|
46903
|
+
const question = interjectionQuestion(clause, record.harness);
|
|
46399
46904
|
const expiresAt = toProtocolTimestamp(now + clause.timeout_ms);
|
|
46400
46905
|
const name = remote.name !== void 0 && remote.name.length <= NAME_MAX2 ? remote.name : null;
|
|
46401
46906
|
const unknown2 = repoUnknownBodySchema.safeParse({
|
|
@@ -46432,21 +46937,28 @@ function raiseInterjection(record, clause, remote, now, fields) {
|
|
|
46432
46937
|
]
|
|
46433
46938
|
});
|
|
46434
46939
|
if (!unknown2.success || !interject.success) return void 0;
|
|
46940
|
+
return {
|
|
46941
|
+
unknown: unknown2.data,
|
|
46942
|
+
interject: interject.data,
|
|
46943
|
+
held: {
|
|
46944
|
+
key,
|
|
46945
|
+
question,
|
|
46946
|
+
expiresAt,
|
|
46947
|
+
workspaceSlug: clause.workspace_slug,
|
|
46948
|
+
configVersion: clause.config_version
|
|
46949
|
+
}
|
|
46950
|
+
};
|
|
46951
|
+
}
|
|
46952
|
+
function sealInterjection(record, pending, fields) {
|
|
46435
46953
|
const events = [
|
|
46436
|
-
record.recorder.sealCollectorEvent("repo.unknown",
|
|
46954
|
+
record.recorder.sealCollectorEvent("repo.unknown", pending.unknown, fields),
|
|
46437
46955
|
record.recorder.sealCollectorEvent(
|
|
46438
46956
|
"control.interject",
|
|
46439
|
-
interject
|
|
46957
|
+
pending.interject,
|
|
46440
46958
|
fields
|
|
46441
46959
|
)
|
|
46442
46960
|
];
|
|
46443
|
-
record.control.interjection = {
|
|
46444
|
-
key,
|
|
46445
|
-
question,
|
|
46446
|
-
expiresAt,
|
|
46447
|
-
workspaceSlug: clause.workspace_slug,
|
|
46448
|
-
configVersion: clause.config_version
|
|
46449
|
-
};
|
|
46961
|
+
record.control.interjection = { ...pending.held };
|
|
46450
46962
|
return events;
|
|
46451
46963
|
}
|
|
46452
46964
|
function expireInterjection(record, now, fields) {
|
|
@@ -46533,7 +47045,7 @@ function settle(record, held, answer, payload, fields) {
|
|
|
46533
47045
|
record.control.interjection = void 0;
|
|
46534
47046
|
return events;
|
|
46535
47047
|
}
|
|
46536
|
-
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_TIMED_OUT_TEXT;
|
|
47048
|
+
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_OPEN, INTERJECTION_TIMED_OUT_TEXT;
|
|
46537
47049
|
var init_interjection2 = __esm({
|
|
46538
47050
|
"../../packages/tacho/src/collector/interjection.ts"() {
|
|
46539
47051
|
"use strict";
|
|
@@ -46544,6 +47056,7 @@ var init_interjection2 = __esm({
|
|
|
46544
47056
|
SLUG_MIN = 2;
|
|
46545
47057
|
SLUG_MAX = 40;
|
|
46546
47058
|
NAME_MAX2 = 120;
|
|
47059
|
+
INTERJECTION_OPEN = "interjection_open";
|
|
46547
47060
|
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.";
|
|
46548
47061
|
}
|
|
46549
47062
|
});
|
|
@@ -46809,21 +47322,23 @@ function promptBlock(view, record) {
|
|
|
46809
47322
|
const block = operatorBlock(view, record);
|
|
46810
47323
|
if (block !== void 0) return block;
|
|
46811
47324
|
const held = record.control.interjection;
|
|
46812
|
-
if (held === void 0
|
|
46813
|
-
|
|
47325
|
+
if (held === void 0 || !showsRefusedPrompt(record.harness))
|
|
47326
|
+
return void 0;
|
|
47327
|
+
return { code: INTERJECTION_OPEN, reason: held.question, source: "bundle" };
|
|
46814
47328
|
}
|
|
46815
|
-
async function
|
|
46816
|
-
if (record.control.repoChecked === true)
|
|
47329
|
+
async function repositoryQuestion(record, view, deps, replay, boundary) {
|
|
47330
|
+
if (record.control.repoChecked === true || questionBoundary(record.harness) !== boundary)
|
|
47331
|
+
return void 0;
|
|
46817
47332
|
record.control.repoChecked = true;
|
|
46818
47333
|
const clause = view.verified ? view.bundle.unbound_repo : void 0;
|
|
46819
|
-
if (clause === void 0 || replay !== void 0 ||
|
|
46820
|
-
return
|
|
47334
|
+
if (clause === void 0 || replay !== void 0 || record.recorder.hasModelCall || record.cwd === void 0 || deps.repositoryRemote === void 0)
|
|
47335
|
+
return void 0;
|
|
46821
47336
|
const remote = await readRepository(
|
|
46822
47337
|
recallView(record),
|
|
46823
47338
|
deps.repositoryRemote
|
|
46824
47339
|
);
|
|
46825
|
-
if (remote === void 0 || isBound(clause, remote)) return
|
|
46826
|
-
return
|
|
47340
|
+
if (remote === void 0 || isBound(clause, remote)) return void 0;
|
|
47341
|
+
return prepareInterjection(record, clause, remote, deps.now());
|
|
46827
47342
|
}
|
|
46828
47343
|
function invocationToolUseId(raw, input, record) {
|
|
46829
47344
|
const derived = input.tool_use_id;
|
|
@@ -47274,12 +47789,19 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47274
47789
|
switch (input.hook_event_name) {
|
|
47275
47790
|
case "SessionStart": {
|
|
47276
47791
|
const block = operatorBlock(view, record);
|
|
47792
|
+
const question = input.agent_id === void 0 ? await repositoryQuestion(record, view, deps, replay, "SessionStart") : void 0;
|
|
47793
|
+
const questionText = question?.held.question;
|
|
47277
47794
|
const steering = block === void 0 && replay === void 0 ? await runSteeringBundle(record, deps) ?? view.bundle : view.bundle;
|
|
47278
47795
|
const context = steering.context.system;
|
|
47279
47796
|
if (block === void 0 && replay === void 0)
|
|
47280
47797
|
await placeSessionSkills(view, record, deps, env);
|
|
47281
|
-
const messages = block === void 0 && replay === void 0 && input.agent_id === void 0 ? drainMessages(
|
|
47282
|
-
|
|
47798
|
+
const messages = block === void 0 && replay === void 0 && input.agent_id === void 0 ? drainMessages(
|
|
47799
|
+
record,
|
|
47800
|
+
deps,
|
|
47801
|
+
events,
|
|
47802
|
+
(context?.length ?? 0) + (questionText?.length ?? 0)
|
|
47803
|
+
) : [];
|
|
47804
|
+
const additional = block === void 0 ? [questionText ?? "", context ?? "", ...messages.map((m) => m.text)].filter((s2) => s2.length > 0).join(CONTEXT_JOINER) : "";
|
|
47283
47805
|
const delivered = replay === void 0 ? void 0 : readDeliveredContext(replay.deliveredContext);
|
|
47284
47806
|
const deliveryAttrs = replay === void 0 ? {
|
|
47285
47807
|
// A blocked start hands the agent nothing, so it names no text.
|
|
@@ -47306,6 +47828,13 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47306
47828
|
})
|
|
47307
47829
|
)
|
|
47308
47830
|
);
|
|
47831
|
+
if (question !== void 0)
|
|
47832
|
+
events.push(
|
|
47833
|
+
...sealInterjection(record, question, {
|
|
47834
|
+
hook_event_name: "SessionStart",
|
|
47835
|
+
attrs: replayed
|
|
47836
|
+
})
|
|
47837
|
+
);
|
|
47309
47838
|
if (block !== void 0) {
|
|
47310
47839
|
events.push(
|
|
47311
47840
|
record.recorder.sealCollectorEvent(
|
|
@@ -47355,14 +47884,15 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47355
47884
|
};
|
|
47356
47885
|
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), questionFields) : void 0;
|
|
47357
47886
|
if (timedOut !== void 0) events.push(...timedOut);
|
|
47358
|
-
const asked = await
|
|
47887
|
+
const asked = await repositoryQuestion(
|
|
47359
47888
|
record,
|
|
47360
47889
|
view,
|
|
47361
47890
|
deps,
|
|
47362
47891
|
replay,
|
|
47363
|
-
|
|
47892
|
+
"UserPromptSubmit"
|
|
47364
47893
|
);
|
|
47365
|
-
|
|
47894
|
+
if (asked !== void 0)
|
|
47895
|
+
events.push(...sealInterjection(record, asked, questionFields));
|
|
47366
47896
|
const block = promptBlock(view, record);
|
|
47367
47897
|
const notice = block === void 0 && timedOut !== void 0 ? INTERJECTION_TIMED_OUT_TEXT : void 0;
|
|
47368
47898
|
const messages = block === void 0 && replay === void 0 && input.agent_id === void 0 && deliversMessages(record.harness, input.hook_event_name) ? drainMessages(record, deps, events, notice?.length ?? 0) : [];
|
|
@@ -47440,12 +47970,17 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47440
47970
|
const toolInput = input.tool_input;
|
|
47441
47971
|
noteToolCall(record, toolName3, toolInput);
|
|
47442
47972
|
noteRecallHints(record, input.tool_name, toolInput);
|
|
47973
|
+
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), {
|
|
47974
|
+
hook_event_name: "PreToolUse",
|
|
47975
|
+
attrs: replayed
|
|
47976
|
+
}) : void 0;
|
|
47977
|
+
if (timedOut !== void 0) events.push(...timedOut);
|
|
47443
47978
|
const decided = await decideToolCall(view, record, input, deps, replay, {
|
|
47444
47979
|
toolName: toolName3,
|
|
47445
47980
|
toolInput
|
|
47446
47981
|
});
|
|
47447
47982
|
const currentView = decided.view;
|
|
47448
|
-
let evaluation = decided.evaluation;
|
|
47983
|
+
let evaluation = replay === void 0 ? holdToolCall(decided.evaluation, record) : decided.evaluation;
|
|
47449
47984
|
if (replay === void 0 && evaluation.decision === "deny" && evaluation.reason_code === "session_paused" && record.control.pauseEffect === void 0)
|
|
47450
47985
|
record.control.pauseEffect = "refused";
|
|
47451
47986
|
const refusal = evaluation.decision === "deny" ? void 0 : refusesForSteer(record.harness, record.control.messages);
|
|
@@ -47471,7 +48006,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47471
48006
|
};
|
|
47472
48007
|
}
|
|
47473
48008
|
}
|
|
47474
|
-
if (evaluation.decision === "deny" && evaluation.source !== "human")
|
|
48009
|
+
if (evaluation.decision === "deny" && evaluation.source !== "human" && evaluation.reason_code !== INTERJECTION_OPEN)
|
|
47475
48010
|
notePolicyDenial(record, toolName3);
|
|
47476
48011
|
const facts = policyFacts2(evaluation, currentView);
|
|
47477
48012
|
const attrs2 = policyAttrs(evaluation, replay);
|
|
@@ -47788,10 +48323,13 @@ var init_hook_handler = __esm({
|
|
|
47788
48323
|
});
|
|
47789
48324
|
|
|
47790
48325
|
// ../../packages/tacho/src/collector/steer-waiters.ts
|
|
48326
|
+
function answerBlocksAgent(response) {
|
|
48327
|
+
return response["decision"] === "block" || response["continue"] === false;
|
|
48328
|
+
}
|
|
47791
48329
|
function owesText(session) {
|
|
47792
48330
|
return session.control.messages.length > 0 || session.control.resumeOwed !== void 0;
|
|
47793
48331
|
}
|
|
47794
|
-
var STEER_WAIT_HOLD_MS, STEER_WAIT_BUSY_KEPT, STEER_WAIT_RELEASING_EVENTS, SteerWaiters;
|
|
48332
|
+
var STEER_WAIT_HOLD_MS, STEER_WAIT_BUSY_KEPT, STEER_WAIT_RELEASING_EVENTS, STEER_WAIT_RELEASED_AFTER_ANSWER, SteerWaiters;
|
|
47795
48333
|
var init_steer_waiters = __esm({
|
|
47796
48334
|
"../../packages/tacho/src/collector/steer-waiters.ts"() {
|
|
47797
48335
|
"use strict";
|
|
@@ -47804,6 +48342,9 @@ var init_steer_waiters = __esm({
|
|
|
47804
48342
|
"PostToolUseFailure",
|
|
47805
48343
|
"SessionEnd"
|
|
47806
48344
|
]);
|
|
48345
|
+
STEER_WAIT_RELEASED_AFTER_ANSWER = /* @__PURE__ */ new Set([
|
|
48346
|
+
"UserPromptSubmit"
|
|
48347
|
+
]);
|
|
47807
48348
|
SteerWaiters = class {
|
|
47808
48349
|
constructor(deps) {
|
|
47809
48350
|
this.deps = deps;
|
|
@@ -47822,12 +48363,17 @@ var init_steer_waiters = __esm({
|
|
|
47822
48363
|
* Hold one waiter request for the session `key` names. `signal` aborts
|
|
47823
48364
|
* when the waiter's connection closes. `startedAt` is when the waiter
|
|
47824
48365
|
* started; one whose session was busy since is told to stop.
|
|
48366
|
+
*
|
|
48367
|
+
* A stale request is refused before it touches the waiter that holds the
|
|
48368
|
+
* key. An old waiter can be told `wait`, and ask again after a prompt and
|
|
48369
|
+
* a later `Stop` installed a newer one. Settling the newer one first ended
|
|
48370
|
+
* both, and left the idle agent with no waiter until the next `Stop`.
|
|
47825
48371
|
*/
|
|
47826
48372
|
wait(key, signal, startedAt) {
|
|
47827
|
-
this.waiting.get(key)?.settle({ done: true });
|
|
47828
48373
|
const busy = this.busyAt.get(key);
|
|
47829
48374
|
if (startedAt !== void 0 && busy !== void 0 && busy >= startedAt)
|
|
47830
48375
|
return Promise.resolve({ done: true });
|
|
48376
|
+
this.waiting.get(key)?.settle({ done: true });
|
|
47831
48377
|
const session = this.deps.find(key);
|
|
47832
48378
|
if (session !== void 0 && (session.sealed || session.pendingTerminal === true))
|
|
47833
48379
|
return Promise.resolve({ done: true });
|
|
@@ -48182,6 +48728,14 @@ function expiredAt(command2, now) {
|
|
|
48182
48728
|
}
|
|
48183
48729
|
async function applyCommands(commands, deps) {
|
|
48184
48730
|
const now = deps.now();
|
|
48731
|
+
if (newCommands(commands, deps).fresh.some(
|
|
48732
|
+
(command2) => command2.session_uuid === null && command2.command === "refresh_bundle" && !expiredAt(command2, now)
|
|
48733
|
+
))
|
|
48734
|
+
await deps.refreshBundle();
|
|
48735
|
+
const seal2 = () => sealNewCommands(commands, deps, now);
|
|
48736
|
+
return deps.exclusive !== void 0 ? deps.exclusive(seal2) : seal2();
|
|
48737
|
+
}
|
|
48738
|
+
function newCommands(commands, deps) {
|
|
48185
48739
|
const fresh = [];
|
|
48186
48740
|
const repeated = [];
|
|
48187
48741
|
for (const command2 of commands) {
|
|
@@ -48189,10 +48743,10 @@ async function applyCommands(commands, deps) {
|
|
|
48189
48743
|
repeated.push(command2.id);
|
|
48190
48744
|
else fresh.push(command2);
|
|
48191
48745
|
}
|
|
48192
|
-
|
|
48193
|
-
|
|
48194
|
-
|
|
48195
|
-
|
|
48746
|
+
return { fresh, repeated };
|
|
48747
|
+
}
|
|
48748
|
+
function sealNewCommands(commands, deps, now) {
|
|
48749
|
+
const { fresh, repeated } = newCommands(commands, deps);
|
|
48196
48750
|
const result2 = sealCommands(fresh, deps, now);
|
|
48197
48751
|
for (const ack of result2.acknowledgements) deps.handled?.remember(ack);
|
|
48198
48752
|
for (const id2 of repeated) {
|
|
@@ -53461,6 +54015,19 @@ import {
|
|
|
53461
54015
|
} from "node:http";
|
|
53462
54016
|
import { Agent as HttpsAgent, request as httpsRequest } from "node:https";
|
|
53463
54017
|
import { brotliDecompress, gunzip, inflate, zstdDecompress } from "node:zlib";
|
|
54018
|
+
async function landedWithin(landing, ms) {
|
|
54019
|
+
let timer;
|
|
54020
|
+
try {
|
|
54021
|
+
return await Promise.race([
|
|
54022
|
+
landing.then(() => true),
|
|
54023
|
+
new Promise((resolve26) => {
|
|
54024
|
+
timer = setTimeout(() => resolve26(false), ms);
|
|
54025
|
+
})
|
|
54026
|
+
]);
|
|
54027
|
+
} finally {
|
|
54028
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
54029
|
+
}
|
|
54030
|
+
}
|
|
53464
54031
|
function streamsAnthropicMessages(route, body2) {
|
|
53465
54032
|
return route.api === "anthropic.messages" && body2?.["stream"] === true;
|
|
53466
54033
|
}
|
|
@@ -53651,6 +54218,7 @@ function createModelProxy(deps) {
|
|
|
53651
54218
|
const maxRequestBytes = deps.maxRequestBytes ?? DEFAULT_MAX_REQUEST_BYTES;
|
|
53652
54219
|
const upstreamIdleMs = deps.upstreamIdleMs ?? DEFAULT_UPSTREAM_IDLE_MS;
|
|
53653
54220
|
const hookTimeoutMs = deps.beforeForwardTimeoutMs ?? DEFAULT_BEFORE_FORWARD_TIMEOUT_MS;
|
|
54221
|
+
const refusalWaitMs = deps.refusalFrameWaitMs ?? DEFAULT_REFUSAL_FRAME_WAIT_MS;
|
|
53654
54222
|
const httpAgent = new HttpAgent({ keepAlive: true, maxSockets: Infinity });
|
|
53655
54223
|
const httpsAgent = new HttpsAgent({ keepAlive: true, maxSockets: Infinity });
|
|
53656
54224
|
const inFlight = /* @__PURE__ */ new Map();
|
|
@@ -53776,10 +54344,10 @@ function createModelProxy(deps) {
|
|
|
53776
54344
|
if (known !== void 0 && !known.sealed && !known.pendingTerminal)
|
|
53777
54345
|
return { record: known, how };
|
|
53778
54346
|
if (known !== void 0) {
|
|
53779
|
-
const
|
|
54347
|
+
const open7 = deps.registry.list().find(
|
|
53780
54348
|
(record2) => record2.harnessSessionId === id2 && !record2.sealed && !record2.pendingTerminal
|
|
53781
54349
|
);
|
|
53782
|
-
if (
|
|
54350
|
+
if (open7 !== void 0) return { record: open7, how };
|
|
53783
54351
|
return { how: "session_closed" };
|
|
53784
54352
|
}
|
|
53785
54353
|
const { record } = deps.registry.ensure(id2, { harness, ambient: true });
|
|
@@ -54006,59 +54574,75 @@ function createModelProxy(deps) {
|
|
|
54006
54574
|
found = { how: "unattributed" };
|
|
54007
54575
|
}
|
|
54008
54576
|
return {
|
|
54577
|
+
...found.record !== void 0 ? { record: found.record } : {},
|
|
54009
54578
|
recorder: found.record?.recorder ?? deps.hostRecorder(),
|
|
54010
54579
|
how: found.how,
|
|
54011
54580
|
attrs: attrsFor(route, found.how)
|
|
54012
54581
|
};
|
|
54013
54582
|
}
|
|
54583
|
+
function landingChain(record, how) {
|
|
54584
|
+
if (record === void 0) return { chain: deps.hostRecorder(), attrs: {} };
|
|
54585
|
+
const owner = deps.registry.byUuid(record.recorder.sessionUuid);
|
|
54586
|
+
if (owner !== void 0 && !owner.sealed && owner.pendingTerminal !== true)
|
|
54587
|
+
return { chain: owner.recorder, attrs: {} };
|
|
54588
|
+
return {
|
|
54589
|
+
chain: deps.hostRecorder(),
|
|
54590
|
+
attrs: {
|
|
54591
|
+
"oxagen.correlation": "session_closed",
|
|
54592
|
+
"oxagen.session_correlation": how,
|
|
54593
|
+
"oxagen.session_uuid": record.recorder.sessionUuid
|
|
54594
|
+
}
|
|
54595
|
+
};
|
|
54596
|
+
}
|
|
54014
54597
|
function sealNotForwarded(req, route, attempt, reason3, status2) {
|
|
54015
54598
|
if (attempt.done) return;
|
|
54016
54599
|
attempt.done = true;
|
|
54017
54600
|
if (route.api === "other") return;
|
|
54018
|
-
let
|
|
54019
|
-
|
|
54601
|
+
let session;
|
|
54602
|
+
const lost = (error) => {
|
|
54603
|
+
deps.log(
|
|
54604
|
+
`model proxy: sealing the frame of a call it did not forward (${reason3}) failed: ${error instanceof Error ? error.message : String(error)} session=${session ?? "unattributed"}`
|
|
54605
|
+
);
|
|
54606
|
+
};
|
|
54020
54607
|
try {
|
|
54021
54608
|
const attribution2 = attempt.attribution ?? attributeByHeaders(req, route);
|
|
54022
|
-
|
|
54023
|
-
recorder = chain;
|
|
54024
|
-
mark = chain.markChain();
|
|
54609
|
+
session = attribution2.recorder.sessionUuid;
|
|
54025
54610
|
const at2 = deps.now();
|
|
54026
|
-
|
|
54027
|
-
|
|
54028
|
-
|
|
54029
|
-
|
|
54030
|
-
|
|
54031
|
-
|
|
54032
|
-
|
|
54033
|
-
|
|
54034
|
-
|
|
54035
|
-
|
|
54036
|
-
|
|
54037
|
-
|
|
54038
|
-
|
|
54039
|
-
|
|
54040
|
-
|
|
54041
|
-
|
|
54042
|
-
|
|
54043
|
-
|
|
54044
|
-
|
|
54045
|
-
|
|
54046
|
-
|
|
54047
|
-
|
|
54048
|
-
|
|
54611
|
+
const body2 = {
|
|
54612
|
+
provider: route.provider,
|
|
54613
|
+
...attempt.model !== void 0 ? { model: attempt.model.slice(0, 512) } : {},
|
|
54614
|
+
...status2 !== void 0 ? { api_status_code: status2 } : {},
|
|
54615
|
+
api_error_class: reason3,
|
|
54616
|
+
api_duration_ms: Math.max(0, at2 - attempt.startedAt)
|
|
54617
|
+
};
|
|
54618
|
+
const attrs2 = {
|
|
54619
|
+
...attribution2.attrs,
|
|
54620
|
+
[NOT_FORWARDED_ATTR]: reason3,
|
|
54621
|
+
"oxagen.provider": route.provider,
|
|
54622
|
+
"oxagen.request_bytes_read": String(attempt.bytesRead),
|
|
54623
|
+
...attempt.request !== void 0 ? { "oxagen.request_digest": digestBytes(attempt.request) } : {}
|
|
54624
|
+
};
|
|
54625
|
+
const land = () => {
|
|
54626
|
+
const landing = landingChain(attribution2.record, attribution2.how);
|
|
54627
|
+
recordOnChain(
|
|
54628
|
+
landing.chain,
|
|
54629
|
+
(chain) => [
|
|
54630
|
+
chain.sealCollectorEvent("error", body2, {
|
|
54631
|
+
ts: toProtocolTimestamp(at2),
|
|
54632
|
+
fidelity: "proxy",
|
|
54633
|
+
attrs: { ...attrs2, ...landing.attrs }
|
|
54634
|
+
})
|
|
54635
|
+
],
|
|
54636
|
+
deps.record
|
|
54637
|
+
);
|
|
54638
|
+
};
|
|
54639
|
+
if (attribution2.record === void 0) land();
|
|
54640
|
+
else
|
|
54641
|
+
void onSessionQueue(deps.exclusive, attribution2.record, land).catch(
|
|
54642
|
+
lost
|
|
54643
|
+
);
|
|
54049
54644
|
} catch (error) {
|
|
54050
|
-
|
|
54051
|
-
try {
|
|
54052
|
-
recorder.rollbackChain(mark);
|
|
54053
|
-
} catch (rollbackError) {
|
|
54054
|
-
deps.log(
|
|
54055
|
-
`model proxy: rolling the chain back after a failed frame failed too: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)} session=${recorder.sessionUuid}`
|
|
54056
|
-
);
|
|
54057
|
-
}
|
|
54058
|
-
}
|
|
54059
|
-
deps.log(
|
|
54060
|
-
`model proxy: sealing the frame of a call it did not forward (${reason3}) failed: ${error instanceof Error ? error.message : String(error)} session=${recorder?.sessionUuid ?? "unattributed"}`
|
|
54061
|
-
);
|
|
54645
|
+
lost(error);
|
|
54062
54646
|
}
|
|
54063
54647
|
}
|
|
54064
54648
|
function sendProviderError(res, route, status2, code, message, retryable = false) {
|
|
@@ -54347,29 +54931,6 @@ function createModelProxy(deps) {
|
|
|
54347
54931
|
}
|
|
54348
54932
|
callsObserved += 1;
|
|
54349
54933
|
observed.set(sessionKey, (observed.get(sessionKey) ?? 0) + 1);
|
|
54350
|
-
const closed2 = record.sealed || record.pendingTerminal === true;
|
|
54351
|
-
const requestText = payload.body.toString("utf8");
|
|
54352
|
-
const memory = new RequestPrefixMemory();
|
|
54353
|
-
if (payload.priorShape !== void 0 && !closed2)
|
|
54354
|
-
memory.remember("parent", {
|
|
54355
|
-
text: "",
|
|
54356
|
-
fullDigest: payload.priorShape.requestDigest,
|
|
54357
|
-
fullBytes: 0,
|
|
54358
|
-
storedBytes: 0,
|
|
54359
|
-
prior: void 0,
|
|
54360
|
-
shape: payload.priorShape,
|
|
54361
|
-
priorPayload: void 0
|
|
54362
|
-
});
|
|
54363
|
-
const fold = memory.fold("parent", requestText);
|
|
54364
|
-
const capped = cappedExchange(
|
|
54365
|
-
fold.storedBytes > TACHO_MAX_BODY_BYTES ? void 0 : fold.text,
|
|
54366
|
-
{
|
|
54367
|
-
text: answer.responseText,
|
|
54368
|
-
tooLarge: answer.responseTooLarge,
|
|
54369
|
-
bytes: answer.responseBytes
|
|
54370
|
-
}
|
|
54371
|
-
);
|
|
54372
|
-
const chain = closed2 ? deps.hostRecorder() : record.recorder;
|
|
54373
54934
|
const callBody2 = llmCallBody({
|
|
54374
54935
|
provider: "anthropic",
|
|
54375
54936
|
model,
|
|
@@ -54385,10 +54946,33 @@ function createModelProxy(deps) {
|
|
|
54385
54946
|
failed: answer.errorClass ?? (answer.status >= 400 ? `http_${answer.status}` : void 0),
|
|
54386
54947
|
requestId: answer.requestId
|
|
54387
54948
|
});
|
|
54388
|
-
const
|
|
54389
|
-
|
|
54390
|
-
|
|
54391
|
-
|
|
54949
|
+
const land = () => {
|
|
54950
|
+
const owner = deps.registry.byUuid(record.recorder.sessionUuid);
|
|
54951
|
+
const closed2 = owner === void 0 || owner.sealed || owner.pendingTerminal === true;
|
|
54952
|
+
const requestText = payload.body.toString("utf8");
|
|
54953
|
+
const memory = new RequestPrefixMemory();
|
|
54954
|
+
if (payload.priorShape !== void 0 && !closed2)
|
|
54955
|
+
memory.remember("parent", {
|
|
54956
|
+
text: "",
|
|
54957
|
+
fullDigest: payload.priorShape.requestDigest,
|
|
54958
|
+
fullBytes: 0,
|
|
54959
|
+
storedBytes: 0,
|
|
54960
|
+
prior: void 0,
|
|
54961
|
+
shape: payload.priorShape,
|
|
54962
|
+
priorPayload: void 0
|
|
54963
|
+
});
|
|
54964
|
+
const fold = memory.fold("parent", requestText);
|
|
54965
|
+
const capped = cappedExchange(
|
|
54966
|
+
fold.storedBytes > TACHO_MAX_BODY_BYTES ? void 0 : fold.text,
|
|
54967
|
+
{
|
|
54968
|
+
text: answer.responseText,
|
|
54969
|
+
tooLarge: answer.responseTooLarge,
|
|
54970
|
+
bytes: answer.responseBytes
|
|
54971
|
+
}
|
|
54972
|
+
);
|
|
54973
|
+
recordOnChain(
|
|
54974
|
+
closed2 ? deps.hostRecorder() : owner.recorder,
|
|
54975
|
+
(chain) => [
|
|
54392
54976
|
chain.sealCollectorEvent("llm_call", callBody2, {
|
|
54393
54977
|
ts: toProtocolTimestamp(settledAt),
|
|
54394
54978
|
fidelity: "proxy",
|
|
@@ -54427,20 +55011,16 @@ function createModelProxy(deps) {
|
|
|
54427
55011
|
}
|
|
54428
55012
|
})
|
|
54429
55013
|
],
|
|
54430
|
-
|
|
55014
|
+
deps.record
|
|
54431
55015
|
);
|
|
54432
|
-
}
|
|
54433
|
-
|
|
54434
|
-
|
|
54435
|
-
} catch (rollbackError) {
|
|
55016
|
+
};
|
|
55017
|
+
void onSessionQueue(deps.exclusive, record, land).catch(
|
|
55018
|
+
(error) => {
|
|
54436
55019
|
deps.log(
|
|
54437
|
-
`model proxy:
|
|
55020
|
+
`model proxy: sealing a cache keep-alive's frame failed: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
54438
55021
|
);
|
|
54439
55022
|
}
|
|
54440
|
-
|
|
54441
|
-
`model proxy: sealing a cache keep-alive's frame failed: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
54442
|
-
);
|
|
54443
|
-
}
|
|
55023
|
+
);
|
|
54444
55024
|
return usage2.cacheReadTokens ?? 0;
|
|
54445
55025
|
}
|
|
54446
55026
|
async function forward(req, res, route, admitted, attempt) {
|
|
@@ -54481,7 +55061,12 @@ function createModelProxy(deps) {
|
|
|
54481
55061
|
const sessionKey = record?.recorder.sessionUuid ?? HOST_KEY;
|
|
54482
55062
|
const credential = resolveCredential(req, route);
|
|
54483
55063
|
const attrs2 = attrsFor(route, how, credential);
|
|
54484
|
-
attempt.attribution = {
|
|
55064
|
+
attempt.attribution = {
|
|
55065
|
+
...record !== void 0 ? { record } : {},
|
|
55066
|
+
recorder,
|
|
55067
|
+
how,
|
|
55068
|
+
attrs: attrs2
|
|
55069
|
+
};
|
|
54485
55070
|
const metered = route.api !== "other";
|
|
54486
55071
|
const { model: askedModel, ambiguous: modelAmbiguous } = modelOf(
|
|
54487
55072
|
readable,
|
|
@@ -54527,44 +55112,58 @@ function createModelProxy(deps) {
|
|
|
54527
55112
|
if (refusal !== void 0) {
|
|
54528
55113
|
refused2 += 1;
|
|
54529
55114
|
const view = deps.policy();
|
|
54530
|
-
const
|
|
54531
|
-
|
|
54532
|
-
|
|
54533
|
-
|
|
54534
|
-
|
|
54535
|
-
|
|
54536
|
-
|
|
54537
|
-
|
|
54538
|
-
|
|
54539
|
-
|
|
54540
|
-
|
|
54541
|
-
|
|
54542
|
-
|
|
54543
|
-
|
|
55115
|
+
const decision = {
|
|
55116
|
+
policy_decision: "deny",
|
|
55117
|
+
policy_source: refusal.source,
|
|
55118
|
+
policy_reason_code: refusal.code,
|
|
55119
|
+
policy_reason_digest: digestText(refusal.message),
|
|
55120
|
+
bundle_version: view.bundle.version,
|
|
55121
|
+
bundle_mode: view.bundle.mode
|
|
55122
|
+
};
|
|
55123
|
+
const decisionAttrs = {
|
|
55124
|
+
...attrs2,
|
|
55125
|
+
"oxagen.refused": "model_call",
|
|
55126
|
+
"oxagen.provider": route.provider,
|
|
55127
|
+
"oxagen.request_digest": digestBytes(body2),
|
|
55128
|
+
// The model the refusal was about, when the proxy could read one. A
|
|
55129
|
+
// `model_not_permitted` frame that does not name the model leaves the
|
|
55130
|
+
// operator guessing which entry to add.
|
|
55131
|
+
...askedModel !== void 0 ? { "oxagen.model": askedModel.slice(0, 512) } : {},
|
|
55132
|
+
...modelAmbiguous ? { "oxagen.model_ambiguous": "true" } : {},
|
|
55133
|
+
...record !== void 0 ? {
|
|
55134
|
+
"oxagen.session_spend_usd_micros": String(spendFor(sessionKey))
|
|
55135
|
+
} : {},
|
|
55136
|
+
..."attrs" in refusal ? refusal.attrs : {}
|
|
55137
|
+
};
|
|
55138
|
+
const land = () => {
|
|
55139
|
+
const landing = landingChain(record, how);
|
|
55140
|
+
recordOnChain(
|
|
55141
|
+
landing.chain,
|
|
55142
|
+
(chain) => [
|
|
55143
|
+
chain.sealCollectorEvent("policy_decision", decision, {
|
|
54544
55144
|
fidelity: "proxy",
|
|
54545
|
-
attrs: {
|
|
54546
|
-
|
|
54547
|
-
|
|
54548
|
-
|
|
54549
|
-
|
|
54550
|
-
|
|
54551
|
-
|
|
54552
|
-
|
|
54553
|
-
|
|
54554
|
-
|
|
54555
|
-
|
|
54556
|
-
|
|
54557
|
-
|
|
54558
|
-
|
|
54559
|
-
|
|
54560
|
-
|
|
54561
|
-
|
|
54562
|
-
|
|
54563
|
-
|
|
54564
|
-
|
|
54565
|
-
|
|
54566
|
-
|
|
54567
|
-
throw error;
|
|
55145
|
+
attrs: { ...decisionAttrs, ...landing.attrs }
|
|
55146
|
+
})
|
|
55147
|
+
],
|
|
55148
|
+
deps.record
|
|
55149
|
+
);
|
|
55150
|
+
};
|
|
55151
|
+
if (record === void 0) land();
|
|
55152
|
+
else {
|
|
55153
|
+
let answered = false;
|
|
55154
|
+
const written2 = onSessionQueue(deps.exclusive, record, land);
|
|
55155
|
+
void written2.catch((error) => {
|
|
55156
|
+
if (answered)
|
|
55157
|
+
deps.log(
|
|
55158
|
+
`model proxy: the frame of a refusal already answered was not written: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
55159
|
+
);
|
|
55160
|
+
});
|
|
55161
|
+
if (!await landedWithin(written2, refusalWaitMs)) {
|
|
55162
|
+
answered = true;
|
|
55163
|
+
deps.log(
|
|
55164
|
+
`model proxy: answered a refused call before its frame could land, because the session's queue was busy for ${refusalWaitMs} ms session=${sessionKey}`
|
|
55165
|
+
);
|
|
55166
|
+
}
|
|
54568
55167
|
}
|
|
54569
55168
|
attempt.done = true;
|
|
54570
55169
|
deps.log(
|
|
@@ -55245,9 +55844,9 @@ function createModelProxy(deps) {
|
|
|
55245
55844
|
callsObservedFor: (sessionUuid2) => observed.get(sessionUuid2) ?? 0,
|
|
55246
55845
|
keepAliveTick: () => keepAlive.tick(),
|
|
55247
55846
|
stats: () => {
|
|
55248
|
-
let
|
|
55249
|
-
for (const calls of inFlight.values())
|
|
55250
|
-
return { callsObserved, refused: refused2, inFlight:
|
|
55847
|
+
let open7 = 0;
|
|
55848
|
+
for (const calls of inFlight.values()) open7 += calls.size;
|
|
55849
|
+
return { callsObserved, refused: refused2, inFlight: open7 };
|
|
55251
55850
|
},
|
|
55252
55851
|
close: () => {
|
|
55253
55852
|
clearInterval(keepAliveTimer);
|
|
@@ -55262,7 +55861,7 @@ function createModelProxy(deps) {
|
|
|
55262
55861
|
}
|
|
55263
55862
|
};
|
|
55264
55863
|
}
|
|
55265
|
-
var DEFAULT_MAX_REQUEST_BYTES, NOT_FORWARDED_ATTR, DEFAULT_UPSTREAM_IDLE_MS, DEFAULT_BEFORE_FORWARD_TIMEOUT_MS, DEFAULT_UPSTREAM_CONNECT_MS, DEFAULT_PAUSE_HOLD_MS, DEFAULT_PAUSE_STREAM_HOLD_MS, DEFAULT_PAUSE_HOLD_PING_MS, DEFAULT_PAUSE_HOLD_CHECK_MS, MAX_HELD_CALLS_PER_SESSION, PAUSE_HOLD_CODES, ANTHROPIC_PING_EVENT, HELD_STREAM_ERROR_BYTES, FREE_SOCKET_TIMEOUT_MS, KEEP_ALIVE_TIMEOUT_MS, KEEP_ALIVE_MAX_RESPONSE_BYTES, BodyCapture, EXCHANGE_OPEN_BYTES, EXCHANGE_JOIN_BYTES, DECODERS, REQUEST_EFFORT_MAX, CREDENTIAL_MESSAGES;
|
|
55864
|
+
var DEFAULT_MAX_REQUEST_BYTES, NOT_FORWARDED_ATTR, DEFAULT_UPSTREAM_IDLE_MS, DEFAULT_BEFORE_FORWARD_TIMEOUT_MS, DEFAULT_UPSTREAM_CONNECT_MS, DEFAULT_REFUSAL_FRAME_WAIT_MS, DEFAULT_PAUSE_HOLD_MS, DEFAULT_PAUSE_STREAM_HOLD_MS, DEFAULT_PAUSE_HOLD_PING_MS, DEFAULT_PAUSE_HOLD_CHECK_MS, MAX_HELD_CALLS_PER_SESSION, PAUSE_HOLD_CODES, ANTHROPIC_PING_EVENT, HELD_STREAM_ERROR_BYTES, FREE_SOCKET_TIMEOUT_MS, KEEP_ALIVE_TIMEOUT_MS, KEEP_ALIVE_MAX_RESPONSE_BYTES, BodyCapture, EXCHANGE_OPEN_BYTES, EXCHANGE_JOIN_BYTES, DECODERS, REQUEST_EFFORT_MAX, CREDENTIAL_MESSAGES;
|
|
55266
55865
|
var init_model_proxy = __esm({
|
|
55267
55866
|
"../../packages/tacho/src/collector/model-proxy.ts"() {
|
|
55268
55867
|
"use strict";
|
|
@@ -55293,6 +55892,7 @@ var init_model_proxy = __esm({
|
|
|
55293
55892
|
DEFAULT_UPSTREAM_IDLE_MS = 10 * 6e4;
|
|
55294
55893
|
DEFAULT_BEFORE_FORWARD_TIMEOUT_MS = 250;
|
|
55295
55894
|
DEFAULT_UPSTREAM_CONNECT_MS = 3e4;
|
|
55895
|
+
DEFAULT_REFUSAL_FRAME_WAIT_MS = 1e3;
|
|
55296
55896
|
DEFAULT_PAUSE_HOLD_MS = 12e4;
|
|
55297
55897
|
DEFAULT_PAUSE_STREAM_HOLD_MS = 12 * 60 * 6e4;
|
|
55298
55898
|
DEFAULT_PAUSE_HOLD_PING_MS = 15e3;
|
|
@@ -55477,7 +56077,7 @@ var init_model_proxy_listener = __esm({
|
|
|
55477
56077
|
import {
|
|
55478
56078
|
createServer as createServer5
|
|
55479
56079
|
} from "node:http";
|
|
55480
|
-
import { chmodSync as chmodSync9, existsSync as existsSync23, statSync as
|
|
56080
|
+
import { chmodSync as chmodSync9, existsSync as existsSync23, statSync as statSync13, unlinkSync as unlinkSync11 } from "node:fs";
|
|
55481
56081
|
import { randomBytes as randomBytes11, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
55482
56082
|
import { createConnection } from "node:net";
|
|
55483
56083
|
function isExportFormat(value) {
|
|
@@ -55853,7 +56453,7 @@ function createRequestHandler(api, log, options = {}) {
|
|
|
55853
56453
|
}
|
|
55854
56454
|
async function removeStaleSocket(socketPath) {
|
|
55855
56455
|
if (!existsSync23(socketPath)) return;
|
|
55856
|
-
if (!
|
|
56456
|
+
if (!statSync13(socketPath).isSocket()) {
|
|
55857
56457
|
throw new Error(`collector socket path is not a socket: ${socketPath}`);
|
|
55858
56458
|
}
|
|
55859
56459
|
const stale = await new Promise((resolve26, reject) => {
|
|
@@ -56022,7 +56622,7 @@ var init_server = __esm({
|
|
|
56022
56622
|
});
|
|
56023
56623
|
|
|
56024
56624
|
// ../../packages/tacho/src/collector/refused.ts
|
|
56025
|
-
import { readdirSync as readdirSync12, readFileSync as readFileSync20, statSync as
|
|
56625
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync20, statSync as statSync14 } from "node:fs";
|
|
56026
56626
|
import { join as join45 } from "node:path";
|
|
56027
56627
|
function refusalRetryable(refusal) {
|
|
56028
56628
|
return refusal === "malformed" || refusal === "parked";
|
|
@@ -56072,7 +56672,7 @@ function readRefusedEntry(file) {
|
|
|
56072
56672
|
let mtimeMs;
|
|
56073
56673
|
try {
|
|
56074
56674
|
record = JSON.parse(readFileSync20(file, "utf8"));
|
|
56075
|
-
mtimeMs =
|
|
56675
|
+
mtimeMs = statSync14(file).mtimeMs;
|
|
56076
56676
|
} catch {
|
|
56077
56677
|
return void 0;
|
|
56078
56678
|
}
|
|
@@ -57025,7 +57625,7 @@ import {
|
|
|
57025
57625
|
readdirSync as readdirSync13,
|
|
57026
57626
|
readFileSync as readFileSync22,
|
|
57027
57627
|
renameSync as renameSync4,
|
|
57028
|
-
statSync as
|
|
57628
|
+
statSync as statSync15,
|
|
57029
57629
|
unlinkSync as unlinkSync13
|
|
57030
57630
|
} from "node:fs";
|
|
57031
57631
|
import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "node:fs/promises";
|
|
@@ -57186,6 +57786,20 @@ function reconcileRestoredCursor(state, wal, log) {
|
|
|
57186
57786
|
for (const child of Object.values(state.children))
|
|
57187
57787
|
reconcileRestoredCursor(child.state, wal, log);
|
|
57188
57788
|
}
|
|
57789
|
+
function startupClock(log, clock2 = () => performance.now()) {
|
|
57790
|
+
const began = clock2();
|
|
57791
|
+
let since = began;
|
|
57792
|
+
return {
|
|
57793
|
+
phase: (name) => {
|
|
57794
|
+
const at2 = clock2();
|
|
57795
|
+
log(`startup phase ${name} took ${Math.round(at2 - since)}ms`);
|
|
57796
|
+
since = at2;
|
|
57797
|
+
},
|
|
57798
|
+
ready: () => {
|
|
57799
|
+
log(`startup took ${Math.round(clock2() - began)}ms to ready`);
|
|
57800
|
+
}
|
|
57801
|
+
};
|
|
57802
|
+
}
|
|
57189
57803
|
async function startDaemon(options) {
|
|
57190
57804
|
const loaded = options.host ?? readHostFile(options.paths.hostFile);
|
|
57191
57805
|
if (loaded === void 0) {
|
|
@@ -57201,6 +57815,7 @@ async function startDaemon(options) {
|
|
|
57201
57815
|
`);
|
|
57202
57816
|
});
|
|
57203
57817
|
const server = createCollectorServer(() => ready, log);
|
|
57818
|
+
const clock2 = startupClock(log);
|
|
57204
57819
|
let port;
|
|
57205
57820
|
try {
|
|
57206
57821
|
if (options.listen ?? true) {
|
|
@@ -57210,21 +57825,24 @@ async function startDaemon(options) {
|
|
|
57210
57825
|
port: options.port ?? loaded.port
|
|
57211
57826
|
})).port;
|
|
57212
57827
|
}
|
|
57828
|
+
clock2.phase("listeners");
|
|
57213
57829
|
return await initializeDaemon(
|
|
57214
57830
|
{ ...options, host: loaded, log },
|
|
57215
57831
|
server,
|
|
57216
57832
|
port,
|
|
57217
57833
|
(api) => {
|
|
57218
57834
|
ready = api;
|
|
57219
|
-
}
|
|
57835
|
+
},
|
|
57836
|
+
clock2
|
|
57220
57837
|
);
|
|
57221
57838
|
} catch (error) {
|
|
57222
57839
|
await server.close();
|
|
57223
57840
|
throw error;
|
|
57224
57841
|
}
|
|
57225
57842
|
}
|
|
57226
|
-
async function initializeDaemon(options, server, port, ready) {
|
|
57227
|
-
const paths = options.paths;
|
|
57843
|
+
async function initializeDaemon(options, server, port, ready, clock2) {
|
|
57844
|
+
const paths = withRecordedHarnessFiles(options.paths, options.host);
|
|
57845
|
+
const harnessHomes = recordedHarnessHomes(options.host);
|
|
57228
57846
|
const now = options.now ?? (() => Date.now());
|
|
57229
57847
|
const log = options.log;
|
|
57230
57848
|
const timers = { ...DEFAULT_TIMERS, ...options.timers };
|
|
@@ -57354,6 +57972,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57354
57972
|
},
|
|
57355
57973
|
(movedTo) => logSetAside("WAL cursor", movedTo)
|
|
57356
57974
|
);
|
|
57975
|
+
clock2.phase("setup");
|
|
57357
57976
|
for (const session of wal.sessions()) {
|
|
57358
57977
|
const outcome = wal.repairTail(session);
|
|
57359
57978
|
if (outcome !== "ok")
|
|
@@ -57362,6 +57981,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57362
57981
|
const orphanBodies = wal.repairOrphanBodies();
|
|
57363
57982
|
if (orphanBodies > 0)
|
|
57364
57983
|
log(`WAL removed ${orphanBodies} body lines a crash left with no event`);
|
|
57984
|
+
clock2.phase("WAL repair");
|
|
57365
57985
|
context.chainTail = (sessionUuid2) => {
|
|
57366
57986
|
const head2 = wal.lastEvent(sessionUuid2);
|
|
57367
57987
|
return head2 === void 0 ? void 0 : { ...cursorAfter(head2), stopped: head2.kind === "agent_stop" };
|
|
@@ -57374,16 +57994,21 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57374
57994
|
processStarts: hookProcessStarts,
|
|
57375
57995
|
adoptedChain: (sessionUuid2) => backfillLedger.chainHead(sessionUuid2)
|
|
57376
57996
|
});
|
|
57377
|
-
const priorStateWrittenAt = existsSync25(paths.daemonState) ?
|
|
57997
|
+
const priorStateWrittenAt = existsSync25(paths.daemonState) ? statSync15(paths.daemonState).mtimeMs : void 0;
|
|
57378
57998
|
const sealedState = parseSealedState(
|
|
57379
57999
|
readJsonStateFile(
|
|
57380
58000
|
paths.daemonSealedState,
|
|
57381
58001
|
(movedTo) => logSetAside("daemon sealed state", movedTo)
|
|
57382
58002
|
)
|
|
57383
58003
|
);
|
|
58004
|
+
let reconcileMs = 0;
|
|
58005
|
+
const reconcile = (state) => {
|
|
58006
|
+
const at2 = performance.now();
|
|
58007
|
+
reconcileRestoredCursor(state, wal, log);
|
|
58008
|
+
reconcileMs += performance.now() - at2;
|
|
58009
|
+
};
|
|
57384
58010
|
if (sealedState !== void 0) {
|
|
57385
|
-
for (const session of sealedState.sessions)
|
|
57386
|
-
reconcileRestoredCursor(session.recorder, wal, log);
|
|
58011
|
+
for (const session of sealedState.sessions) reconcile(session.recorder);
|
|
57387
58012
|
registry2.restore(
|
|
57388
58013
|
{ schema: "tacho.daemon-state.v1", sessions: sealedState.sessions },
|
|
57389
58014
|
{ sealedFile: true }
|
|
@@ -57396,8 +58021,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57396
58021
|
)
|
|
57397
58022
|
);
|
|
57398
58023
|
if (persisted !== void 0) {
|
|
57399
|
-
for (const session of persisted.sessions)
|
|
57400
|
-
reconcileRestoredCursor(session.recorder, wal, log);
|
|
58024
|
+
for (const session of persisted.sessions) reconcile(session.recorder);
|
|
57401
58025
|
registry2.restore(persisted);
|
|
57402
58026
|
}
|
|
57403
58027
|
const journaledHookIds = restoreHookIdJournal(
|
|
@@ -57405,6 +58029,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57405
58029
|
registry2,
|
|
57406
58030
|
(uuid) => wal.lastEvent(uuid)?.seq
|
|
57407
58031
|
);
|
|
58032
|
+
log(`startup phase cursor reconcile took ${Math.round(reconcileMs)}ms`);
|
|
58033
|
+
clock2.phase("state restore");
|
|
57408
58034
|
const bootId = `tachod-${ulid(now())}`;
|
|
57409
58035
|
const hostRecord = registry2.ensure(bootId, { pid: process.pid }).record;
|
|
57410
58036
|
const hostRecorder = hostRecord.recorder;
|
|
@@ -57521,7 +58147,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57521
58147
|
},
|
|
57522
58148
|
...options.workOrders?.spawn !== void 0 ? { spawn: options.workOrders.spawn } : {},
|
|
57523
58149
|
...options.workOrders?.isAlive !== void 0 ? { isAlive: options.workOrders.isAlive } : {},
|
|
57524
|
-
...options.workOrders?.findCheckout !== void 0 ? { findCheckout: options.workOrders.findCheckout } : {}
|
|
58150
|
+
...options.workOrders?.findCheckout !== void 0 ? { findCheckout: options.workOrders.findCheckout } : {},
|
|
58151
|
+
...options.workOrders?.wait !== void 0 ? { wait: options.workOrders.wait } : {}
|
|
57525
58152
|
});
|
|
57526
58153
|
void workOrderAutostart.clearDeadMarks();
|
|
57527
58154
|
function persistState(options2 = {}) {
|
|
@@ -57736,25 +58363,24 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57736
58363
|
});
|
|
57737
58364
|
}
|
|
57738
58365
|
async function applyCommandsRecorded(commands, deps) {
|
|
57739
|
-
|
|
57740
|
-
|
|
57741
|
-
|
|
57742
|
-
|
|
57743
|
-
|
|
57744
|
-
|
|
57745
|
-
|
|
57746
|
-
|
|
57747
|
-
|
|
58366
|
+
return applyCommands2(commands, {
|
|
58367
|
+
...deps,
|
|
58368
|
+
exclusive: (seal2) => queues.host(async () => {
|
|
58369
|
+
if (hostRecord.sealed) throw new Error(STOPPING);
|
|
58370
|
+
const marks = markCommandChains(commands);
|
|
58371
|
+
let result2;
|
|
58372
|
+
try {
|
|
58373
|
+
result2 = seal2();
|
|
58374
|
+
record(result2.events);
|
|
58375
|
+
return result2;
|
|
58376
|
+
} catch (error) {
|
|
58377
|
+
for (const { session, mark } of [...marks].reverse())
|
|
58378
|
+
session.recorder.rollbackChain(mark);
|
|
58379
|
+
result2?.restore();
|
|
58380
|
+
throw error;
|
|
57748
58381
|
}
|
|
57749
|
-
})
|
|
57750
|
-
|
|
57751
|
-
return result2;
|
|
57752
|
-
} catch (error) {
|
|
57753
|
-
for (const { session, mark } of [...marks].reverse())
|
|
57754
|
-
session.recorder.rollbackChain(mark);
|
|
57755
|
-
result2?.restore();
|
|
57756
|
-
throw error;
|
|
57757
|
-
}
|
|
58382
|
+
})
|
|
58383
|
+
});
|
|
57758
58384
|
}
|
|
57759
58385
|
let modelBaseUrls = [];
|
|
57760
58386
|
const spoolFacts = /* @__PURE__ */ new Map();
|
|
@@ -57876,6 +58502,31 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57876
58502
|
}
|
|
57877
58503
|
}
|
|
57878
58504
|
function retryOwedBodyPurge() {
|
|
58505
|
+
if (existsSync25(bodyPurgeOwedPath)) void settleOwedBodyPurge("owed");
|
|
58506
|
+
}
|
|
58507
|
+
let bodyPurge;
|
|
58508
|
+
let bodyPurgeAgain = false;
|
|
58509
|
+
let bodyPurgeNarrowing = false;
|
|
58510
|
+
function settleOwedBodyPurge(trigger) {
|
|
58511
|
+
if (trigger === "narrowed") bodyPurgeNarrowing = true;
|
|
58512
|
+
if (bodyPurge !== void 0) {
|
|
58513
|
+
bodyPurgeAgain = true;
|
|
58514
|
+
return bodyPurge;
|
|
58515
|
+
}
|
|
58516
|
+
const run3 = (async () => {
|
|
58517
|
+
do {
|
|
58518
|
+
bodyPurgeAgain = false;
|
|
58519
|
+
const narrowing = bodyPurgeNarrowing;
|
|
58520
|
+
bodyPurgeNarrowing = false;
|
|
58521
|
+
await sweepOwedBodies(narrowing);
|
|
58522
|
+
} while (bodyPurgeAgain && !stopped2);
|
|
58523
|
+
})().finally(() => {
|
|
58524
|
+
if (bodyPurge === run3) bodyPurge = void 0;
|
|
58525
|
+
});
|
|
58526
|
+
bodyPurge = run3;
|
|
58527
|
+
return run3;
|
|
58528
|
+
}
|
|
58529
|
+
async function sweepOwedBodies(narrowing) {
|
|
57879
58530
|
const owed = owedBodyPurge();
|
|
57880
58531
|
if (owed === void 0) return;
|
|
57881
58532
|
let clause = owed.retention;
|
|
@@ -57885,16 +58536,28 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57885
58536
|
clause = inForce.mandate;
|
|
57886
58537
|
}
|
|
57887
58538
|
try {
|
|
57888
|
-
const purged = wal.
|
|
58539
|
+
const purged = await wal.purgeBodiesOutsideMandateAsync(clause, {
|
|
58540
|
+
signal: stopping.signal
|
|
58541
|
+
}) + purgePendingEndBodies(clause);
|
|
57889
58542
|
purgeQueuedPrompts(clause);
|
|
57890
|
-
clearBodyPurgeOwed();
|
|
58543
|
+
if (!bodyPurgeAgain) clearBodyPurgeOwed();
|
|
57891
58544
|
log(
|
|
57892
|
-
`completed an owed body purge: erased ${purged} queued body(ies) the mandate does not cover`
|
|
58545
|
+
narrowing ? `mandate narrowed (${owed.classes.join(", ")}): erased ${purged} queued body(ies) from the WAL` : `completed an owed body purge: erased ${purged} queued body(ies) the mandate does not cover`
|
|
57893
58546
|
);
|
|
57894
58547
|
} catch (error) {
|
|
57895
|
-
|
|
57896
|
-
|
|
57897
|
-
|
|
58548
|
+
const reason3 = error instanceof Error ? error.message : String(error);
|
|
58549
|
+
if (stopping.signal.aborted)
|
|
58550
|
+
log(
|
|
58551
|
+
"stop: left an owed body purge unfinished; the next start finishes it"
|
|
58552
|
+
);
|
|
58553
|
+
else if (narrowing)
|
|
58554
|
+
log(
|
|
58555
|
+
`failed to erase bodies the narrowed mandate no longer covers (${owed.classes.join(", ")}); content remains in the WAL: ${reason3}; check free space and permissions under ${paths.wal}. The purge is retried at each bundle confirmation`
|
|
58556
|
+
);
|
|
58557
|
+
else
|
|
58558
|
+
log(
|
|
58559
|
+
`an owed body purge failed again; content remains in the WAL: ${reason3}; check free space and permissions under ${paths.wal}. The purge is retried at each bundle confirmation`
|
|
58560
|
+
);
|
|
57898
58561
|
}
|
|
57899
58562
|
}
|
|
57900
58563
|
function purgeQueuedPrompts(clause) {
|
|
@@ -57917,21 +58580,30 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57917
58580
|
const dropped = HOST_RETENTION_CLASSES.filter(
|
|
57918
58581
|
(contentClass) => retentionAllows(previous, contentClass) && !retentionAllows(next, contentClass)
|
|
57919
58582
|
);
|
|
57920
|
-
if (dropped.length === 0) return
|
|
57921
|
-
|
|
58583
|
+
if (dropped.length === 0) return "none";
|
|
58584
|
+
if (markBodyPurgeOwed(next, dropped)) {
|
|
58585
|
+
try {
|
|
58586
|
+
purgePendingEndBodies(next);
|
|
58587
|
+
purgeQueuedPrompts(next);
|
|
58588
|
+
} catch (error) {
|
|
58589
|
+
log(
|
|
58590
|
+
`failed to erase bodies the narrowed mandate no longer covers (${dropped.join(", ")}); content remains on disk: ${error instanceof Error ? error.message : String(error)}`
|
|
58591
|
+
);
|
|
58592
|
+
}
|
|
58593
|
+
return "owed";
|
|
58594
|
+
}
|
|
57922
58595
|
try {
|
|
57923
58596
|
const purged = wal.purgeBodiesOutsideMandate(next) + purgePendingEndBodies(next);
|
|
57924
58597
|
purgeQueuedPrompts(next);
|
|
57925
|
-
clearBodyPurgeOwed();
|
|
57926
58598
|
log(
|
|
57927
58599
|
`mandate narrowed (${dropped.join(", ")}): erased ${purged} queued body(ies) from the WAL`
|
|
57928
58600
|
);
|
|
57929
|
-
return
|
|
58601
|
+
return "swept";
|
|
57930
58602
|
} catch (error) {
|
|
57931
58603
|
log(
|
|
57932
58604
|
`failed to erase bodies the narrowed mandate no longer covers (${dropped.join(", ")}); content remains in the WAL: ${error instanceof Error ? error.message : String(error)}`
|
|
57933
58605
|
);
|
|
57934
|
-
return
|
|
58606
|
+
return "refused";
|
|
57935
58607
|
}
|
|
57936
58608
|
}
|
|
57937
58609
|
async function fetchBundle() {
|
|
@@ -57963,10 +58635,11 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57963
58635
|
);
|
|
57964
58636
|
return "refused";
|
|
57965
58637
|
}
|
|
57966
|
-
|
|
58638
|
+
const narrowing = purgeBodiesNarrowedOut(
|
|
57967
58639
|
host.bundle.retention,
|
|
57968
58640
|
response.bundle.retention
|
|
57969
|
-
)
|
|
58641
|
+
);
|
|
58642
|
+
if (narrowing === "refused") {
|
|
57970
58643
|
log(
|
|
57971
58644
|
"refusing to cache a narrowed bundle this host can neither enforce on disk nor remember owing; the old etag stands so the next poll retries"
|
|
57972
58645
|
);
|
|
@@ -57979,6 +58652,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57979
58652
|
bundleVerified = true;
|
|
57980
58653
|
mandateConfirmedAt = now();
|
|
57981
58654
|
log(`bundle ${response.bundle.version} (${response.bundle.etag}) cached`);
|
|
58655
|
+
if (narrowing === "owed") void settleOwedBodyPurge("narrowed");
|
|
57982
58656
|
return "cached";
|
|
57983
58657
|
} catch (error) {
|
|
57984
58658
|
log(
|
|
@@ -58341,7 +59015,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
58341
59015
|
lastIngestAt ?? -Infinity,
|
|
58342
59016
|
lastCommandPollAt ?? -Infinity
|
|
58343
59017
|
);
|
|
58344
|
-
|
|
59018
|
+
const pollEveryMs = registry2.live().some((session) => session !== hostRecord) ? timers.commandsPollMs : timers.commandsPollMs * IDLE_COMMAND_POLL_FACTOR;
|
|
59019
|
+
if (pendingAcks.length === 0 && now() - lastEnvelopeAt < pollEveryMs) {
|
|
58345
59020
|
return;
|
|
58346
59021
|
}
|
|
58347
59022
|
if (now() < commandPollNextAttemptAt) return;
|
|
@@ -58614,9 +59289,15 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
58614
59289
|
}) : void 0;
|
|
58615
59290
|
void drained?.catch(() => void 0);
|
|
58616
59291
|
const answer = await queues.session(harnessSessionId, async () => {
|
|
58617
|
-
|
|
58618
|
-
|
|
58619
|
-
|
|
59292
|
+
let inner;
|
|
59293
|
+
try {
|
|
59294
|
+
if (options2.refuseWhenStopping && stopped2) throw new Error(STOPPING);
|
|
59295
|
+
if (drained !== void 0) await drained;
|
|
59296
|
+
inner = await handleHookInner(envelope2, "session");
|
|
59297
|
+
return inner;
|
|
59298
|
+
} finally {
|
|
59299
|
+
options2.answered?.(inner?.response);
|
|
59300
|
+
}
|
|
58620
59301
|
});
|
|
58621
59302
|
if (answer.durable !== void 0) await answer.durable;
|
|
58622
59303
|
return answer.response;
|
|
@@ -58742,6 +59423,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
58742
59423
|
restoreEveryQueue(queued);
|
|
58743
59424
|
throw error;
|
|
58744
59425
|
}
|
|
59426
|
+
const workOrder = workOrderIdOf(envelope2.env?.[WORK_ORDER_ENV]);
|
|
59427
|
+
if (workOrder !== void 0) workOrderAutostart.noteSession(workOrder);
|
|
58745
59428
|
if (pending !== void 0) {
|
|
58746
59429
|
const state = registry2.state();
|
|
58747
59430
|
const key = sessionMapKey(harnessSessionId, {
|
|
@@ -59244,7 +59927,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59244
59927
|
const state = await readModelBaseUrlState({
|
|
59245
59928
|
home: options.home ?? homedir8(),
|
|
59246
59929
|
port: modelProxyPortFor(host),
|
|
59247
|
-
stellaHome: dirname26(
|
|
59930
|
+
stellaHome: dirname26(paths.stellaToml),
|
|
59931
|
+
...harnessHomes,
|
|
59248
59932
|
harnesses: ["claude-code", "codex", "stella"]
|
|
59249
59933
|
});
|
|
59250
59934
|
const next = {};
|
|
@@ -59568,18 +60252,24 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59568
60252
|
quarantineChanged();
|
|
59569
60253
|
return Promise.reject(readable.error);
|
|
59570
60254
|
}
|
|
59571
|
-
|
|
59572
|
-
|
|
59573
|
-
|
|
59574
|
-
|
|
59575
|
-
|
|
59576
|
-
|
|
59577
|
-
|
|
59578
|
-
);
|
|
60255
|
+
const waiterKey = envelope2.replay === void 0 && readable.data.agent_id === void 0 && STEER_WAIT_RELEASING_EVENTS.has(readable.data.hook_event_name) ? sessionMapKey(readable.data.session_id, {
|
|
60256
|
+
harness: envelope2.harness,
|
|
60257
|
+
customAgent: envelope2.agent
|
|
60258
|
+
}) : void 0;
|
|
60259
|
+
const arrivedAt = waiterKey !== void 0 ? now() : 0;
|
|
60260
|
+
const releasesAfterAnswer = waiterKey !== void 0 && STEER_WAIT_RELEASED_AFTER_ANSWER.has(readable.data.hook_event_name);
|
|
60261
|
+
if (waiterKey !== void 0 && !releasesAfterAnswer)
|
|
60262
|
+
steerWaiters.release(waiterKey, arrivedAt);
|
|
59579
60263
|
const timed = envelope2.answer_by === void 0 && envelope2.answer_within_ms !== void 0 ? { ...envelope2, answer_by: now() + envelope2.answer_within_ms } : envelope2;
|
|
59580
60264
|
return answerHook(timed, readable.data.session_id, {
|
|
59581
60265
|
drainSpoolFirst: true,
|
|
59582
|
-
refuseWhenStopping: true
|
|
60266
|
+
refuseWhenStopping: true,
|
|
60267
|
+
...waiterKey !== void 0 && releasesAfterAnswer ? {
|
|
60268
|
+
answered: (response) => {
|
|
60269
|
+
if (response === void 0 || !answerBlocksAgent(response))
|
|
60270
|
+
steerWaiters.release(waiterKey, arrivedAt);
|
|
60271
|
+
}
|
|
60272
|
+
} : {}
|
|
59583
60273
|
});
|
|
59584
60274
|
},
|
|
59585
60275
|
// Each session the post names takes the post's records on its own queue,
|
|
@@ -59736,6 +60426,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59736
60426
|
return exportSession(events, format);
|
|
59737
60427
|
}
|
|
59738
60428
|
};
|
|
60429
|
+
clock2.phase("services");
|
|
59739
60430
|
if (!hostRecorder.hasStarted) {
|
|
59740
60431
|
record([
|
|
59741
60432
|
hostRecorder.sealCollectorEvent("agent_start", {
|
|
@@ -59771,6 +60462,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59771
60462
|
);
|
|
59772
60463
|
}
|
|
59773
60464
|
}
|
|
60465
|
+
clock2.phase("restart gaps");
|
|
59774
60466
|
try {
|
|
59775
60467
|
const day = utcDay(now());
|
|
59776
60468
|
startupDaySpend = { day, micros: walDaySpendMicros(day) };
|
|
@@ -59779,7 +60471,9 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59779
60471
|
`day spend not read from the WAL at startup: ${error instanceof Error ? error.message : String(error)}`
|
|
59780
60472
|
);
|
|
59781
60473
|
}
|
|
60474
|
+
clock2.phase("day spend");
|
|
59782
60475
|
ready(api);
|
|
60476
|
+
clock2.ready();
|
|
59783
60477
|
servingSince = now();
|
|
59784
60478
|
if (options.listen ?? true) {
|
|
59785
60479
|
const unixSocket = (options.platform ?? process.platform) !== "win32";
|
|
@@ -59807,7 +60501,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59807
60501
|
if (!name.endsWith(".json")) continue;
|
|
59808
60502
|
const file = join47(paths.quarantine, name);
|
|
59809
60503
|
try {
|
|
59810
|
-
const refusedAt = readRefusedEntry(file)?.refusedAt ??
|
|
60504
|
+
const refusedAt = readRefusedEntry(file)?.refusedAt ?? statSync15(file).mtimeMs;
|
|
59811
60505
|
if (at2 - refusedAt < retainMs) continue;
|
|
59812
60506
|
unlinkSync13(file);
|
|
59813
60507
|
removed += 1;
|
|
@@ -60080,7 +60774,11 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60080
60774
|
else if (typeof refreshed === "object")
|
|
60081
60775
|
log(`ChatGPT login refresh: ${refreshed.failed}`);
|
|
60082
60776
|
if (refreshed !== "none")
|
|
60083
|
-
restateCodexLastRefresh(
|
|
60777
|
+
restateCodexLastRefresh(
|
|
60778
|
+
options.home ?? homedir8(),
|
|
60779
|
+
now(),
|
|
60780
|
+
harnessHomes
|
|
60781
|
+
);
|
|
60084
60782
|
} catch (error) {
|
|
60085
60783
|
log(
|
|
60086
60784
|
`ChatGPT login refresh: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -60093,6 +60791,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60093
60791
|
await renewStaticToken(harness, {
|
|
60094
60792
|
home: options.home ?? homedir8(),
|
|
60095
60793
|
stellaHome: dirname26(paths.stellaToml),
|
|
60794
|
+
...harnessHomes,
|
|
60096
60795
|
host,
|
|
60097
60796
|
runTokenKeyPath: paths.runTokenKey,
|
|
60098
60797
|
now,
|
|
@@ -60222,6 +60921,9 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60222
60921
|
drainSpool: () => queues.host(() => drainSpool()),
|
|
60223
60922
|
queues,
|
|
60224
60923
|
refreshBundle: () => refreshBundle({ force: true }),
|
|
60924
|
+
bodyPurgeIdle: async () => {
|
|
60925
|
+
while (bodyPurge !== void 0) await bodyPurge;
|
|
60926
|
+
},
|
|
60225
60927
|
workOrdersIdle: () => workOrderAutostart.idle(),
|
|
60226
60928
|
stop: async () => {
|
|
60227
60929
|
if (stopped2) return;
|
|
@@ -60240,7 +60942,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60240
60942
|
}
|
|
60241
60943
|
const [gitSettled, memorySettled] = await Promise.all([
|
|
60242
60944
|
settleWithin(gitLane, timers.stopLaneMs),
|
|
60243
|
-
settleWithin(memoryScan, timers.stopLaneMs)
|
|
60945
|
+
settleWithin(memoryScan, timers.stopLaneMs),
|
|
60946
|
+
settleWithin(bodyPurge, timers.stopLaneMs)
|
|
60244
60947
|
]);
|
|
60245
60948
|
if (!gitSettled)
|
|
60246
60949
|
log(
|
|
@@ -60281,7 +60984,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60281
60984
|
}
|
|
60282
60985
|
};
|
|
60283
60986
|
}
|
|
60284
|
-
var DEFAULT_TIMERS, STATIC_TOKEN_RENEWAL_CHECK_MS, CHATGPT_LOGIN_CHECK_MS, MEMORY_SCAN_MS, CLOUD_GATEWAY_ORIGIN, CLOUD_GATEWAY_BASE_PATH, QUEUED_PROMPT_CLASS, TRACE_DRAIN_TIMEOUT_MS, RECORDER_EVENTS_KEPT, owedBodyPurgeSchema, objectSchema, spoolFileSchema, otlpResourceListSchema, otlpPayloadSchema, defaultExecAsync, STOPPING, STOPPED_EXEC, STATE_WRITE_DEFER_MS;
|
|
60987
|
+
var IDLE_COMMAND_POLL_FACTOR, DEFAULT_TIMERS, STATIC_TOKEN_RENEWAL_CHECK_MS, CHATGPT_LOGIN_CHECK_MS, MEMORY_SCAN_MS, CLOUD_GATEWAY_ORIGIN, CLOUD_GATEWAY_BASE_PATH, QUEUED_PROMPT_CLASS, TRACE_DRAIN_TIMEOUT_MS, RECORDER_EVENTS_KEPT, owedBodyPurgeSchema, objectSchema, spoolFileSchema, otlpResourceListSchema, otlpPayloadSchema, defaultExecAsync, STOPPING, STOPPED_EXEC, STATE_WRITE_DEFER_MS;
|
|
60285
60988
|
var init_daemon = __esm({
|
|
60286
60989
|
"../../packages/tacho/src/collector/daemon.ts"() {
|
|
60287
60990
|
"use strict";
|
|
@@ -60357,6 +61060,7 @@ var init_daemon = __esm({
|
|
|
60357
61060
|
init_refused();
|
|
60358
61061
|
init_session_heads();
|
|
60359
61062
|
init_transcript_tailer();
|
|
61063
|
+
IDLE_COMMAND_POLL_FACTOR = 8;
|
|
60360
61064
|
DEFAULT_TIMERS = {
|
|
60361
61065
|
shipMs: 5e3,
|
|
60362
61066
|
bundleRefreshMs: 5 * 6e4,
|
|
@@ -60650,7 +61354,7 @@ import {
|
|
|
60650
61354
|
lstatSync as lstatSync8,
|
|
60651
61355
|
mkdirSync as mkdirSync7,
|
|
60652
61356
|
openSync as openSync8,
|
|
60653
|
-
readSync as
|
|
61357
|
+
readSync as readSync5,
|
|
60654
61358
|
realpathSync as realpathSync6,
|
|
60655
61359
|
writeFileSync as writeFileSync4
|
|
60656
61360
|
} from "node:fs";
|
|
@@ -60696,11 +61400,11 @@ function readBounded(root, relative11, limit = ARP_MAX_BLOB_BYTES) {
|
|
|
60696
61400
|
const bytes = Buffer.alloc(stat7.size);
|
|
60697
61401
|
let offset = 0;
|
|
60698
61402
|
while (offset < bytes.length) {
|
|
60699
|
-
const count12 =
|
|
61403
|
+
const count12 = readSync5(fd2, bytes, offset, bytes.length - offset, offset);
|
|
60700
61404
|
if (!count12) arpFail(`The bundle file ${relative11} changed while it was read.`);
|
|
60701
61405
|
offset += count12;
|
|
60702
61406
|
}
|
|
60703
|
-
if (
|
|
61407
|
+
if (readSync5(fd2, Buffer.alloc(1), 0, 1, offset) !== 0)
|
|
60704
61408
|
arpFail(`The bundle file ${relative11} changed while it was read.`);
|
|
60705
61409
|
return bytes;
|
|
60706
61410
|
} finally {
|
|
@@ -60883,13 +61587,13 @@ function verifySettledEvidence(events) {
|
|
|
60883
61587
|
}
|
|
60884
61588
|
}
|
|
60885
61589
|
if (tools.size || children.size || approvals.size) {
|
|
60886
|
-
const
|
|
61590
|
+
const open7 = [
|
|
60887
61591
|
...[...tools].map((id2) => `tool ${id2}`),
|
|
60888
61592
|
...[...approvals].map((id2) => `approval ${id2}`),
|
|
60889
61593
|
...[...children].map((id2) => `child work ${id2}`)
|
|
60890
61594
|
];
|
|
60891
61595
|
arpFail(
|
|
60892
|
-
`The source has unsettled tools, approvals, or child work at its boundary: ${
|
|
61596
|
+
`The source has unsettled tools, approvals, or child work at its boundary: ${open7.join(", ")}.`
|
|
60893
61597
|
);
|
|
60894
61598
|
}
|
|
60895
61599
|
const present = (value) => value !== void 0 && value !== null && value !== false && !(Array.isArray(value) && value.length === 0);
|
|
@@ -61621,7 +62325,7 @@ import {
|
|
|
61621
62325
|
lstatSync as lstatSync9,
|
|
61622
62326
|
mkdirSync as mkdirSync8,
|
|
61623
62327
|
openSync as openSync9,
|
|
61624
|
-
readSync as
|
|
62328
|
+
readSync as readSync6,
|
|
61625
62329
|
realpathSync as realpathSync7,
|
|
61626
62330
|
rmSync as rmSync9,
|
|
61627
62331
|
writeFileSync as writeFileSync5
|
|
@@ -61647,14 +62351,14 @@ function readRegular(label2, path2, limit) {
|
|
|
61647
62351
|
const bytes = Buffer.alloc(before.size);
|
|
61648
62352
|
let offset = 0;
|
|
61649
62353
|
while (offset < bytes.length) {
|
|
61650
|
-
const count12 =
|
|
62354
|
+
const count12 = readSync6(fd2, bytes, offset, bytes.length - offset, offset);
|
|
61651
62355
|
if (count12 === 0)
|
|
61652
62356
|
arpFail(
|
|
61653
62357
|
`${label2} ${path2} changed while it was read. Stop its writer and capture again.`
|
|
61654
62358
|
);
|
|
61655
62359
|
offset += count12;
|
|
61656
62360
|
}
|
|
61657
|
-
if (
|
|
62361
|
+
if (readSync6(fd2, Buffer.alloc(1), 0, 1, offset) !== 0)
|
|
61658
62362
|
arpFail(
|
|
61659
62363
|
`${label2} ${path2} grew while it was read. Stop its writer and capture again.`
|
|
61660
62364
|
);
|
|
@@ -62672,7 +63376,7 @@ var init_package = __esm({
|
|
|
62672
63376
|
"package.json"() {
|
|
62673
63377
|
package_default = {
|
|
62674
63378
|
name: "@oxagen/cli",
|
|
62675
|
-
version: "2.1.5-
|
|
63379
|
+
version: "2.1.5-73",
|
|
62676
63380
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
62677
63381
|
type: "module",
|
|
62678
63382
|
main: "./dist/index.js",
|
|
@@ -62768,7 +63472,7 @@ var init_atomic_write = __esm({
|
|
|
62768
63472
|
// src/lib/config.ts
|
|
62769
63473
|
import { homedir as homedir9 } from "os";
|
|
62770
63474
|
import { join as join51 } from "path";
|
|
62771
|
-
import { readFileSync as readFileSync25, mkdirSync as mkdirSync9, existsSync as existsSync27, statSync as
|
|
63475
|
+
import { readFileSync as readFileSync25, mkdirSync as mkdirSync9, existsSync as existsSync27, statSync as statSync16 } from "fs";
|
|
62772
63476
|
function getConfigDir() {
|
|
62773
63477
|
return CONFIG_DIR;
|
|
62774
63478
|
}
|
|
@@ -62798,7 +63502,7 @@ function parseConfig(raw) {
|
|
|
62798
63502
|
function readConfig() {
|
|
62799
63503
|
let identity;
|
|
62800
63504
|
try {
|
|
62801
|
-
const info =
|
|
63505
|
+
const info = statSync16(CONFIG_FILE);
|
|
62802
63506
|
identity = `${info.ino}:${info.size}:${info.mtimeMs}`;
|
|
62803
63507
|
} catch {
|
|
62804
63508
|
cached2 = void 0;
|
|
@@ -78078,7 +78782,7 @@ var init_json_wire = __esm({
|
|
|
78078
78782
|
|
|
78079
78783
|
// ../../packages/run-evidence/src/contextgraph.ts
|
|
78080
78784
|
function defineReadonly(target2, key, value) {
|
|
78081
|
-
|
|
78785
|
+
intrinsicObjectDefineProperty(target2, key, {
|
|
78082
78786
|
configurable: false,
|
|
78083
78787
|
enumerable: true,
|
|
78084
78788
|
value,
|
|
@@ -78086,13 +78790,13 @@ function defineReadonly(target2, key, value) {
|
|
|
78086
78790
|
});
|
|
78087
78791
|
}
|
|
78088
78792
|
function createIndexedSnapshot(length) {
|
|
78089
|
-
const snapshot =
|
|
78793
|
+
const snapshot = intrinsicObjectCreate(null);
|
|
78090
78794
|
defineReadonly(snapshot, "length", length);
|
|
78091
78795
|
return snapshot;
|
|
78092
78796
|
}
|
|
78093
78797
|
function captureDescriptor(descriptor) {
|
|
78094
|
-
const isData =
|
|
78095
|
-
const snapshot =
|
|
78798
|
+
const isData = intrinsicObjectHasOwn(descriptor, "value");
|
|
78799
|
+
const snapshot = intrinsicObjectCreate(null);
|
|
78096
78800
|
defineReadonly(snapshot, "configurable", descriptor.configurable === true);
|
|
78097
78801
|
defineReadonly(snapshot, "enumerable", descriptor.enumerable === true);
|
|
78098
78802
|
defineReadonly(snapshot, "isData", isData);
|
|
@@ -78104,29 +78808,29 @@ function captureDescriptor(descriptor) {
|
|
|
78104
78808
|
defineReadonly(snapshot, "value", isData ? descriptor.value : void 0);
|
|
78105
78809
|
defineReadonly(snapshot, "get", isData ? void 0 : descriptor.get);
|
|
78106
78810
|
defineReadonly(snapshot, "set", isData ? void 0 : descriptor.set);
|
|
78107
|
-
return
|
|
78811
|
+
return intrinsicObjectFreeze(snapshot);
|
|
78108
78812
|
}
|
|
78109
78813
|
function capturePrototype(label2, target2) {
|
|
78110
|
-
const keys =
|
|
78814
|
+
const keys = intrinsicReflectOwnKeys(target2);
|
|
78111
78815
|
const entries2 = createIndexedSnapshot(keys.length);
|
|
78112
78816
|
for (let index = 0; index < keys.length; index += 1) {
|
|
78113
78817
|
const key = keys[index];
|
|
78114
|
-
const descriptor =
|
|
78818
|
+
const descriptor = intrinsicObjectGetOwnPropertyDescriptor(
|
|
78115
78819
|
target2,
|
|
78116
78820
|
key
|
|
78117
78821
|
);
|
|
78118
|
-
const entry2 =
|
|
78822
|
+
const entry2 = intrinsicObjectCreate(null);
|
|
78119
78823
|
defineReadonly(entry2, "key", key);
|
|
78120
78824
|
defineReadonly(entry2, "descriptor", captureDescriptor(descriptor));
|
|
78121
|
-
defineReadonly(entries2,
|
|
78825
|
+
defineReadonly(entries2, `${index}`, intrinsicObjectFreeze(entry2));
|
|
78122
78826
|
}
|
|
78123
|
-
const snapshot =
|
|
78827
|
+
const snapshot = intrinsicObjectCreate(null);
|
|
78124
78828
|
defineReadonly(snapshot, "label", label2);
|
|
78125
78829
|
defineReadonly(snapshot, "target", target2);
|
|
78126
|
-
defineReadonly(snapshot, "entries",
|
|
78127
|
-
return
|
|
78830
|
+
defineReadonly(snapshot, "entries", intrinsicObjectFreeze(entries2));
|
|
78831
|
+
return intrinsicObjectFreeze(snapshot);
|
|
78128
78832
|
}
|
|
78129
|
-
var intrinsicMathFround, intrinsicNumberIsFinite2, intrinsicObjectIs, u32Schema, finiteNumberSchema, f32NumberSchema, protectedPrototypes, contextFrameKindV1Schema, contextProvenanceV1Schema, contextFrameEmbeddingV1Schema, contextRelationV1Schema, contextRepresentationV1Schema, contextContentFidelityV1Schema, contextInlineContentRequirementV1Schema, contextContentRefV1Schema, contextTransformV1Schema, contextFrameObjectV1Schema, contextFrameV1Schema, contextQueryV1Schema;
|
|
78833
|
+
var intrinsicMathFround, intrinsicNumberIsFinite2, intrinsicObjectCreate, intrinsicObjectDefineProperty, intrinsicObjectFreeze, intrinsicObjectGetOwnPropertyDescriptor, intrinsicObjectHasOwn, intrinsicObjectIs, intrinsicReflectOwnKeys, u32Schema, finiteNumberSchema, f32NumberSchema, protectedTargets, protectedPrototypes, contextFrameKindV1Schema, contextProvenanceV1Schema, contextFrameEmbeddingV1Schema, contextRelationV1Schema, contextRepresentationV1Schema, contextContentFidelityV1Schema, contextInlineContentRequirementV1Schema, contextContentRefV1Schema, contextTransformV1Schema, contextFrameObjectV1Schema, contextFrameV1Schema, contextQueryV1Schema;
|
|
78130
78834
|
var init_contextgraph = __esm({
|
|
78131
78835
|
"../../packages/run-evidence/src/contextgraph.ts"() {
|
|
78132
78836
|
"use strict";
|
|
@@ -78135,7 +78839,13 @@ var init_contextgraph = __esm({
|
|
|
78135
78839
|
init_json_wire();
|
|
78136
78840
|
intrinsicMathFround = Math.fround;
|
|
78137
78841
|
intrinsicNumberIsFinite2 = Number.isFinite;
|
|
78842
|
+
intrinsicObjectCreate = Object.create;
|
|
78843
|
+
intrinsicObjectDefineProperty = Object.defineProperty;
|
|
78844
|
+
intrinsicObjectFreeze = Object.freeze;
|
|
78845
|
+
intrinsicObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
78846
|
+
intrinsicObjectHasOwn = Object.hasOwn;
|
|
78138
78847
|
intrinsicObjectIs = Object.is;
|
|
78848
|
+
intrinsicReflectOwnKeys = Reflect.ownKeys;
|
|
78139
78849
|
u32Schema = external_exports.number().int().min(0).max(4294967295).refine((value) => !intrinsicObjectIs(value, -0), {
|
|
78140
78850
|
message: "u32 value must not be negative zero"
|
|
78141
78851
|
});
|
|
@@ -78144,28 +78854,27 @@ var init_contextgraph = __esm({
|
|
|
78144
78854
|
(value) => intrinsicNumberIsFinite2(intrinsicMathFround(value)),
|
|
78145
78855
|
{ message: "embedding value must be representable as a finite f32" }
|
|
78146
78856
|
);
|
|
78147
|
-
|
|
78148
|
-
|
|
78149
|
-
|
|
78150
|
-
"
|
|
78151
|
-
|
|
78152
|
-
|
|
78153
|
-
|
|
78154
|
-
|
|
78155
|
-
|
|
78156
|
-
|
|
78157
|
-
|
|
78158
|
-
|
|
78159
|
-
|
|
78160
|
-
|
|
78161
|
-
|
|
78162
|
-
|
|
78163
|
-
|
|
78164
|
-
|
|
78165
|
-
|
|
78166
|
-
|
|
78167
|
-
);
|
|
78168
|
-
Object.freeze(protectedPrototypes);
|
|
78857
|
+
protectedTargets = [
|
|
78858
|
+
["Array.prototype", Array.prototype],
|
|
78859
|
+
["Object.prototype", Object.prototype],
|
|
78860
|
+
["Set.prototype", Set.prototype],
|
|
78861
|
+
["String.prototype", String.prototype],
|
|
78862
|
+
["Object", Object],
|
|
78863
|
+
["Reflect", Reflect],
|
|
78864
|
+
["JSON", JSON]
|
|
78865
|
+
];
|
|
78866
|
+
protectedPrototypes = createIndexedSnapshot(
|
|
78867
|
+
protectedTargets.length
|
|
78868
|
+
);
|
|
78869
|
+
for (let index = 0; index < protectedTargets.length; index += 1) {
|
|
78870
|
+
const [label2, target2] = protectedTargets[index];
|
|
78871
|
+
defineReadonly(
|
|
78872
|
+
protectedPrototypes,
|
|
78873
|
+
`${index}`,
|
|
78874
|
+
capturePrototype(label2, target2)
|
|
78875
|
+
);
|
|
78876
|
+
}
|
|
78877
|
+
intrinsicObjectFreeze(protectedPrototypes);
|
|
78169
78878
|
contextFrameKindV1Schema = external_exports.enum([
|
|
78170
78879
|
"snippet",
|
|
78171
78880
|
"symbol",
|
|
@@ -82174,6 +82883,16 @@ var init_run_list = __esm({
|
|
|
82174
82883
|
* when the read did not look.
|
|
82175
82884
|
*/
|
|
82176
82885
|
tokens: tokenCountsSchema.nullable().optional(),
|
|
82886
|
+
/**
|
|
82887
|
+
* `cost.run_totals.model_calls` and `tool_calls`: the model calls and
|
|
82888
|
+
* tool calls the run's rollup row counted (#4391). A wrapped run whose
|
|
82889
|
+
* row holds tool calls and no model call made its model calls where no
|
|
82890
|
+
* frame could report them, the rule `get_spend` counts such runs by.
|
|
82891
|
+
* Null when the run has no rollup row. Absent when the read did not
|
|
82892
|
+
* look.
|
|
82893
|
+
*/
|
|
82894
|
+
modelCalls: external_exports.number().int().nonnegative().nullable().optional(),
|
|
82895
|
+
toolCalls: external_exports.number().int().nonnegative().nullable().optional(),
|
|
82177
82896
|
/**
|
|
82178
82897
|
* `cost.run_totals.cache_hit_rate`: cache reads over uncached input plus
|
|
82179
82898
|
* cache reads, weighted by spend over the run's frames, from 0 to 1. Null
|
|
@@ -87507,7 +88226,7 @@ __export(verify_exports, {
|
|
|
87507
88226
|
readBundle: () => readBundle,
|
|
87508
88227
|
verifyBundle: () => verifyBundle3
|
|
87509
88228
|
});
|
|
87510
|
-
import { existsSync as existsSync30, readFileSync as readFileSync27, statSync as
|
|
88229
|
+
import { existsSync as existsSync30, readFileSync as readFileSync27, statSync as statSync17 } from "node:fs";
|
|
87511
88230
|
import { join as join61 } from "node:path";
|
|
87512
88231
|
function readDirectory(dir) {
|
|
87513
88232
|
const read2 = (name) => {
|
|
@@ -87558,7 +88277,7 @@ function readBundle(path2) {
|
|
|
87558
88277
|
if (!existsSync30(path2)) {
|
|
87559
88278
|
throw new BundleReadError(`${path2} does not exist.`);
|
|
87560
88279
|
}
|
|
87561
|
-
return
|
|
88280
|
+
return statSync17(path2).isDirectory() ? readDirectory(path2) : readZip(path2);
|
|
87562
88281
|
}
|
|
87563
88282
|
function plural3(count12, one, many) {
|
|
87564
88283
|
return `${count12} ${count12 === 1 ? one : many}`;
|
|
@@ -91257,7 +91976,7 @@ var init_upstream_tool = __esm({
|
|
|
91257
91976
|
});
|
|
91258
91977
|
|
|
91259
91978
|
// ../../packages/mcp-studio/src/contract/lock.ts
|
|
91260
|
-
var LOCK_BYTES_MAX, serverVersionSchema, lockPackageSchema, pypiLockFileSchema, fileOnlyForPypi, registryLockPackageSchema, remoteLockSourceSchema, urlOrPackage, transportOnlyWithUrl, launchOnlyWithPackage, registryLockSourceSchema, localLockSourceSchema, mcpLockSourceSchema, DEFINITION_LABELS, fromFitsType, definitionLockSourceSchema, versionSchema, definitionHashSchema, upstreamHashSchema, mcpLockedToolSchema, definitionLockedToolSchema, mcpLockSchema, definitionLockSchema, mcpToolsLockSchema;
|
|
91979
|
+
var LOCK_BYTES_MAX, PACKAGE_NAME_MAX, PACKAGE_VERSION_MAX, LAUNCH_ARG_MAX, LAUNCH_ARGS_MAX, serverVersionSchema, lockPackageSchema, pypiLockFileSchema, fileOnlyForPypi, registryLockPackageSchema, remoteLockSourceSchema, urlOrPackage, transportOnlyWithUrl, launchOnlyWithPackage, registryLockSourceSchema, localLockSourceSchema, mcpLockSourceSchema, DEFINITION_LABELS, fromFitsType, definitionLockSourceSchema, versionSchema, definitionHashSchema, upstreamHashSchema, mcpLockedToolSchema, definitionLockedToolSchema, mcpLockSchema, definitionLockSchema, mcpToolsLockSchema;
|
|
91261
91980
|
var init_lock = __esm({
|
|
91262
91981
|
"../../packages/mcp-studio/src/contract/lock.ts"() {
|
|
91263
91982
|
"use strict";
|
|
@@ -91270,14 +91989,18 @@ var init_lock = __esm({
|
|
|
91270
91989
|
init_primitives();
|
|
91271
91990
|
init_server2();
|
|
91272
91991
|
LOCK_BYTES_MAX = 5 * 1024 * 1024;
|
|
91992
|
+
PACKAGE_NAME_MAX = 214;
|
|
91993
|
+
PACKAGE_VERSION_MAX = 64;
|
|
91994
|
+
LAUNCH_ARG_MAX = 4096;
|
|
91995
|
+
LAUNCH_ARGS_MAX = 1024;
|
|
91273
91996
|
serverVersionSchema = external_exports.string().min(1).max(64).optional().describe(
|
|
91274
91997
|
"The version the server reported in initialize, when it reported one."
|
|
91275
91998
|
);
|
|
91276
91999
|
lockPackageSchema = external_exports.object({
|
|
91277
|
-
name: external_exports.string().min(1).max(
|
|
92000
|
+
name: external_exports.string().min(1).max(PACKAGE_NAME_MAX).describe(
|
|
91278
92001
|
"The package or binary: @modelcontextprotocol/server-filesystem."
|
|
91279
92002
|
),
|
|
91280
|
-
version: external_exports.string().min(1).max(
|
|
92003
|
+
version: external_exports.string().min(1).max(PACKAGE_VERSION_MAX),
|
|
91281
92004
|
digest: sha256Schema2.describe("SHA-256 of the package or binary.")
|
|
91282
92005
|
}).strict();
|
|
91283
92006
|
pypiLockFileSchema = external_exports.object({
|
|
@@ -91380,7 +92103,7 @@ var init_lock = __esm({
|
|
|
91380
92103
|
command: external_exports.string().min(1).max(1024).optional().describe(
|
|
91381
92104
|
"For a package: the command the local gateway runs, npx, uvx, docker, or dnx."
|
|
91382
92105
|
),
|
|
91383
|
-
args: external_exports.array(external_exports.string().max(
|
|
92106
|
+
args: external_exports.array(external_exports.string().max(LAUNCH_ARG_MAX)).max(LAUNCH_ARGS_MAX).optional().describe(
|
|
91384
92107
|
"For a package: the command's arguments. ${NAME} stays for the local gateway to fill from the machine, and $$ writes one $."
|
|
91385
92108
|
),
|
|
91386
92109
|
server_version: serverVersionSchema
|
|
@@ -92039,6 +92762,9 @@ function keyProblems(all, given, type) {
|
|
|
92039
92762
|
}
|
|
92040
92763
|
return problems;
|
|
92041
92764
|
}
|
|
92765
|
+
function fromPackage(texts) {
|
|
92766
|
+
return texts.map((text5) => ({ text: text5, field: "source.registry_type" }));
|
|
92767
|
+
}
|
|
92042
92768
|
function words(slot, given, problems) {
|
|
92043
92769
|
const { argument, label: label2, key } = slot;
|
|
92044
92770
|
const field = key === void 0 ? "source.registry_type" : `source.arguments.${key}`;
|
|
@@ -92078,7 +92804,38 @@ function words(slot, given, problems) {
|
|
|
92078
92804
|
}
|
|
92079
92805
|
return [];
|
|
92080
92806
|
}
|
|
92081
|
-
|
|
92807
|
+
const valueWord = { text: value, field };
|
|
92808
|
+
return argument.type === "named" ? [...fromPackage([literal2(argument.name)]), valueWord] : [valueWord];
|
|
92809
|
+
}
|
|
92810
|
+
function lockLimitProblems(type, pkg, version2, launch) {
|
|
92811
|
+
const problems = [];
|
|
92812
|
+
if (pkg.identifier.length > PACKAGE_NAME_MAX) {
|
|
92813
|
+
problems.push({
|
|
92814
|
+
field: "source.registry_type",
|
|
92815
|
+
message: `the ${type} package's identifier is ${pkg.identifier.length} characters long, and the lock holds at most ${PACKAGE_NAME_MAX}`
|
|
92816
|
+
});
|
|
92817
|
+
}
|
|
92818
|
+
if (version2.length > PACKAGE_VERSION_MAX) {
|
|
92819
|
+
problems.push({
|
|
92820
|
+
field: "source.registry_type",
|
|
92821
|
+
message: `the ${type} package's version is ${version2.length} characters long, and the lock holds at most ${PACKAGE_VERSION_MAX}`
|
|
92822
|
+
});
|
|
92823
|
+
}
|
|
92824
|
+
launch.forEach(({ text: text5, field }, index) => {
|
|
92825
|
+
if (text5.length > LAUNCH_ARG_MAX) {
|
|
92826
|
+
problems.push({
|
|
92827
|
+
field,
|
|
92828
|
+
message: `args[${index}] is ${text5.length} characters long once each $ is written $$, and the lock holds at most ${LAUNCH_ARG_MAX}`
|
|
92829
|
+
});
|
|
92830
|
+
}
|
|
92831
|
+
});
|
|
92832
|
+
if (launch.length > LAUNCH_ARGS_MAX) {
|
|
92833
|
+
problems.push({
|
|
92834
|
+
field: "source.registry_type",
|
|
92835
|
+
message: `the ${type} package's launch has ${launch.length} args, and the lock holds at most ${LAUNCH_ARGS_MAX}`
|
|
92836
|
+
});
|
|
92837
|
+
}
|
|
92838
|
+
return problems;
|
|
92082
92839
|
}
|
|
92083
92840
|
function registryLaunch({
|
|
92084
92841
|
source,
|
|
@@ -92144,18 +92901,22 @@ function registryLaunch({
|
|
|
92144
92901
|
const reference = pinned !== void 0 ? ["--from", literal2(pinned.url), literal2(pkg.identifier)] : [
|
|
92145
92902
|
`${literal2(pkg.identifier)}@${runner.pin === "digest" ? digest6 : literal2(version2)}`
|
|
92146
92903
|
];
|
|
92147
|
-
const
|
|
92148
|
-
...runner.flags,
|
|
92149
|
-
...type === "oci" ? env.flatMap((name) => [
|
|
92904
|
+
const launch = [
|
|
92905
|
+
...fromPackage(runner.flags),
|
|
92906
|
+
...type === "oci" ? env.flatMap((name) => [
|
|
92907
|
+
...fromPackage(["-e"]),
|
|
92908
|
+
{ text: name, field: "source.env" }
|
|
92909
|
+
]) : [],
|
|
92150
92910
|
...runtime.flatMap((slot) => words(slot, given, problems)),
|
|
92151
|
-
...reference,
|
|
92911
|
+
...fromPackage(reference),
|
|
92152
92912
|
...packaged.flatMap((slot) => words(slot, given, problems))
|
|
92153
92913
|
];
|
|
92914
|
+
problems.push(...lockLimitProblems(type, pkg, version2, launch));
|
|
92154
92915
|
if (problems.length > 0) return { ok: false, problems };
|
|
92155
92916
|
return {
|
|
92156
92917
|
ok: true,
|
|
92157
92918
|
command: runner.command,
|
|
92158
|
-
args,
|
|
92919
|
+
args: launch.map((word) => word.text),
|
|
92159
92920
|
package: {
|
|
92160
92921
|
name: pkg.identifier,
|
|
92161
92922
|
version: version2,
|
|
@@ -92169,6 +92930,7 @@ var REGISTRY_RUNNERS2, ONE_VARIABLE;
|
|
|
92169
92930
|
var init_registry_launch = __esm({
|
|
92170
92931
|
"../../packages/mcp-studio/src/model/registry-launch.ts"() {
|
|
92171
92932
|
"use strict";
|
|
92933
|
+
init_lock();
|
|
92172
92934
|
REGISTRY_RUNNERS2 = {
|
|
92173
92935
|
npm: { command: "npx", flags: ["--yes"], pin: "version" },
|
|
92174
92936
|
pypi: { command: "uvx", flags: [], pin: "file" },
|
|
@@ -106314,15 +107076,15 @@ var init_print = __esm({
|
|
|
106314
107076
|
// ── Extensions ─────────────────────────────────────────────────────────────
|
|
106315
107077
|
/** `extend` blocks, one for each run of extensions of the same message. */
|
|
106316
107078
|
extensions(fields, scope, path2) {
|
|
106317
|
-
let
|
|
107079
|
+
let open7;
|
|
106318
107080
|
fields.forEach((field, index) => {
|
|
106319
107081
|
const where = `the extension ${scope === "" ? "" : `${scope}.`}${field.name}`;
|
|
106320
107082
|
if (field.extendee === "")
|
|
106321
107083
|
this.refuse(`${where} names no message to extend`);
|
|
106322
107084
|
if (isFieldSet(field, FieldDescriptorProtoSchema.field.oneofIndex))
|
|
106323
107085
|
this.refuse(`${where} is in a oneof`);
|
|
106324
|
-
if (field.extendee !==
|
|
106325
|
-
if (
|
|
107086
|
+
if (field.extendee !== open7) {
|
|
107087
|
+
if (open7 !== void 0) this.close();
|
|
106326
107088
|
const extendee = this.typeName(
|
|
106327
107089
|
field.extendee,
|
|
106328
107090
|
scope,
|
|
@@ -106332,7 +107094,7 @@ var init_print = __esm({
|
|
|
106332
107094
|
this.gap();
|
|
106333
107095
|
this.line(`extend ${extendee} {`);
|
|
106334
107096
|
this.depth += 1;
|
|
106335
|
-
|
|
107097
|
+
open7 = field.extendee;
|
|
106336
107098
|
}
|
|
106337
107099
|
this.comment([...path2, index]);
|
|
106338
107100
|
this.line(
|
|
@@ -106345,7 +107107,7 @@ var init_print = __esm({
|
|
|
106345
107107
|
)
|
|
106346
107108
|
);
|
|
106347
107109
|
});
|
|
106348
|
-
if (
|
|
107110
|
+
if (open7 !== void 0) this.close();
|
|
106349
107111
|
}
|
|
106350
107112
|
// ── Options ────────────────────────────────────────────────────────────────
|
|
106351
107113
|
/**
|
|
@@ -106841,7 +107603,7 @@ function importOrder(sources, loaded) {
|
|
|
106841
107603
|
const done = /* @__PURE__ */ new Set();
|
|
106842
107604
|
const stack = [];
|
|
106843
107605
|
const onStack = /* @__PURE__ */ new Set();
|
|
106844
|
-
const
|
|
107606
|
+
const open7 = (name, importer) => {
|
|
106845
107607
|
const entry2 = load(name, importer, sources);
|
|
106846
107608
|
loaded.set(name, entry2);
|
|
106847
107609
|
const imports = entry2.kind === "source" ? entry2.parsed.header.imports.map((each) => each.path) : entry2.proto.dependency;
|
|
@@ -106850,7 +107612,7 @@ function importOrder(sources, loaded) {
|
|
|
106850
107612
|
};
|
|
106851
107613
|
for (const root of [...sources.keys()].sort()) {
|
|
106852
107614
|
if (done.has(root)) continue;
|
|
106853
|
-
|
|
107615
|
+
open7(root, void 0);
|
|
106854
107616
|
for (let top = stack.at(-1); top !== void 0; top = stack.at(-1)) {
|
|
106855
107617
|
const next = top.imports[top.next];
|
|
106856
107618
|
top.next += 1;
|
|
@@ -106863,7 +107625,7 @@ function importOrder(sources, loaded) {
|
|
|
106863
107625
|
const at2 = stack.findIndex((frame) => frame.name === next);
|
|
106864
107626
|
throw cycle([...stack.slice(at2).map((frame) => frame.name), next]);
|
|
106865
107627
|
} else if (!done.has(next)) {
|
|
106866
|
-
|
|
107628
|
+
open7(next, top.name);
|
|
106867
107629
|
}
|
|
106868
107630
|
}
|
|
106869
107631
|
}
|
|
@@ -107350,8 +108112,8 @@ var init_json_schema4 = __esm({
|
|
|
107350
108112
|
description: `Cut: messages nest past ${DEPTH_MAX} levels here.`
|
|
107351
108113
|
};
|
|
107352
108114
|
}
|
|
107353
|
-
const
|
|
107354
|
-
if (
|
|
108115
|
+
const open7 = this.active.get(name) ?? 0;
|
|
108116
|
+
if (open7 >= RECURSION_DEPTH) {
|
|
107355
108117
|
this.note(
|
|
107356
108118
|
`Import cut the recursive message ${name} at depth ${RECURSION_DEPTH}.`
|
|
107357
108119
|
);
|
|
@@ -107369,12 +108131,12 @@ var init_json_schema4 = __esm({
|
|
|
107369
108131
|
description: `Cut: this tool's schemas passed ${count8(TOOL_NODES_SOFT_MAX)} nodes.`
|
|
107370
108132
|
};
|
|
107371
108133
|
}
|
|
107372
|
-
this.active.set(name,
|
|
108134
|
+
this.active.set(name, open7 + 1);
|
|
107373
108135
|
try {
|
|
107374
108136
|
return this.fieldsOf(desc, direction, depth);
|
|
107375
108137
|
} finally {
|
|
107376
|
-
if (
|
|
107377
|
-
else this.active.set(name,
|
|
108138
|
+
if (open7 === 0) this.active.delete(name);
|
|
108139
|
+
else this.active.set(name, open7);
|
|
107378
108140
|
}
|
|
107379
108141
|
}
|
|
107380
108142
|
fieldsOf(desc, direction, depth) {
|
|
@@ -107890,7 +108652,7 @@ function selectOutput(outputSchema, select) {
|
|
|
107890
108652
|
return trimObject(outputSchema, selectTree(select));
|
|
107891
108653
|
}
|
|
107892
108654
|
function selectionProblem(selection) {
|
|
107893
|
-
const
|
|
108655
|
+
const open7 = [];
|
|
107894
108656
|
let quoted3 = false;
|
|
107895
108657
|
for (let index = 0; index < selection.length; index += 1) {
|
|
107896
108658
|
const char = selection[index];
|
|
@@ -107900,15 +108662,15 @@ function selectionProblem(selection) {
|
|
|
107900
108662
|
continue;
|
|
107901
108663
|
}
|
|
107902
108664
|
if (char === '"') quoted3 = true;
|
|
107903
|
-
else if (char === "{" || char === "(")
|
|
108665
|
+
else if (char === "{" || char === "(") open7.push(char);
|
|
107904
108666
|
else if (char === "}" || char === ")") {
|
|
107905
108667
|
const expected = char === "}" ? "{" : "(";
|
|
107906
|
-
if (
|
|
108668
|
+
if (open7.pop() !== expected)
|
|
107907
108669
|
return `selection has an unmatched ${char} at character ${index + 1}.`;
|
|
107908
108670
|
}
|
|
107909
108671
|
}
|
|
107910
108672
|
if (quoted3) return "selection has a string with no closing quote.";
|
|
107911
|
-
const unclosed =
|
|
108673
|
+
const unclosed = open7.pop();
|
|
107912
108674
|
if (unclosed !== void 0) return `selection has an unclosed ${unclosed}.`;
|
|
107913
108675
|
if (!/[_A-Za-z]/.test(selection)) return "selection names no field.";
|
|
107914
108676
|
return void 0;
|
|
@@ -109691,8 +110453,7 @@ function locationWithoutQuery(location) {
|
|
|
109691
110453
|
url = new URL(location);
|
|
109692
110454
|
} catch {
|
|
109693
110455
|
const cut = location.search(/[?#]/);
|
|
109694
|
-
|
|
109695
|
-
return head2.replace(/^\/\/[^/]*@/, "//");
|
|
110456
|
+
return withoutUserinfo(cut === -1 ? location : location.slice(0, cut));
|
|
109696
110457
|
}
|
|
109697
110458
|
url.username = "";
|
|
109698
110459
|
url.password = "";
|
|
@@ -109700,6 +110461,13 @@ function locationWithoutQuery(location) {
|
|
|
109700
110461
|
url.hash = "";
|
|
109701
110462
|
return url.href;
|
|
109702
110463
|
}
|
|
110464
|
+
function withoutUserinfo(head2) {
|
|
110465
|
+
const match = UNPARSED_USERINFO.exec(head2);
|
|
110466
|
+
if (match === null) return head2;
|
|
110467
|
+
const prefix = match[1] ?? "";
|
|
110468
|
+
const rest = head2.slice(match[0].length);
|
|
110469
|
+
return rest === "" || /^[\\/]/.test(rest) ? `${prefix}@${rest}` : `${prefix}${rest}`;
|
|
110470
|
+
}
|
|
109703
110471
|
function recordedResponseHeaders(headers) {
|
|
109704
110472
|
const out = /* @__PURE__ */ new Map();
|
|
109705
110473
|
for (const [name, raw] of headers) {
|
|
@@ -109733,12 +110501,13 @@ function recordHttpResponse(response, bytes) {
|
|
|
109733
110501
|
...body2 === void 0 ? {} : { body: body2 }
|
|
109734
110502
|
};
|
|
109735
110503
|
}
|
|
109736
|
-
var REFUSED_RESPONSE_HEADERS;
|
|
110504
|
+
var UNPARSED_USERINFO, REFUSED_RESPONSE_HEADERS;
|
|
109737
110505
|
var init_exchange = __esm({
|
|
109738
110506
|
"../../packages/mcp-studio/src/execute/exchange.ts"() {
|
|
109739
110507
|
"use strict";
|
|
109740
110508
|
init_tests_files();
|
|
109741
110509
|
init_body();
|
|
110510
|
+
UNPARSED_USERINFO = /^([A-Za-z][A-Za-z0-9+.-]*:[\\/]*|[\\/]{2})[^/\\]*@/;
|
|
109742
110511
|
REFUSED_RESPONSE_HEADERS = new Set(
|
|
109743
110512
|
CREDENTIAL_RESPONSE_HEADERS
|
|
109744
110513
|
);
|
|
@@ -110248,14 +111017,17 @@ async function notifyInitialized(session) {
|
|
|
110248
111017
|
});
|
|
110249
111018
|
return read2.ok ? { ok: true, value: void 0 } : read2;
|
|
110250
111019
|
}
|
|
110251
|
-
|
|
110252
|
-
|
|
110253
|
-
const sent = await post(session, {
|
|
111020
|
+
function toolsCallMessage(template, args) {
|
|
111021
|
+
return {
|
|
110254
111022
|
jsonrpc: "2.0",
|
|
110255
111023
|
id: CALL_ID,
|
|
110256
111024
|
method: "tools/call",
|
|
110257
111025
|
params: { name: template.tool, arguments: args }
|
|
110258
|
-
}
|
|
111026
|
+
};
|
|
111027
|
+
}
|
|
111028
|
+
async function callTool2(session) {
|
|
111029
|
+
const { template, args } = session.call;
|
|
111030
|
+
const sent = await post(session, toolsCallMessage(template, args));
|
|
110259
111031
|
if (!sent.ok) return { attempt: sent, exchange: void 0 };
|
|
110260
111032
|
const response = sent.value;
|
|
110261
111033
|
if (response.status < 200 || response.status >= 300) {
|
|
@@ -111171,7 +111943,7 @@ async function attemptCall(call2, context, deadline, settings) {
|
|
|
111171
111943
|
const controller = new AbortController();
|
|
111172
111944
|
const clock2 = new Clock(deadline, context.signal, controller);
|
|
111173
111945
|
try {
|
|
111174
|
-
const opening =
|
|
111946
|
+
const opening = open5(context.transport, {
|
|
111175
111947
|
...call2.request,
|
|
111176
111948
|
deadline_ms: Math.max(1, deadline - Date.now()),
|
|
111177
111949
|
signal: controller.signal
|
|
@@ -111191,7 +111963,7 @@ async function attemptCall(call2, context, deadline, settings) {
|
|
|
111191
111963
|
clock2.dispose();
|
|
111192
111964
|
}
|
|
111193
111965
|
}
|
|
111194
|
-
async function
|
|
111966
|
+
async function open5(transport, request3) {
|
|
111195
111967
|
return transport.grpc(request3);
|
|
111196
111968
|
}
|
|
111197
111969
|
async function read(response, call2, clock2, settings) {
|
|
@@ -130596,6 +131368,19 @@ var init_transport2 = __esm({
|
|
|
130596
131368
|
}
|
|
130597
131369
|
});
|
|
130598
131370
|
|
|
131371
|
+
// ../../packages/mcp-studio/src/execute/request-size.ts
|
|
131372
|
+
var init_request_size = __esm({
|
|
131373
|
+
"../../packages/mcp-studio/src/execute/request-size.ts"() {
|
|
131374
|
+
"use strict";
|
|
131375
|
+
init_body();
|
|
131376
|
+
init_graphql2();
|
|
131377
|
+
init_http();
|
|
131378
|
+
init_mcp();
|
|
131379
|
+
init_shape_input();
|
|
131380
|
+
init_util4();
|
|
131381
|
+
}
|
|
131382
|
+
});
|
|
131383
|
+
|
|
130599
131384
|
// ../../packages/mcp-studio/src/execute/index.ts
|
|
130600
131385
|
var init_execute = __esm({
|
|
130601
131386
|
"../../packages/mcp-studio/src/execute/index.ts"() {
|
|
@@ -130612,6 +131397,7 @@ var init_execute = __esm({
|
|
|
130612
131397
|
init_http();
|
|
130613
131398
|
init_mcp();
|
|
130614
131399
|
init_senders();
|
|
131400
|
+
init_request_size();
|
|
130615
131401
|
init_validate();
|
|
130616
131402
|
init_body();
|
|
130617
131403
|
init_http_call();
|
|
@@ -131388,15 +132174,11 @@ var init_env = __esm({
|
|
|
131388
132174
|
// explicit "false", but the startup guard (assertRlsEnforcedInProduction)
|
|
131389
132175
|
// refuses to boot in that state.
|
|
131390
132176
|
TENANT_RLS_ENFORCEMENT_ENABLED: external_exports.union([external_exports.literal("true"), external_exports.literal("false")]).optional().transform((v) => v === void 0 ? isProductionRuntime() : v === "true"),
|
|
131391
|
-
// ── Billing /
|
|
131392
|
-
//
|
|
131393
|
-
//
|
|
131394
|
-
|
|
131395
|
-
|
|
131396
|
-
// never recomputes the blended-margin solve. `pnpm billing:stripe-sync`
|
|
131397
|
-
// prints the value to set. Must be >= 1 (a markup below 1 would sell
|
|
131398
|
-
// credits below provider cost).
|
|
131399
|
-
OXAGEN_METER_MARKUP: external_exports.coerce.number().gte(1).optional(),
|
|
132177
|
+
// ── Billing / assistant credit meter (see @oxagen/billing pricing.ts) ──
|
|
132178
|
+
// The markup on the provider's list price for the in-app assistant's model
|
|
132179
|
+
// calls on Oxagen's key. Unset means 1.20. Must be >= 1 (a markup below 1
|
|
132180
|
+
// would sell credits below provider cost).
|
|
132181
|
+
OXAGEN_ASSISTANT_MARKUP: external_exports.coerce.number().gte(1).optional(),
|
|
131400
132182
|
// ── Usage-purchase volume discount (hybrid SaaS + usage pricing) ──
|
|
131401
132183
|
// When a customer buys usage credits they earn a volume discount of
|
|
131402
132184
|
// OXAGEN_USAGE_DISCOUNT_PERCENT% off for every OXAGEN_USAGE_DISCOUNT_INCREMENT
|
|
@@ -133315,7 +134097,7 @@ import {
|
|
|
133315
134097
|
mkdirSync as mkdirSync13,
|
|
133316
134098
|
readFileSync as readFileSync30,
|
|
133317
134099
|
readlinkSync as readlinkSync4,
|
|
133318
|
-
statSync as
|
|
134100
|
+
statSync as statSync18
|
|
133319
134101
|
} from "node:fs";
|
|
133320
134102
|
import { dirname as dirname36, isAbsolute as isAbsolute18, join as join64, relative as relative9, resolve as resolve25, sep as sep12 } from "node:path";
|
|
133321
134103
|
function git5(cwd, args, input) {
|
|
@@ -133428,14 +134210,14 @@ function chooseBase(root, ref2) {
|
|
|
133428
134210
|
}
|
|
133429
134211
|
function isFile(path2) {
|
|
133430
134212
|
try {
|
|
133431
|
-
return
|
|
134213
|
+
return statSync18(path2).isFile();
|
|
133432
134214
|
} catch {
|
|
133433
134215
|
return false;
|
|
133434
134216
|
}
|
|
133435
134217
|
}
|
|
133436
134218
|
function isDir(path2) {
|
|
133437
134219
|
try {
|
|
133438
|
-
return
|
|
134220
|
+
return statSync18(path2).isDirectory();
|
|
133439
134221
|
} catch {
|
|
133440
134222
|
return false;
|
|
133441
134223
|
}
|
|
@@ -136727,16 +137509,16 @@ function assignmentValue(bytes, assignment, nameStart, nameEnd) {
|
|
|
136727
137509
|
if (!assignment.names.some((k) => containsLower(name, k))) return null;
|
|
136728
137510
|
while (isBlank2(bytes[p])) p += 1;
|
|
136729
137511
|
if (p >= n2) return null;
|
|
136730
|
-
const
|
|
137512
|
+
const open7 = bytes[p];
|
|
136731
137513
|
let start;
|
|
136732
137514
|
let end;
|
|
136733
137515
|
let quoted3;
|
|
136734
|
-
if (
|
|
137516
|
+
if (open7 === QUOTE || open7 === APOSTROPHE || open7 === BACKTICK) {
|
|
136735
137517
|
start = p + 1;
|
|
136736
137518
|
end = start;
|
|
136737
|
-
while (end < n2 && bytes[end] !==
|
|
137519
|
+
while (end < n2 && bytes[end] !== open7 && bytes[end] !== NEWLINE2)
|
|
136738
137520
|
end += bytes[end] === BACKSLASH ? 2 : 1;
|
|
136739
|
-
if (end >= n2 || bytes[end] !==
|
|
137521
|
+
if (end >= n2 || bytes[end] !== open7) return null;
|
|
136740
137522
|
quoted3 = true;
|
|
136741
137523
|
} else {
|
|
136742
137524
|
start = p;
|
|
@@ -137912,7 +138694,7 @@ __export(logs_exports, {
|
|
|
137912
138694
|
handleLogs: () => handleLogs
|
|
137913
138695
|
});
|
|
137914
138696
|
import { watch } from "node:fs";
|
|
137915
|
-
import { open as
|
|
138697
|
+
import { open as open6, stat as stat6 } from "node:fs/promises";
|
|
137916
138698
|
function formatEntry(entry2) {
|
|
137917
138699
|
const head2 = `${entry2.ts} ${entry2.category.padEnd(11)} ${entry2.event}`;
|
|
137918
138700
|
if (entry2.data === void 0) return head2;
|
|
@@ -137943,7 +138725,7 @@ async function logSize(file) {
|
|
|
137943
138725
|
async function readAppended(file, offset) {
|
|
137944
138726
|
let handle;
|
|
137945
138727
|
try {
|
|
137946
|
-
handle = await
|
|
138728
|
+
handle = await open6(file, "r");
|
|
137947
138729
|
} catch {
|
|
137948
138730
|
return { entries: [], offset: 0 };
|
|
137949
138731
|
}
|