@ponythewhite/base-context 1.0.11 → 1.0.13

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/base-context-runtime/pyproject.toml +1 -1
  3. package/dist/base-context-runtime/uv.lock +1 -1
  4. package/dist/build-info.json +1 -1
  5. package/dist/bundle/amazon-bedrock.js +3 -3
  6. package/dist/bundle/{anthropic-5PSCZEER.js → anthropic-BJVPUMPB.js} +2 -2
  7. package/dist/bundle/{azure-openai-responses-AYTLJR33.js → azure-openai-responses-ERRMAXK6.js} +4 -5
  8. package/dist/bundle/{bundled-modules-PEFT72QN.js → bundled-modules-URKVA3UB.js} +5 -5
  9. package/dist/bundle/{chunk-D3KOF57W.js → chunk-25VYRAC6.js} +14 -1
  10. package/dist/bundle/{chunk-2IPDSTDR.js → chunk-AEMRBMI2.js} +9 -9
  11. package/dist/bundle/{chunk-Q3MBSBEB.js → chunk-FOGKLC7V.js} +1 -1
  12. package/dist/bundle/{chunk-KT2BNEPE.js → chunk-MUFZODP5.js} +1 -1
  13. package/dist/bundle/{chunk-QKIFBA7N.js → chunk-Q6UAHLII.js} +2 -2
  14. package/dist/bundle/{chunk-TOOVREMP.js → chunk-TKOBEJ5E.js} +515 -107
  15. package/dist/bundle/{chunk-JZHGOOFM.js → chunk-TXVF6Q5H.js} +118 -22
  16. package/dist/bundle/{cli-main-BRXGYTGK.js → cli-main-ZTJM5EEH.js} +4 -4
  17. package/dist/bundle/cli.js +1 -1
  18. package/dist/bundle/{google-HTMCUJ7X.js → google-4GA4YMUX.js} +2 -2
  19. package/dist/bundle/{google-vertex-ZQO65AXF.js → google-vertex-7AMALD7D.js} +2 -2
  20. package/dist/bundle/{main-POUXGEL6.js → main-53I74INO.js} +5 -5
  21. package/dist/bundle/{mistral-SB7LU56G.js → mistral-74BXMNRM.js} +1 -1
  22. package/dist/bundle/{openai-codex-responses-5CEW4VN3.js → openai-codex-responses-COXNC4IH.js} +2 -2
  23. package/dist/bundle/{openai-completions-BAZJQSS2.js → openai-completions-BCSA5Q6S.js} +2 -2
  24. package/dist/bundle/{openai-responses-VHOE427P.js → openai-responses-ONCIZSJS.js} +3 -3
  25. package/dist/core/agent-session.d.ts +6 -0
  26. package/dist/core/agent-session.d.ts.map +1 -1
  27. package/dist/core/agent-session.js +362 -103
  28. package/dist/core/agent-session.js.map +1 -1
  29. package/dist/core/compaction/compaction.d.ts +9 -1
  30. package/dist/core/compaction/compaction.d.ts.map +1 -1
  31. package/dist/core/compaction/compaction.js +29 -3
  32. package/dist/core/compaction/compaction.js.map +1 -1
  33. package/dist/core/context-tree.d.ts +13 -10
  34. package/dist/core/context-tree.d.ts.map +1 -1
  35. package/dist/core/context-tree.js +49 -3
  36. package/dist/core/context-tree.js.map +1 -1
  37. package/dist/core/inference-coordinator.d.ts +1 -1
  38. package/dist/core/inference-coordinator.d.ts.map +1 -1
  39. package/dist/core/inference-coordinator.js +18 -5
  40. package/dist/core/inference-coordinator.js.map +1 -1
  41. package/dist/core/messages.d.ts +2 -0
  42. package/dist/core/messages.d.ts.map +1 -1
  43. package/dist/core/messages.js +2 -0
  44. package/dist/core/messages.js.map +1 -1
  45. package/dist/core/refinement/refinement.d.ts +2 -0
  46. package/dist/core/refinement/refinement.d.ts.map +1 -1
  47. package/dist/core/refinement/refinement.js +10 -1
  48. package/dist/core/refinement/refinement.js.map +1 -1
  49. package/dist/core/request-usage.d.ts +34 -0
  50. package/dist/core/request-usage.d.ts.map +1 -0
  51. package/dist/core/request-usage.js +111 -0
  52. package/dist/core/request-usage.js.map +1 -0
  53. package/dist/core/settings-manager.d.ts +3 -0
  54. package/dist/core/settings-manager.d.ts.map +1 -1
  55. package/dist/core/settings-manager.js +7 -0
  56. package/dist/core/settings-manager.js.map +1 -1
  57. package/dist/core/system-prompt.d.ts +2 -0
  58. package/dist/core/system-prompt.d.ts.map +1 -1
  59. package/dist/core/system-prompt.js +4 -2
  60. package/dist/core/system-prompt.js.map +1 -1
  61. package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
  62. package/dist/modes/agent-connection/daemon-agent-connection.js +8 -1
  63. package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
  64. package/dist/modes/daemon/daemon-protocol.d.ts +13 -3
  65. package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
  66. package/dist/modes/daemon/daemon-protocol.js +10 -2
  67. package/dist/modes/daemon/daemon-protocol.js.map +1 -1
  68. package/dist/modes/daemon/daemon-session-summarizer.d.ts +3 -0
  69. package/dist/modes/daemon/daemon-session-summarizer.d.ts.map +1 -1
  70. package/dist/modes/daemon/daemon-session-summarizer.js +71 -32
  71. package/dist/modes/daemon/daemon-session-summarizer.js.map +1 -1
  72. package/dist/modes/interactive/components/context-tree-format.d.ts.map +1 -1
  73. package/dist/modes/interactive/components/context-tree-format.js +49 -0
  74. package/dist/modes/interactive/components/context-tree-format.js.map +1 -1
  75. package/docs/compaction.md +57 -4
  76. package/docs/context-management.md +23 -1
  77. package/docs/rlm.md +1 -1
  78. package/docs/settings.md +21 -0
  79. package/docs/usage.md +24 -1
  80. package/package.json +4 -4
@@ -32,7 +32,7 @@ import {
32
32
  typebox_exports,
33
33
  validateToolArguments,
34
34
  waitForChildProcess
35
- } from "./chunk-2IPDSTDR.js";
35
+ } from "./chunk-AEMRBMI2.js";
36
36
  import {
37
37
  cleanupSessionResources,
38
38
  registerSessionResourceCleanup
@@ -67,7 +67,7 @@ import {
67
67
  requestTokenRouteIdentity,
68
68
  supportsFastMode,
69
69
  withRequestBody
70
- } from "./chunk-D3KOF57W.js";
70
+ } from "./chunk-25VYRAC6.js";
71
71
  import {
72
72
  __commonJS,
73
73
  __export,
@@ -10887,8 +10887,8 @@ var DAEMON_PROTOCOL_NAME = PRODUCT.daemonService;
10887
10887
  var DAEMON_PROTOCOL_VERSION = 13;
10888
10888
  var DAEMON_LEGACY_INSPECTION_PROTOCOL_VERSIONS = [8, 9, 10];
10889
10889
  var DAEMON_COMMAND_ENVELOPE_MIN_PROTOCOL_VERSION = 8;
10890
- var DAEMON_SCHEMA_REVISION = 49;
10891
- var DAEMON_SCHEMA_ID = "protocol-13-schema-49-subagent-capacity";
10890
+ var DAEMON_SCHEMA_REVISION = 50;
10891
+ var DAEMON_SCHEMA_ID = "protocol-13-schema-50-context-request-usage";
10892
10892
  var DAEMON_PROTOCOL_INFO = {
10893
10893
  name: DAEMON_PROTOCOL_NAME,
10894
10894
  version: DAEMON_PROTOCOL_VERSION
@@ -10913,6 +10913,7 @@ var DAEMON_DEFAULT_SERVER_CAPABILITIES = [
10913
10913
  "cron_resume",
10914
10914
  "agent_results",
10915
10915
  "model_catalog",
10916
+ "context_request_usage",
10916
10917
  "side_question_transcript",
10917
10918
  "transient_bash",
10918
10919
  "session_input_admission",
@@ -28085,6 +28086,7 @@ var SESSION_SLASH_COMMAND_CUSTOM_TYPE = "session_slash_command";
28085
28086
  var SESSION_SLASH_COMMAND_RESULT_CUSTOM_TYPE = "session_slash_command_result";
28086
28087
  var COMPACTION_OUTCOME_CUSTOM_TYPE = "compaction_outcome";
28087
28088
  var REFINEMENT_OUTCOME_CUSTOM_TYPE = "refinement_outcome";
28089
+ var HARNESS_SNAPSHOT_CUSTOM_TYPE = "harness_snapshot";
28088
28090
  var RLM_CHILD_FAILURE_CUSTOM_TYPE = "rlm_child_failure";
28089
28091
  var RLM_CHILD_TERMINAL_NOTICE_CUSTOM_TYPE = "rlm_child_terminal_notice";
28090
28092
  function createRlmChildFailureMessage(details, timestamp = Date.now()) {
@@ -31728,7 +31730,7 @@ var CanonicalContextCompiler = class {
31728
31730
  hasActiveEntry(entryId) {
31729
31731
  return this.entries.has(entryId);
31730
31732
  }
31731
- async compile(view, limits, omittedAssistantIds = /* @__PURE__ */ new Set(), frameOptions = {}, resourceCapture, initialContextMode = "on", allowPendingToolPublic = false, purpose = "request") {
31733
+ async compile(view, limits, omittedAssistantIds = /* @__PURE__ */ new Set(), frameOptions = {}, resourceCapture, initialContextMode = "on", allowPendingToolPublic = false, purpose2 = "request") {
31732
31734
  const generation = this.generation;
31733
31735
  const frameLimits = taskFrameLimits(frameOptions);
31734
31736
  const previousSource = this.source;
@@ -31866,7 +31868,7 @@ var CanonicalContextCompiler = class {
31866
31868
  const referenceFrame = resetFrame ? checkpoint?.taskFrame : previousFrame;
31867
31869
  if (resetFrame || referenceFrame && referenceFrame.messages.length <= 1)
31868
31870
  this.forceTaskFrameRebase = false;
31869
- const forceRebase = purpose === "request" && this.forceTaskFrameRebase;
31871
+ const forceRebase = purpose2 === "request" && this.forceTaskFrameRebase;
31870
31872
  let taskFrame = tasks ? compileTaskFrame(tasks, frameLimits, forceRebase ? void 0 : referenceFrame) : void 0;
31871
31873
  const taskFrameRebased = Boolean(mode === "on" && referenceFrame && taskFrame !== referenceFrame && (!taskFrame || taskFrame.messages.length === 1));
31872
31874
  const resource = mode === "on" && resourceCapture && (resourceCapture.enabled || checkpoint) ? renderResourceView(resourceCapture) : void 0;
@@ -32198,7 +32200,7 @@ ${JSON.stringify(selections.map((skill) => ({
32198
32200
  });
32199
32201
  if (frozenGroups.length !== candidates.filter((candidate) => candidate.prior).length)
32200
32202
  throw new Error("Committed tool continuation lost its original group");
32201
- if (purpose === "request" && candidates.length && (!allowPendingToolPublic || mode === "off"))
32203
+ if (purpose2 === "request" && candidates.length && (!allowPendingToolPublic || mode === "off"))
32202
32204
  throw new Error("Tool continuation requires an enabled native public request boundary");
32203
32205
  const readToolEvidence = async (metadata) => {
32204
32206
  const cached = next.get(metadata.id);
@@ -32453,7 +32455,7 @@ ${JSON.stringify(selections.map((skill) => ({
32453
32455
  }
32454
32456
  compiledEpochContexts.set(closedMessages, {
32455
32457
  ...inheritedRecoveryCoverage.length ? { inheritedRecoveryCoverage } : {},
32456
- ...purpose === "read" ? { readOnly: true } : {},
32458
+ ...purpose2 === "read" ? { readOnly: true } : {},
32457
32459
  mode,
32458
32460
  source: { ...view.source },
32459
32461
  checkpoint,
@@ -32473,7 +32475,7 @@ ${JSON.stringify(selections.map((skill) => ({
32473
32475
  this.source = view.source;
32474
32476
  this.sourceBytes = sourceBytes;
32475
32477
  this.messageCount = messageCount;
32476
- return purpose === "read" && pendingPublicMessageGroups.length ? renderToolContinuationWindow(closedMessages).messages : closedMessages;
32478
+ return purpose2 === "read" && pendingPublicMessageGroups.length ? renderToolContinuationWindow(closedMessages).messages : closedMessages;
32477
32479
  }
32478
32480
  };
32479
32481
 
@@ -33143,6 +33145,9 @@ function wrapStreamFnWithSemanticEdges(streamFn, recorder) {
33143
33145
  }
33144
33146
 
33145
33147
  // dist/core/inference-coordinator.js
33148
+ function isPrimaryRequest(purpose2) {
33149
+ return purpose2 === "main" || purpose2 === "child";
33150
+ }
33146
33151
  var REQUEST_STREAM_BINDING = /* @__PURE__ */ Symbol("base-context.request-stream-binding");
33147
33152
  var captureNativeCompactionRequests = /* @__PURE__ */ Symbol("base-context.native-compaction-requests");
33148
33153
  var captureNativeBranchRequests = /* @__PURE__ */ Symbol("base-context.native-branch-requests");
@@ -33374,7 +33379,7 @@ var InferenceCoordinator = class _InferenceCoordinator {
33374
33379
  this.notifyActivity();
33375
33380
  return captured;
33376
33381
  }
33377
- /** Explicit Root-owned epoch boundary, on this same captured MAIN source only. */
33382
+ /** Explicit session-owned epoch boundary, on this same captured primary source only. */
33378
33383
  bindRequestViewBoundary(messages, commit, validate2, fixedPrepare, isSourceCurrent) {
33379
33384
  this.assertAdmission();
33380
33385
  if (!this.capturedSink)
@@ -33592,7 +33597,7 @@ var InferenceCoordinator = class _InferenceCoordinator {
33592
33597
  activeUser = true;
33593
33598
  this.releaseCapture();
33594
33599
  this.finishCapturePending?.();
33595
- if (this.work.budget || this.requestViewBoundary && operation.metadata.purpose === "main") {
33600
+ if (this.work.budget || this.requestViewBoundary && isPrimaryRequest(operation.metadata.purpose)) {
33596
33601
  model = structuredClone(model);
33597
33602
  context = structuredClone({
33598
33603
  ...context,
@@ -33625,7 +33630,7 @@ var InferenceCoordinator = class _InferenceCoordinator {
33625
33630
  if (!this.work.admissionOpen)
33626
33631
  throw new Error("Inference owner is closing");
33627
33632
  const parentBudget = this.work.budget;
33628
- const boundary = operation.metadata.purpose === "main" ? this.requestViewBoundary : void 0;
33633
+ const boundary = isPrimaryRequest(operation.metadata.purpose) ? this.requestViewBoundary : void 0;
33629
33634
  const budget = boundary ? parentBudget?.capture() : parentBudget;
33630
33635
  let measuredForAdmission = false;
33631
33636
  let countingInput = false;
@@ -33807,7 +33812,14 @@ var InferenceCoordinator = class _InferenceCoordinator {
33807
33812
  }
33808
33813
  };
33809
33814
  const signal = options?.signal ? AbortSignal.any([options.signal, this.work.cancellation.signal]) : this.work.cancellation.signal;
33810
- const events = await send(model, context, { ...options, signal, attempts, requireProviderAttempts: true });
33815
+ const sessionId = options?.sessionId ?? (isPrimaryRequest(operation.metadata.purpose) ? source.sessionId : `${operation.metadata.purpose}:${source.sessionId}`);
33816
+ const events = await send(model, context, {
33817
+ ...options,
33818
+ sessionId,
33819
+ signal,
33820
+ attempts,
33821
+ requireProviderAttempts: true
33822
+ });
33811
33823
  localSimulation = isLocalFauxStream(events);
33812
33824
  const settled = settle(events.result());
33813
33825
  events.result = async () => (await settled).message;
@@ -33926,7 +33938,7 @@ var InferenceCoordinator = class _InferenceCoordinator {
33926
33938
  if (captured || previous?.metadata.operationId !== operationId) {
33927
33939
  previous = executor.bindOperation(model, { ...request, semanticEdgeId }, operationId);
33928
33940
  }
33929
- return (await executor.execute(previous, model, context, options, inner, captured !== void 0 && request.purpose === "main")).events;
33941
+ return (await executor.execute(previous, model, context, options, inner, captured !== void 0 && isPrimaryRequest(request.purpose))).events;
33930
33942
  };
33931
33943
  wrapped[REQUEST_STREAM_BINDING] = { coordinator: this, inner };
33932
33944
  return wrapped;
@@ -34178,12 +34190,31 @@ function estimateContextTokens(messages) {
34178
34190
  lastUsageIndex: usageInfo.index
34179
34191
  };
34180
34192
  }
34181
- function shouldCompact(contextTokens, contextWindow, settings) {
34193
+ function shouldCompact(contextTokens, contextWindow, settings, fixedContextTokens = 0) {
34182
34194
  if (!settings.enabled)
34183
34195
  return false;
34184
34196
  if (contextWindow <= 0)
34185
34197
  return false;
34186
- return contextTokens > contextWindow - settings.reserveTokens;
34198
+ const modelLimit = contextWindow - settings.reserveTokens;
34199
+ const target = settings.targetTokens === "model-limit" ? modelLimit : Math.max(settings.targetTokens ?? Math.floor(contextWindow * 0.9), fixedContextTokens + 4 * settings.keepRecentTokens);
34200
+ return contextTokens > Math.min(target, modelLimit);
34201
+ }
34202
+ function estimateFixedCompactionTokens(systemPrompt, tools, messages) {
34203
+ const toolSchemas = tools.map(({ name, description, parameters }) => ({ name, description, parameters }));
34204
+ let tokens = Math.ceil((systemPrompt.length + (tools.length ? JSON.stringify(toolSchemas).length : 0)) / 4);
34205
+ let hasHarnessSnapshot = false;
34206
+ for (let index = messages.length - 1; index >= 0; index--) {
34207
+ const message2 = messages[index];
34208
+ if (message2.role !== "custom")
34209
+ continue;
34210
+ if (message2.customType === TASK_FRAME_CUSTOM_TYPE)
34211
+ tokens += estimateTokens(message2);
34212
+ else if (message2.customType === HARNESS_SNAPSHOT_CUSTOM_TYPE && !hasHarnessSnapshot) {
34213
+ tokens += estimateTokens(message2);
34214
+ hasHarnessSnapshot = true;
34215
+ }
34216
+ }
34217
+ return tokens;
34187
34218
  }
34188
34219
  function compactionTokenScale(messages) {
34189
34220
  const usageInfo = getLastAssistantUsageInfo(messages);
@@ -43085,6 +43116,99 @@ ${instructions}`;
43085
43116
  // dist/core/context-tree.js
43086
43117
  import { existsSync as existsSync14, opendirSync, statSync as statSync6 } from "node:fs";
43087
43118
  import { basename as basename6, join as join20 } from "node:path";
43119
+
43120
+ // dist/core/request-usage.js
43121
+ function emptyRequestUsageTotals() {
43122
+ return {
43123
+ attempts: 0,
43124
+ settledAttempts: 0,
43125
+ partialUsageAttempts: 0,
43126
+ missingUsageAttempts: 0,
43127
+ unsettledAttempts: 0,
43128
+ unpricedAttempts: 0,
43129
+ input: 0,
43130
+ inputTotal: 0,
43131
+ output: 0,
43132
+ cacheRead: 0,
43133
+ cacheWrite: 0,
43134
+ processedTokens: 0,
43135
+ catalogEstimateUsd: 0
43136
+ };
43137
+ }
43138
+ function addRequestUsageTotals(total, usage) {
43139
+ for (const field of Object.keys(total))
43140
+ total[field] += usage[field];
43141
+ }
43142
+ function purpose(event) {
43143
+ if (event.purpose === "native-control" && event.purposeDetail === "daemon-status")
43144
+ return "status";
43145
+ if (event.purpose === "summary" && (event.purposeDetail === "compaction" || event.purposeDetail === "compaction-turn-prefix"))
43146
+ return "compaction";
43147
+ return event.purpose;
43148
+ }
43149
+ function inputTotal(usage) {
43150
+ if (usage.inputTotal !== void 0)
43151
+ return usage.inputTotal;
43152
+ if (usage.input !== void 0 && usage.cacheRead !== void 0 && usage.cacheWrite !== void 0)
43153
+ return usage.input + usage.cacheRead + usage.cacheWrite;
43154
+ if (usage.totalTokens !== void 0 && usage.output !== void 0)
43155
+ return usage.totalTokens - usage.output;
43156
+ return void 0;
43157
+ }
43158
+ var RequestUsageAccumulator = class {
43159
+ sessionId;
43160
+ attempts = /* @__PURE__ */ new Map();
43161
+ constructor(sessionId) {
43162
+ this.sessionId = sessionId;
43163
+ }
43164
+ add(event) {
43165
+ if (event.source.sessionId !== this.sessionId || event.purpose === "native-control" && event.purposeDetail === "input-token-count")
43166
+ return;
43167
+ const previous = this.attempts.get(event.attemptId);
43168
+ if (event.type === "attempt_admitted" && previous)
43169
+ return;
43170
+ const totals = emptyRequestUsageTotals();
43171
+ totals.attempts = 1;
43172
+ if (event.type === "attempt_admitted") {
43173
+ totals.unsettledAttempts = 1;
43174
+ } else {
43175
+ totals.settledAttempts = 1;
43176
+ const { usage, usageCompleteness } = event.receipt;
43177
+ const incompleteBuckets = [usage.input, usage.output, usage.cacheRead, usage.cacheWrite].some((value) => value === void 0);
43178
+ totals.partialUsageAttempts = usageCompleteness === "partial" || usageCompleteness !== "none" && incompleteBuckets ? 1 : 0;
43179
+ totals.missingUsageAttempts = usageCompleteness === "none" ? 1 : 0;
43180
+ totals.input = usage.input ?? 0;
43181
+ totals.inputTotal = inputTotal(usage) ?? (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
43182
+ totals.output = usage.output ?? 0;
43183
+ totals.cacheRead = usage.cacheRead ?? 0;
43184
+ totals.cacheWrite = usage.cacheWrite ?? 0;
43185
+ const input = inputTotal(usage);
43186
+ totals.processedTokens = input !== void 0 && usage.output !== void 0 ? input + usage.output : usage.totalTokens ?? totals.inputTotal + totals.output;
43187
+ const pricing = event.modelContract.pricing;
43188
+ const rates = pricing.status !== "unavailable" && pricing.currency === "USD" && pricing.unit === "million-tokens" ? pricing.catalogRates : void 0;
43189
+ if (rates && usage.input !== void 0 && usage.output !== void 0 && usage.cacheRead !== void 0 && usage.cacheWrite !== void 0) {
43190
+ totals.catalogEstimateUsd = (usage.input * rates.input + usage.output * rates.output + usage.cacheRead * rates.cacheRead + usage.cacheWrite * rates.cacheWrite) / 1e6;
43191
+ } else {
43192
+ totals.unpricedAttempts = 1;
43193
+ }
43194
+ }
43195
+ this.attempts.set(event.attemptId, { purpose: purpose(event), totals });
43196
+ }
43197
+ finish() {
43198
+ if (this.attempts.size === 0)
43199
+ return void 0;
43200
+ const result = { sessionId: this.sessionId, byPurpose: {}, total: emptyRequestUsageTotals() };
43201
+ for (const attempt of this.attempts.values()) {
43202
+ const bucket = result.byPurpose[attempt.purpose] ?? emptyRequestUsageTotals();
43203
+ result.byPurpose[attempt.purpose] = bucket;
43204
+ addRequestUsageTotals(bucket, attempt.totals);
43205
+ addRequestUsageTotals(result.total, attempt.totals);
43206
+ }
43207
+ return result;
43208
+ }
43209
+ };
43210
+
43211
+ // dist/core/context-tree.js
43088
43212
  var ContextTreeLimitError = class extends Error {
43089
43213
  };
43090
43214
  var ContextTreeRequest = class {
@@ -43178,6 +43302,11 @@ function computeOwnAndTotalUsage(branch, allEntries) {
43178
43302
  }
43179
43303
  function readResidentContextTreeUsage(manager, limits = { maxEntries: 16384, maxSourceBytes: 64 * 1024 * 1024 }, availabilityMaxSourceBytes) {
43180
43304
  const snapshot = manager.materializeResidentHistory(limits);
43305
+ const receipts = new RequestUsageAccumulator(manager.getSessionId());
43306
+ for (const entry of snapshot.entries)
43307
+ if (entry.type === "request")
43308
+ receipts.add(entry.request);
43309
+ const ownRequestUsage = receipts.finish();
43181
43310
  const branch = branchEntries(snapshot.entries, snapshot.leafId, availabilityMaxSourceBytes !== void 0);
43182
43311
  if (availabilityMaxSourceBytes !== void 0) {
43183
43312
  if (!Number.isSafeInteger(availabilityMaxSourceBytes) || availabilityMaxSourceBytes <= 0)
@@ -43191,6 +43320,7 @@ function readResidentContextTreeUsage(manager, limits = { maxEntries: 16384, max
43191
43320
  }
43192
43321
  return {
43193
43322
  ...computeOwnAndTotalUsage(branch, snapshot.entries),
43323
+ ...ownRequestUsage ? { ownRequestUsage } : {},
43194
43324
  ...availabilityMaxSourceBytes === void 0 ? {} : { hasPostCompactionUsage: hasPostCompactionUsage(branch) }
43195
43325
  };
43196
43326
  }
@@ -43208,6 +43338,9 @@ async function readContextTreeUsage(manager, limits = { maxEntries: 16384, maxSo
43208
43338
  request?.retainMetadata(history.source);
43209
43339
  const reduce = async () => {
43210
43340
  const allEntries = [];
43341
+ let receipts = new RequestUsageAccumulator(history.source.sessionId);
43342
+ let requestEntries = 0;
43343
+ let requestBytes = 0;
43211
43344
  let sourceBytes = 0;
43212
43345
  let after = 0;
43213
43346
  for (; ; ) {
@@ -43215,6 +43348,23 @@ async function readContextTreeUsage(manager, limits = { maxEntries: 16384, maxSo
43215
43348
  if (page.indexedThrough < history.source.sourceSequence)
43216
43349
  throw new Error("Captured history has incomplete index coverage");
43217
43350
  for (const reference of page.events) {
43351
+ if (reference.kind === "request" && receipts) {
43352
+ requestEntries++;
43353
+ requestBytes += reference.locator.length;
43354
+ if (requestEntries > capturedLimits.maxEntries || requestBytes > capturedLimits.maxSourceBytes) {
43355
+ receipts = void 0;
43356
+ } else {
43357
+ try {
43358
+ const hydrated2 = await history.hydrateEntry(reference.id, reference.locator.length);
43359
+ if (hydrated2?.entry.type !== "request")
43360
+ receipts = void 0;
43361
+ else
43362
+ receipts.add(hydrated2.entry.request);
43363
+ } catch {
43364
+ receipts = void 0;
43365
+ }
43366
+ }
43367
+ }
43218
43368
  if (!isContextTreeUsageReference(reference))
43219
43369
  continue;
43220
43370
  if (allEntries.length >= capturedLimits.maxEntries)
@@ -43266,8 +43416,10 @@ async function readContextTreeUsage(manager, limits = { maxEntries: 16384, maxSo
43266
43416
  available = calculateContextTokens(assistant.message.usage) > 0;
43267
43417
  }
43268
43418
  }
43419
+ const ownRequestUsage = receipts?.finish();
43269
43420
  const usage = {
43270
43421
  ...computeOwnAndTotalUsage(branch, allEntries),
43422
+ ...ownRequestUsage ? { ownRequestUsage } : {},
43271
43423
  ...available === void 0 ? {} : { hasPostCompactionUsage: available }
43272
43424
  };
43273
43425
  request?.retainMetadata(usage);
@@ -43434,6 +43586,9 @@ async function readContextTreeProjectionFromDisk(sessionFile, request) {
43434
43586
  const hiddenParents = /* @__PURE__ */ new Map();
43435
43587
  let leafId = null;
43436
43588
  let hasHeader = false;
43589
+ let receipts;
43590
+ let requestEntries = 0;
43591
+ let requestBytes = 0;
43437
43592
  let sourceBytes = 0;
43438
43593
  let metadataBytes = 0;
43439
43594
  try {
@@ -43446,6 +43601,15 @@ async function readContextTreeProjectionFromDisk(sessionFile, request) {
43446
43601
  if (entry.type !== "session" || typeof entry.id !== "string")
43447
43602
  throw new Error("Session source has no valid header");
43448
43603
  hasHeader = true;
43604
+ receipts = new RequestUsageAccumulator(entry.id);
43605
+ }
43606
+ if (entry.type === "request" && receipts) {
43607
+ requestEntries++;
43608
+ requestBytes += record2.source?.locator.length ?? Buffer.byteLength(record2.json) + 1;
43609
+ if (requestEntries > request.limits.maxEntries || requestBytes > request.limits.maxSourceBytes)
43610
+ receipts = void 0;
43611
+ else
43612
+ receipts.add(entry.request);
43449
43613
  }
43450
43614
  if (entry.type !== "session")
43451
43615
  leafId = entry.id;
@@ -43478,13 +43642,14 @@ async function readContextTreeProjectionFromDisk(sessionFile, request) {
43478
43642
  const hasSourceLeaf = leafId !== null;
43479
43643
  leafId = visibleParent(leafId);
43480
43644
  applyChildUsageAttributions(entries);
43481
- return { entries, leafId, hasSourceLeaf };
43645
+ const ownRequestUsage = receipts?.finish();
43646
+ return { entries, leafId, hasSourceLeaf, ...ownRequestUsage ? { ownRequestUsage } : {} };
43482
43647
  } finally {
43483
43648
  request.releaseMetadata(metadataBytes);
43484
43649
  }
43485
43650
  }
43486
43651
  async function readContextTreeChildNodeFromDisk(childSessionDir, sessionFile, resolveContextWindow, request, identity) {
43487
- const { entries: allEntries, leafId, hasSourceLeaf } = await readContextTreeProjectionFromDisk(sessionFile, request);
43652
+ const { entries: allEntries, leafId, hasSourceLeaf, ownRequestUsage } = await readContextTreeProjectionFromDisk(sessionFile, request);
43488
43653
  const branch = branchEntries(allEntries, leafId);
43489
43654
  if (branch.length === 0 && !hasSourceLeaf) {
43490
43655
  return void 0;
@@ -43515,9 +43680,10 @@ async function readContextTreeChildNodeFromDisk(childSessionDir, sessionFile, re
43515
43680
  model,
43516
43681
  ownUsage,
43517
43682
  totalUsage,
43683
+ ...ownRequestUsage ? { ownRequestUsage } : {},
43518
43684
  contextUsage: computeContextUsageFromEntries(allEntries, branch, contextWindow)
43519
43685
  };
43520
- request.retainMetadata(identity ? { model, ownUsage, totalUsage, contextUsage: metadata.contextUsage } : metadata);
43686
+ request.retainMetadata(identity ? { model, ownUsage, totalUsage, ownRequestUsage, contextUsage: metadata.contextUsage } : metadata);
43521
43687
  return { ...metadata, children: [] };
43522
43688
  }
43523
43689
  async function loadContextTreeChildFromDisk(childSessionDir, resolveContextWindow, limits = {}, identity) {
@@ -45917,7 +46083,7 @@ async function loadExtensionModule(extensionPath) {
45917
46083
  // (file-path aliases would load a second, divergent copy of each package).
45918
46084
  // Also disable tryNative so jiti handles ALL imports (not just the entry point)
45919
46085
  // Node/dev must also share the native AI registry and implementation identities.
45920
- ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-PEFT72QN.js")).VIRTUAL_MODULES, tryNative: false } : {
46086
+ ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-URKVA3UB.js")).VIRTUAL_MODULES, tryNative: false } : {
45921
46087
  alias: getAliases(),
45922
46088
  virtualModules: {
45923
46089
  "@ponythewhite/base-context-ai": src_exports,
@@ -47656,6 +47822,15 @@ function formatHarnessStateForPrompt(state, options = {}) {
47656
47822
  includeIpythonExamples ? "Call contract: read each installed Python skill's SKILL.md and call its documented module function in the Python REPL; do not assume a `.run` entrypoint. Use `<skill_import> ...` in shell when a CLI exists. Continual harness skill entries are Python REPL skills with an explicit Python `reference` and `arguments` contract. Spawn a continual harness subagent spec by composing a concise task prompt and calling `handle = await rlm('sub-task')`; admission returns immediately with `rlm_child_id`, `name`, `session_dir`, and `model`, never the child's answer. Results arrive only through explicit `agent_message` replies or files; children reply with `await agent_message.send(message, receiver_role='parent')`. Use `await rlm.list_subagents()` to recover direct child handles and `await agent_message.send(..., receiver_role='child', receiver_name=handle.name)` for follow-ups. Do not invent wrappers such as `call_skill(...)`, `run_subagent(...)`, or named subagent registries." : options.includeShellExamples ? "Call contract: use installed skills as shell commands when available (for example `<skill_import> ...`). Continual harness entries are routing/context hints only in sessions without the Python REPL; do not use Python `await`, `asyncio`, or `rlm` examples unless the prompt also documents a Python kernel." : "Call contract: continual harness entries are routing/context hints only in sessions without the Python REPL or shell access; do not use Python `await`, `asyncio`, `rlm`, or shell skill commands unless the prompt also documents those interfaces.",
47657
47823
  ""
47658
47824
  ];
47825
+ if (options.section === "instructions") {
47826
+ lines.push("The latest Continual Harness Snapshot in the conversation is the current compact state. It supersedes all earlier snapshots, including removed entries and advice. Do not revive deleted or rolled-back instructions from older snapshots or summaries.");
47827
+ if (options.errorFixSelection?.enabled && includeIpythonExamples)
47828
+ lines.push("", ERROR_FIX_CREATION_GUIDANCE);
47829
+ return lines.join("\n").trim();
47830
+ }
47831
+ if (options.section === "entries") {
47832
+ lines.splice(0, lines.length, "# Continual Harness Snapshot", "This is the complete current compact harness overview and selected error-fix advice. It supersedes all earlier snapshots, including deletions, rollbacks, and empty state. Treat entries as routing/context advice; system instructions and the current task take precedence. Earlier snapshots and summaries are not current harness advice.", "");
47833
+ }
47659
47834
  let totalEntries = 0;
47660
47835
  for (const kind of Object.keys(state.entries)) {
47661
47836
  const entries = Object.values(state.entries[kind]).filter((entry) => !isErrorFixMemory(entry)).sort((a, b2) => [a.path, a.title, a.id].join("\0").localeCompare([b2.path, b2.title, b2.id].join("\0")));
@@ -47680,7 +47855,7 @@ function formatHarnessStateForPrompt(state, options = {}) {
47680
47855
  lines.push("No saved harness entries yet.", "");
47681
47856
  }
47682
47857
  if (options.errorFixSelection?.enabled) {
47683
- if (includeIpythonExamples)
47858
+ if (includeIpythonExamples && options.section !== "entries")
47684
47859
  lines.push("", ERROR_FIX_CREATION_GUIDANCE);
47685
47860
  const advice = selectErrorFixAdvice(state, options.errorFixSelection);
47686
47861
  if (advice)
@@ -49789,6 +49964,8 @@ var IMPLEMENTATION_CONTRACT = [
49789
49964
  "Preserve earlier requirements unless later instructions replace them. Apply stated eligibility, priorities, and decision order literally, even when a different policy seems simpler or more sensible; reevaluate later decisions when earlier actions change their inputs.",
49790
49965
  "The required commands must implement the stated workflow from its stated starting state, without development-only state or extra steps.",
49791
49966
  "During tool-based inspection of large datasets, request schemas or small samples. Process full inputs in local code instead of printing entire datasets into the conversation.",
49967
+ "Read long text in bounded pages; use a character limit as well as a line limit when lines are long. If output is truncated, page the retained result instead of repeating the original command or printing the whole file again.",
49968
+ "Batch nonurgent child updates. Send results, blockers, or decisions that need action rather than acknowledgements and repeated status requests. Continue independent work while children run, and report meaningful milestones to the user.",
49792
49969
  "Do not repeat a successful check without a concrete reason, such as changed input, an edit, or an observed failure.",
49793
49970
  "Choose algorithms whose time and memory costs fit the stated input limits.",
49794
49971
  "For constrained search, prune known-impossible partial states before expanding them; do not postpone all feasibility checks until completed candidates.",
@@ -49852,7 +50029,7 @@ ${childDoctrine}`;
49852
50029
  if (harnessState) {
49853
50030
  prompt2 += `
49854
50031
 
49855
- ${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill, errorFixSelection: options.errorFixSelection })}`;
50032
+ ${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill, errorFixSelection: options.errorFixSelection, section: options.harnessSection })}`;
49856
50033
  }
49857
50034
  if (genericMcpSection) {
49858
50035
  prompt2 += `
@@ -49891,7 +50068,7 @@ ${buildSubagentGuidance({
49891
50068
  if (harnessState) {
49892
50069
  prompt += `
49893
50070
 
49894
- ${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill, errorFixSelection: options.errorFixSelection })}`;
50071
+ ${formatHarnessStateForPrompt(harnessState, { includeIpythonExamples: hasIpython, includeShellExamples: hasBash, includeRefineExamples: hasIpython && hasRefineSkill, errorFixSelection: options.errorFixSelection, section: options.harnessSection })}`;
49895
50072
  }
49896
50073
  if (genericMcpSection) {
49897
50074
  prompt += `
@@ -59005,6 +59182,7 @@ var StaleCompactionOwnerError = class extends Error {
59005
59182
  function createPostCompactionContinuationSettlement(resume) {
59006
59183
  return { ...createAgentMessageDeferred(), resume, settled: false };
59007
59184
  }
59185
+ var RLM_PARENT_USAGE_CUSTOM_TYPE = "rlm_parent_usage";
59008
59186
  var KERNEL_STATE_LISTING_TIMEOUT_MS = 5e3;
59009
59187
  var RLM_MAX_DEPTH_STATE_CUSTOM_TYPE = "rlm_max_depth_state";
59010
59188
  function noopRlmChildAbort() {
@@ -59242,6 +59420,8 @@ var AgentSession = class _AgentSession {
59242
59420
  // Kept alive for retained children so nested updates (e.g. a grandchild cancel)
59243
59421
  // still forward to root; torn down when the retained child is disposed.
59244
59422
  _rlmChildUnsubscribes = /* @__PURE__ */ new Map();
59423
+ _rlmChildUsageSources = /* @__PURE__ */ new Map();
59424
+ _rlmParentUsageAttribution;
59245
59425
  /** Latest recap for this session, written by the daemon summarizer; read by a parent to label its child snapshots. */
59246
59426
  _currentRecap;
59247
59427
  _initialGoal;
@@ -59357,10 +59537,12 @@ var AgentSession = class _AgentSession {
59357
59537
  await this._goalResumeOperation;
59358
59538
  await this._waitForAgentEventsBeforeContext();
59359
59539
  await this._waitForChildUsageWrites();
59540
+ const assertHarnessSourceCurrent = await this._appendHarnessSnapshotIfChanged();
59360
59541
  await this.sessionManager.flushNow();
59542
+ assertHarnessSourceCurrent();
59361
59543
  if (!this.sessionManager.isPersisted()) {
59362
59544
  if (!this._compactionSetupFailure)
59363
- return;
59545
+ return { messages: this.agent.state.messages, adoptMessages: true };
59364
59546
  const rebuilt = await readSessionBootstrap(this.sessionManager, this.settingsManager.getCanonicalContextLimits());
59365
59547
  this._compactionSetupFailure = void 0;
59366
59548
  return { messages: rebuilt.context.messages, adoptMessages: true };
@@ -61447,7 +61629,7 @@ var AgentSession = class _AgentSession {
61447
61629
  if (compactionTimestamp !== void 0 && context.message.timestamp <= compactionTimestamp)
61448
61630
  return false;
61449
61631
  const contextTokens = this._getThresholdContextTokens(context.message, compactionTimestamp);
61450
- if (contextTokens === void 0 || !shouldCompact(contextTokens, contextWindow, settings))
61632
+ if (contextTokens === void 0 || !shouldCompact(contextTokens, contextWindow, settings, estimateFixedCompactionTokens(this.systemPrompt, this.agent.state.tools, this.messages)))
61451
61633
  return false;
61452
61634
  if (this._hasFailedThresholdCompaction())
61453
61635
  return false;
@@ -61780,7 +61962,7 @@ var AgentSession = class _AgentSession {
61780
61962
  }
61781
61963
  return {
61782
61964
  scheduled: true,
61783
- note: "Refinement runs when the current turn ends; the harness rebuilds the system prompt and resumes you automatically. Continue working normally."
61965
+ note: "Refinement runs when the current turn ends; fresh harness advice is added to the next request and you resume automatically. Continue working normally."
61784
61966
  };
61785
61967
  }
61786
61968
  default:
@@ -62723,6 +62905,7 @@ var AgentSession = class _AgentSession {
62723
62905
  for (const { session } of this._rlmChildSessions.values())
62724
62906
  await drain(() => session.disposeAsync());
62725
62907
  this._rlmChildSessions.clear();
62908
+ this._rlmChildUsageSources.clear();
62726
62909
  this._rlmChildCleanupFailures.clear();
62727
62910
  this._deletedRlmChildIds.clear();
62728
62911
  await drain(() => this._ipythonKernelProvisioner?.dispose({ snapshot: kernelSnapshot }));
@@ -62812,6 +62995,7 @@ var AgentSession = class _AgentSession {
62812
62995
  session.dispose();
62813
62996
  }
62814
62997
  this._rlmChildSessions.clear();
62998
+ this._rlmChildUsageSources.clear();
62815
62999
  this._rlmChildCleanupFailures.clear();
62816
63000
  this._deletedRlmChildIds.clear();
62817
63001
  this._pendingNextTurnMessages = [];
@@ -63046,6 +63230,7 @@ var AgentSession = class _AgentSession {
63046
63230
  rlmDepth: this._rlmDepth,
63047
63231
  rlmParentAgent: this._rlmParentAgent,
63048
63232
  harnessState: this._loadMergedHarnessState(),
63233
+ harnessSection: "instructions",
63049
63234
  errorFixSelection: {
63050
63235
  enabled: this.settingsManager.getLearningEnabled(),
63051
63236
  tools: validToolNames,
@@ -63058,6 +63243,106 @@ var AgentSession = class _AgentSession {
63058
63243
  };
63059
63244
  return buildSystemPrompt(this._baseSystemPromptOptions);
63060
63245
  }
63246
+ /** Read only snapshot candidates in the active literal tail and accepted epoch recipes. */
63247
+ async _readHarnessSnapshot(view) {
63248
+ const { maxMessages, maxSourceBytes } = this.settingsManager.getCanonicalContextLimits();
63249
+ const refs = [];
63250
+ let summary = null;
63251
+ let cursor;
63252
+ let count = 0;
63253
+ let bytes = 0;
63254
+ do {
63255
+ const page = await view.contextManifest({ cursor, limit: 128 });
63256
+ if (page.selection !== "known")
63257
+ throw new Error(`Harness snapshot context selection is ${page.selection}`);
63258
+ summary = page.summaryRef;
63259
+ count += page.refs.length;
63260
+ if (count + (summary ? 1 : 0) > maxMessages)
63261
+ throw new Error("Harness snapshot context message budget exceeded");
63262
+ refs.push(...page.refs.filter((ref) => ref.kind === "custom_message"));
63263
+ cursor = page.nextCursor ?? void 0;
63264
+ } while (cursor);
63265
+ const read2 = async (ref, source = view) => {
63266
+ bytes += ref.locator.length;
63267
+ if (bytes > maxSourceBytes)
63268
+ throw new Error("Harness snapshot source byte budget exceeded");
63269
+ const metadata = await source.get(ref.entryId);
63270
+ if (!metadata || metadata.revision !== ref.revision)
63271
+ throw new Error("Harness snapshot source is unavailable");
63272
+ const hydrated = await hydrateCapturedHistoryEntry(metadata, ref.locator.length, source.readPayload);
63273
+ if (!hydrated)
63274
+ throw new Error("Harness snapshot payload is unavailable");
63275
+ return hydrated.entry;
63276
+ };
63277
+ const content = (entry2) => entry2.type === "custom_message" && entry2.customType === HARNESS_SNAPSHOT_CUSTOM_TYPE && typeof entry2.content === "string" ? entry2.content : void 0;
63278
+ for (const ref of refs.reverse()) {
63279
+ const snapshot = content(await read2(ref));
63280
+ if (snapshot !== void 0)
63281
+ return snapshot;
63282
+ }
63283
+ if (!summary)
63284
+ return;
63285
+ const entry = await read2(summary);
63286
+ if (entry.type !== "compaction" || summary.qualification !== "native-context-epoch" || summary.retention === "retained-import")
63287
+ return;
63288
+ const checkpoint = readContextEpoch(entry.details, maxSourceBytes);
63289
+ if (!checkpoint)
63290
+ return;
63291
+ if (count + checkpoint.views.length > maxMessages)
63292
+ throw new Error("Harness snapshot context message budget exceeded");
63293
+ for (const pinned of [...checkpoint.views].reverse()) {
63294
+ if (pinned.ref.kind !== "custom_message")
63295
+ continue;
63296
+ if (!view.atSnapshot)
63297
+ throw new Error("Harness snapshot epoch requires its captured source");
63298
+ const snapshot = content(await read2(pinned.ref, await view.atSnapshot(pinned.source)));
63299
+ if (snapshot !== void 0)
63300
+ return snapshot;
63301
+ }
63302
+ }
63303
+ /** Persist mutable advice before the request owner captures its source and epoch ACK boundary. */
63304
+ async _appendHarnessSnapshotIfChanged() {
63305
+ const manager = this.sessionManager;
63306
+ let leafId = manager.getLeafId();
63307
+ const sourceIsCurrent = manager.captureCompactionSourceOwner();
63308
+ const assertCurrent = () => {
63309
+ if (this._disposed || this.sessionManager !== manager || !sourceIsCurrent() || manager.getLeafId() !== leafId)
63310
+ throw new Error("Harness snapshot source changed before request ownership");
63311
+ };
63312
+ let previous;
63313
+ if (manager.isPersisted()) {
63314
+ previous = await manager.readBranchHistory((view) => this._readHarnessSnapshot(view.branchContext));
63315
+ } else {
63316
+ const snapshot = manager.buildSessionContext().messages.reverse().find((message2) => message2.role === "custom" && message2.customType === HARNESS_SNAPSHOT_CUSTOM_TYPE);
63317
+ if (snapshot?.role === "custom")
63318
+ previous = snapshot.content;
63319
+ }
63320
+ assertCurrent();
63321
+ const options = this._baseSystemPromptOptions;
63322
+ const tools = options.selectedTools ?? [];
63323
+ const hasIpython = tools.includes("ipython");
63324
+ const content = formatHarnessStateForPrompt(this._loadMergedHarnessState(), {
63325
+ section: "entries",
63326
+ includeIpythonExamples: hasIpython,
63327
+ includeShellExamples: tools.includes("bash"),
63328
+ errorFixSelection: options.errorFixSelection ? { ...options.errorFixSelection, enabled: this.settingsManager.getLearningEnabled() } : void 0
63329
+ });
63330
+ if (previous === content)
63331
+ return assertCurrent;
63332
+ const entryId = await manager.appendCustomMessageEntryWithRollback(HARNESS_SNAPSHOT_CUSTOM_TYPE, content, false);
63333
+ if (this._disposed || this.sessionManager !== manager || !sourceIsCurrent() || manager.getLeafId() !== entryId)
63334
+ throw new Error("Harness snapshot source changed during append");
63335
+ if (!manager.isPersisted())
63336
+ this.agent.state.messages.push({
63337
+ role: "custom",
63338
+ customType: HARNESS_SNAPSHOT_CUSTOM_TYPE,
63339
+ content,
63340
+ display: false,
63341
+ timestamp: Date.now()
63342
+ });
63343
+ leafId = entryId;
63344
+ return assertCurrent;
63345
+ }
63061
63346
  _refreshExtensionSystemPrompt(extensionPrompt, baseSnapshot) {
63062
63347
  if (this._baseSystemPrompt === baseSnapshot) {
63063
63348
  return extensionPrompt;
@@ -66822,8 +67107,10 @@ ${parsed.args}` : block;
66822
67107
  }
66823
67108
  if (refinementAuditAppendError)
66824
67109
  throw refinementAuditAppendError.error;
66825
- this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
66826
- this.agent.state.systemPrompt = this._baseSystemPrompt;
67110
+ this._baseSystemPromptOptions = {
67111
+ ...this._baseSystemPromptOptions,
67112
+ harnessState: this._loadMergedHarnessState()
67113
+ };
66827
67114
  try {
66828
67115
  this._emit({ type: "refine_complete", result });
66829
67116
  } catch {
@@ -66961,7 +67248,7 @@ ${parsed.args}` : block;
66961
67248
  const contextTokens = this._getThresholdContextTokens(assistantMessage, compactionTimestamp);
66962
67249
  if (contextTokens === void 0)
66963
67250
  return false;
66964
- if (shouldCompact(contextTokens, contextWindow, settings)) {
67251
+ if (shouldCompact(contextTokens, contextWindow, settings, estimateFixedCompactionTokens(this.systemPrompt, this.agent.state.tools, this.messages))) {
66965
67252
  if (this._hasFailedThresholdCompaction())
66966
67253
  return false;
66967
67254
  if (!this._pendingCheckpoint && queueAutonomousContinuation) {
@@ -68384,6 +68671,7 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68384
68671
  this._rlmChildUnsubscribes.get(childId)?.();
68385
68672
  this._rlmChildUnsubscribes.delete(childId);
68386
68673
  this._rlmChildSessions.delete(childId);
68674
+ this._rlmChildUsageSources.delete(childId);
68387
68675
  this._rlmChildCleanupFailures.delete(childId);
68388
68676
  this._abandonedRlmQuiescenceChildIds.delete(childId);
68389
68677
  if (!run2 || this._activeRlmChildRuns.get(childId) === run2) {
@@ -68458,6 +68746,145 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68458
68746
  this._removeRlmSubagentTracking(childId);
68459
68747
  return { subagent };
68460
68748
  }
68749
+ async _restoreRlmChildUsageSource(childId, child) {
68750
+ if (this._rlmChildUsageSources.has(childId))
68751
+ return;
68752
+ const readSource = (entry) => {
68753
+ if (entry.type !== "custom" || entry.customType !== RLM_PARENT_USAGE_CUSTOM_TYPE)
68754
+ return;
68755
+ const data = entry.data;
68756
+ if (!data || data.sessionId !== this.sessionId || data.sessionFile !== this.sessionFile || typeof data.entryId !== "string")
68757
+ return;
68758
+ return { sessionId: data.sessionId, sessionFile: data.sessionFile, entryId: data.entryId };
68759
+ };
68760
+ const source = child.sessionManager.supportsCapturedHistoryReads() ? await child.sessionManager.readBranchHistory(async (history) => {
68761
+ let after = 0;
68762
+ while (true) {
68763
+ const page = await history.page(after, 64);
68764
+ for (const ref of page.events) {
68765
+ if (ref.kind !== "custom" || ref.locator.length > 16 * 1024)
68766
+ continue;
68767
+ const record2 = await history.hydrateEntry(ref.id, 16 * 1024);
68768
+ const source2 = record2 && readSource(record2.entry);
68769
+ if (source2)
68770
+ return source2;
68771
+ }
68772
+ if (page.nextAfter === null)
68773
+ return;
68774
+ after = page.nextAfter;
68775
+ }
68776
+ }) : child.sessionManager.getBranch().map(readSource).find((source2) => source2 !== void 0);
68777
+ if (!source || source.sessionId !== this.sessionId || source.sessionFile !== this.sessionFile)
68778
+ return;
68779
+ const target = await this.sessionManager.readEntry(source.entryId);
68780
+ if (target?.type !== "message" || target.message.role !== "assistant")
68781
+ return;
68782
+ if (source.sessionId !== this.sessionId || source.sessionFile !== this.sessionFile)
68783
+ return;
68784
+ this._rlmChildUsageSources.set(childId, source);
68785
+ }
68786
+ _subscribeRlmChildEvents(childId, child, run2, onUsageWrite) {
68787
+ let runningToolCount = 0;
68788
+ const emitChildUpdate = () => {
68789
+ if (run2)
68790
+ run2.emitUpdate?.();
68791
+ else
68792
+ this._emit({ type: "rlm_child_update", child: this._rlmChildSnapshotForSession(childId, child) });
68793
+ };
68794
+ const attributeUsage = (usage, origin) => {
68795
+ const source = this._rlmChildUsageSources.get(childId);
68796
+ if (!source || source.sessionId !== this.sessionId || source.sessionFile !== this.sessionFile)
68797
+ return Promise.resolve();
68798
+ const delta = structuredClone(usage);
68799
+ const target = this.messages.find((message2) => message2.role === "assistant" && this._findAssistantEntryIdForMessage(message2) === source.entryId);
68800
+ const refreshOutput = this._refreshInvocationOutput;
68801
+ const forwardUsage = this._rlmParentUsageAttribution;
68802
+ const write2 = this.sessionManager.appendChildUsageAttributionWithAggregate(source.entryId, delta, void 0, origin).then(async ({ aggregateUsage }) => {
68803
+ if (target) {
68804
+ target.usage = structuredClone(aggregateUsage);
68805
+ refreshOutput?.(target);
68806
+ }
68807
+ await forwardUsage?.(delta, origin);
68808
+ });
68809
+ this._childUsageWrites.add(write2);
68810
+ onUsageWrite?.(write2);
68811
+ void write2.then(() => this._childUsageWrites.delete(write2), (error) => {
68812
+ this._childUsageWrites.delete(write2);
68813
+ if (run2)
68814
+ run2.error = `Child usage attribution was not acknowledged: ${this._asError(error).message}`;
68815
+ this._surfaceSessionInputError(error);
68816
+ });
68817
+ return write2;
68818
+ };
68819
+ child._rlmParentUsageAttribution = attributeUsage;
68820
+ const unsubscribe = child.subscribe((event) => {
68821
+ if (event.type === "rlm_child_update") {
68822
+ this._emit(event);
68823
+ return;
68824
+ }
68825
+ if (event.type === "agent_start") {
68826
+ if (run2)
68827
+ run2.activity = { kind: "waiting" };
68828
+ emitChildUpdate();
68829
+ } else if (event.type === "agent_end") {
68830
+ if (run2)
68831
+ run2.activity = void 0;
68832
+ emitChildUpdate();
68833
+ } else if (event.type === "message_end" && event.message.role === "assistant") {
68834
+ const assistant = event.message;
68835
+ if (run2) {
68836
+ run2.terminalAssistantOutcome = {
68837
+ stopReason: assistant.stopReason,
68838
+ errorMessage: assistant.errorMessage
68839
+ };
68840
+ }
68841
+ const update = () => {
68842
+ const text2 = compactRlmText(readAssistantText(assistant));
68843
+ if (run2 && text2)
68844
+ run2.answerPreview = text2;
68845
+ emitChildUpdate();
68846
+ };
68847
+ if (assistant.stopReason !== "error" && assistant.stopReason !== "aborted") {
68848
+ const messages = child.messages;
68849
+ const precedingPrompt = messages.slice(0, messages.lastIndexOf(assistant)).reverse().find((message2) => message2.role === "user" || message2.role === "custom" && message2.customType !== HARNESS_SNAPSHOT_CUSTOM_TYPE);
68850
+ const origin = precedingPrompt?.role === "custom" && isAgentSessionMessage(precedingPrompt) ? precedingPrompt.details.id.startsWith("spawn:") ? "spawn_task" : "agent_message" : "direct_user";
68851
+ void attributeUsage(assistant.usage, origin).then(update, () => {
68852
+ });
68853
+ } else
68854
+ update();
68855
+ } else if (event.type === "message_start" || event.type === "message_update") {
68856
+ if (event.message.role === "assistant") {
68857
+ if (run2) {
68858
+ const text2 = compactRlmText(readAssistantText(event.message));
68859
+ if (text2)
68860
+ run2.answerPreview = text2;
68861
+ run2.activity = { kind: "writing" };
68862
+ }
68863
+ emitChildUpdate();
68864
+ }
68865
+ } else if (event.type === "tool_execution_start") {
68866
+ if (run2) {
68867
+ run2.toolUseCount++;
68868
+ runningToolCount++;
68869
+ run2.activity = { kind: "executing", toolName: event.toolName };
68870
+ }
68871
+ emitChildUpdate();
68872
+ } else if (event.type === "tool_execution_end") {
68873
+ if (run2) {
68874
+ runningToolCount = Math.max(0, runningToolCount - 1);
68875
+ if (runningToolCount === 0)
68876
+ run2.activity = { kind: "waiting" };
68877
+ }
68878
+ emitChildUpdate();
68879
+ } else if (event.type === "session_info_changed" || event.type === "recap_update")
68880
+ emitChildUpdate();
68881
+ });
68882
+ return () => {
68883
+ unsubscribe();
68884
+ if (child._rlmParentUsageAttribution === attributeUsage)
68885
+ child._rlmParentUsageAttribution = void 0;
68886
+ };
68887
+ }
68461
68888
  /**
68462
68889
  * Retain a finished child session for the parent lifetime so inspectors and
68463
68890
  * daemon-hosted agent messaging can keep addressing it. Returns false (and disposes
@@ -68487,10 +68914,24 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68487
68914
  }
68488
68915
  }
68489
68916
  }
68490
- this._rlmChildSessions.set(childId, { session, run: this._activeRlmChildRuns.get(childId) });
68491
- if (unsubscribe) {
68492
- this._rlmChildUnsubscribes.set(childId, unsubscribe);
68917
+ await this._restoreRlmChildUsageSource(childId, session);
68918
+ if (this._disposed || this._disposing) {
68919
+ await session.disposeAsync();
68920
+ return false;
68921
+ }
68922
+ if (this._deletingRlmChildren.has(childId) || this._deletedRlmChildIds.has(childId))
68923
+ return false;
68924
+ const retained = this._rlmChildSessions.get(childId);
68925
+ const run2 = this._activeRlmChildRuns.get(childId);
68926
+ if (!run2?.unsubscribe && (retained?.session !== session || !this._rlmChildUnsubscribes.has(childId))) {
68927
+ this._rlmChildUnsubscribes.get(childId)?.();
68928
+ const ownedUnsubscribe = this._subscribeRlmChildEvents(childId, session);
68929
+ this._rlmChildUnsubscribes.set(childId, () => {
68930
+ ownedUnsubscribe();
68931
+ unsubscribe?.();
68932
+ });
68493
68933
  }
68934
+ this._rlmChildSessions.set(childId, { session, run: run2 });
68494
68935
  return true;
68495
68936
  }
68496
68937
  releaseRlmChildSession(childId, session) {
@@ -68498,8 +68939,10 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68498
68939
  if (run2?.session === session && run2.status === "done") {
68499
68940
  const unsubscribe2 = run2.unsubscribe ?? noopRlmChildEventUnsubscribe;
68500
68941
  return () => {
68501
- run2.unsubscribe = void 0;
68502
- this._activeRlmChildRuns.delete(childId);
68942
+ if (run2.unsubscribe === unsubscribe2)
68943
+ run2.unsubscribe = void 0;
68944
+ if (this._activeRlmChildRuns.get(childId) === run2)
68945
+ this._activeRlmChildRuns.delete(childId);
68503
68946
  unsubscribe2();
68504
68947
  };
68505
68948
  }
@@ -68507,8 +68950,10 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68507
68950
  return false;
68508
68951
  const unsubscribe = this._rlmChildUnsubscribes.get(childId) ?? noopRlmChildEventUnsubscribe;
68509
68952
  return () => {
68510
- this._rlmChildUnsubscribes.delete(childId);
68511
- this._rlmChildSessions.delete(childId);
68953
+ if (this._rlmChildSessions.get(childId)?.session === session && this._rlmChildUnsubscribes.get(childId) === unsubscribe) {
68954
+ this._rlmChildUnsubscribes.delete(childId);
68955
+ this._rlmChildSessions.delete(childId);
68956
+ }
68512
68957
  unsubscribe();
68513
68958
  };
68514
68959
  }
@@ -68628,7 +69073,7 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68628
69073
  return [...sessions];
68629
69074
  }
68630
69075
  _hasUnsettledRlmQuiescenceWork() {
68631
- if (this.requests.hasPending)
69076
+ if (this.requests.hasPending || this._childUsageWrites.size > 0)
68632
69077
  return true;
68633
69078
  if (this._hasDeferredRlmTerminalNotices())
68634
69079
  return true;
@@ -68672,6 +69117,7 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68672
69117
  return;
68673
69118
  await wait(Promise.all([
68674
69119
  ...unsettledRuns.map((run2) => run2.settlement.promise),
69120
+ ...this._childUsageWrites,
68675
69121
  ...childSessions.map((child) => child.waitForRlmQuiescence(cancellation.signal))
68676
69122
  ]));
68677
69123
  }
@@ -68826,6 +69272,12 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68826
69272
  async _startRlmChildRun(prompt, admission, kwargs = {}, spawnCode) {
68827
69273
  const spawnedByRequestId = this.isStreaming ? this._semanticEdges.lastTurnRequestId : void 0;
68828
69274
  const parentAssistantForUsage = this._findLastAssistantMessage();
69275
+ const parentEntryId = parentAssistantForUsage && this._findAssistantEntryIdForMessage(parentAssistantForUsage);
69276
+ const usageSource = parentEntryId ? {
69277
+ sessionId: this.sessionId,
69278
+ sessionFile: this.sessionFile,
69279
+ entryId: parentEntryId
69280
+ } : void 0;
68829
69281
  const { name: rawName, model: rawModel, thinking: rawThinking, ...unsupported } = kwargs;
68830
69282
  const unsupportedKwargs = Object.keys(unsupported);
68831
69283
  if (unsupportedKwargs.length > 0) {
@@ -68870,7 +69322,6 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68870
69322
  await this._assertRlmSubagentSessionNameAvailable(sessionName);
68871
69323
  admission.assertCurrent();
68872
69324
  const startedAt = Date.now();
68873
- let runningToolCount = 0;
68874
69325
  let childSession;
68875
69326
  let usageSettlement = Promise.resolve();
68876
69327
  const run2 = {
@@ -68892,6 +69343,8 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68892
69343
  throw new Error(run2.error ?? "RLM child cancelled");
68893
69344
  };
68894
69345
  this._activeRlmChildRuns.set(run2.id, run2);
69346
+ if (usageSource)
69347
+ this._rlmChildUsageSources.set(run2.id, usageSource);
68895
69348
  this._unsettledRlmChildRuns.add(run2);
68896
69349
  const emitChildUpdate = () => {
68897
69350
  const child = this._rlmChildSnapshotForRun(run2);
@@ -68974,73 +69427,12 @@ This compaction outcome could not be saved to session history: ${persistenceErro
68974
69427
  throwIfCancelled();
68975
69428
  run2.status = "running";
68976
69429
  emitChildUpdate();
68977
- const unsubscribeChildEvents = child.subscribe((event) => {
68978
- if (event.type === "rlm_child_update") {
68979
- this._emit(event);
68980
- return;
68981
- }
68982
- if (event.type === "agent_start") {
68983
- run2.activity = { kind: "waiting" };
68984
- emitChildUpdate();
68985
- } else if (event.type === "agent_end") {
68986
- run2.activity = void 0;
68987
- emitChildUpdate();
68988
- } else if (event.type === "message_end" && event.message.role === "assistant") {
68989
- const assistant = event.message;
68990
- if (assistant.stopReason !== "error" && assistant.stopReason !== "aborted") {
68991
- if (parentAssistantForUsage) {
68992
- const parentEntryId = this._findAssistantEntryIdForMessage(parentAssistantForUsage);
68993
- if (parentEntryId) {
68994
- const messages = child.messages;
68995
- const assistantIndex = messages.lastIndexOf(assistant);
68996
- const precedingPrompt = messages.slice(0, assistantIndex).reverse().find((message2) => message2.role === "user" || message2.role === "custom");
68997
- const origin = precedingPrompt?.role === "custom" && isAgentSessionMessage(precedingPrompt) ? precedingPrompt.details.id.startsWith("spawn:") ? "spawn_task" : "agent_message" : "direct_user";
68998
- const text3 = compactRlmText(readAssistantText(assistant));
68999
- const refreshOutput = this._refreshInvocationOutput;
69000
- const write2 = this.sessionManager.appendChildUsageAttributionWithAggregate(parentEntryId, assistant.usage, void 0, origin).then(({ aggregateUsage }) => {
69001
- parentAssistantForUsage.usage = structuredClone(aggregateUsage);
69002
- refreshOutput?.(parentAssistantForUsage);
69003
- if (text3)
69004
- run2.answerPreview = text3;
69005
- emitChildUpdate();
69006
- });
69007
- this._childUsageWrites.add(write2);
69008
- usageSettlement = Promise.all([usageSettlement, write2]).then(() => void 0);
69009
- void usageSettlement.catch(() => void 0);
69010
- void write2.then(() => this._childUsageWrites.delete(write2), (error) => {
69011
- this._childUsageWrites.delete(write2);
69012
- run2.error = `Child usage attribution was not acknowledged: ${this._asError(error).message}`;
69013
- this._surfaceSessionInputError(error);
69014
- });
69015
- return;
69016
- }
69017
- }
69018
- }
69019
- const text2 = compactRlmText(readAssistantText(assistant));
69020
- if (text2)
69021
- run2.answerPreview = text2;
69022
- emitChildUpdate();
69023
- } else if (event.type === "message_start" || event.type === "message_update") {
69024
- if (event.message.role === "assistant") {
69025
- const text2 = compactRlmText(readAssistantText(event.message));
69026
- if (text2)
69027
- run2.answerPreview = text2;
69028
- run2.activity = { kind: "writing" };
69029
- emitChildUpdate();
69030
- }
69031
- } else if (event.type === "tool_execution_start") {
69032
- run2.toolUseCount += 1;
69033
- runningToolCount += 1;
69034
- run2.activity = { kind: "executing", toolName: event.toolName };
69035
- emitChildUpdate();
69036
- } else if (event.type === "tool_execution_end") {
69037
- runningToolCount = Math.max(0, runningToolCount - 1);
69038
- if (runningToolCount === 0)
69039
- run2.activity = { kind: "waiting" };
69040
- emitChildUpdate();
69041
- } else if (event.type === "session_info_changed" || event.type === "recap_update") {
69042
- emitChildUpdate();
69043
- }
69430
+ if (usageSource) {
69431
+ await child.sessionManager.appendCustomEntry(RLM_PARENT_USAGE_CUSTOM_TYPE, usageSource);
69432
+ }
69433
+ const unsubscribeChildEvents = this._subscribeRlmChildEvents(run2.id, child, run2, (write2) => {
69434
+ usageSettlement = Promise.all([usageSettlement, write2]).then(() => void 0);
69435
+ void usageSettlement.catch(() => void 0);
69044
69436
  });
69045
69437
  run2.unsubscribe = unsubscribeChildEvents;
69046
69438
  const content = `[task from parent]
@@ -69070,8 +69462,17 @@ ${prompt}`;
69070
69462
  source: "extension",
69071
69463
  customMessage: spawnMessage
69072
69464
  });
69465
+ const terminal = run2.terminalAssistantOutcome;
69466
+ if (terminal?.stopReason === "aborted") {
69467
+ run2.status = "cancelled";
69468
+ run2.error ??= terminal.errorMessage || "RLM child aborted";
69469
+ }
69470
+ throwIfCancelled();
69471
+ if (terminal?.stopReason === "error")
69472
+ throw new Error(terminal.errorMessage || "RLM child inference failed");
69073
69473
  await child.waitForRlmQuiescence();
69074
69474
  await usageSettlement;
69475
+ throwIfCancelled();
69075
69476
  if (run2.error)
69076
69477
  throw new Error(run2.error);
69077
69478
  run2.status = "done";
@@ -69960,7 +70361,12 @@ ${command}` : command;
69960
70361
  if (!usage)
69961
70362
  throw new Error("Context tree usage source is unavailable");
69962
70363
  const contextUsage = estimate ? usage.hasPostCompactionUsage ? { tokens: estimate.tokens, contextWindow, percent: estimate.tokens / contextWindow * 100 } : { tokens: null, contextWindow, percent: null } : void 0;
69963
- const usageMetadata = { ownUsage: usage.ownUsage, totalUsage: usage.totalUsage, contextUsage };
70364
+ const usageMetadata = {
70365
+ ownUsage: usage.ownUsage,
70366
+ totalUsage: usage.totalUsage,
70367
+ ...usage.ownRequestUsage ? { ownRequestUsage: usage.ownRequestUsage } : {},
70368
+ contextUsage
70369
+ };
69964
70370
  request.retainMetadata({ contextUsage });
69965
70371
  return {
69966
70372
  ...rootNode,
@@ -70506,7 +70912,7 @@ import { resolve as resolve15 } from "node:path";
70506
70912
  var BASE_CONTEXT_BUILD_ID_ENV = "BASE_CONTEXT_BUILD_ID";
70507
70913
  var BASE_CONTEXT_LAUNCHER_PATH_ENV = "BASE_CONTEXT_LAUNCHER_PATH";
70508
70914
  function bundledBuildId() {
70509
- return false ? void 0 : "v1.0.10-1-g67d926ccc";
70915
+ return false ? void 0 : "v1.0.12-2-gc29f87f19";
70510
70916
  }
70511
70917
  function getDaemonRuntimeIdentity(environment = process.env) {
70512
70918
  const entrypoint = process.argv[1];
@@ -71211,6 +71617,8 @@ export {
71211
71617
  collectEntriesForBranchSummary,
71212
71618
  prepareBranchEntries,
71213
71619
  generateBranchSummary,
71620
+ emptyRequestUsageTotals,
71621
+ addRequestUsageTotals,
71214
71622
  SESSION_SCHEDULED_JOBS_FILENAME,
71215
71623
  DEFAULT_HEARTBEAT_SCHEDULE,
71216
71624
  DEFAULT_HEARTBEAT_DELIVERY_MODE,