@oxagen/cli 2.1.5-63 → 2.1.5-69
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 +957 -316
- 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)
|
|
@@ -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-69";
|
|
26627
26676
|
try {
|
|
26628
26677
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
26629
26678
|
const pkg = JSON.parse(
|
|
@@ -28194,13 +28243,15 @@ function* readLinesFrom(path2, from = 0, chunkBytes = SCAN_CHUNK_BYTES) {
|
|
|
28194
28243
|
closeSync5(fd2);
|
|
28195
28244
|
}
|
|
28196
28245
|
}
|
|
28197
|
-
async function* readLinesFromAsync(path2, from = 0) {
|
|
28246
|
+
async function* readLinesFromAsync(path2, from = 0, to = Number.POSITIVE_INFINITY) {
|
|
28198
28247
|
const handle = await open2(path2, "r");
|
|
28199
28248
|
try {
|
|
28200
28249
|
const splitter = new LineSplitter(from);
|
|
28201
28250
|
let position = from;
|
|
28202
|
-
|
|
28203
|
-
const chunk2 = Buffer.allocUnsafe(
|
|
28251
|
+
while (position < to) {
|
|
28252
|
+
const chunk2 = Buffer.allocUnsafe(
|
|
28253
|
+
Math.min(SCAN_CHUNK_BYTES, to - position)
|
|
28254
|
+
);
|
|
28204
28255
|
const { bytesRead } = await handle.read(chunk2, 0, chunk2.length, position);
|
|
28205
28256
|
if (bytesRead <= 0) break;
|
|
28206
28257
|
position += bytesRead;
|
|
@@ -28542,6 +28593,7 @@ import {
|
|
|
28542
28593
|
writeSync as writeSync4
|
|
28543
28594
|
} from "node:fs";
|
|
28544
28595
|
import { randomUUID } from "node:crypto";
|
|
28596
|
+
import { open as open3 } from "node:fs/promises";
|
|
28545
28597
|
import { join as join18 } from "node:path";
|
|
28546
28598
|
function activityAt(event) {
|
|
28547
28599
|
const at2 = Date.parse(event.ts);
|
|
@@ -28576,7 +28628,66 @@ function isResumeMark(value) {
|
|
|
28576
28628
|
function sizeOf(path2) {
|
|
28577
28629
|
return statSync6(path2, { throwIfNoEntry: false })?.size ?? 0;
|
|
28578
28630
|
}
|
|
28579
|
-
|
|
28631
|
+
function statIfExists2(path2) {
|
|
28632
|
+
return statSync6(path2, { throwIfNoEntry: false });
|
|
28633
|
+
}
|
|
28634
|
+
async function writeAll2(out, bytes) {
|
|
28635
|
+
let written2 = 0;
|
|
28636
|
+
while (written2 < bytes.length) {
|
|
28637
|
+
const { bytesWritten } = await out.write(
|
|
28638
|
+
bytes,
|
|
28639
|
+
written2,
|
|
28640
|
+
bytes.length - written2
|
|
28641
|
+
);
|
|
28642
|
+
written2 += bytesWritten;
|
|
28643
|
+
}
|
|
28644
|
+
}
|
|
28645
|
+
async function copyRange(path2, out, from, to, signal) {
|
|
28646
|
+
if (to <= from) return;
|
|
28647
|
+
const source = await open3(path2, "r");
|
|
28648
|
+
try {
|
|
28649
|
+
const buffer = Buffer.allocUnsafe(
|
|
28650
|
+
Math.min(BODY_PURGE_SLICE_BYTES, to - from)
|
|
28651
|
+
);
|
|
28652
|
+
for (let at2 = from; at2 < to; ) {
|
|
28653
|
+
signal?.throwIfAborted();
|
|
28654
|
+
const { bytesRead } = await source.read(
|
|
28655
|
+
buffer,
|
|
28656
|
+
0,
|
|
28657
|
+
Math.min(buffer.length, to - at2),
|
|
28658
|
+
at2
|
|
28659
|
+
);
|
|
28660
|
+
if (bytesRead <= 0) return;
|
|
28661
|
+
await writeAll2(out, buffer.subarray(0, bytesRead));
|
|
28662
|
+
at2 += bytesRead;
|
|
28663
|
+
}
|
|
28664
|
+
} finally {
|
|
28665
|
+
await source.close();
|
|
28666
|
+
}
|
|
28667
|
+
}
|
|
28668
|
+
function readRangeSync(path2, from, to) {
|
|
28669
|
+
const buffer = Buffer.alloc(Math.max(0, to - from));
|
|
28670
|
+
if (buffer.length === 0) return buffer;
|
|
28671
|
+
const fd2 = openSync6(path2, "r");
|
|
28672
|
+
try {
|
|
28673
|
+
let filled = 0;
|
|
28674
|
+
while (filled < buffer.length) {
|
|
28675
|
+
const read2 = readSync3(
|
|
28676
|
+
fd2,
|
|
28677
|
+
buffer,
|
|
28678
|
+
filled,
|
|
28679
|
+
buffer.length - filled,
|
|
28680
|
+
from + filled
|
|
28681
|
+
);
|
|
28682
|
+
if (read2 <= 0) break;
|
|
28683
|
+
filled += read2;
|
|
28684
|
+
}
|
|
28685
|
+
return buffer.subarray(0, filled);
|
|
28686
|
+
} finally {
|
|
28687
|
+
closeSync6(fd2);
|
|
28688
|
+
}
|
|
28689
|
+
}
|
|
28690
|
+
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
28691
|
var init_wal = __esm({
|
|
28581
28692
|
"../../packages/tacho/src/host/wal.ts"() {
|
|
28582
28693
|
"use strict";
|
|
@@ -28586,6 +28697,9 @@ var init_wal = __esm({
|
|
|
28586
28697
|
BODY_READ_SLICE = 32;
|
|
28587
28698
|
BODY_DROP_SLICE_BYTES = 1024 * 1024;
|
|
28588
28699
|
BODY_DROP_SCANS = 3;
|
|
28700
|
+
BODY_PURGE_SLICE_BYTES = 1024 * 1024;
|
|
28701
|
+
BODY_PURGE_SCANS = 3;
|
|
28702
|
+
BODY_PURGE_CATCH_UPS = 3;
|
|
28589
28703
|
NEWLINE = 10;
|
|
28590
28704
|
EVENT_TAIL_WINDOW = 16 * 1024;
|
|
28591
28705
|
WalRecoveryConflict = class extends Error {
|
|
@@ -28685,6 +28799,18 @@ var init_wal = __esm({
|
|
|
28685
28799
|
* WAL has ever opened. See `flush` for why this exists.
|
|
28686
28800
|
*/
|
|
28687
28801
|
dirtyPaths = /* @__PURE__ */ new Set();
|
|
28802
|
+
/**
|
|
28803
|
+
* The awaited body sweeps running now, one entry per session scan
|
|
28804
|
+
* (`purgeBodiesOutsideMandateAsync`). Every write to a body file other than
|
|
28805
|
+
* an append marks the entries for its session, so a scan whose bytes moved
|
|
28806
|
+
* under it does not rename its copy over the file.
|
|
28807
|
+
*/
|
|
28808
|
+
bodyWatches = /* @__PURE__ */ new Set();
|
|
28809
|
+
/**
|
|
28810
|
+
* The temporary files those sweeps are writing. `compact` removes a
|
|
28811
|
+
* temporary file a crashed rewrite left, and must not remove one of these.
|
|
28812
|
+
*/
|
|
28813
|
+
liveTemps = /* @__PURE__ */ new Set();
|
|
28688
28814
|
fileFor(sessionUuid2) {
|
|
28689
28815
|
return join18(this.dir, `${sessionUuid2}.ndjson`);
|
|
28690
28816
|
}
|
|
@@ -29407,6 +29533,7 @@ ${lines.join("\n")}
|
|
|
29407
29533
|
if (next > 0) await new Promise((resolve26) => setImmediate(resolve26));
|
|
29408
29534
|
const slice = this.blankSlice(path2, found, next, idems);
|
|
29409
29535
|
if (slice === void 0) break;
|
|
29536
|
+
if (slice.blanked > 0) this.bodyRewritten(session);
|
|
29410
29537
|
blanked += slice.blanked;
|
|
29411
29538
|
moved ||= slice.moved;
|
|
29412
29539
|
next = slice.next;
|
|
@@ -29663,6 +29790,7 @@ ${lines.join("\n")}
|
|
|
29663
29790
|
this.dirtyPaths.add(path2);
|
|
29664
29791
|
}
|
|
29665
29792
|
this.bodyIndexes.invalidate(sessionUuid2);
|
|
29793
|
+
this.bodyRewritten(sessionUuid2);
|
|
29666
29794
|
return cut;
|
|
29667
29795
|
}
|
|
29668
29796
|
/**
|
|
@@ -29989,27 +30117,241 @@ ${lines.join("\n")}
|
|
|
29989
30117
|
* that withholds a body from a shipment. See `purgeBodiesNarrowedOut` in
|
|
29990
30118
|
* the daemon, which calls this when a replacement bundle verifies and
|
|
29991
30119
|
* narrows the clause.
|
|
30120
|
+
*
|
|
30121
|
+
* This reads every event file and every body file on the synchronous path,
|
|
30122
|
+
* which ADR-231 rules out on the daemon's thread. The daemon calls
|
|
30123
|
+
* `purgeBodiesOutsideMandateAsync`. It calls this only when it cannot record
|
|
30124
|
+
* the purge it owes, the one case where the erase has to finish before the
|
|
30125
|
+
* narrowed bundle is cached.
|
|
29992
30126
|
*/
|
|
29993
30127
|
purgeBodiesOutsideMandate(retention) {
|
|
29994
30128
|
let purged = 0;
|
|
29995
|
-
const
|
|
29996
|
-
|
|
29997
|
-
|
|
29998
|
-
|
|
29999
|
-
|
|
30129
|
+
for (const session of this.sessionsToPurge())
|
|
30130
|
+
purged += this.purgeSessionSync(session, retention);
|
|
30131
|
+
return purged;
|
|
30132
|
+
}
|
|
30133
|
+
/**
|
|
30134
|
+
* The same sweep, without holding the daemon's thread (#5176, ADR-231).
|
|
30135
|
+
* Every read is awaited, and a turn of the event loop separates two
|
|
30136
|
+
* sessions, so a hook or a proxied model call waits for one read and not
|
|
30137
|
+
* for the sweep.
|
|
30138
|
+
*
|
|
30139
|
+
* Each session is rewritten the way `rewriteBodies` rewrites it: the lines
|
|
30140
|
+
* kept go to a temporary file, and a rename puts it over the body file. A
|
|
30141
|
+
* crash part way leaves the old file whole, and the caller's record of the
|
|
30142
|
+
* purge it owes runs the sweep again. Hooks append to the file while the
|
|
30143
|
+
* scan awaits its reads, and three rules keep those appends:
|
|
30144
|
+
*
|
|
30145
|
+
* - The scan measures the body file and the event file in one synchronous
|
|
30146
|
+
* stretch, and reads each only up to that size. `append` writes a body
|
|
30147
|
+
* and then its event in one synchronous stretch too, so every body the
|
|
30148
|
+
* scan reads has its event in the part of the event file the scan reads,
|
|
30149
|
+
* or is a crash orphan. A body appended later is never judged an orphan.
|
|
30150
|
+
* - Bytes appended after that moment go to the new file as they are. They
|
|
30151
|
+
* were recorded under the mandate in force when they were appended, and
|
|
30152
|
+
* the daemon caches the narrowed mandate before it starts this sweep.
|
|
30153
|
+
* - The rename happens in one synchronous stretch, after a last check. When
|
|
30154
|
+
* the file was replaced, cut short, or written other than by an append
|
|
30155
|
+
* while the scan read it (`dropBodiesAsync` blanks lines in place), the
|
|
30156
|
+
* copy is thrown away and the session is scanned again. After
|
|
30157
|
+
* `BODY_PURGE_SCANS` scans the session goes through the synchronous sweep.
|
|
30158
|
+
*
|
|
30159
|
+
* The copy is synced to disk with an awaited call before that stretch, so
|
|
30160
|
+
* the stretch copies and syncs only what was appended since, about
|
|
30161
|
+
* `BODY_PURGE_SLICE_BYTES` at most.
|
|
30162
|
+
*/
|
|
30163
|
+
async purgeBodiesOutsideMandateAsync(retention, options = {}) {
|
|
30164
|
+
const { signal } = options;
|
|
30165
|
+
let purged = 0;
|
|
30166
|
+
for (const session of this.sessionsToPurge()) {
|
|
30167
|
+
await new Promise((resolve26) => setImmediate(resolve26));
|
|
30168
|
+
signal?.throwIfAborted();
|
|
30169
|
+
await options.beforeSession?.(session);
|
|
30170
|
+
signal?.throwIfAborted();
|
|
30000
30171
|
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
|
-
);
|
|
30172
|
+
let swept = "moved";
|
|
30173
|
+
for (let scan = 0; scan < BODY_PURGE_SCANS && swept === "moved"; scan++)
|
|
30174
|
+
swept = await this.purgeSessionAsync(session, retention, signal);
|
|
30175
|
+
purged += swept === "moved" ? this.purgeSessionSync(session, retention) : swept;
|
|
30010
30176
|
}
|
|
30011
30177
|
return purged;
|
|
30012
30178
|
}
|
|
30179
|
+
/**
|
|
30180
|
+
* Every session that has an event file OR a body file. `sessions()` lists
|
|
30181
|
+
* `.ndjson` only, so a crash between `append`'s body write and its first
|
|
30182
|
+
* event write leaves a `<uuid>.bodies.jsonl` with no `.ndjson` beside it,
|
|
30183
|
+
* invisible to a sweep that walked `sessions()` and to `compact`, which
|
|
30184
|
+
* does. Those bytes would outlive every mechanism meant to remove them.
|
|
30185
|
+
*/
|
|
30186
|
+
sessionsToPurge() {
|
|
30187
|
+
return /* @__PURE__ */ new Set([...this.sessions(), ...this.sessionsWithBodies()]);
|
|
30188
|
+
}
|
|
30189
|
+
/** One session of `purgeBodiesOutsideMandate`, read and rewritten at once. */
|
|
30190
|
+
purgeSessionSync(session, retention) {
|
|
30191
|
+
if (!existsSync12(this.bodyFileFor(session))) return 0;
|
|
30192
|
+
const kindOf2 = new Map(
|
|
30193
|
+
this.read(session).map(
|
|
30194
|
+
(event) => [event.event_id_idem, event.kind]
|
|
30195
|
+
)
|
|
30196
|
+
);
|
|
30197
|
+
return this.rewriteBodies(
|
|
30198
|
+
session,
|
|
30199
|
+
(stored) => this.keeps(stored, kindOf2, retention)
|
|
30200
|
+
);
|
|
30201
|
+
}
|
|
30202
|
+
/**
|
|
30203
|
+
* One scan of `purgeBodiesOutsideMandateAsync` over one session. Answers
|
|
30204
|
+
* how many lines went, or `moved` when the file changed under the scan
|
|
30205
|
+
* other than by an append, in which case nothing was renamed.
|
|
30206
|
+
*/
|
|
30207
|
+
async purgeSessionAsync(session, retention, signal) {
|
|
30208
|
+
const path2 = this.bodyFileFor(session);
|
|
30209
|
+
const start = statIfExists2(path2);
|
|
30210
|
+
if (start === void 0) return 0;
|
|
30211
|
+
const eventEnd = statIfExists2(this.fileFor(session))?.size ?? 0;
|
|
30212
|
+
const watch2 = { session, moved: false };
|
|
30213
|
+
this.bodyWatches.add(watch2);
|
|
30214
|
+
const tmp = `${path2}.${randomUUID()}.tmp`;
|
|
30215
|
+
let out;
|
|
30216
|
+
try {
|
|
30217
|
+
const kindOf2 = await this.eventKindsUpTo(session, eventEnd, signal);
|
|
30218
|
+
let cut = 0;
|
|
30219
|
+
let kept = 0;
|
|
30220
|
+
let held = [];
|
|
30221
|
+
let heldBytes = 0;
|
|
30222
|
+
const writeHeld = async (to) => {
|
|
30223
|
+
if (heldBytes === 0) return;
|
|
30224
|
+
await writeAll2(to, Buffer.concat(held, heldBytes));
|
|
30225
|
+
held = [];
|
|
30226
|
+
heldBytes = 0;
|
|
30227
|
+
};
|
|
30228
|
+
for await (const line of readLinesFromAsync(path2, 0, start.size)) {
|
|
30229
|
+
signal?.throwIfAborted();
|
|
30230
|
+
if (line.text.trim().length === 0) continue;
|
|
30231
|
+
if (this.keeps(parseStoredBody(line.text), kindOf2, retention)) {
|
|
30232
|
+
kept += 1;
|
|
30233
|
+
if (out === void 0) continue;
|
|
30234
|
+
const bytes = Buffer.from(`${line.text}
|
|
30235
|
+
`);
|
|
30236
|
+
held.push(bytes);
|
|
30237
|
+
heldBytes += bytes.length;
|
|
30238
|
+
if (heldBytes >= BODY_PURGE_SLICE_BYTES) await writeHeld(out);
|
|
30239
|
+
continue;
|
|
30240
|
+
}
|
|
30241
|
+
cut += 1;
|
|
30242
|
+
if (out === void 0) {
|
|
30243
|
+
this.liveTemps.add(tmp);
|
|
30244
|
+
out = await open3(tmp, "wx", 384);
|
|
30245
|
+
await copyRange(path2, out, 0, line.offset, signal);
|
|
30246
|
+
}
|
|
30247
|
+
}
|
|
30248
|
+
if (out === void 0) return watch2.moved ? "moved" : 0;
|
|
30249
|
+
await writeHeld(out);
|
|
30250
|
+
let copied = start.size;
|
|
30251
|
+
for (let round = 0; round < BODY_PURGE_CATCH_UPS; round += 1) {
|
|
30252
|
+
const size = statIfExists2(path2)?.size;
|
|
30253
|
+
if (size === void 0 || size - copied <= BODY_PURGE_SLICE_BYTES)
|
|
30254
|
+
break;
|
|
30255
|
+
await copyRange(path2, out, copied, size, signal);
|
|
30256
|
+
copied = size;
|
|
30257
|
+
}
|
|
30258
|
+
await out.sync();
|
|
30259
|
+
await out.close();
|
|
30260
|
+
out = void 0;
|
|
30261
|
+
signal?.throwIfAborted();
|
|
30262
|
+
if (watch2.moved) return "moved";
|
|
30263
|
+
return this.commitPurge(session, tmp, {
|
|
30264
|
+
start,
|
|
30265
|
+
copied,
|
|
30266
|
+
keptAny: kept > 0 || copied > start.size,
|
|
30267
|
+
cut
|
|
30268
|
+
});
|
|
30269
|
+
} catch (error) {
|
|
30270
|
+
if (error.code === "ENOENT" && !existsSync12(path2))
|
|
30271
|
+
return 0;
|
|
30272
|
+
throw error;
|
|
30273
|
+
} finally {
|
|
30274
|
+
this.bodyWatches.delete(watch2);
|
|
30275
|
+
if (out !== void 0) await out.close().catch(() => void 0);
|
|
30276
|
+
if (existsSync12(tmp)) unlinkSync9(tmp);
|
|
30277
|
+
this.liveTemps.delete(tmp);
|
|
30278
|
+
}
|
|
30279
|
+
}
|
|
30280
|
+
/**
|
|
30281
|
+
* The kind of every event in the first `end` bytes of a session's event
|
|
30282
|
+
* file, by event id, read with awaited reads. A line that does not parse is
|
|
30283
|
+
* reported and skipped, as `read` does. A line cut off at `end` was torn by
|
|
30284
|
+
* a crash, since `append` ends every write with a newline, and is skipped.
|
|
30285
|
+
*/
|
|
30286
|
+
async eventKindsUpTo(session, end, signal) {
|
|
30287
|
+
const kindOf2 = /* @__PURE__ */ new Map();
|
|
30288
|
+
if (end === 0) return kindOf2;
|
|
30289
|
+
for await (const line of readLinesFromAsync(
|
|
30290
|
+
this.fileFor(session),
|
|
30291
|
+
0,
|
|
30292
|
+
end
|
|
30293
|
+
)) {
|
|
30294
|
+
signal?.throwIfAborted();
|
|
30295
|
+
if (!line.terminated || line.text.trim().length === 0) continue;
|
|
30296
|
+
try {
|
|
30297
|
+
const event = parseEventLine(line.text);
|
|
30298
|
+
kindOf2.set(event.event_id_idem, event.kind);
|
|
30299
|
+
} catch (error) {
|
|
30300
|
+
this.reportEventParseFailure({
|
|
30301
|
+
session_uuid: session,
|
|
30302
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
30303
|
+
});
|
|
30304
|
+
}
|
|
30305
|
+
}
|
|
30306
|
+
return kindOf2;
|
|
30307
|
+
}
|
|
30308
|
+
/**
|
|
30309
|
+
* The rename of `purgeSessionAsync`, in one synchronous stretch, so nothing
|
|
30310
|
+
* else can write the body file between the check and the rename. Copies
|
|
30311
|
+
* what was appended since `copied`, syncs it, and puts the copy over the
|
|
30312
|
+
* file, or removes the file when nothing in it is left.
|
|
30313
|
+
*/
|
|
30314
|
+
commitPurge(session, tmp, scan) {
|
|
30315
|
+
const path2 = this.bodyFileFor(session);
|
|
30316
|
+
const now = statIfExists2(path2);
|
|
30317
|
+
if (now === void 0) return 0;
|
|
30318
|
+
if (now.ino !== scan.start.ino || now.dev !== scan.start.dev || now.size < scan.copied)
|
|
30319
|
+
return "moved";
|
|
30320
|
+
const tail = readRangeSync(path2, scan.copied, now.size);
|
|
30321
|
+
if (!scan.keptAny && tail.toString("utf8").trim().length === 0) {
|
|
30322
|
+
unlinkSync9(path2);
|
|
30323
|
+
} else {
|
|
30324
|
+
const fd2 = openSync6(tmp, "r+");
|
|
30325
|
+
try {
|
|
30326
|
+
let written2 = 0;
|
|
30327
|
+
const at2 = fstatSync(fd2).size;
|
|
30328
|
+
while (written2 < tail.length)
|
|
30329
|
+
written2 += writeSync4(
|
|
30330
|
+
fd2,
|
|
30331
|
+
tail,
|
|
30332
|
+
written2,
|
|
30333
|
+
tail.length - written2,
|
|
30334
|
+
at2 + written2
|
|
30335
|
+
);
|
|
30336
|
+
fdatasyncSync(fd2);
|
|
30337
|
+
} finally {
|
|
30338
|
+
closeSync6(fd2);
|
|
30339
|
+
}
|
|
30340
|
+
renameSync3(tmp, path2);
|
|
30341
|
+
}
|
|
30342
|
+
this.bodyIndexes.invalidate(session);
|
|
30343
|
+
this.bodyRewritten(session);
|
|
30344
|
+
return scan.cut;
|
|
30345
|
+
}
|
|
30346
|
+
/**
|
|
30347
|
+
* Tell every awaited sweep of this session that its body file changed
|
|
30348
|
+
* other than by an append. Each write that cuts, blanks, or replaces body
|
|
30349
|
+
* bytes calls this in the same synchronous stretch as the write.
|
|
30350
|
+
*/
|
|
30351
|
+
bodyRewritten(session) {
|
|
30352
|
+
for (const watch2 of this.bodyWatches)
|
|
30353
|
+
if (watch2.session === session) watch2.moved = true;
|
|
30354
|
+
}
|
|
30013
30355
|
/**
|
|
30014
30356
|
* Whether one stored body survives this mandate. Three answers, each for a
|
|
30015
30357
|
* reason:
|
|
@@ -30027,7 +30369,9 @@ ${lines.join("\n")}
|
|
|
30027
30369
|
* the two writes and no event will ever arrive for it. Keeping it kept
|
|
30028
30370
|
* prompt or tool bytes that no mandate covers and that nothing would
|
|
30029
30371
|
* ever ship, delete or compact, because every one of those paths starts
|
|
30030
|
-
* from the event.
|
|
30372
|
+
* from the event. The awaited sweep does let appends land while it reads,
|
|
30373
|
+
* so it judges only the bodies written before it measured the files, and
|
|
30374
|
+
* their events are all in the part of the event file it reads.
|
|
30031
30375
|
* - Otherwise the class comes from the event's kind and the one retention
|
|
30032
30376
|
* gate answers. A kind the table does not name has no class, so no mandate
|
|
30033
30377
|
* can cover it and the body goes.
|
|
@@ -30089,6 +30433,7 @@ ${lines.join("\n")}
|
|
|
30089
30433
|
if (kept === 0) unlinkSync9(path2);
|
|
30090
30434
|
else renameSync3(tmp, path2);
|
|
30091
30435
|
this.bodyIndexes.invalidate(sessionUuid2);
|
|
30436
|
+
this.bodyRewritten(sessionUuid2);
|
|
30092
30437
|
return cut;
|
|
30093
30438
|
} finally {
|
|
30094
30439
|
if (existsSync12(tmp)) unlinkSync9(tmp);
|
|
@@ -30116,6 +30461,7 @@ ${lines.join("\n")}
|
|
|
30116
30461
|
`^${uuid}\\.bodies\\.jsonl\\.${uuid}\\.tmp$`
|
|
30117
30462
|
);
|
|
30118
30463
|
for (const name of readdirSync7(this.dir)) {
|
|
30464
|
+
if (this.liveTemps.has(join18(this.dir, name))) continue;
|
|
30119
30465
|
if (abandonedRewrite.test(name)) {
|
|
30120
30466
|
try {
|
|
30121
30467
|
unlinkSync9(join18(this.dir, name));
|
|
@@ -30199,6 +30545,7 @@ ${lines.join("\n")}
|
|
|
30199
30545
|
const path2 = this.bodyFileFor(session);
|
|
30200
30546
|
if (existsSync12(path2)) unlinkSync9(path2);
|
|
30201
30547
|
this.bodyIndexes.invalidate(session);
|
|
30548
|
+
this.bodyRewritten(session);
|
|
30202
30549
|
return true;
|
|
30203
30550
|
} catch (error) {
|
|
30204
30551
|
this.bodyFailure(session, "cleanup", error);
|
|
@@ -30551,8 +30898,12 @@ function daemonServiceSpec(daemonCommand, deps) {
|
|
|
30551
30898
|
command: daemonCommand,
|
|
30552
30899
|
env: {
|
|
30553
30900
|
...deps.env["TACHO_HOME"] !== void 0 ? { TACHO_HOME: deps.env["TACHO_HOME"] } : {},
|
|
30554
|
-
// The harness homes
|
|
30555
|
-
//
|
|
30901
|
+
// The harness homes this shell moved. Each collector reads its agent's
|
|
30902
|
+
// harness files where that agent's host.json recorded them at enroll
|
|
30903
|
+
// (`harness_files`), so these decide nothing for an agent with a
|
|
30904
|
+
// record. They stay for an agent enrolled before the record existed.
|
|
30905
|
+
// One service serves every agent, so they come from whichever shell
|
|
30906
|
+
// installed it last (#5409).
|
|
30556
30907
|
...Object.fromEntries(
|
|
30557
30908
|
HARNESS_HOME_VARS.flatMap((key) => {
|
|
30558
30909
|
const value = deps.env[key];
|
|
@@ -43081,7 +43432,11 @@ async function renewStaticToken(harness, deps) {
|
|
|
43081
43432
|
const label2 = TACHO_HARNESS_LABELS[harness];
|
|
43082
43433
|
if (deps.host.host_status !== "active" || !deps.inCustody(provider, harness))
|
|
43083
43434
|
return "skipped";
|
|
43084
|
-
const dirs =
|
|
43435
|
+
const dirs = {
|
|
43436
|
+
...deps.stellaHome !== void 0 ? { stellaHome: deps.stellaHome } : {},
|
|
43437
|
+
...deps.codexHome !== void 0 ? { codexHome: deps.codexHome } : {},
|
|
43438
|
+
...deps.claudeConfigDir !== void 0 ? { claudeConfigDir: deps.claudeConfigDir } : {}
|
|
43439
|
+
};
|
|
43085
43440
|
let brokered = false;
|
|
43086
43441
|
try {
|
|
43087
43442
|
brokered = (await readModelCredentialState({
|
|
@@ -44021,8 +44376,33 @@ var init_git_facts = __esm({
|
|
|
44021
44376
|
|
|
44022
44377
|
// ../../packages/tacho/src/collector/work-order-autostart.ts
|
|
44023
44378
|
import { spawn as spawn7 } from "node:child_process";
|
|
44024
|
-
import { closeSync as closeSync7, existsSync as existsSync21, openSync as openSync7 } from "node:fs";
|
|
44379
|
+
import { closeSync as closeSync7, existsSync as existsSync21, openSync as openSync7, readSync as readSync4, statSync as statSync12 } from "node:fs";
|
|
44025
44380
|
import { dirname as dirname20, join as join36 } from "node:path";
|
|
44381
|
+
function lastLogLine(path2) {
|
|
44382
|
+
let fd2;
|
|
44383
|
+
try {
|
|
44384
|
+
const size = statSync12(path2).size;
|
|
44385
|
+
const length = Math.min(size, 4096);
|
|
44386
|
+
const buffer = Buffer.alloc(length);
|
|
44387
|
+
fd2 = openSync7(path2, "r");
|
|
44388
|
+
readSync4(fd2, buffer, 0, length, size - length);
|
|
44389
|
+
const line = buffer.toString("utf8").replace(TERMINAL_CODE, "").split(/\r?\n/).map((text5) => text5.trim()).filter((text5) => text5.length > 0).pop();
|
|
44390
|
+
if (line === void 0) return void 0;
|
|
44391
|
+
return line.length > EXIT_REPORT_QUOTE ? `${line.slice(0, EXIT_REPORT_QUOTE - 1)}\u2026` : line;
|
|
44392
|
+
} catch {
|
|
44393
|
+
return void 0;
|
|
44394
|
+
} finally {
|
|
44395
|
+
if (fd2 !== void 0) {
|
|
44396
|
+
try {
|
|
44397
|
+
closeSync7(fd2);
|
|
44398
|
+
} catch {
|
|
44399
|
+
}
|
|
44400
|
+
}
|
|
44401
|
+
}
|
|
44402
|
+
}
|
|
44403
|
+
function exitPhrase(exit) {
|
|
44404
|
+
return exit.signal !== null ? `ended on ${exit.signal}` : `exited with code ${String(exit.code)}`;
|
|
44405
|
+
}
|
|
44026
44406
|
function asError(error) {
|
|
44027
44407
|
return error instanceof Error ? error : new Error(String(error));
|
|
44028
44408
|
}
|
|
@@ -44037,6 +44417,10 @@ function isPlainBranchName(name) {
|
|
|
44037
44417
|
function createWorkOrderAutostart(deps) {
|
|
44038
44418
|
const { paths, log } = deps;
|
|
44039
44419
|
const isAlive = deps.isAlive ?? processIsAlive;
|
|
44420
|
+
const wait = deps.wait ?? ((ms) => new Promise((done) => {
|
|
44421
|
+
setTimeout(done, ms).unref();
|
|
44422
|
+
}));
|
|
44423
|
+
const sessions = /* @__PURE__ */ new Set();
|
|
44040
44424
|
const spawnHarness = deps.spawn ?? spawnDetached;
|
|
44041
44425
|
let searchPath;
|
|
44042
44426
|
const pathForHarness = () => {
|
|
@@ -44222,7 +44606,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44222
44606
|
`work order ${id2}: could not clear its running mark: ${asError(error).message}`
|
|
44223
44607
|
);
|
|
44224
44608
|
}
|
|
44225
|
-
const ended = exit === void 0 ? "ended while the daemon was stopped" : "never" in exit ? `never started (${exit.never})` :
|
|
44609
|
+
const ended = exit === void 0 ? "ended while the daemon was stopped" : "never" in exit ? `never started (${exit.never})` : exitPhrase(exit);
|
|
44226
44610
|
const { worktree, root, branch, base_sha: base2 } = mark;
|
|
44227
44611
|
if (worktree === void 0 || !existsSync21(worktree)) {
|
|
44228
44612
|
log(`work order ${id2}: the harness ${ended}`);
|
|
@@ -44276,13 +44660,28 @@ function createWorkOrderAutostart(deps) {
|
|
|
44276
44660
|
`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
44661
|
);
|
|
44278
44662
|
}
|
|
44279
|
-
function
|
|
44663
|
+
async function reportExit(id2, binary, exit, logPath) {
|
|
44664
|
+
if (sessions.has(id2)) return;
|
|
44665
|
+
await wait(EXIT_REPORT_GRACE_MS);
|
|
44666
|
+
if (sessions.has(id2)) return;
|
|
44667
|
+
const said = lastLogLine(logPath);
|
|
44668
|
+
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.`;
|
|
44669
|
+
const failed3 = await refuseWorkOrder(deps.client, id2, reason3.slice(0, 512));
|
|
44670
|
+
log(
|
|
44671
|
+
failed3 === void 0 ? `work order ${id2}: ${reason3} Oxagen ended the send.` : `work order ${id2}: ${reason3} Oxagen kept the send (${failed3}).`
|
|
44672
|
+
);
|
|
44673
|
+
}
|
|
44674
|
+
function watch2(id2, binary, workspace, exited) {
|
|
44280
44675
|
void exited.then((exit) => {
|
|
44281
|
-
const done =
|
|
44676
|
+
const done = Promise.all([
|
|
44677
|
+
cleanUp({ work_order: id2, ...workspace }, exit),
|
|
44678
|
+
reportExit(id2, binary, exit, workspace.log)
|
|
44679
|
+
]).then(() => void 0).catch((error) => {
|
|
44282
44680
|
log(
|
|
44283
44681
|
`work order ${id2}: cleanup after the harness failed: ${asError(error).message}`
|
|
44284
44682
|
);
|
|
44285
44683
|
}).finally(() => {
|
|
44684
|
+
sessions.delete(id2);
|
|
44286
44685
|
cleanups.delete(done);
|
|
44287
44686
|
});
|
|
44288
44687
|
cleanups.add(done);
|
|
@@ -44292,8 +44691,8 @@ function createWorkOrderAutostart(deps) {
|
|
|
44292
44691
|
const id2 = order.work_order;
|
|
44293
44692
|
const running = runningWorkOrder(paths, id2, isAlive);
|
|
44294
44693
|
if (running !== void 0) return;
|
|
44295
|
-
const
|
|
44296
|
-
if (
|
|
44694
|
+
const wait2 = retry.get(id2);
|
|
44695
|
+
if (wait2 !== void 0 && deps.now() < wait2.at) return;
|
|
44297
44696
|
const outcome = await claimForStart(deps.client, deps.host(), id2);
|
|
44298
44697
|
if (outcome.kind === "refused" && outcome.final) {
|
|
44299
44698
|
log(
|
|
@@ -44389,7 +44788,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44389
44788
|
log(
|
|
44390
44789
|
`work order ${id2} for ${claim.work_order.item_number} started ${binary} (process ${started.pid}) in ${workspace.worktree}; output goes to ${workspace.log}`
|
|
44391
44790
|
);
|
|
44392
|
-
watch2(id2, workspace, started.exited);
|
|
44791
|
+
watch2(id2, binary, workspace, started.exited);
|
|
44393
44792
|
}
|
|
44394
44793
|
async function runPass() {
|
|
44395
44794
|
let orders;
|
|
@@ -44438,6 +44837,9 @@ function createWorkOrderAutostart(deps) {
|
|
|
44438
44837
|
}
|
|
44439
44838
|
}
|
|
44440
44839
|
},
|
|
44840
|
+
noteSession: (workOrder) => {
|
|
44841
|
+
sessions.add(workOrder);
|
|
44842
|
+
},
|
|
44441
44843
|
idle: async () => {
|
|
44442
44844
|
while (pass2 !== void 0 || cleanups.size > 0) {
|
|
44443
44845
|
await Promise.allSettled([pass2, ...cleanups]);
|
|
@@ -44445,7 +44847,7 @@ function createWorkOrderAutostart(deps) {
|
|
|
44445
44847
|
}
|
|
44446
44848
|
};
|
|
44447
44849
|
}
|
|
44448
|
-
var SLOW_GIT_MS, RETRY_MIN_MS, RETRY_MAX_MS, spawnDetached;
|
|
44850
|
+
var SLOW_GIT_MS, RETRY_MIN_MS, RETRY_MAX_MS, EXIT_REPORT_GRACE_MS, TERMINAL_CODE, EXIT_REPORT_QUOTE, spawnDetached;
|
|
44449
44851
|
var init_work_order_autostart = __esm({
|
|
44450
44852
|
"../../packages/tacho/src/collector/work-order-autostart.ts"() {
|
|
44451
44853
|
"use strict";
|
|
@@ -44459,6 +44861,12 @@ var init_work_order_autostart = __esm({
|
|
|
44459
44861
|
SLOW_GIT_MS = 12e4;
|
|
44460
44862
|
RETRY_MIN_MS = 15e3;
|
|
44461
44863
|
RETRY_MAX_MS = 5 * 6e4;
|
|
44864
|
+
EXIT_REPORT_GRACE_MS = 6e4;
|
|
44865
|
+
TERMINAL_CODE = new RegExp(
|
|
44866
|
+
`${String.fromCharCode(27)}\\[[0-9;?]*[A-Za-z]`,
|
|
44867
|
+
"g"
|
|
44868
|
+
);
|
|
44869
|
+
EXIT_REPORT_QUOTE = 240;
|
|
44462
44870
|
spawnDetached = (command2, args, options) => new Promise((resolve26) => {
|
|
44463
44871
|
let fd2;
|
|
44464
44872
|
try {
|
|
@@ -44468,10 +44876,10 @@ var init_work_order_autostart = __esm({
|
|
|
44468
44876
|
resolve26({ ok: false, error: asError(error) });
|
|
44469
44877
|
return;
|
|
44470
44878
|
}
|
|
44471
|
-
let
|
|
44879
|
+
let open7 = true;
|
|
44472
44880
|
const close = () => {
|
|
44473
|
-
if (!
|
|
44474
|
-
|
|
44881
|
+
if (!open7) return;
|
|
44882
|
+
open7 = false;
|
|
44475
44883
|
try {
|
|
44476
44884
|
closeSync7(fd2);
|
|
44477
44885
|
} catch {
|
|
@@ -44559,7 +44967,7 @@ import { createReadStream } from "node:fs";
|
|
|
44559
44967
|
import {
|
|
44560
44968
|
lstat,
|
|
44561
44969
|
mkdir,
|
|
44562
|
-
open as
|
|
44970
|
+
open as open4,
|
|
44563
44971
|
readdir,
|
|
44564
44972
|
readlink,
|
|
44565
44973
|
rename,
|
|
@@ -44612,7 +45020,7 @@ async function contentHash(absolutePath, kind, keep) {
|
|
|
44612
45020
|
const temp2 = join37(keep.dir, `.partial-${randomUUID3()}`);
|
|
44613
45021
|
copy = {
|
|
44614
45022
|
temp: temp2,
|
|
44615
|
-
handle: await
|
|
45023
|
+
handle: await open4(temp2, "wx", keep.executable ? 448 : 384)
|
|
44616
45024
|
};
|
|
44617
45025
|
} catch {
|
|
44618
45026
|
copy = null;
|
|
@@ -46380,22 +46788,41 @@ var init_interjection = __esm({
|
|
|
46380
46788
|
function showsRefusedPrompt(harness) {
|
|
46381
46789
|
return harness !== "stella";
|
|
46382
46790
|
}
|
|
46791
|
+
function questionBoundary(harness) {
|
|
46792
|
+
return showsRefusedPrompt(harness) ? "UserPromptSubmit" : "SessionStart";
|
|
46793
|
+
}
|
|
46794
|
+
function holdToolCall(evaluation, record) {
|
|
46795
|
+
const held = record.control.interjection;
|
|
46796
|
+
if (held === void 0 || evaluation.decision === "deny") return evaluation;
|
|
46797
|
+
const refused2 = {
|
|
46798
|
+
...evaluation,
|
|
46799
|
+
decision: "deny",
|
|
46800
|
+
evaluated: "deny",
|
|
46801
|
+
source: "bundle",
|
|
46802
|
+
reason_code: INTERJECTION_OPEN,
|
|
46803
|
+
reason: held.question
|
|
46804
|
+
};
|
|
46805
|
+
delete refused2.rule;
|
|
46806
|
+
delete refused2.rules;
|
|
46807
|
+
return refused2;
|
|
46808
|
+
}
|
|
46383
46809
|
function isBound(clause, remote) {
|
|
46384
46810
|
const bound = new Set(clause.bound_remote_digests);
|
|
46385
46811
|
return bound.has(remote.remote_digest) || bound.has(remote.remote_digest_folded);
|
|
46386
46812
|
}
|
|
46387
|
-
function interjectionQuestion(clause) {
|
|
46813
|
+
function interjectionQuestion(clause, harness) {
|
|
46388
46814
|
const minutes = Math.max(1, Math.round(clause.timeout_ms / 6e4));
|
|
46389
46815
|
const slug = clause.workspace_slug;
|
|
46390
|
-
|
|
46816
|
+
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. `;
|
|
46817
|
+
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
46818
|
}
|
|
46392
46819
|
function proposedSlug(name) {
|
|
46393
46820
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").slice(0, SLUG_MAX).replace(/-+$/, "");
|
|
46394
46821
|
return slug.length >= SLUG_MIN && SLUG_PATTERN.test(slug) ? slug : null;
|
|
46395
46822
|
}
|
|
46396
|
-
function
|
|
46823
|
+
function prepareInterjection(record, clause, remote, now) {
|
|
46397
46824
|
const key = ulid(now);
|
|
46398
|
-
const question = interjectionQuestion(clause);
|
|
46825
|
+
const question = interjectionQuestion(clause, record.harness);
|
|
46399
46826
|
const expiresAt = toProtocolTimestamp(now + clause.timeout_ms);
|
|
46400
46827
|
const name = remote.name !== void 0 && remote.name.length <= NAME_MAX2 ? remote.name : null;
|
|
46401
46828
|
const unknown2 = repoUnknownBodySchema.safeParse({
|
|
@@ -46432,21 +46859,28 @@ function raiseInterjection(record, clause, remote, now, fields) {
|
|
|
46432
46859
|
]
|
|
46433
46860
|
});
|
|
46434
46861
|
if (!unknown2.success || !interject.success) return void 0;
|
|
46862
|
+
return {
|
|
46863
|
+
unknown: unknown2.data,
|
|
46864
|
+
interject: interject.data,
|
|
46865
|
+
held: {
|
|
46866
|
+
key,
|
|
46867
|
+
question,
|
|
46868
|
+
expiresAt,
|
|
46869
|
+
workspaceSlug: clause.workspace_slug,
|
|
46870
|
+
configVersion: clause.config_version
|
|
46871
|
+
}
|
|
46872
|
+
};
|
|
46873
|
+
}
|
|
46874
|
+
function sealInterjection(record, pending, fields) {
|
|
46435
46875
|
const events = [
|
|
46436
|
-
record.recorder.sealCollectorEvent("repo.unknown",
|
|
46876
|
+
record.recorder.sealCollectorEvent("repo.unknown", pending.unknown, fields),
|
|
46437
46877
|
record.recorder.sealCollectorEvent(
|
|
46438
46878
|
"control.interject",
|
|
46439
|
-
interject
|
|
46879
|
+
pending.interject,
|
|
46440
46880
|
fields
|
|
46441
46881
|
)
|
|
46442
46882
|
];
|
|
46443
|
-
record.control.interjection = {
|
|
46444
|
-
key,
|
|
46445
|
-
question,
|
|
46446
|
-
expiresAt,
|
|
46447
|
-
workspaceSlug: clause.workspace_slug,
|
|
46448
|
-
configVersion: clause.config_version
|
|
46449
|
-
};
|
|
46883
|
+
record.control.interjection = { ...pending.held };
|
|
46450
46884
|
return events;
|
|
46451
46885
|
}
|
|
46452
46886
|
function expireInterjection(record, now, fields) {
|
|
@@ -46533,7 +46967,7 @@ function settle(record, held, answer, payload, fields) {
|
|
|
46533
46967
|
record.control.interjection = void 0;
|
|
46534
46968
|
return events;
|
|
46535
46969
|
}
|
|
46536
|
-
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_TIMED_OUT_TEXT;
|
|
46970
|
+
var SLUG_PATTERN, SLUG_MIN, SLUG_MAX, NAME_MAX2, INTERJECTION_OPEN, INTERJECTION_TIMED_OUT_TEXT;
|
|
46537
46971
|
var init_interjection2 = __esm({
|
|
46538
46972
|
"../../packages/tacho/src/collector/interjection.ts"() {
|
|
46539
46973
|
"use strict";
|
|
@@ -46544,6 +46978,7 @@ var init_interjection2 = __esm({
|
|
|
46544
46978
|
SLUG_MIN = 2;
|
|
46545
46979
|
SLUG_MAX = 40;
|
|
46546
46980
|
NAME_MAX2 = 120;
|
|
46981
|
+
INTERJECTION_OPEN = "interjection_open";
|
|
46547
46982
|
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
46983
|
}
|
|
46549
46984
|
});
|
|
@@ -46809,21 +47244,23 @@ function promptBlock(view, record) {
|
|
|
46809
47244
|
const block = operatorBlock(view, record);
|
|
46810
47245
|
if (block !== void 0) return block;
|
|
46811
47246
|
const held = record.control.interjection;
|
|
46812
|
-
if (held === void 0
|
|
46813
|
-
|
|
47247
|
+
if (held === void 0 || !showsRefusedPrompt(record.harness))
|
|
47248
|
+
return void 0;
|
|
47249
|
+
return { code: INTERJECTION_OPEN, reason: held.question, source: "bundle" };
|
|
46814
47250
|
}
|
|
46815
|
-
async function
|
|
46816
|
-
if (record.control.repoChecked === true)
|
|
47251
|
+
async function repositoryQuestion(record, view, deps, replay, boundary) {
|
|
47252
|
+
if (record.control.repoChecked === true || questionBoundary(record.harness) !== boundary)
|
|
47253
|
+
return void 0;
|
|
46817
47254
|
record.control.repoChecked = true;
|
|
46818
47255
|
const clause = view.verified ? view.bundle.unbound_repo : void 0;
|
|
46819
|
-
if (clause === void 0 || replay !== void 0 ||
|
|
46820
|
-
return
|
|
47256
|
+
if (clause === void 0 || replay !== void 0 || record.recorder.hasModelCall || record.cwd === void 0 || deps.repositoryRemote === void 0)
|
|
47257
|
+
return void 0;
|
|
46821
47258
|
const remote = await readRepository(
|
|
46822
47259
|
recallView(record),
|
|
46823
47260
|
deps.repositoryRemote
|
|
46824
47261
|
);
|
|
46825
|
-
if (remote === void 0 || isBound(clause, remote)) return
|
|
46826
|
-
return
|
|
47262
|
+
if (remote === void 0 || isBound(clause, remote)) return void 0;
|
|
47263
|
+
return prepareInterjection(record, clause, remote, deps.now());
|
|
46827
47264
|
}
|
|
46828
47265
|
function invocationToolUseId(raw, input, record) {
|
|
46829
47266
|
const derived = input.tool_use_id;
|
|
@@ -47274,12 +47711,19 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47274
47711
|
switch (input.hook_event_name) {
|
|
47275
47712
|
case "SessionStart": {
|
|
47276
47713
|
const block = operatorBlock(view, record);
|
|
47714
|
+
const question = input.agent_id === void 0 ? await repositoryQuestion(record, view, deps, replay, "SessionStart") : void 0;
|
|
47715
|
+
const questionText = question?.held.question;
|
|
47277
47716
|
const steering = block === void 0 && replay === void 0 ? await runSteeringBundle(record, deps) ?? view.bundle : view.bundle;
|
|
47278
47717
|
const context = steering.context.system;
|
|
47279
47718
|
if (block === void 0 && replay === void 0)
|
|
47280
47719
|
await placeSessionSkills(view, record, deps, env);
|
|
47281
|
-
const messages = block === void 0 && replay === void 0 && input.agent_id === void 0 ? drainMessages(
|
|
47282
|
-
|
|
47720
|
+
const messages = block === void 0 && replay === void 0 && input.agent_id === void 0 ? drainMessages(
|
|
47721
|
+
record,
|
|
47722
|
+
deps,
|
|
47723
|
+
events,
|
|
47724
|
+
(context?.length ?? 0) + (questionText?.length ?? 0)
|
|
47725
|
+
) : [];
|
|
47726
|
+
const additional = block === void 0 ? [questionText ?? "", context ?? "", ...messages.map((m) => m.text)].filter((s2) => s2.length > 0).join(CONTEXT_JOINER) : "";
|
|
47283
47727
|
const delivered = replay === void 0 ? void 0 : readDeliveredContext(replay.deliveredContext);
|
|
47284
47728
|
const deliveryAttrs = replay === void 0 ? {
|
|
47285
47729
|
// A blocked start hands the agent nothing, so it names no text.
|
|
@@ -47306,6 +47750,13 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47306
47750
|
})
|
|
47307
47751
|
)
|
|
47308
47752
|
);
|
|
47753
|
+
if (question !== void 0)
|
|
47754
|
+
events.push(
|
|
47755
|
+
...sealInterjection(record, question, {
|
|
47756
|
+
hook_event_name: "SessionStart",
|
|
47757
|
+
attrs: replayed
|
|
47758
|
+
})
|
|
47759
|
+
);
|
|
47309
47760
|
if (block !== void 0) {
|
|
47310
47761
|
events.push(
|
|
47311
47762
|
record.recorder.sealCollectorEvent(
|
|
@@ -47355,14 +47806,15 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47355
47806
|
};
|
|
47356
47807
|
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), questionFields) : void 0;
|
|
47357
47808
|
if (timedOut !== void 0) events.push(...timedOut);
|
|
47358
|
-
const asked = await
|
|
47809
|
+
const asked = await repositoryQuestion(
|
|
47359
47810
|
record,
|
|
47360
47811
|
view,
|
|
47361
47812
|
deps,
|
|
47362
47813
|
replay,
|
|
47363
|
-
|
|
47814
|
+
"UserPromptSubmit"
|
|
47364
47815
|
);
|
|
47365
|
-
|
|
47816
|
+
if (asked !== void 0)
|
|
47817
|
+
events.push(...sealInterjection(record, asked, questionFields));
|
|
47366
47818
|
const block = promptBlock(view, record);
|
|
47367
47819
|
const notice = block === void 0 && timedOut !== void 0 ? INTERJECTION_TIMED_OUT_TEXT : void 0;
|
|
47368
47820
|
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 +47892,17 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47440
47892
|
const toolInput = input.tool_input;
|
|
47441
47893
|
noteToolCall(record, toolName3, toolInput);
|
|
47442
47894
|
noteRecallHints(record, input.tool_name, toolInput);
|
|
47895
|
+
const timedOut = replay === void 0 ? expireInterjection(record, deps.now(), {
|
|
47896
|
+
hook_event_name: "PreToolUse",
|
|
47897
|
+
attrs: replayed
|
|
47898
|
+
}) : void 0;
|
|
47899
|
+
if (timedOut !== void 0) events.push(...timedOut);
|
|
47443
47900
|
const decided = await decideToolCall(view, record, input, deps, replay, {
|
|
47444
47901
|
toolName: toolName3,
|
|
47445
47902
|
toolInput
|
|
47446
47903
|
});
|
|
47447
47904
|
const currentView = decided.view;
|
|
47448
|
-
let evaluation = decided.evaluation;
|
|
47905
|
+
let evaluation = replay === void 0 ? holdToolCall(decided.evaluation, record) : decided.evaluation;
|
|
47449
47906
|
if (replay === void 0 && evaluation.decision === "deny" && evaluation.reason_code === "session_paused" && record.control.pauseEffect === void 0)
|
|
47450
47907
|
record.control.pauseEffect = "refused";
|
|
47451
47908
|
const refusal = evaluation.decision === "deny" ? void 0 : refusesForSteer(record.harness, record.control.messages);
|
|
@@ -47471,7 +47928,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
47471
47928
|
};
|
|
47472
47929
|
}
|
|
47473
47930
|
}
|
|
47474
|
-
if (evaluation.decision === "deny" && evaluation.source !== "human")
|
|
47931
|
+
if (evaluation.decision === "deny" && evaluation.source !== "human" && evaluation.reason_code !== INTERJECTION_OPEN)
|
|
47475
47932
|
notePolicyDenial(record, toolName3);
|
|
47476
47933
|
const facts = policyFacts2(evaluation, currentView);
|
|
47477
47934
|
const attrs2 = policyAttrs(evaluation, replay);
|
|
@@ -48182,6 +48639,14 @@ function expiredAt(command2, now) {
|
|
|
48182
48639
|
}
|
|
48183
48640
|
async function applyCommands(commands, deps) {
|
|
48184
48641
|
const now = deps.now();
|
|
48642
|
+
if (newCommands(commands, deps).fresh.some(
|
|
48643
|
+
(command2) => command2.session_uuid === null && command2.command === "refresh_bundle" && !expiredAt(command2, now)
|
|
48644
|
+
))
|
|
48645
|
+
await deps.refreshBundle();
|
|
48646
|
+
const seal2 = () => sealNewCommands(commands, deps, now);
|
|
48647
|
+
return deps.exclusive !== void 0 ? deps.exclusive(seal2) : seal2();
|
|
48648
|
+
}
|
|
48649
|
+
function newCommands(commands, deps) {
|
|
48185
48650
|
const fresh = [];
|
|
48186
48651
|
const repeated = [];
|
|
48187
48652
|
for (const command2 of commands) {
|
|
@@ -48189,10 +48654,10 @@ async function applyCommands(commands, deps) {
|
|
|
48189
48654
|
repeated.push(command2.id);
|
|
48190
48655
|
else fresh.push(command2);
|
|
48191
48656
|
}
|
|
48192
|
-
|
|
48193
|
-
|
|
48194
|
-
|
|
48195
|
-
|
|
48657
|
+
return { fresh, repeated };
|
|
48658
|
+
}
|
|
48659
|
+
function sealNewCommands(commands, deps, now) {
|
|
48660
|
+
const { fresh, repeated } = newCommands(commands, deps);
|
|
48196
48661
|
const result2 = sealCommands(fresh, deps, now);
|
|
48197
48662
|
for (const ack of result2.acknowledgements) deps.handled?.remember(ack);
|
|
48198
48663
|
for (const id2 of repeated) {
|
|
@@ -53461,6 +53926,19 @@ import {
|
|
|
53461
53926
|
} from "node:http";
|
|
53462
53927
|
import { Agent as HttpsAgent, request as httpsRequest } from "node:https";
|
|
53463
53928
|
import { brotliDecompress, gunzip, inflate, zstdDecompress } from "node:zlib";
|
|
53929
|
+
async function landedWithin(landing, ms) {
|
|
53930
|
+
let timer;
|
|
53931
|
+
try {
|
|
53932
|
+
return await Promise.race([
|
|
53933
|
+
landing.then(() => true),
|
|
53934
|
+
new Promise((resolve26) => {
|
|
53935
|
+
timer = setTimeout(() => resolve26(false), ms);
|
|
53936
|
+
})
|
|
53937
|
+
]);
|
|
53938
|
+
} finally {
|
|
53939
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
53940
|
+
}
|
|
53941
|
+
}
|
|
53464
53942
|
function streamsAnthropicMessages(route, body2) {
|
|
53465
53943
|
return route.api === "anthropic.messages" && body2?.["stream"] === true;
|
|
53466
53944
|
}
|
|
@@ -53651,6 +54129,7 @@ function createModelProxy(deps) {
|
|
|
53651
54129
|
const maxRequestBytes = deps.maxRequestBytes ?? DEFAULT_MAX_REQUEST_BYTES;
|
|
53652
54130
|
const upstreamIdleMs = deps.upstreamIdleMs ?? DEFAULT_UPSTREAM_IDLE_MS;
|
|
53653
54131
|
const hookTimeoutMs = deps.beforeForwardTimeoutMs ?? DEFAULT_BEFORE_FORWARD_TIMEOUT_MS;
|
|
54132
|
+
const refusalWaitMs = deps.refusalFrameWaitMs ?? DEFAULT_REFUSAL_FRAME_WAIT_MS;
|
|
53654
54133
|
const httpAgent = new HttpAgent({ keepAlive: true, maxSockets: Infinity });
|
|
53655
54134
|
const httpsAgent = new HttpsAgent({ keepAlive: true, maxSockets: Infinity });
|
|
53656
54135
|
const inFlight = /* @__PURE__ */ new Map();
|
|
@@ -53776,10 +54255,10 @@ function createModelProxy(deps) {
|
|
|
53776
54255
|
if (known !== void 0 && !known.sealed && !known.pendingTerminal)
|
|
53777
54256
|
return { record: known, how };
|
|
53778
54257
|
if (known !== void 0) {
|
|
53779
|
-
const
|
|
54258
|
+
const open7 = deps.registry.list().find(
|
|
53780
54259
|
(record2) => record2.harnessSessionId === id2 && !record2.sealed && !record2.pendingTerminal
|
|
53781
54260
|
);
|
|
53782
|
-
if (
|
|
54261
|
+
if (open7 !== void 0) return { record: open7, how };
|
|
53783
54262
|
return { how: "session_closed" };
|
|
53784
54263
|
}
|
|
53785
54264
|
const { record } = deps.registry.ensure(id2, { harness, ambient: true });
|
|
@@ -54006,59 +54485,75 @@ function createModelProxy(deps) {
|
|
|
54006
54485
|
found = { how: "unattributed" };
|
|
54007
54486
|
}
|
|
54008
54487
|
return {
|
|
54488
|
+
...found.record !== void 0 ? { record: found.record } : {},
|
|
54009
54489
|
recorder: found.record?.recorder ?? deps.hostRecorder(),
|
|
54010
54490
|
how: found.how,
|
|
54011
54491
|
attrs: attrsFor(route, found.how)
|
|
54012
54492
|
};
|
|
54013
54493
|
}
|
|
54494
|
+
function landingChain(record, how) {
|
|
54495
|
+
if (record === void 0) return { chain: deps.hostRecorder(), attrs: {} };
|
|
54496
|
+
const owner = deps.registry.byUuid(record.recorder.sessionUuid);
|
|
54497
|
+
if (owner !== void 0 && !owner.sealed && owner.pendingTerminal !== true)
|
|
54498
|
+
return { chain: owner.recorder, attrs: {} };
|
|
54499
|
+
return {
|
|
54500
|
+
chain: deps.hostRecorder(),
|
|
54501
|
+
attrs: {
|
|
54502
|
+
"oxagen.correlation": "session_closed",
|
|
54503
|
+
"oxagen.session_correlation": how,
|
|
54504
|
+
"oxagen.session_uuid": record.recorder.sessionUuid
|
|
54505
|
+
}
|
|
54506
|
+
};
|
|
54507
|
+
}
|
|
54014
54508
|
function sealNotForwarded(req, route, attempt, reason3, status2) {
|
|
54015
54509
|
if (attempt.done) return;
|
|
54016
54510
|
attempt.done = true;
|
|
54017
54511
|
if (route.api === "other") return;
|
|
54018
|
-
let
|
|
54019
|
-
|
|
54512
|
+
let session;
|
|
54513
|
+
const lost = (error) => {
|
|
54514
|
+
deps.log(
|
|
54515
|
+
`model proxy: sealing the frame of a call it did not forward (${reason3}) failed: ${error instanceof Error ? error.message : String(error)} session=${session ?? "unattributed"}`
|
|
54516
|
+
);
|
|
54517
|
+
};
|
|
54020
54518
|
try {
|
|
54021
54519
|
const attribution2 = attempt.attribution ?? attributeByHeaders(req, route);
|
|
54022
|
-
|
|
54023
|
-
recorder = chain;
|
|
54024
|
-
mark = chain.markChain();
|
|
54520
|
+
session = attribution2.recorder.sessionUuid;
|
|
54025
54521
|
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
|
-
|
|
54522
|
+
const body2 = {
|
|
54523
|
+
provider: route.provider,
|
|
54524
|
+
...attempt.model !== void 0 ? { model: attempt.model.slice(0, 512) } : {},
|
|
54525
|
+
...status2 !== void 0 ? { api_status_code: status2 } : {},
|
|
54526
|
+
api_error_class: reason3,
|
|
54527
|
+
api_duration_ms: Math.max(0, at2 - attempt.startedAt)
|
|
54528
|
+
};
|
|
54529
|
+
const attrs2 = {
|
|
54530
|
+
...attribution2.attrs,
|
|
54531
|
+
[NOT_FORWARDED_ATTR]: reason3,
|
|
54532
|
+
"oxagen.provider": route.provider,
|
|
54533
|
+
"oxagen.request_bytes_read": String(attempt.bytesRead),
|
|
54534
|
+
...attempt.request !== void 0 ? { "oxagen.request_digest": digestBytes(attempt.request) } : {}
|
|
54535
|
+
};
|
|
54536
|
+
const land = () => {
|
|
54537
|
+
const landing = landingChain(attribution2.record, attribution2.how);
|
|
54538
|
+
recordOnChain(
|
|
54539
|
+
landing.chain,
|
|
54540
|
+
(chain) => [
|
|
54541
|
+
chain.sealCollectorEvent("error", body2, {
|
|
54542
|
+
ts: toProtocolTimestamp(at2),
|
|
54543
|
+
fidelity: "proxy",
|
|
54544
|
+
attrs: { ...attrs2, ...landing.attrs }
|
|
54545
|
+
})
|
|
54546
|
+
],
|
|
54547
|
+
deps.record
|
|
54548
|
+
);
|
|
54549
|
+
};
|
|
54550
|
+
if (attribution2.record === void 0) land();
|
|
54551
|
+
else
|
|
54552
|
+
void onSessionQueue(deps.exclusive, attribution2.record, land).catch(
|
|
54553
|
+
lost
|
|
54554
|
+
);
|
|
54049
54555
|
} 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
|
-
);
|
|
54556
|
+
lost(error);
|
|
54062
54557
|
}
|
|
54063
54558
|
}
|
|
54064
54559
|
function sendProviderError(res, route, status2, code, message, retryable = false) {
|
|
@@ -54347,29 +54842,6 @@ function createModelProxy(deps) {
|
|
|
54347
54842
|
}
|
|
54348
54843
|
callsObserved += 1;
|
|
54349
54844
|
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
54845
|
const callBody2 = llmCallBody({
|
|
54374
54846
|
provider: "anthropic",
|
|
54375
54847
|
model,
|
|
@@ -54385,10 +54857,33 @@ function createModelProxy(deps) {
|
|
|
54385
54857
|
failed: answer.errorClass ?? (answer.status >= 400 ? `http_${answer.status}` : void 0),
|
|
54386
54858
|
requestId: answer.requestId
|
|
54387
54859
|
});
|
|
54388
|
-
const
|
|
54389
|
-
|
|
54390
|
-
|
|
54391
|
-
|
|
54860
|
+
const land = () => {
|
|
54861
|
+
const owner = deps.registry.byUuid(record.recorder.sessionUuid);
|
|
54862
|
+
const closed2 = owner === void 0 || owner.sealed || owner.pendingTerminal === true;
|
|
54863
|
+
const requestText = payload.body.toString("utf8");
|
|
54864
|
+
const memory = new RequestPrefixMemory();
|
|
54865
|
+
if (payload.priorShape !== void 0 && !closed2)
|
|
54866
|
+
memory.remember("parent", {
|
|
54867
|
+
text: "",
|
|
54868
|
+
fullDigest: payload.priorShape.requestDigest,
|
|
54869
|
+
fullBytes: 0,
|
|
54870
|
+
storedBytes: 0,
|
|
54871
|
+
prior: void 0,
|
|
54872
|
+
shape: payload.priorShape,
|
|
54873
|
+
priorPayload: void 0
|
|
54874
|
+
});
|
|
54875
|
+
const fold = memory.fold("parent", requestText);
|
|
54876
|
+
const capped = cappedExchange(
|
|
54877
|
+
fold.storedBytes > TACHO_MAX_BODY_BYTES ? void 0 : fold.text,
|
|
54878
|
+
{
|
|
54879
|
+
text: answer.responseText,
|
|
54880
|
+
tooLarge: answer.responseTooLarge,
|
|
54881
|
+
bytes: answer.responseBytes
|
|
54882
|
+
}
|
|
54883
|
+
);
|
|
54884
|
+
recordOnChain(
|
|
54885
|
+
closed2 ? deps.hostRecorder() : owner.recorder,
|
|
54886
|
+
(chain) => [
|
|
54392
54887
|
chain.sealCollectorEvent("llm_call", callBody2, {
|
|
54393
54888
|
ts: toProtocolTimestamp(settledAt),
|
|
54394
54889
|
fidelity: "proxy",
|
|
@@ -54427,20 +54922,16 @@ function createModelProxy(deps) {
|
|
|
54427
54922
|
}
|
|
54428
54923
|
})
|
|
54429
54924
|
],
|
|
54430
|
-
|
|
54925
|
+
deps.record
|
|
54431
54926
|
);
|
|
54432
|
-
}
|
|
54433
|
-
|
|
54434
|
-
|
|
54435
|
-
} catch (rollbackError) {
|
|
54927
|
+
};
|
|
54928
|
+
void onSessionQueue(deps.exclusive, record, land).catch(
|
|
54929
|
+
(error) => {
|
|
54436
54930
|
deps.log(
|
|
54437
|
-
`model proxy:
|
|
54931
|
+
`model proxy: sealing a cache keep-alive's frame failed: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
54438
54932
|
);
|
|
54439
54933
|
}
|
|
54440
|
-
|
|
54441
|
-
`model proxy: sealing a cache keep-alive's frame failed: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
54442
|
-
);
|
|
54443
|
-
}
|
|
54934
|
+
);
|
|
54444
54935
|
return usage2.cacheReadTokens ?? 0;
|
|
54445
54936
|
}
|
|
54446
54937
|
async function forward(req, res, route, admitted, attempt) {
|
|
@@ -54481,7 +54972,12 @@ function createModelProxy(deps) {
|
|
|
54481
54972
|
const sessionKey = record?.recorder.sessionUuid ?? HOST_KEY;
|
|
54482
54973
|
const credential = resolveCredential(req, route);
|
|
54483
54974
|
const attrs2 = attrsFor(route, how, credential);
|
|
54484
|
-
attempt.attribution = {
|
|
54975
|
+
attempt.attribution = {
|
|
54976
|
+
...record !== void 0 ? { record } : {},
|
|
54977
|
+
recorder,
|
|
54978
|
+
how,
|
|
54979
|
+
attrs: attrs2
|
|
54980
|
+
};
|
|
54485
54981
|
const metered = route.api !== "other";
|
|
54486
54982
|
const { model: askedModel, ambiguous: modelAmbiguous } = modelOf(
|
|
54487
54983
|
readable,
|
|
@@ -54527,44 +55023,58 @@ function createModelProxy(deps) {
|
|
|
54527
55023
|
if (refusal !== void 0) {
|
|
54528
55024
|
refused2 += 1;
|
|
54529
55025
|
const view = deps.policy();
|
|
54530
|
-
const
|
|
54531
|
-
|
|
54532
|
-
|
|
54533
|
-
|
|
54534
|
-
|
|
54535
|
-
|
|
54536
|
-
|
|
54537
|
-
|
|
54538
|
-
|
|
54539
|
-
|
|
54540
|
-
|
|
54541
|
-
|
|
54542
|
-
|
|
54543
|
-
|
|
55026
|
+
const decision = {
|
|
55027
|
+
policy_decision: "deny",
|
|
55028
|
+
policy_source: refusal.source,
|
|
55029
|
+
policy_reason_code: refusal.code,
|
|
55030
|
+
policy_reason_digest: digestText(refusal.message),
|
|
55031
|
+
bundle_version: view.bundle.version,
|
|
55032
|
+
bundle_mode: view.bundle.mode
|
|
55033
|
+
};
|
|
55034
|
+
const decisionAttrs = {
|
|
55035
|
+
...attrs2,
|
|
55036
|
+
"oxagen.refused": "model_call",
|
|
55037
|
+
"oxagen.provider": route.provider,
|
|
55038
|
+
"oxagen.request_digest": digestBytes(body2),
|
|
55039
|
+
// The model the refusal was about, when the proxy could read one. A
|
|
55040
|
+
// `model_not_permitted` frame that does not name the model leaves the
|
|
55041
|
+
// operator guessing which entry to add.
|
|
55042
|
+
...askedModel !== void 0 ? { "oxagen.model": askedModel.slice(0, 512) } : {},
|
|
55043
|
+
...modelAmbiguous ? { "oxagen.model_ambiguous": "true" } : {},
|
|
55044
|
+
...record !== void 0 ? {
|
|
55045
|
+
"oxagen.session_spend_usd_micros": String(spendFor(sessionKey))
|
|
55046
|
+
} : {},
|
|
55047
|
+
..."attrs" in refusal ? refusal.attrs : {}
|
|
55048
|
+
};
|
|
55049
|
+
const land = () => {
|
|
55050
|
+
const landing = landingChain(record, how);
|
|
55051
|
+
recordOnChain(
|
|
55052
|
+
landing.chain,
|
|
55053
|
+
(chain) => [
|
|
55054
|
+
chain.sealCollectorEvent("policy_decision", decision, {
|
|
54544
55055
|
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;
|
|
55056
|
+
attrs: { ...decisionAttrs, ...landing.attrs }
|
|
55057
|
+
})
|
|
55058
|
+
],
|
|
55059
|
+
deps.record
|
|
55060
|
+
);
|
|
55061
|
+
};
|
|
55062
|
+
if (record === void 0) land();
|
|
55063
|
+
else {
|
|
55064
|
+
let answered = false;
|
|
55065
|
+
const written2 = onSessionQueue(deps.exclusive, record, land);
|
|
55066
|
+
void written2.catch((error) => {
|
|
55067
|
+
if (answered)
|
|
55068
|
+
deps.log(
|
|
55069
|
+
`model proxy: the frame of a refusal already answered was not written: ${error instanceof Error ? error.message : String(error)} session=${sessionKey}`
|
|
55070
|
+
);
|
|
55071
|
+
});
|
|
55072
|
+
if (!await landedWithin(written2, refusalWaitMs)) {
|
|
55073
|
+
answered = true;
|
|
55074
|
+
deps.log(
|
|
55075
|
+
`model proxy: answered a refused call before its frame could land, because the session's queue was busy for ${refusalWaitMs} ms session=${sessionKey}`
|
|
55076
|
+
);
|
|
55077
|
+
}
|
|
54568
55078
|
}
|
|
54569
55079
|
attempt.done = true;
|
|
54570
55080
|
deps.log(
|
|
@@ -55245,9 +55755,9 @@ function createModelProxy(deps) {
|
|
|
55245
55755
|
callsObservedFor: (sessionUuid2) => observed.get(sessionUuid2) ?? 0,
|
|
55246
55756
|
keepAliveTick: () => keepAlive.tick(),
|
|
55247
55757
|
stats: () => {
|
|
55248
|
-
let
|
|
55249
|
-
for (const calls of inFlight.values())
|
|
55250
|
-
return { callsObserved, refused: refused2, inFlight:
|
|
55758
|
+
let open7 = 0;
|
|
55759
|
+
for (const calls of inFlight.values()) open7 += calls.size;
|
|
55760
|
+
return { callsObserved, refused: refused2, inFlight: open7 };
|
|
55251
55761
|
},
|
|
55252
55762
|
close: () => {
|
|
55253
55763
|
clearInterval(keepAliveTimer);
|
|
@@ -55262,7 +55772,7 @@ function createModelProxy(deps) {
|
|
|
55262
55772
|
}
|
|
55263
55773
|
};
|
|
55264
55774
|
}
|
|
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;
|
|
55775
|
+
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
55776
|
var init_model_proxy = __esm({
|
|
55267
55777
|
"../../packages/tacho/src/collector/model-proxy.ts"() {
|
|
55268
55778
|
"use strict";
|
|
@@ -55293,6 +55803,7 @@ var init_model_proxy = __esm({
|
|
|
55293
55803
|
DEFAULT_UPSTREAM_IDLE_MS = 10 * 6e4;
|
|
55294
55804
|
DEFAULT_BEFORE_FORWARD_TIMEOUT_MS = 250;
|
|
55295
55805
|
DEFAULT_UPSTREAM_CONNECT_MS = 3e4;
|
|
55806
|
+
DEFAULT_REFUSAL_FRAME_WAIT_MS = 1e3;
|
|
55296
55807
|
DEFAULT_PAUSE_HOLD_MS = 12e4;
|
|
55297
55808
|
DEFAULT_PAUSE_STREAM_HOLD_MS = 12 * 60 * 6e4;
|
|
55298
55809
|
DEFAULT_PAUSE_HOLD_PING_MS = 15e3;
|
|
@@ -55477,7 +55988,7 @@ var init_model_proxy_listener = __esm({
|
|
|
55477
55988
|
import {
|
|
55478
55989
|
createServer as createServer5
|
|
55479
55990
|
} from "node:http";
|
|
55480
|
-
import { chmodSync as chmodSync9, existsSync as existsSync23, statSync as
|
|
55991
|
+
import { chmodSync as chmodSync9, existsSync as existsSync23, statSync as statSync13, unlinkSync as unlinkSync11 } from "node:fs";
|
|
55481
55992
|
import { randomBytes as randomBytes11, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
55482
55993
|
import { createConnection } from "node:net";
|
|
55483
55994
|
function isExportFormat(value) {
|
|
@@ -55853,7 +56364,7 @@ function createRequestHandler(api, log, options = {}) {
|
|
|
55853
56364
|
}
|
|
55854
56365
|
async function removeStaleSocket(socketPath) {
|
|
55855
56366
|
if (!existsSync23(socketPath)) return;
|
|
55856
|
-
if (!
|
|
56367
|
+
if (!statSync13(socketPath).isSocket()) {
|
|
55857
56368
|
throw new Error(`collector socket path is not a socket: ${socketPath}`);
|
|
55858
56369
|
}
|
|
55859
56370
|
const stale = await new Promise((resolve26, reject) => {
|
|
@@ -56022,7 +56533,7 @@ var init_server = __esm({
|
|
|
56022
56533
|
});
|
|
56023
56534
|
|
|
56024
56535
|
// ../../packages/tacho/src/collector/refused.ts
|
|
56025
|
-
import { readdirSync as readdirSync12, readFileSync as readFileSync20, statSync as
|
|
56536
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync20, statSync as statSync14 } from "node:fs";
|
|
56026
56537
|
import { join as join45 } from "node:path";
|
|
56027
56538
|
function refusalRetryable(refusal) {
|
|
56028
56539
|
return refusal === "malformed" || refusal === "parked";
|
|
@@ -56072,7 +56583,7 @@ function readRefusedEntry(file) {
|
|
|
56072
56583
|
let mtimeMs;
|
|
56073
56584
|
try {
|
|
56074
56585
|
record = JSON.parse(readFileSync20(file, "utf8"));
|
|
56075
|
-
mtimeMs =
|
|
56586
|
+
mtimeMs = statSync14(file).mtimeMs;
|
|
56076
56587
|
} catch {
|
|
56077
56588
|
return void 0;
|
|
56078
56589
|
}
|
|
@@ -57025,7 +57536,7 @@ import {
|
|
|
57025
57536
|
readdirSync as readdirSync13,
|
|
57026
57537
|
readFileSync as readFileSync22,
|
|
57027
57538
|
renameSync as renameSync4,
|
|
57028
|
-
statSync as
|
|
57539
|
+
statSync as statSync15,
|
|
57029
57540
|
unlinkSync as unlinkSync13
|
|
57030
57541
|
} from "node:fs";
|
|
57031
57542
|
import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "node:fs/promises";
|
|
@@ -57224,7 +57735,8 @@ async function startDaemon(options) {
|
|
|
57224
57735
|
}
|
|
57225
57736
|
}
|
|
57226
57737
|
async function initializeDaemon(options, server, port, ready) {
|
|
57227
|
-
const paths = options.paths;
|
|
57738
|
+
const paths = withRecordedHarnessFiles(options.paths, options.host);
|
|
57739
|
+
const harnessHomes = recordedHarnessHomes(options.host);
|
|
57228
57740
|
const now = options.now ?? (() => Date.now());
|
|
57229
57741
|
const log = options.log;
|
|
57230
57742
|
const timers = { ...DEFAULT_TIMERS, ...options.timers };
|
|
@@ -57374,7 +57886,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57374
57886
|
processStarts: hookProcessStarts,
|
|
57375
57887
|
adoptedChain: (sessionUuid2) => backfillLedger.chainHead(sessionUuid2)
|
|
57376
57888
|
});
|
|
57377
|
-
const priorStateWrittenAt = existsSync25(paths.daemonState) ?
|
|
57889
|
+
const priorStateWrittenAt = existsSync25(paths.daemonState) ? statSync15(paths.daemonState).mtimeMs : void 0;
|
|
57378
57890
|
const sealedState = parseSealedState(
|
|
57379
57891
|
readJsonStateFile(
|
|
57380
57892
|
paths.daemonSealedState,
|
|
@@ -57521,7 +58033,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57521
58033
|
},
|
|
57522
58034
|
...options.workOrders?.spawn !== void 0 ? { spawn: options.workOrders.spawn } : {},
|
|
57523
58035
|
...options.workOrders?.isAlive !== void 0 ? { isAlive: options.workOrders.isAlive } : {},
|
|
57524
|
-
...options.workOrders?.findCheckout !== void 0 ? { findCheckout: options.workOrders.findCheckout } : {}
|
|
58036
|
+
...options.workOrders?.findCheckout !== void 0 ? { findCheckout: options.workOrders.findCheckout } : {},
|
|
58037
|
+
...options.workOrders?.wait !== void 0 ? { wait: options.workOrders.wait } : {}
|
|
57525
58038
|
});
|
|
57526
58039
|
void workOrderAutostart.clearDeadMarks();
|
|
57527
58040
|
function persistState(options2 = {}) {
|
|
@@ -57736,25 +58249,24 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57736
58249
|
});
|
|
57737
58250
|
}
|
|
57738
58251
|
async function applyCommandsRecorded(commands, deps) {
|
|
57739
|
-
|
|
57740
|
-
|
|
57741
|
-
|
|
57742
|
-
|
|
57743
|
-
|
|
57744
|
-
|
|
57745
|
-
|
|
57746
|
-
|
|
57747
|
-
|
|
58252
|
+
return applyCommands2(commands, {
|
|
58253
|
+
...deps,
|
|
58254
|
+
exclusive: (seal2) => queues.host(async () => {
|
|
58255
|
+
if (hostRecord.sealed) throw new Error(STOPPING);
|
|
58256
|
+
const marks = markCommandChains(commands);
|
|
58257
|
+
let result2;
|
|
58258
|
+
try {
|
|
58259
|
+
result2 = seal2();
|
|
58260
|
+
record(result2.events);
|
|
58261
|
+
return result2;
|
|
58262
|
+
} catch (error) {
|
|
58263
|
+
for (const { session, mark } of [...marks].reverse())
|
|
58264
|
+
session.recorder.rollbackChain(mark);
|
|
58265
|
+
result2?.restore();
|
|
58266
|
+
throw error;
|
|
57748
58267
|
}
|
|
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
|
-
}
|
|
58268
|
+
})
|
|
58269
|
+
});
|
|
57758
58270
|
}
|
|
57759
58271
|
let modelBaseUrls = [];
|
|
57760
58272
|
const spoolFacts = /* @__PURE__ */ new Map();
|
|
@@ -57876,6 +58388,31 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57876
58388
|
}
|
|
57877
58389
|
}
|
|
57878
58390
|
function retryOwedBodyPurge() {
|
|
58391
|
+
if (existsSync25(bodyPurgeOwedPath)) void settleOwedBodyPurge("owed");
|
|
58392
|
+
}
|
|
58393
|
+
let bodyPurge;
|
|
58394
|
+
let bodyPurgeAgain = false;
|
|
58395
|
+
let bodyPurgeNarrowing = false;
|
|
58396
|
+
function settleOwedBodyPurge(trigger) {
|
|
58397
|
+
if (trigger === "narrowed") bodyPurgeNarrowing = true;
|
|
58398
|
+
if (bodyPurge !== void 0) {
|
|
58399
|
+
bodyPurgeAgain = true;
|
|
58400
|
+
return bodyPurge;
|
|
58401
|
+
}
|
|
58402
|
+
const run3 = (async () => {
|
|
58403
|
+
do {
|
|
58404
|
+
bodyPurgeAgain = false;
|
|
58405
|
+
const narrowing = bodyPurgeNarrowing;
|
|
58406
|
+
bodyPurgeNarrowing = false;
|
|
58407
|
+
await sweepOwedBodies(narrowing);
|
|
58408
|
+
} while (bodyPurgeAgain && !stopped2);
|
|
58409
|
+
})().finally(() => {
|
|
58410
|
+
if (bodyPurge === run3) bodyPurge = void 0;
|
|
58411
|
+
});
|
|
58412
|
+
bodyPurge = run3;
|
|
58413
|
+
return run3;
|
|
58414
|
+
}
|
|
58415
|
+
async function sweepOwedBodies(narrowing) {
|
|
57879
58416
|
const owed = owedBodyPurge();
|
|
57880
58417
|
if (owed === void 0) return;
|
|
57881
58418
|
let clause = owed.retention;
|
|
@@ -57885,16 +58422,28 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57885
58422
|
clause = inForce.mandate;
|
|
57886
58423
|
}
|
|
57887
58424
|
try {
|
|
57888
|
-
const purged = wal.
|
|
58425
|
+
const purged = await wal.purgeBodiesOutsideMandateAsync(clause, {
|
|
58426
|
+
signal: stopping.signal
|
|
58427
|
+
}) + purgePendingEndBodies(clause);
|
|
57889
58428
|
purgeQueuedPrompts(clause);
|
|
57890
|
-
clearBodyPurgeOwed();
|
|
58429
|
+
if (!bodyPurgeAgain) clearBodyPurgeOwed();
|
|
57891
58430
|
log(
|
|
57892
|
-
`completed an owed body purge: erased ${purged} queued body(ies) the mandate does not cover`
|
|
58431
|
+
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
58432
|
);
|
|
57894
58433
|
} catch (error) {
|
|
57895
|
-
|
|
57896
|
-
|
|
57897
|
-
|
|
58434
|
+
const reason3 = error instanceof Error ? error.message : String(error);
|
|
58435
|
+
if (stopping.signal.aborted)
|
|
58436
|
+
log(
|
|
58437
|
+
"stop: left an owed body purge unfinished; the next start finishes it"
|
|
58438
|
+
);
|
|
58439
|
+
else if (narrowing)
|
|
58440
|
+
log(
|
|
58441
|
+
`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`
|
|
58442
|
+
);
|
|
58443
|
+
else
|
|
58444
|
+
log(
|
|
58445
|
+
`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`
|
|
58446
|
+
);
|
|
57898
58447
|
}
|
|
57899
58448
|
}
|
|
57900
58449
|
function purgeQueuedPrompts(clause) {
|
|
@@ -57917,21 +58466,30 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57917
58466
|
const dropped = HOST_RETENTION_CLASSES.filter(
|
|
57918
58467
|
(contentClass) => retentionAllows(previous, contentClass) && !retentionAllows(next, contentClass)
|
|
57919
58468
|
);
|
|
57920
|
-
if (dropped.length === 0) return
|
|
57921
|
-
|
|
58469
|
+
if (dropped.length === 0) return "none";
|
|
58470
|
+
if (markBodyPurgeOwed(next, dropped)) {
|
|
58471
|
+
try {
|
|
58472
|
+
purgePendingEndBodies(next);
|
|
58473
|
+
purgeQueuedPrompts(next);
|
|
58474
|
+
} catch (error) {
|
|
58475
|
+
log(
|
|
58476
|
+
`failed to erase bodies the narrowed mandate no longer covers (${dropped.join(", ")}); content remains on disk: ${error instanceof Error ? error.message : String(error)}`
|
|
58477
|
+
);
|
|
58478
|
+
}
|
|
58479
|
+
return "owed";
|
|
58480
|
+
}
|
|
57922
58481
|
try {
|
|
57923
58482
|
const purged = wal.purgeBodiesOutsideMandate(next) + purgePendingEndBodies(next);
|
|
57924
58483
|
purgeQueuedPrompts(next);
|
|
57925
|
-
clearBodyPurgeOwed();
|
|
57926
58484
|
log(
|
|
57927
58485
|
`mandate narrowed (${dropped.join(", ")}): erased ${purged} queued body(ies) from the WAL`
|
|
57928
58486
|
);
|
|
57929
|
-
return
|
|
58487
|
+
return "swept";
|
|
57930
58488
|
} catch (error) {
|
|
57931
58489
|
log(
|
|
57932
58490
|
`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
58491
|
);
|
|
57934
|
-
return
|
|
58492
|
+
return "refused";
|
|
57935
58493
|
}
|
|
57936
58494
|
}
|
|
57937
58495
|
async function fetchBundle() {
|
|
@@ -57963,10 +58521,11 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57963
58521
|
);
|
|
57964
58522
|
return "refused";
|
|
57965
58523
|
}
|
|
57966
|
-
|
|
58524
|
+
const narrowing = purgeBodiesNarrowedOut(
|
|
57967
58525
|
host.bundle.retention,
|
|
57968
58526
|
response.bundle.retention
|
|
57969
|
-
)
|
|
58527
|
+
);
|
|
58528
|
+
if (narrowing === "refused") {
|
|
57970
58529
|
log(
|
|
57971
58530
|
"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
58531
|
);
|
|
@@ -57979,6 +58538,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
57979
58538
|
bundleVerified = true;
|
|
57980
58539
|
mandateConfirmedAt = now();
|
|
57981
58540
|
log(`bundle ${response.bundle.version} (${response.bundle.etag}) cached`);
|
|
58541
|
+
if (narrowing === "owed") void settleOwedBodyPurge("narrowed");
|
|
57982
58542
|
return "cached";
|
|
57983
58543
|
} catch (error) {
|
|
57984
58544
|
log(
|
|
@@ -58341,7 +58901,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
58341
58901
|
lastIngestAt ?? -Infinity,
|
|
58342
58902
|
lastCommandPollAt ?? -Infinity
|
|
58343
58903
|
);
|
|
58344
|
-
|
|
58904
|
+
const pollEveryMs = registry2.live().some((session) => session !== hostRecord) ? timers.commandsPollMs : timers.commandsPollMs * IDLE_COMMAND_POLL_FACTOR;
|
|
58905
|
+
if (pendingAcks.length === 0 && now() - lastEnvelopeAt < pollEveryMs) {
|
|
58345
58906
|
return;
|
|
58346
58907
|
}
|
|
58347
58908
|
if (now() < commandPollNextAttemptAt) return;
|
|
@@ -58742,6 +59303,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
58742
59303
|
restoreEveryQueue(queued);
|
|
58743
59304
|
throw error;
|
|
58744
59305
|
}
|
|
59306
|
+
const workOrder = workOrderIdOf(envelope2.env?.[WORK_ORDER_ENV]);
|
|
59307
|
+
if (workOrder !== void 0) workOrderAutostart.noteSession(workOrder);
|
|
58745
59308
|
if (pending !== void 0) {
|
|
58746
59309
|
const state = registry2.state();
|
|
58747
59310
|
const key = sessionMapKey(harnessSessionId, {
|
|
@@ -59244,7 +59807,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59244
59807
|
const state = await readModelBaseUrlState({
|
|
59245
59808
|
home: options.home ?? homedir8(),
|
|
59246
59809
|
port: modelProxyPortFor(host),
|
|
59247
|
-
stellaHome: dirname26(
|
|
59810
|
+
stellaHome: dirname26(paths.stellaToml),
|
|
59811
|
+
...harnessHomes,
|
|
59248
59812
|
harnesses: ["claude-code", "codex", "stella"]
|
|
59249
59813
|
});
|
|
59250
59814
|
const next = {};
|
|
@@ -59807,7 +60371,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
59807
60371
|
if (!name.endsWith(".json")) continue;
|
|
59808
60372
|
const file = join47(paths.quarantine, name);
|
|
59809
60373
|
try {
|
|
59810
|
-
const refusedAt = readRefusedEntry(file)?.refusedAt ??
|
|
60374
|
+
const refusedAt = readRefusedEntry(file)?.refusedAt ?? statSync15(file).mtimeMs;
|
|
59811
60375
|
if (at2 - refusedAt < retainMs) continue;
|
|
59812
60376
|
unlinkSync13(file);
|
|
59813
60377
|
removed += 1;
|
|
@@ -60080,7 +60644,11 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60080
60644
|
else if (typeof refreshed === "object")
|
|
60081
60645
|
log(`ChatGPT login refresh: ${refreshed.failed}`);
|
|
60082
60646
|
if (refreshed !== "none")
|
|
60083
|
-
restateCodexLastRefresh(
|
|
60647
|
+
restateCodexLastRefresh(
|
|
60648
|
+
options.home ?? homedir8(),
|
|
60649
|
+
now(),
|
|
60650
|
+
harnessHomes
|
|
60651
|
+
);
|
|
60084
60652
|
} catch (error) {
|
|
60085
60653
|
log(
|
|
60086
60654
|
`ChatGPT login refresh: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -60093,6 +60661,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60093
60661
|
await renewStaticToken(harness, {
|
|
60094
60662
|
home: options.home ?? homedir8(),
|
|
60095
60663
|
stellaHome: dirname26(paths.stellaToml),
|
|
60664
|
+
...harnessHomes,
|
|
60096
60665
|
host,
|
|
60097
60666
|
runTokenKeyPath: paths.runTokenKey,
|
|
60098
60667
|
now,
|
|
@@ -60222,6 +60791,9 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60222
60791
|
drainSpool: () => queues.host(() => drainSpool()),
|
|
60223
60792
|
queues,
|
|
60224
60793
|
refreshBundle: () => refreshBundle({ force: true }),
|
|
60794
|
+
bodyPurgeIdle: async () => {
|
|
60795
|
+
while (bodyPurge !== void 0) await bodyPurge;
|
|
60796
|
+
},
|
|
60225
60797
|
workOrdersIdle: () => workOrderAutostart.idle(),
|
|
60226
60798
|
stop: async () => {
|
|
60227
60799
|
if (stopped2) return;
|
|
@@ -60240,7 +60812,8 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60240
60812
|
}
|
|
60241
60813
|
const [gitSettled, memorySettled] = await Promise.all([
|
|
60242
60814
|
settleWithin(gitLane, timers.stopLaneMs),
|
|
60243
|
-
settleWithin(memoryScan, timers.stopLaneMs)
|
|
60815
|
+
settleWithin(memoryScan, timers.stopLaneMs),
|
|
60816
|
+
settleWithin(bodyPurge, timers.stopLaneMs)
|
|
60244
60817
|
]);
|
|
60245
60818
|
if (!gitSettled)
|
|
60246
60819
|
log(
|
|
@@ -60281,7 +60854,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
60281
60854
|
}
|
|
60282
60855
|
};
|
|
60283
60856
|
}
|
|
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;
|
|
60857
|
+
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
60858
|
var init_daemon = __esm({
|
|
60286
60859
|
"../../packages/tacho/src/collector/daemon.ts"() {
|
|
60287
60860
|
"use strict";
|
|
@@ -60357,6 +60930,7 @@ var init_daemon = __esm({
|
|
|
60357
60930
|
init_refused();
|
|
60358
60931
|
init_session_heads();
|
|
60359
60932
|
init_transcript_tailer();
|
|
60933
|
+
IDLE_COMMAND_POLL_FACTOR = 8;
|
|
60360
60934
|
DEFAULT_TIMERS = {
|
|
60361
60935
|
shipMs: 5e3,
|
|
60362
60936
|
bundleRefreshMs: 5 * 6e4,
|
|
@@ -60650,7 +61224,7 @@ import {
|
|
|
60650
61224
|
lstatSync as lstatSync8,
|
|
60651
61225
|
mkdirSync as mkdirSync7,
|
|
60652
61226
|
openSync as openSync8,
|
|
60653
|
-
readSync as
|
|
61227
|
+
readSync as readSync5,
|
|
60654
61228
|
realpathSync as realpathSync6,
|
|
60655
61229
|
writeFileSync as writeFileSync4
|
|
60656
61230
|
} from "node:fs";
|
|
@@ -60696,11 +61270,11 @@ function readBounded(root, relative11, limit = ARP_MAX_BLOB_BYTES) {
|
|
|
60696
61270
|
const bytes = Buffer.alloc(stat7.size);
|
|
60697
61271
|
let offset = 0;
|
|
60698
61272
|
while (offset < bytes.length) {
|
|
60699
|
-
const count12 =
|
|
61273
|
+
const count12 = readSync5(fd2, bytes, offset, bytes.length - offset, offset);
|
|
60700
61274
|
if (!count12) arpFail(`The bundle file ${relative11} changed while it was read.`);
|
|
60701
61275
|
offset += count12;
|
|
60702
61276
|
}
|
|
60703
|
-
if (
|
|
61277
|
+
if (readSync5(fd2, Buffer.alloc(1), 0, 1, offset) !== 0)
|
|
60704
61278
|
arpFail(`The bundle file ${relative11} changed while it was read.`);
|
|
60705
61279
|
return bytes;
|
|
60706
61280
|
} finally {
|
|
@@ -60883,13 +61457,13 @@ function verifySettledEvidence(events) {
|
|
|
60883
61457
|
}
|
|
60884
61458
|
}
|
|
60885
61459
|
if (tools.size || children.size || approvals.size) {
|
|
60886
|
-
const
|
|
61460
|
+
const open7 = [
|
|
60887
61461
|
...[...tools].map((id2) => `tool ${id2}`),
|
|
60888
61462
|
...[...approvals].map((id2) => `approval ${id2}`),
|
|
60889
61463
|
...[...children].map((id2) => `child work ${id2}`)
|
|
60890
61464
|
];
|
|
60891
61465
|
arpFail(
|
|
60892
|
-
`The source has unsettled tools, approvals, or child work at its boundary: ${
|
|
61466
|
+
`The source has unsettled tools, approvals, or child work at its boundary: ${open7.join(", ")}.`
|
|
60893
61467
|
);
|
|
60894
61468
|
}
|
|
60895
61469
|
const present = (value) => value !== void 0 && value !== null && value !== false && !(Array.isArray(value) && value.length === 0);
|
|
@@ -61621,7 +62195,7 @@ import {
|
|
|
61621
62195
|
lstatSync as lstatSync9,
|
|
61622
62196
|
mkdirSync as mkdirSync8,
|
|
61623
62197
|
openSync as openSync9,
|
|
61624
|
-
readSync as
|
|
62198
|
+
readSync as readSync6,
|
|
61625
62199
|
realpathSync as realpathSync7,
|
|
61626
62200
|
rmSync as rmSync9,
|
|
61627
62201
|
writeFileSync as writeFileSync5
|
|
@@ -61647,14 +62221,14 @@ function readRegular(label2, path2, limit) {
|
|
|
61647
62221
|
const bytes = Buffer.alloc(before.size);
|
|
61648
62222
|
let offset = 0;
|
|
61649
62223
|
while (offset < bytes.length) {
|
|
61650
|
-
const count12 =
|
|
62224
|
+
const count12 = readSync6(fd2, bytes, offset, bytes.length - offset, offset);
|
|
61651
62225
|
if (count12 === 0)
|
|
61652
62226
|
arpFail(
|
|
61653
62227
|
`${label2} ${path2} changed while it was read. Stop its writer and capture again.`
|
|
61654
62228
|
);
|
|
61655
62229
|
offset += count12;
|
|
61656
62230
|
}
|
|
61657
|
-
if (
|
|
62231
|
+
if (readSync6(fd2, Buffer.alloc(1), 0, 1, offset) !== 0)
|
|
61658
62232
|
arpFail(
|
|
61659
62233
|
`${label2} ${path2} grew while it was read. Stop its writer and capture again.`
|
|
61660
62234
|
);
|
|
@@ -62672,7 +63246,7 @@ var init_package = __esm({
|
|
|
62672
63246
|
"package.json"() {
|
|
62673
63247
|
package_default = {
|
|
62674
63248
|
name: "@oxagen/cli",
|
|
62675
|
-
version: "2.1.5-
|
|
63249
|
+
version: "2.1.5-69",
|
|
62676
63250
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
62677
63251
|
type: "module",
|
|
62678
63252
|
main: "./dist/index.js",
|
|
@@ -62768,7 +63342,7 @@ var init_atomic_write = __esm({
|
|
|
62768
63342
|
// src/lib/config.ts
|
|
62769
63343
|
import { homedir as homedir9 } from "os";
|
|
62770
63344
|
import { join as join51 } from "path";
|
|
62771
|
-
import { readFileSync as readFileSync25, mkdirSync as mkdirSync9, existsSync as existsSync27, statSync as
|
|
63345
|
+
import { readFileSync as readFileSync25, mkdirSync as mkdirSync9, existsSync as existsSync27, statSync as statSync16 } from "fs";
|
|
62772
63346
|
function getConfigDir() {
|
|
62773
63347
|
return CONFIG_DIR;
|
|
62774
63348
|
}
|
|
@@ -62798,7 +63372,7 @@ function parseConfig(raw) {
|
|
|
62798
63372
|
function readConfig() {
|
|
62799
63373
|
let identity;
|
|
62800
63374
|
try {
|
|
62801
|
-
const info =
|
|
63375
|
+
const info = statSync16(CONFIG_FILE);
|
|
62802
63376
|
identity = `${info.ino}:${info.size}:${info.mtimeMs}`;
|
|
62803
63377
|
} catch {
|
|
62804
63378
|
cached2 = void 0;
|
|
@@ -87507,7 +88081,7 @@ __export(verify_exports, {
|
|
|
87507
88081
|
readBundle: () => readBundle,
|
|
87508
88082
|
verifyBundle: () => verifyBundle3
|
|
87509
88083
|
});
|
|
87510
|
-
import { existsSync as existsSync30, readFileSync as readFileSync27, statSync as
|
|
88084
|
+
import { existsSync as existsSync30, readFileSync as readFileSync27, statSync as statSync17 } from "node:fs";
|
|
87511
88085
|
import { join as join61 } from "node:path";
|
|
87512
88086
|
function readDirectory(dir) {
|
|
87513
88087
|
const read2 = (name) => {
|
|
@@ -87558,7 +88132,7 @@ function readBundle(path2) {
|
|
|
87558
88132
|
if (!existsSync30(path2)) {
|
|
87559
88133
|
throw new BundleReadError(`${path2} does not exist.`);
|
|
87560
88134
|
}
|
|
87561
|
-
return
|
|
88135
|
+
return statSync17(path2).isDirectory() ? readDirectory(path2) : readZip(path2);
|
|
87562
88136
|
}
|
|
87563
88137
|
function plural3(count12, one, many) {
|
|
87564
88138
|
return `${count12} ${count12 === 1 ? one : many}`;
|
|
@@ -91257,7 +91831,7 @@ var init_upstream_tool = __esm({
|
|
|
91257
91831
|
});
|
|
91258
91832
|
|
|
91259
91833
|
// ../../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;
|
|
91834
|
+
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
91835
|
var init_lock = __esm({
|
|
91262
91836
|
"../../packages/mcp-studio/src/contract/lock.ts"() {
|
|
91263
91837
|
"use strict";
|
|
@@ -91270,14 +91844,18 @@ var init_lock = __esm({
|
|
|
91270
91844
|
init_primitives();
|
|
91271
91845
|
init_server2();
|
|
91272
91846
|
LOCK_BYTES_MAX = 5 * 1024 * 1024;
|
|
91847
|
+
PACKAGE_NAME_MAX = 214;
|
|
91848
|
+
PACKAGE_VERSION_MAX = 64;
|
|
91849
|
+
LAUNCH_ARG_MAX = 4096;
|
|
91850
|
+
LAUNCH_ARGS_MAX = 1024;
|
|
91273
91851
|
serverVersionSchema = external_exports.string().min(1).max(64).optional().describe(
|
|
91274
91852
|
"The version the server reported in initialize, when it reported one."
|
|
91275
91853
|
);
|
|
91276
91854
|
lockPackageSchema = external_exports.object({
|
|
91277
|
-
name: external_exports.string().min(1).max(
|
|
91855
|
+
name: external_exports.string().min(1).max(PACKAGE_NAME_MAX).describe(
|
|
91278
91856
|
"The package or binary: @modelcontextprotocol/server-filesystem."
|
|
91279
91857
|
),
|
|
91280
|
-
version: external_exports.string().min(1).max(
|
|
91858
|
+
version: external_exports.string().min(1).max(PACKAGE_VERSION_MAX),
|
|
91281
91859
|
digest: sha256Schema2.describe("SHA-256 of the package or binary.")
|
|
91282
91860
|
}).strict();
|
|
91283
91861
|
pypiLockFileSchema = external_exports.object({
|
|
@@ -91380,7 +91958,7 @@ var init_lock = __esm({
|
|
|
91380
91958
|
command: external_exports.string().min(1).max(1024).optional().describe(
|
|
91381
91959
|
"For a package: the command the local gateway runs, npx, uvx, docker, or dnx."
|
|
91382
91960
|
),
|
|
91383
|
-
args: external_exports.array(external_exports.string().max(
|
|
91961
|
+
args: external_exports.array(external_exports.string().max(LAUNCH_ARG_MAX)).max(LAUNCH_ARGS_MAX).optional().describe(
|
|
91384
91962
|
"For a package: the command's arguments. ${NAME} stays for the local gateway to fill from the machine, and $$ writes one $."
|
|
91385
91963
|
),
|
|
91386
91964
|
server_version: serverVersionSchema
|
|
@@ -92039,6 +92617,9 @@ function keyProblems(all, given, type) {
|
|
|
92039
92617
|
}
|
|
92040
92618
|
return problems;
|
|
92041
92619
|
}
|
|
92620
|
+
function fromPackage(texts) {
|
|
92621
|
+
return texts.map((text5) => ({ text: text5, field: "source.registry_type" }));
|
|
92622
|
+
}
|
|
92042
92623
|
function words(slot, given, problems) {
|
|
92043
92624
|
const { argument, label: label2, key } = slot;
|
|
92044
92625
|
const field = key === void 0 ? "source.registry_type" : `source.arguments.${key}`;
|
|
@@ -92078,7 +92659,38 @@ function words(slot, given, problems) {
|
|
|
92078
92659
|
}
|
|
92079
92660
|
return [];
|
|
92080
92661
|
}
|
|
92081
|
-
|
|
92662
|
+
const valueWord = { text: value, field };
|
|
92663
|
+
return argument.type === "named" ? [...fromPackage([literal2(argument.name)]), valueWord] : [valueWord];
|
|
92664
|
+
}
|
|
92665
|
+
function lockLimitProblems(type, pkg, version2, launch) {
|
|
92666
|
+
const problems = [];
|
|
92667
|
+
if (pkg.identifier.length > PACKAGE_NAME_MAX) {
|
|
92668
|
+
problems.push({
|
|
92669
|
+
field: "source.registry_type",
|
|
92670
|
+
message: `the ${type} package's identifier is ${pkg.identifier.length} characters long, and the lock holds at most ${PACKAGE_NAME_MAX}`
|
|
92671
|
+
});
|
|
92672
|
+
}
|
|
92673
|
+
if (version2.length > PACKAGE_VERSION_MAX) {
|
|
92674
|
+
problems.push({
|
|
92675
|
+
field: "source.registry_type",
|
|
92676
|
+
message: `the ${type} package's version is ${version2.length} characters long, and the lock holds at most ${PACKAGE_VERSION_MAX}`
|
|
92677
|
+
});
|
|
92678
|
+
}
|
|
92679
|
+
launch.forEach(({ text: text5, field }, index) => {
|
|
92680
|
+
if (text5.length > LAUNCH_ARG_MAX) {
|
|
92681
|
+
problems.push({
|
|
92682
|
+
field,
|
|
92683
|
+
message: `args[${index}] is ${text5.length} characters long once each $ is written $$, and the lock holds at most ${LAUNCH_ARG_MAX}`
|
|
92684
|
+
});
|
|
92685
|
+
}
|
|
92686
|
+
});
|
|
92687
|
+
if (launch.length > LAUNCH_ARGS_MAX) {
|
|
92688
|
+
problems.push({
|
|
92689
|
+
field: "source.registry_type",
|
|
92690
|
+
message: `the ${type} package's launch has ${launch.length} args, and the lock holds at most ${LAUNCH_ARGS_MAX}`
|
|
92691
|
+
});
|
|
92692
|
+
}
|
|
92693
|
+
return problems;
|
|
92082
92694
|
}
|
|
92083
92695
|
function registryLaunch({
|
|
92084
92696
|
source,
|
|
@@ -92144,18 +92756,22 @@ function registryLaunch({
|
|
|
92144
92756
|
const reference = pinned !== void 0 ? ["--from", literal2(pinned.url), literal2(pkg.identifier)] : [
|
|
92145
92757
|
`${literal2(pkg.identifier)}@${runner.pin === "digest" ? digest6 : literal2(version2)}`
|
|
92146
92758
|
];
|
|
92147
|
-
const
|
|
92148
|
-
...runner.flags,
|
|
92149
|
-
...type === "oci" ? env.flatMap((name) => [
|
|
92759
|
+
const launch = [
|
|
92760
|
+
...fromPackage(runner.flags),
|
|
92761
|
+
...type === "oci" ? env.flatMap((name) => [
|
|
92762
|
+
...fromPackage(["-e"]),
|
|
92763
|
+
{ text: name, field: "source.env" }
|
|
92764
|
+
]) : [],
|
|
92150
92765
|
...runtime.flatMap((slot) => words(slot, given, problems)),
|
|
92151
|
-
...reference,
|
|
92766
|
+
...fromPackage(reference),
|
|
92152
92767
|
...packaged.flatMap((slot) => words(slot, given, problems))
|
|
92153
92768
|
];
|
|
92769
|
+
problems.push(...lockLimitProblems(type, pkg, version2, launch));
|
|
92154
92770
|
if (problems.length > 0) return { ok: false, problems };
|
|
92155
92771
|
return {
|
|
92156
92772
|
ok: true,
|
|
92157
92773
|
command: runner.command,
|
|
92158
|
-
args,
|
|
92774
|
+
args: launch.map((word) => word.text),
|
|
92159
92775
|
package: {
|
|
92160
92776
|
name: pkg.identifier,
|
|
92161
92777
|
version: version2,
|
|
@@ -92169,6 +92785,7 @@ var REGISTRY_RUNNERS2, ONE_VARIABLE;
|
|
|
92169
92785
|
var init_registry_launch = __esm({
|
|
92170
92786
|
"../../packages/mcp-studio/src/model/registry-launch.ts"() {
|
|
92171
92787
|
"use strict";
|
|
92788
|
+
init_lock();
|
|
92172
92789
|
REGISTRY_RUNNERS2 = {
|
|
92173
92790
|
npm: { command: "npx", flags: ["--yes"], pin: "version" },
|
|
92174
92791
|
pypi: { command: "uvx", flags: [], pin: "file" },
|
|
@@ -106314,15 +106931,15 @@ var init_print = __esm({
|
|
|
106314
106931
|
// ── Extensions ─────────────────────────────────────────────────────────────
|
|
106315
106932
|
/** `extend` blocks, one for each run of extensions of the same message. */
|
|
106316
106933
|
extensions(fields, scope, path2) {
|
|
106317
|
-
let
|
|
106934
|
+
let open7;
|
|
106318
106935
|
fields.forEach((field, index) => {
|
|
106319
106936
|
const where = `the extension ${scope === "" ? "" : `${scope}.`}${field.name}`;
|
|
106320
106937
|
if (field.extendee === "")
|
|
106321
106938
|
this.refuse(`${where} names no message to extend`);
|
|
106322
106939
|
if (isFieldSet(field, FieldDescriptorProtoSchema.field.oneofIndex))
|
|
106323
106940
|
this.refuse(`${where} is in a oneof`);
|
|
106324
|
-
if (field.extendee !==
|
|
106325
|
-
if (
|
|
106941
|
+
if (field.extendee !== open7) {
|
|
106942
|
+
if (open7 !== void 0) this.close();
|
|
106326
106943
|
const extendee = this.typeName(
|
|
106327
106944
|
field.extendee,
|
|
106328
106945
|
scope,
|
|
@@ -106332,7 +106949,7 @@ var init_print = __esm({
|
|
|
106332
106949
|
this.gap();
|
|
106333
106950
|
this.line(`extend ${extendee} {`);
|
|
106334
106951
|
this.depth += 1;
|
|
106335
|
-
|
|
106952
|
+
open7 = field.extendee;
|
|
106336
106953
|
}
|
|
106337
106954
|
this.comment([...path2, index]);
|
|
106338
106955
|
this.line(
|
|
@@ -106345,7 +106962,7 @@ var init_print = __esm({
|
|
|
106345
106962
|
)
|
|
106346
106963
|
);
|
|
106347
106964
|
});
|
|
106348
|
-
if (
|
|
106965
|
+
if (open7 !== void 0) this.close();
|
|
106349
106966
|
}
|
|
106350
106967
|
// ── Options ────────────────────────────────────────────────────────────────
|
|
106351
106968
|
/**
|
|
@@ -106841,7 +107458,7 @@ function importOrder(sources, loaded) {
|
|
|
106841
107458
|
const done = /* @__PURE__ */ new Set();
|
|
106842
107459
|
const stack = [];
|
|
106843
107460
|
const onStack = /* @__PURE__ */ new Set();
|
|
106844
|
-
const
|
|
107461
|
+
const open7 = (name, importer) => {
|
|
106845
107462
|
const entry2 = load(name, importer, sources);
|
|
106846
107463
|
loaded.set(name, entry2);
|
|
106847
107464
|
const imports = entry2.kind === "source" ? entry2.parsed.header.imports.map((each) => each.path) : entry2.proto.dependency;
|
|
@@ -106850,7 +107467,7 @@ function importOrder(sources, loaded) {
|
|
|
106850
107467
|
};
|
|
106851
107468
|
for (const root of [...sources.keys()].sort()) {
|
|
106852
107469
|
if (done.has(root)) continue;
|
|
106853
|
-
|
|
107470
|
+
open7(root, void 0);
|
|
106854
107471
|
for (let top = stack.at(-1); top !== void 0; top = stack.at(-1)) {
|
|
106855
107472
|
const next = top.imports[top.next];
|
|
106856
107473
|
top.next += 1;
|
|
@@ -106863,7 +107480,7 @@ function importOrder(sources, loaded) {
|
|
|
106863
107480
|
const at2 = stack.findIndex((frame) => frame.name === next);
|
|
106864
107481
|
throw cycle([...stack.slice(at2).map((frame) => frame.name), next]);
|
|
106865
107482
|
} else if (!done.has(next)) {
|
|
106866
|
-
|
|
107483
|
+
open7(next, top.name);
|
|
106867
107484
|
}
|
|
106868
107485
|
}
|
|
106869
107486
|
}
|
|
@@ -107350,8 +107967,8 @@ var init_json_schema4 = __esm({
|
|
|
107350
107967
|
description: `Cut: messages nest past ${DEPTH_MAX} levels here.`
|
|
107351
107968
|
};
|
|
107352
107969
|
}
|
|
107353
|
-
const
|
|
107354
|
-
if (
|
|
107970
|
+
const open7 = this.active.get(name) ?? 0;
|
|
107971
|
+
if (open7 >= RECURSION_DEPTH) {
|
|
107355
107972
|
this.note(
|
|
107356
107973
|
`Import cut the recursive message ${name} at depth ${RECURSION_DEPTH}.`
|
|
107357
107974
|
);
|
|
@@ -107369,12 +107986,12 @@ var init_json_schema4 = __esm({
|
|
|
107369
107986
|
description: `Cut: this tool's schemas passed ${count8(TOOL_NODES_SOFT_MAX)} nodes.`
|
|
107370
107987
|
};
|
|
107371
107988
|
}
|
|
107372
|
-
this.active.set(name,
|
|
107989
|
+
this.active.set(name, open7 + 1);
|
|
107373
107990
|
try {
|
|
107374
107991
|
return this.fieldsOf(desc, direction, depth);
|
|
107375
107992
|
} finally {
|
|
107376
|
-
if (
|
|
107377
|
-
else this.active.set(name,
|
|
107993
|
+
if (open7 === 0) this.active.delete(name);
|
|
107994
|
+
else this.active.set(name, open7);
|
|
107378
107995
|
}
|
|
107379
107996
|
}
|
|
107380
107997
|
fieldsOf(desc, direction, depth) {
|
|
@@ -107890,7 +108507,7 @@ function selectOutput(outputSchema, select) {
|
|
|
107890
108507
|
return trimObject(outputSchema, selectTree(select));
|
|
107891
108508
|
}
|
|
107892
108509
|
function selectionProblem(selection) {
|
|
107893
|
-
const
|
|
108510
|
+
const open7 = [];
|
|
107894
108511
|
let quoted3 = false;
|
|
107895
108512
|
for (let index = 0; index < selection.length; index += 1) {
|
|
107896
108513
|
const char = selection[index];
|
|
@@ -107900,15 +108517,15 @@ function selectionProblem(selection) {
|
|
|
107900
108517
|
continue;
|
|
107901
108518
|
}
|
|
107902
108519
|
if (char === '"') quoted3 = true;
|
|
107903
|
-
else if (char === "{" || char === "(")
|
|
108520
|
+
else if (char === "{" || char === "(") open7.push(char);
|
|
107904
108521
|
else if (char === "}" || char === ")") {
|
|
107905
108522
|
const expected = char === "}" ? "{" : "(";
|
|
107906
|
-
if (
|
|
108523
|
+
if (open7.pop() !== expected)
|
|
107907
108524
|
return `selection has an unmatched ${char} at character ${index + 1}.`;
|
|
107908
108525
|
}
|
|
107909
108526
|
}
|
|
107910
108527
|
if (quoted3) return "selection has a string with no closing quote.";
|
|
107911
|
-
const unclosed =
|
|
108528
|
+
const unclosed = open7.pop();
|
|
107912
108529
|
if (unclosed !== void 0) return `selection has an unclosed ${unclosed}.`;
|
|
107913
108530
|
if (!/[_A-Za-z]/.test(selection)) return "selection names no field.";
|
|
107914
108531
|
return void 0;
|
|
@@ -109691,8 +110308,7 @@ function locationWithoutQuery(location) {
|
|
|
109691
110308
|
url = new URL(location);
|
|
109692
110309
|
} catch {
|
|
109693
110310
|
const cut = location.search(/[?#]/);
|
|
109694
|
-
|
|
109695
|
-
return head2.replace(/^\/\/[^/]*@/, "//");
|
|
110311
|
+
return withoutUserinfo(cut === -1 ? location : location.slice(0, cut));
|
|
109696
110312
|
}
|
|
109697
110313
|
url.username = "";
|
|
109698
110314
|
url.password = "";
|
|
@@ -109700,6 +110316,13 @@ function locationWithoutQuery(location) {
|
|
|
109700
110316
|
url.hash = "";
|
|
109701
110317
|
return url.href;
|
|
109702
110318
|
}
|
|
110319
|
+
function withoutUserinfo(head2) {
|
|
110320
|
+
const match = UNPARSED_USERINFO.exec(head2);
|
|
110321
|
+
if (match === null) return head2;
|
|
110322
|
+
const prefix = match[1] ?? "";
|
|
110323
|
+
const rest = head2.slice(match[0].length);
|
|
110324
|
+
return rest === "" || /^[\\/]/.test(rest) ? `${prefix}@${rest}` : `${prefix}${rest}`;
|
|
110325
|
+
}
|
|
109703
110326
|
function recordedResponseHeaders(headers) {
|
|
109704
110327
|
const out = /* @__PURE__ */ new Map();
|
|
109705
110328
|
for (const [name, raw] of headers) {
|
|
@@ -109733,12 +110356,13 @@ function recordHttpResponse(response, bytes) {
|
|
|
109733
110356
|
...body2 === void 0 ? {} : { body: body2 }
|
|
109734
110357
|
};
|
|
109735
110358
|
}
|
|
109736
|
-
var REFUSED_RESPONSE_HEADERS;
|
|
110359
|
+
var UNPARSED_USERINFO, REFUSED_RESPONSE_HEADERS;
|
|
109737
110360
|
var init_exchange = __esm({
|
|
109738
110361
|
"../../packages/mcp-studio/src/execute/exchange.ts"() {
|
|
109739
110362
|
"use strict";
|
|
109740
110363
|
init_tests_files();
|
|
109741
110364
|
init_body();
|
|
110365
|
+
UNPARSED_USERINFO = /^([A-Za-z][A-Za-z0-9+.-]*:[\\/]*|[\\/]{2})[^/\\]*@/;
|
|
109742
110366
|
REFUSED_RESPONSE_HEADERS = new Set(
|
|
109743
110367
|
CREDENTIAL_RESPONSE_HEADERS
|
|
109744
110368
|
);
|
|
@@ -110248,14 +110872,17 @@ async function notifyInitialized(session) {
|
|
|
110248
110872
|
});
|
|
110249
110873
|
return read2.ok ? { ok: true, value: void 0 } : read2;
|
|
110250
110874
|
}
|
|
110251
|
-
|
|
110252
|
-
|
|
110253
|
-
const sent = await post(session, {
|
|
110875
|
+
function toolsCallMessage(template, args) {
|
|
110876
|
+
return {
|
|
110254
110877
|
jsonrpc: "2.0",
|
|
110255
110878
|
id: CALL_ID,
|
|
110256
110879
|
method: "tools/call",
|
|
110257
110880
|
params: { name: template.tool, arguments: args }
|
|
110258
|
-
}
|
|
110881
|
+
};
|
|
110882
|
+
}
|
|
110883
|
+
async function callTool2(session) {
|
|
110884
|
+
const { template, args } = session.call;
|
|
110885
|
+
const sent = await post(session, toolsCallMessage(template, args));
|
|
110259
110886
|
if (!sent.ok) return { attempt: sent, exchange: void 0 };
|
|
110260
110887
|
const response = sent.value;
|
|
110261
110888
|
if (response.status < 200 || response.status >= 300) {
|
|
@@ -111171,7 +111798,7 @@ async function attemptCall(call2, context, deadline, settings) {
|
|
|
111171
111798
|
const controller = new AbortController();
|
|
111172
111799
|
const clock2 = new Clock(deadline, context.signal, controller);
|
|
111173
111800
|
try {
|
|
111174
|
-
const opening =
|
|
111801
|
+
const opening = open5(context.transport, {
|
|
111175
111802
|
...call2.request,
|
|
111176
111803
|
deadline_ms: Math.max(1, deadline - Date.now()),
|
|
111177
111804
|
signal: controller.signal
|
|
@@ -111191,7 +111818,7 @@ async function attemptCall(call2, context, deadline, settings) {
|
|
|
111191
111818
|
clock2.dispose();
|
|
111192
111819
|
}
|
|
111193
111820
|
}
|
|
111194
|
-
async function
|
|
111821
|
+
async function open5(transport, request3) {
|
|
111195
111822
|
return transport.grpc(request3);
|
|
111196
111823
|
}
|
|
111197
111824
|
async function read(response, call2, clock2, settings) {
|
|
@@ -130596,6 +131223,19 @@ var init_transport2 = __esm({
|
|
|
130596
131223
|
}
|
|
130597
131224
|
});
|
|
130598
131225
|
|
|
131226
|
+
// ../../packages/mcp-studio/src/execute/request-size.ts
|
|
131227
|
+
var init_request_size = __esm({
|
|
131228
|
+
"../../packages/mcp-studio/src/execute/request-size.ts"() {
|
|
131229
|
+
"use strict";
|
|
131230
|
+
init_body();
|
|
131231
|
+
init_graphql2();
|
|
131232
|
+
init_http();
|
|
131233
|
+
init_mcp();
|
|
131234
|
+
init_shape_input();
|
|
131235
|
+
init_util4();
|
|
131236
|
+
}
|
|
131237
|
+
});
|
|
131238
|
+
|
|
130599
131239
|
// ../../packages/mcp-studio/src/execute/index.ts
|
|
130600
131240
|
var init_execute = __esm({
|
|
130601
131241
|
"../../packages/mcp-studio/src/execute/index.ts"() {
|
|
@@ -130612,6 +131252,7 @@ var init_execute = __esm({
|
|
|
130612
131252
|
init_http();
|
|
130613
131253
|
init_mcp();
|
|
130614
131254
|
init_senders();
|
|
131255
|
+
init_request_size();
|
|
130615
131256
|
init_validate();
|
|
130616
131257
|
init_body();
|
|
130617
131258
|
init_http_call();
|
|
@@ -133315,7 +133956,7 @@ import {
|
|
|
133315
133956
|
mkdirSync as mkdirSync13,
|
|
133316
133957
|
readFileSync as readFileSync30,
|
|
133317
133958
|
readlinkSync as readlinkSync4,
|
|
133318
|
-
statSync as
|
|
133959
|
+
statSync as statSync18
|
|
133319
133960
|
} from "node:fs";
|
|
133320
133961
|
import { dirname as dirname36, isAbsolute as isAbsolute18, join as join64, relative as relative9, resolve as resolve25, sep as sep12 } from "node:path";
|
|
133321
133962
|
function git5(cwd, args, input) {
|
|
@@ -133428,14 +134069,14 @@ function chooseBase(root, ref2) {
|
|
|
133428
134069
|
}
|
|
133429
134070
|
function isFile(path2) {
|
|
133430
134071
|
try {
|
|
133431
|
-
return
|
|
134072
|
+
return statSync18(path2).isFile();
|
|
133432
134073
|
} catch {
|
|
133433
134074
|
return false;
|
|
133434
134075
|
}
|
|
133435
134076
|
}
|
|
133436
134077
|
function isDir(path2) {
|
|
133437
134078
|
try {
|
|
133438
|
-
return
|
|
134079
|
+
return statSync18(path2).isDirectory();
|
|
133439
134080
|
} catch {
|
|
133440
134081
|
return false;
|
|
133441
134082
|
}
|
|
@@ -136727,16 +137368,16 @@ function assignmentValue(bytes, assignment, nameStart, nameEnd) {
|
|
|
136727
137368
|
if (!assignment.names.some((k) => containsLower(name, k))) return null;
|
|
136728
137369
|
while (isBlank2(bytes[p])) p += 1;
|
|
136729
137370
|
if (p >= n2) return null;
|
|
136730
|
-
const
|
|
137371
|
+
const open7 = bytes[p];
|
|
136731
137372
|
let start;
|
|
136732
137373
|
let end;
|
|
136733
137374
|
let quoted3;
|
|
136734
|
-
if (
|
|
137375
|
+
if (open7 === QUOTE || open7 === APOSTROPHE || open7 === BACKTICK) {
|
|
136735
137376
|
start = p + 1;
|
|
136736
137377
|
end = start;
|
|
136737
|
-
while (end < n2 && bytes[end] !==
|
|
137378
|
+
while (end < n2 && bytes[end] !== open7 && bytes[end] !== NEWLINE2)
|
|
136738
137379
|
end += bytes[end] === BACKSLASH ? 2 : 1;
|
|
136739
|
-
if (end >= n2 || bytes[end] !==
|
|
137380
|
+
if (end >= n2 || bytes[end] !== open7) return null;
|
|
136740
137381
|
quoted3 = true;
|
|
136741
137382
|
} else {
|
|
136742
137383
|
start = p;
|
|
@@ -137912,7 +138553,7 @@ __export(logs_exports, {
|
|
|
137912
138553
|
handleLogs: () => handleLogs
|
|
137913
138554
|
});
|
|
137914
138555
|
import { watch } from "node:fs";
|
|
137915
|
-
import { open as
|
|
138556
|
+
import { open as open6, stat as stat6 } from "node:fs/promises";
|
|
137916
138557
|
function formatEntry(entry2) {
|
|
137917
138558
|
const head2 = `${entry2.ts} ${entry2.category.padEnd(11)} ${entry2.event}`;
|
|
137918
138559
|
if (entry2.data === void 0) return head2;
|
|
@@ -137943,7 +138584,7 @@ async function logSize(file) {
|
|
|
137943
138584
|
async function readAppended(file, offset) {
|
|
137944
138585
|
let handle;
|
|
137945
138586
|
try {
|
|
137946
|
-
handle = await
|
|
138587
|
+
handle = await open6(file, "r");
|
|
137947
138588
|
} catch {
|
|
137948
138589
|
return { entries: [], offset: 0 };
|
|
137949
138590
|
}
|