@orkestrel/agent 0.0.31 → 0.0.32

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.
@@ -9,7 +9,7 @@ let _orkestrel_workspace = require("@orkestrel/workspace");
9
9
  let _orkestrel_queue = require("@orkestrel/queue");
10
10
  let _orkestrel_workflow = require("@orkestrel/workflow");
11
11
  let _orkestrel_abort = require("@orkestrel/abort");
12
- //#region src/core/constants.ts
12
+ // src/core/constants.ts
13
13
  /**
14
14
  * Lists the roles a conversation message can play, in the order the wire contract names them —
15
15
  * the one list the {@link import('./types.js').MessageRole} union derives from, the message
@@ -21,8 +21,7 @@ var MESSAGE_ROLES = Object.freeze([
21
21
  "assistant",
22
22
  "tool"
23
23
  ]);
24
- //#endregion
25
- //#region src/core/errors.ts
24
+ // src/core/errors.ts
26
25
  /**
27
26
  * Reports a judge call cancelled by the caller's signal or its deadline, carrying the
28
27
  * {@link JudgeResult} merged from the calls that completed before the cancel and the
@@ -58,8 +57,7 @@ var JudgeAbortError = class extends Error {
58
57
  function isJudgeAbortError(value) {
59
58
  return (0, _orkestrel_contract.isInstance)(value, JudgeAbortError);
60
59
  }
61
- //#endregion
62
- //#region src/core/shapers.ts
60
+ // src/core/shapers.ts
63
61
  /**
64
62
  * Describes a tool call's JSON wire projection.
65
63
  *
@@ -89,12 +87,10 @@ var messageShape = (0, _orkestrel_contract.objectShape)({
89
87
  images: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.arrayShape)((0, _orkestrel_contract.stringShape)())),
90
88
  thinking: (0, _orkestrel_contract.optionalShape)((0, _orkestrel_contract.stringShape)())
91
89
  });
92
- //#endregion
93
- //#region src/core/contracts.ts
90
+ // src/core/contracts.ts
94
91
  /** Validates and projects conversation messages at a JSON wire boundary. */
95
92
  var messageContract = (0, _orkestrel_contract.createContract)(messageShape);
96
- //#endregion
97
- //#region src/core/cloners.ts
93
+ // src/core/cloners.ts
98
94
  /**
99
95
  * Owns a value by serializing it to JSON and parsing the text, so the copy shares nothing with its source.
100
96
  *
@@ -116,8 +112,7 @@ function copyJSON(value) {
116
112
  if (!text.success || typeof text.value !== "string") return void 0;
117
113
  return (0, _orkestrel_contract.parseJSON)(text.value);
118
114
  }
119
- //#endregion
120
- //#region src/core/helpers.ts
115
+ // src/core/helpers.ts
121
116
  /**
122
117
  * Filters a list of members by a {@link import('./contexts/index.js').ScopeInterface} allow-list of keys —
123
118
  * `undefined` passes everything, `[]` passes nothing, and a non-empty list passes the listed keys
@@ -456,8 +451,7 @@ function renderJSON(value) {
456
451
  function matchesJudgment(judgment, question, sources, state, model) {
457
452
  return judgment.model === model && judgment.state === state && judgment.sources.length === sources.length && judgment.sources.every((id, index) => id === sources[index]) && JSON.stringify(judgment.question) === JSON.stringify(question);
458
453
  }
459
- //#endregion
460
- //#region src/core/validators.ts
454
+ // src/core/validators.ts
461
455
  /**
462
456
  * Checks whether a value is a judge entry: a string, a JSON record, or a JSON array.
463
457
  *
@@ -534,8 +528,7 @@ function isJudgeQuestion(value) {
534
528
  function isNonNegativeSafeInteger(value) {
535
529
  return (0, _orkestrel_contract.isFiniteNumber)(value) && Number.isSafeInteger(value) && value >= 0;
536
530
  }
537
- //#endregion
538
- //#region src/core/providers/constants.ts
531
+ // src/core/providers/constants.ts
539
532
  /**
540
533
  * Names the opening tag a {@link import('./ThinkSplitter.js').ThinkSplitter} recognizes as the start of
541
534
  * an in-content reasoning span — `'<think>'`, the de-facto wire convention thinking models
@@ -601,8 +594,7 @@ var INVALID_RELAY_STATUS = 400;
601
594
  var OVERSIZED_RELAY_STATUS = 413;
602
595
  /** Names the System One decision endpoint shared by compatible servers. */
603
596
  var SYSTEM_ONE_PATH = "/v1/systemone";
604
- //#endregion
605
- //#region src/core/providers/errors.ts
597
+ // src/core/providers/errors.ts
606
598
  /**
607
599
  * Reports a provider stream cancelled mid-flight by its bound signal — thrown by the
608
600
  * `stream` method of a {@link ProviderInterface}, carrying the {@link ProviderResult} assembled from
@@ -713,8 +705,7 @@ var JudgeError = class extends Error {
713
705
  function isJudgeError(value) {
714
706
  return (0, _orkestrel_contract.isInstance)(value, JudgeError);
715
707
  }
716
- //#endregion
717
- //#region src/core/providers/shapers.ts
708
+ // src/core/providers/shapers.ts
718
709
  /**
719
710
  * Describes a provider request's JSON wire projection.
720
711
  *
@@ -774,16 +765,14 @@ var relayFrameShape = (0, _orkestrel_contract.unionShape)((0, _orkestrel_contrac
774
765
  channel: (0, _orkestrel_contract.literalShape)(["error"]),
775
766
  message: (0, _orkestrel_contract.stringShape)()
776
767
  }));
777
- //#endregion
778
- //#region src/core/providers/contracts.ts
768
+ // src/core/providers/contracts.ts
779
769
  /** Validates and projects provider requests at a JSON wire boundary. */
780
770
  var providerRequestContract = (0, _orkestrel_contract.createContract)(providerRequestShape);
781
771
  /** Validates and projects provider results at a JSON wire boundary. */
782
772
  var providerResultContract = (0, _orkestrel_contract.createContract)(providerResultShape);
783
773
  /** Validates and projects channel-discriminated relay frames at a JSON wire boundary. */
784
774
  var relayFrameContract = (0, _orkestrel_contract.createContract)(relayFrameShape);
785
- //#endregion
786
- //#region src/core/providers/helpers.ts
775
+ // src/core/providers/helpers.ts
787
776
  /**
788
777
  * Assembles a provider result with only populated optional fields.
789
778
  *
@@ -1264,8 +1253,7 @@ function extractSystemOneUsage(usage) {
1264
1253
  });
1265
1254
  return extracted.success ? extracted.value : void 0;
1266
1255
  }
1267
- //#endregion
1268
- //#region src/core/providers/RelayStream.ts
1256
+ // src/core/providers/RelayStream.ts
1269
1257
  /**
1270
1258
  * Streams a provider call as validated NDJSON frames under response backpressure.
1271
1259
  *
@@ -1373,8 +1361,7 @@ var RelayStream = class {
1373
1361
  this.#signal.removeEventListener("abort", this.#listener);
1374
1362
  }
1375
1363
  };
1376
- //#endregion
1377
- //#region src/core/providers/ThinkSplitter.ts
1364
+ // src/core/providers/ThinkSplitter.ts
1378
1365
  /**
1379
1366
  * Separates `<think>…</think>` spans from raw content deltas with per-stream state: text inside a
1380
1367
  * span accumulates on `thinking`, and text outside it returns as clean content, so a provider
@@ -1492,8 +1479,7 @@ var ThinkSplitter = class {
1492
1479
  return Array.from({ length: max }, (_, index) => max - index).find((length) => this.#pending.endsWith(tag.slice(0, length))) ?? 0;
1493
1480
  }
1494
1481
  };
1495
- //#endregion
1496
- //#region src/core/providers/AgentProvider.ts
1482
+ // src/core/providers/AgentProvider.ts
1497
1483
  /**
1498
1484
  * Implements bounded HTTP streaming and result assembly behind concrete wire seams.
1499
1485
  *
@@ -1704,8 +1690,7 @@ var AgentProvider = class {
1704
1690
  return response;
1705
1691
  }
1706
1692
  };
1707
- //#endregion
1708
- //#region src/core/providers/RelayProvider.ts
1693
+ // src/core/providers/RelayProvider.ts
1709
1694
  /**
1710
1695
  * Carries provider calls over an authenticated NDJSON relay endpoint.
1711
1696
  *
@@ -1822,8 +1807,7 @@ var RelayProvider = class extends AgentProvider {
1822
1807
  return parser.parse("\n");
1823
1808
  }
1824
1809
  };
1825
- //#endregion
1826
- //#region src/core/providers/AgentJudge.ts
1810
+ // src/core/providers/AgentJudge.ts
1827
1811
  /**
1828
1812
  * Implements the bounded HTTP calls, validation, and result merging of a judge behind concrete
1829
1813
  * wire seams.
@@ -1963,8 +1947,7 @@ var AgentJudge = class {
1963
1947
  }
1964
1948
  }
1965
1949
  };
1966
- //#endregion
1967
- //#region src/core/providers/validators.ts
1950
+ // src/core/providers/validators.ts
1968
1951
  /**
1969
1952
  * Checks whether a value is a System One response envelope with optional model and usage.
1970
1953
  *
@@ -2022,8 +2005,7 @@ function isSystemOneAnswer(value) {
2022
2005
  });
2023
2006
  return checked.success && checked.value;
2024
2007
  }
2025
- //#endregion
2026
- //#region src/core/providers/SystemOneJudge.ts
2008
+ // src/core/providers/SystemOneJudge.ts
2027
2009
  /**
2028
2010
  * Carries judge questions over the System One protocol and derives answers from server distributions.
2029
2011
  *
@@ -2124,8 +2106,7 @@ var SystemOneJudge = class extends AgentJudge {
2124
2106
  };
2125
2107
  }
2126
2108
  };
2127
- //#endregion
2128
- //#region src/core/providers/factories.ts
2109
+ // src/core/providers/factories.ts
2129
2110
  /**
2130
2111
  * Creates an authorized relay handler that validates a bounded JSON request before streaming.
2131
2112
  *
@@ -2284,8 +2265,7 @@ function createThinkSplitter() {
2284
2265
  function createSystemOneJudge(options) {
2285
2266
  return new SystemOneJudge(options);
2286
2267
  }
2287
- //#endregion
2288
- //#region src/core/conversations/constants.ts
2268
+ // src/core/conversations/constants.ts
2289
2269
  /**
2290
2270
  * Sets the default number of recent live messages the `compact()` method of a
2291
2271
  * {@link ConversationInterface} retains verbatim — `0`, so a manual `compact()` keeps no recent tail and folds every
@@ -2312,8 +2292,7 @@ var DEFAULT_CONVERSATION_KEEP = 0;
2312
2292
  * because it interpolates the per-call provenance `label`).
2313
2293
  */
2314
2294
  var CONVERSATION_RECAP_PREFIX = "[Summary of earlier messages] ";
2315
- //#endregion
2316
- //#region src/core/conversations/errors.ts
2295
+ // src/core/conversations/errors.ts
2317
2296
  /**
2318
2297
  * Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages with, a
2319
2298
  * `sections` cap below `1`, a `keep` that is not a nonnegative safe integer, or a judgment or
@@ -2373,8 +2352,7 @@ var ConversationError = class extends Error {
2373
2352
  function isConversationError(value) {
2374
2353
  return (0, _orkestrel_contract.isInstance)(value, ConversationError);
2375
2354
  }
2376
- //#endregion
2377
- //#region src/core/conversations/validators.ts
2355
+ // src/core/conversations/validators.ts
2378
2356
  /**
2379
2357
  * Checks whether a value satisfies the domain conversation-message contract.
2380
2358
  *
@@ -2516,8 +2494,7 @@ function isConversationSnapshot(value) {
2516
2494
  judgments: (0, _orkestrel_contract.optionalOf)((0, _orkestrel_contract.arrayOf)(isJudgment))
2517
2495
  }, ["judgments"])(value);
2518
2496
  }
2519
- //#endregion
2520
- //#region src/core/conversations/helpers.ts
2497
+ // src/core/conversations/helpers.ts
2521
2498
  /**
2522
2499
  * Builds records for answered or refused request keys, attaching usage only for a single question.
2523
2500
  *
@@ -2726,8 +2703,7 @@ function raceSignal(promise, signal) {
2726
2703
  promise.then(resolve, reject).finally(() => settled.abort());
2727
2704
  });
2728
2705
  }
2729
- //#endregion
2730
- //#region src/core/conversations/JudgmentManager.ts
2706
+ // src/core/conversations/JudgmentManager.ts
2731
2707
  /**
2732
2708
  * Stores judgments in insertion order and asks a judge only for unmatched question identities.
2733
2709
  *
@@ -2823,8 +2799,7 @@ var JudgmentManager = class {
2823
2799
  return structuredClone(judgment);
2824
2800
  }
2825
2801
  };
2826
- //#endregion
2827
- //#region src/core/conversations/Conversation.ts
2802
+ // src/core/conversations/Conversation.ts
2828
2803
  /**
2829
2804
  * Represents a conversation — a live uncompacted tail of messages it owns directly above a flat
2830
2805
  * message store, plus compacted, summarized {@link Section} records and a `summarizable` flag,
@@ -3042,8 +3017,7 @@ var Conversation = class {
3042
3017
  return message;
3043
3018
  }
3044
3019
  };
3045
- //#endregion
3046
- //#region src/core/conversations/ConversationManager.ts
3020
+ // src/core/conversations/ConversationManager.ts
3047
3021
  /**
3048
3022
  * Registers {@link Conversation} instances keyed by `id`, in insertion order, with an active pointer —
3049
3023
  * the id-keyed store over the conversation layer, the `active` / `switch` seam the
@@ -3165,8 +3139,7 @@ var ConversationManager = class {
3165
3139
  return removed;
3166
3140
  }
3167
3141
  };
3168
- //#endregion
3169
- //#region src/core/conversations/stores/MemoryConversationStore.ts
3142
+ // src/core/conversations/stores/MemoryConversationStore.ts
3170
3143
  /**
3171
3144
  * Implements the {@link ConversationStoreInterface} in memory — a process-lifetime `Map` of
3172
3145
  * {@link ConversationSnapshot} records keyed by conversation id, the default store
@@ -3239,8 +3212,7 @@ var MemoryConversationStore = class {
3239
3212
  return Promise.resolve();
3240
3213
  }
3241
3214
  };
3242
- //#endregion
3243
- //#region src/core/conversations/stores/DatabaseConversationStore.ts
3215
+ // src/core/conversations/stores/DatabaseConversationStore.ts
3244
3216
  /**
3245
3217
  * Backs a {@link ConversationStoreInterface} with one table of the `databases` layer — a
3246
3218
  * conversation's durable state is a row holding the snapshot as one opaque JSON column, narrowed
@@ -3347,8 +3319,7 @@ var DatabaseConversationStore = class {
3347
3319
  await this.#table.remove(id);
3348
3320
  }
3349
3321
  };
3350
- //#endregion
3351
- //#region src/core/conversations/factories.ts
3322
+ // src/core/conversations/factories.ts
3352
3323
  /**
3353
3324
  * Creates a conversation — a {@link ConversationInterface} grouping messages above a flat
3354
3325
  * message store it owns directly, with compaction into summarized sections, on-demand
@@ -3523,8 +3494,7 @@ function createDatabaseConversationStore(driver = (0, _orkestrel_database.create
3523
3494
  tables: { conversations: columns }
3524
3495
  }).table("conversations"));
3525
3496
  }
3526
- //#endregion
3527
- //#region src/core/contexts/constants.ts
3497
+ // src/core/contexts/constants.ts
3528
3498
  /**
3529
3499
  * Names the section header the `build()` method of {@link import('./AgentContext.js').AgentContext}
3530
3500
  * renders the active workspace's text files under — `'## Workspace'`, the leading line of the dedicated
@@ -3540,8 +3510,7 @@ function createDatabaseConversationStore(driver = (0, _orkestrel_database.create
3540
3510
  * `base64` payload attaches to the last user message.
3541
3511
  */
3542
3512
  var WORKSPACE_SECTION_HEADER = "## Workspace";
3543
- //#endregion
3544
- //#region src/core/contexts/instructions/Instruction.ts
3513
+ // src/core/contexts/instructions/Instruction.ts
3545
3514
  /**
3546
3515
  * Represents an immutable named directive — an {@link InstructionInterface} assembled once from
3547
3516
  * its input (`name` / `content` and an optional `priority`), the `id` minted at
@@ -3576,8 +3545,7 @@ var Instruction = class {
3576
3545
  if (input.override !== void 0) this.override = input.override;
3577
3546
  }
3578
3547
  };
3579
- //#endregion
3580
- //#region src/core/contexts/instructions/InstructionManager.ts
3548
+ // src/core/contexts/instructions/InstructionManager.ts
3581
3549
  /**
3582
3550
  * Registers the immutable {@link Instruction} instances a richer context assembles a directives block
3583
3551
  * from — keyed by `name` so adding an instruction whose name is already stored overwrites it,
@@ -3668,8 +3636,7 @@ var InstructionManager = class {
3668
3636
  return removed;
3669
3637
  }
3670
3638
  };
3671
- //#endregion
3672
- //#region src/core/contexts/helpers.ts
3639
+ // src/core/contexts/helpers.ts
3673
3640
  /**
3674
3641
  * Renders a path-addressed text body as a fenced reference block — a `File: <path>` label line
3675
3642
  * over a language-tagged fence, the framing the
@@ -3840,8 +3807,7 @@ function intersectKeys(parent, child) {
3840
3807
  const allowed = new Set(parent);
3841
3808
  return child.filter((key) => allowed.has(key));
3842
3809
  }
3843
- //#endregion
3844
- //#region src/core/contexts/scopes/Scope.ts
3810
+ // src/core/contexts/scopes/Scope.ts
3845
3811
  /**
3846
3812
  * Represents a named, immutable filter over a richer context's items — an optional allow-list per
3847
3813
  * category (`instructions` / `tools` / `files`), each keyed by that category's identity (an
@@ -3901,8 +3867,7 @@ var Scope = class Scope {
3901
3867
  });
3902
3868
  }
3903
3869
  };
3904
- //#endregion
3905
- //#region src/core/contexts/scopes/ScopeManager.ts
3870
+ // src/core/contexts/scopes/ScopeManager.ts
3906
3871
  /**
3907
3872
  * Registers the named filters a richer context reuses — immutable {@link Scope} instances keyed by their
3908
3873
  * minted `id`, in insertion order, where `add` always mints and stores rather than overwriting,
@@ -3969,8 +3934,7 @@ var ScopeManager = class {
3969
3934
  return removed;
3970
3935
  }
3971
3936
  };
3972
- //#endregion
3973
- //#region src/core/contexts/AgentContext.ts
3937
+ // src/core/contexts/AgentContext.ts
3974
3938
  /**
3975
3939
  * Assembles a provider request from the richer turn context — the optional system prompt, the
3976
3940
  * observable context managers (instructions / workspaces), the
@@ -4124,8 +4088,7 @@ var AgentContext = class {
4124
4088
  return this.#conversations.active ?? conversation;
4125
4089
  }
4126
4090
  };
4127
- //#endregion
4128
- //#region src/core/contexts/factories.ts
4091
+ // src/core/contexts/factories.ts
4129
4092
  /**
4130
4093
  * Creates an instruction — an immutable {@link InstructionInterface} (a named directive)
4131
4094
  * from its `name` / `content` and optional `priority`, the `id` minted at construction.
@@ -4269,8 +4232,7 @@ function createScopeManager(options) {
4269
4232
  function createAgentContext(options) {
4270
4233
  return new AgentContext(options);
4271
4234
  }
4272
- //#endregion
4273
- //#region src/core/agents/constants.ts
4235
+ // src/core/agents/constants.ts
4274
4236
  /**
4275
4237
  * Caps an {@link AgentInterface} turn's tool iterations by default — `10` context → provider →
4276
4238
  * tools cycles before the loop stops, so a model that keeps requesting tools can never loop
@@ -4297,8 +4259,7 @@ var MESSAGE_TOKEN_OVERHEAD = 4;
4297
4259
  * exact count.
4298
4260
  */
4299
4261
  var IMAGE_TOKEN_ESTIMATE = 512;
4300
- //#endregion
4301
- //#region src/core/agents/errors.ts
4262
+ // src/core/agents/errors.ts
4302
4263
  /**
4303
4264
  * Reports an {@link AgentInterface} run that ended {@link AgentResult.partial} under a
4304
4265
  * `partial` policy of `false` (the default) — thrown by an agent-job handler (a
@@ -4403,8 +4364,7 @@ var AgentError = class extends Error {
4403
4364
  function isAgentError(value) {
4404
4365
  return (0, _orkestrel_contract.isInstance)(value, AgentError);
4405
4366
  }
4406
- //#endregion
4407
- //#region src/core/agents/Channel.ts
4367
+ // src/core/agents/Channel.ts
4408
4368
  /**
4409
4369
  * Buffers chunks in a minimal unbounded async channel — the eager pump writes them in (`push`)
4410
4370
  * and ends it (`close` / `fail`) regardless of consumption, while a consumer reads them back live
@@ -4474,8 +4434,7 @@ var Channel = class {
4474
4434
  });
4475
4435
  }
4476
4436
  };
4477
- //#endregion
4478
- //#region src/core/agents/helpers.ts
4437
+ // src/core/agents/helpers.ts
4479
4438
  /**
4480
4439
  * Projects an unknown value onto a fresh, exact `JSONValue` representation of an
4481
4440
  * {@link AgentResult} — capturing each structural field once through a total boundary,
@@ -5057,8 +5016,7 @@ function extractQueueOptions(options) {
5057
5016
  ...timeout === void 0 ? {} : { timeout }
5058
5017
  };
5059
5018
  }
5060
- //#endregion
5061
- //#region src/core/agents/Agent.ts
5019
+ // src/core/agents/Agent.ts
5062
5020
  /**
5063
5021
  * Composes a {@link ProviderInterface}, an {@link AgentContext}, and a
5064
5022
  * {@link ToolManagerInterface} into a bounded context → provider → tools → repeat turn, exposed
@@ -5621,8 +5579,7 @@ var Agent = class {
5621
5579
  return AbortSignal.any(signals);
5622
5580
  }
5623
5581
  };
5624
- //#endregion
5625
- //#region src/core/agents/AgentFanout.ts
5582
+ // src/core/agents/AgentFanout.ts
5626
5583
  /**
5627
5584
  * Executes one runner's agent jobs — spawning each unit's declared children on its first attempt
5628
5585
  * only, then rehydrating the unit through a registry with the controller signal and settling it
@@ -5680,8 +5637,7 @@ var AgentFanout = class {
5680
5637
  return settleAgentJob(this.#registry.build(controller.input, controller.signal), this.#partial);
5681
5638
  }
5682
5639
  };
5683
- //#endregion
5684
- //#region src/core/agents/Authority.ts
5640
+ // src/core/agents/Authority.ts
5685
5641
  /**
5686
5642
  * Gates the agent loop's tool calls — the synchronous policy consulted before each call runs,
5687
5643
  * turning one {@link AuthorityContext} into an {@link AuthorityDecision} by walking the ordered
@@ -5735,8 +5691,7 @@ var Authority = class {
5735
5691
  return this.#fallback;
5736
5692
  }
5737
5693
  };
5738
- //#endregion
5739
- //#region src/core/agents/AgentRegistry.ts
5694
+ // src/core/agents/AgentRegistry.ts
5740
5695
  /**
5741
5696
  * Makes a durable, JSON-serializable {@link AgentJobInput} runnable — holds the named pools of
5742
5697
  * live, non-serializable pieces (providers, tools, authorities, schedulers), throws on a name
@@ -5823,8 +5778,7 @@ var AgentRegistry = class {
5823
5778
  return manager;
5824
5779
  }
5825
5780
  };
5826
- //#endregion
5827
- //#region src/core/agents/factories.ts
5781
+ // src/core/agents/factories.ts
5828
5782
  /**
5829
5783
  * Creates an agent loop — an {@link AgentInterface} composing a
5830
5784
  * {@link ProviderInterface}, its {@link AgentContextInterface}, and a tool registry
@@ -6059,8 +6013,7 @@ function createAgentRunner(options) {
6059
6013
  handler: fanout.execute.bind(fanout)
6060
6014
  });
6061
6015
  }
6062
- //#endregion
6063
- //#region src/core/ledgers/constants.ts
6016
+ // src/core/ledgers/constants.ts
6064
6017
  /**
6065
6018
  * Lists the categories the ledger files a message under, in the order the category question
6066
6019
  * names them — the one list the {@link LedgerCategory} union derives from.
@@ -6163,8 +6116,7 @@ var DEFAULT_RECALL_LIMIT = 2;
6163
6116
  var LEDGER_SCALE_DRIFT = .06;
6164
6117
  /** Matches the logprob decoding failure `invalid or duplicate top logprob token`, which the ledger holds for the ledger's life. */
6165
6118
  var DETERMINISTIC_JUDGE_ERROR = /invalid or duplicate top logprob token/;
6166
- //#endregion
6167
- //#region src/core/ledgers/errors.ts
6119
+ // src/core/ledgers/errors.ts
6168
6120
  /**
6169
6121
  * Reports an invalid ledger configuration, failed calibration, or unowned request selection,
6170
6122
  * carrying the machine-readable `code`.
@@ -6206,15 +6158,14 @@ var LedgerError = class extends Error {
6206
6158
  function isLedgerError(value) {
6207
6159
  return (0, _orkestrel_contract.isInstance)(value, LedgerError);
6208
6160
  }
6209
- //#endregion
6210
- //#region src/core/ledgers/helpers.ts
6161
+ // src/core/ledgers/helpers.ts
6211
6162
  /**
6212
6163
  * Collects the live message ids placed in records or left without a record.
6213
6164
  * @param projection - The projected records and unplaced ids
6214
6165
  * @returns The distinct live message ids
6215
6166
  * @example
6216
6167
  * ```ts
6217
- * collectProjectionIds({ records: [], stale: [], orphans: ['message-1'] }) // Set { 'message-1' }
6168
+ * collectProjectionIds({ records: [], amendments: [], orphans: ['message-1'] }) // Set { 'message-1' }
6218
6169
  * ```
6219
6170
  */
6220
6171
  function collectProjectionIds(projection) {
@@ -6653,8 +6604,8 @@ function matchEntities(registry, text, partial) {
6653
6604
  * argument. A message that names no owner joins where its earlier side of an amendment pair joins,
6654
6605
  * or on the rules record when it is filed as a rule or a correction, and is an orphan otherwise.
6655
6606
  *
6656
- * A sentence an amending message made stale is left out and listed in `stale`. An amending message
6657
- * that is itself replaced keeps that effect, so the old value never revives.
6607
+ * Every live sentence is retained. Accepted direct edges are listed in `amendments`. An amending message
6608
+ * that is itself superseded retains its accepted edge without restoring its text.
6658
6609
  *
6659
6610
  * A sentence that opens with a pronoun takes the party named in the sentence before it. The reading
6660
6611
  * trusts capitals, so a capitalized word that is no person, such as a carrier named mid-sentence,
@@ -6662,7 +6613,7 @@ function matchEntities(registry, text, partial) {
6662
6613
  * the follow-up facts the records exist for.
6663
6614
  *
6664
6615
  * @param input - The messages, readings, entities, and classification to project
6665
- * @returns The records with owner records ordered by their first member and the rules record last, the stale sentences, and the live message ids no record placed
6616
+ * @returns The records with owner records ordered by their first member and the rules record last, the accepted amendments, and the live message ids no record placed
6666
6617
  *
6667
6618
  * @example
6668
6619
  * ```ts
@@ -6687,8 +6638,7 @@ function buildRecords(input) {
6687
6638
  earlier,
6688
6639
  later
6689
6640
  }))), (pair) => pair.later)].map(([later, pairs]) => [later, pairs.map((pair) => pair.earlier)]));
6690
- const stale = collectStale(input, byId, live);
6691
- const dead = new Set(stale.map((entry) => `${entry.source} ${entry.sentence}`));
6641
+ const amendments = collectAmendments(input, byId, live);
6692
6642
  const holders = [...input.owners.values()].flat();
6693
6643
  const system = collectNames(input.system);
6694
6644
  const settled = /* @__PURE__ */ new Map();
@@ -6703,7 +6653,7 @@ function buildRecords(input) {
6703
6653
  id
6704
6654
  }))), (entry) => entry.key)].map(([key, entries]) => {
6705
6655
  const ids = entries.map((entry) => entry.id);
6706
- const lines = ids.flatMap((id) => buildLines(input, byId, id, dead, holders, system));
6656
+ const lines = ids.flatMap((id) => buildLines(input, byId, id, holders, system));
6707
6657
  const owner = key.slice(LEDGER_OWNER_PREFIX.length);
6708
6658
  const holder = input.owners.get(owner)?.[0];
6709
6659
  const title = key === "rules" ? "Rules" : holder === void 0 ? `account ${owner}` : `${holder} (account ${owner})`;
@@ -6717,17 +6667,19 @@ function buildRecords(input) {
6717
6667
  }
6718
6668
  };
6719
6669
  }).sort((left, right) => Number(left.record.key === "rules") - Number(right.record.key === "rules") || left.first - right.first || (left.record.key < right.record.key ? -1 : left.record.key > right.record.key ? 1 : 0)).map(({ record }) => record),
6720
- stale,
6670
+ amendments,
6721
6671
  orphans
6722
6672
  };
6723
6673
  }
6724
6674
  /**
6725
- * Selects a request's view of the projected records.
6675
+ * Selects a request's records, collapsing owners with equal ordered member ids under titles joined with `; `.
6726
6676
  *
6727
6677
  * @remarks
6728
6678
  * The view holds the owner records the request names in the order it names them, then the rules
6729
6679
  * record with the lines whose topics meet the request's first, each group in position order. The
6730
- * returned records and lines are copies.
6680
+ * returned records and lines are copies. Owner records with the same member ids in the same order
6681
+ * collapse into the first requested record, keeping its key, members, and lines and joining their
6682
+ * titles with `; ` before trimming.
6731
6683
  *
6732
6684
  * @param projection - The output of {@link buildRecords}
6733
6685
  * @param request - The owners and the desk topics the request names
@@ -6743,10 +6695,14 @@ function selectRecords(projection, request) {
6743
6695
  const topics = new Set(request.topics);
6744
6696
  const rules = projection.records.find((one) => one.key === LEDGER_RULES_KEY);
6745
6697
  const sides = Map.groupBy((rules?.lines ?? []).filter(() => true), (line) => line.topics.some((topic) => topics.has(topic)));
6746
- return [...[...new Set(request.owners)].flatMap((owner) => {
6698
+ const owners = [...new Set(request.owners)].flatMap((owner) => {
6747
6699
  const record = projection.records.find((one) => one.key === `${LEDGER_OWNER_PREFIX}${owner}`);
6748
- return record === void 0 ? [] : [structuredClone(record)];
6749
- }), ...rules === void 0 ? [] : [structuredClone({
6700
+ return record === void 0 ? [] : [record];
6701
+ });
6702
+ return [...[...Map.groupBy(owners, (record) => JSON.stringify(record.members)).values()].flatMap(([record, ...rest]) => record === void 0 ? [] : [structuredClone({
6703
+ ...record,
6704
+ title: [record.title, ...rest.map((one) => one.title)].join("; ")
6705
+ })]), ...rules === void 0 ? [] : [structuredClone({
6750
6706
  ...rules,
6751
6707
  lines: [...sides.get(true) ?? [], ...sides.get(false) ?? []]
6752
6708
  })]];
@@ -6758,6 +6714,7 @@ function selectRecords(projection, request) {
6758
6714
  * The briefing joins rendered records with one blank line.
6759
6715
  *
6760
6716
  * @param record - A record or view with a `title` and `lines`
6717
+ * @param context - Rendering facts for optional accepted amendment annotations
6761
6718
  * @returns `## TITLE` followed by `- LINE` for each line
6762
6719
  *
6763
6720
  * @example
@@ -6766,13 +6723,14 @@ function selectRecords(projection, request) {
6766
6723
  * // '## Rules\n- Refunds need a manager.'
6767
6724
  * ```
6768
6725
  */
6769
- function renderLedgerRecord(record) {
6770
- return [`## ${record.title}`, ...record.lines.map((line) => `- ${line.text}`)].join("\n");
6726
+ function renderLedgerRecord(record, context) {
6727
+ return [`## ${record.title}`, ...record.lines.flatMap((line) => [context === void 0 ? "" : renderLedgerAnnotation(line, context), `- ${line.text}`].filter((text) => text !== ""))].join("\n");
6771
6728
  }
6772
6729
  /**
6773
6730
  * Renders one owner record under a `###` heading, which the briefing nests under its one `## Pinned` heading.
6774
6731
  *
6775
6732
  * @param record - An owner record or view with a `title` and `lines`
6733
+ * @param context - Rendering facts for optional accepted amendment annotations
6776
6734
  * @returns `### TITLE` followed by `- LINE` for each line
6777
6735
  *
6778
6736
  * @example
@@ -6780,8 +6738,57 @@ function renderLedgerRecord(record) {
6780
6738
  * renderLedgerPinned({ title: 'Odile Marlow (account OM-30418)', lines: [] }) // '### Odile Marlow (account OM-30418)'
6781
6739
  * ```
6782
6740
  */
6783
- function renderLedgerPinned(record) {
6784
- return `#${renderLedgerRecord(record)}`;
6741
+ function renderLedgerPinned(record, context) {
6742
+ return `#${renderLedgerRecord(record, context)}`;
6743
+ }
6744
+ /**
6745
+ * Derives complete source identities, first occurrences, and local references from the actual briefing lines.
6746
+ * @param messages - Original messages whose indexed sentences establish completeness
6747
+ * @param lines - Retained lines in rendering order after deduplication and trimming
6748
+ * @param amendments - Accepted direct message amendment edges
6749
+ * @returns Immutable rendering facts for this retained population
6750
+ *
6751
+ * @example
6752
+ * ```ts
6753
+ * buildLedgerRenderContext([], [], []).complete.size // 0
6754
+ * ```
6755
+ */
6756
+ function buildLedgerRenderContext(messages, lines, amendments) {
6757
+ const identities = new Set(lines.map((line) => `${line.source} ${line.sentence}`));
6758
+ return {
6759
+ amendments,
6760
+ complete: new Set(messages.filter((message) => {
6761
+ const sentences = splitSentences(message.content);
6762
+ return sentences.length > 0 && sentences.every((_, index) => identities.has(`${message.id} ${index}`));
6763
+ }).map((message) => message.id)),
6764
+ first: new Map(lines.toReversed().map((line) => [line.source, line])),
6765
+ references: new Map([...new Set(lines.map((line) => line.source))].map((source, index) => [source, String(index + 1)]))
6766
+ };
6767
+ }
6768
+ /**
6769
+ * Renders source framing and unresolved amendment scope at a source's first retained line.
6770
+ * @param line - The retained occurrence to annotate
6771
+ * @param context - Actual complete sources, first occurrences, local references, and accepted amendment edges
6772
+ * @returns Source framing and truthful inclusion notes, or empty text for an unrelated or repeated occurrence
6773
+ * @throws {LedgerError} Thrown when the context holds no reference for the annotated source or a fully included amender (code `'REQUEST'`)
6774
+ *
6775
+ * @example
6776
+ * ```ts
6777
+ * renderLedgerAnnotation({ text: 'Unchanged.', source: 'user-1', sentence: 0, topics: [], role: 'user' }, buildLedgerRenderContext([], [], [])) // ''
6778
+ * ```
6779
+ */
6780
+ function renderLedgerAnnotation(line, context) {
6781
+ if (context.first.get(line.source) !== line) return "";
6782
+ const amendments = context.amendments.filter((pair) => pair.earlier === line.source);
6783
+ const endpoint = context.complete.has(line.source) && context.amendments.some((pair) => pair.later === line.source && context.first.has(pair.earlier));
6784
+ if (amendments.length === 0 && !endpoint) return "";
6785
+ const included = amendments.filter((pair) => context.complete.has(pair.later));
6786
+ if (context.references.get(line.source) === void 0 || included.some((pair) => context.references.get(pair.later) === void 0)) throw new LedgerError("REFERENCE", "Ledger rendering requires retained source references");
6787
+ return [
6788
+ `[Ledger source ${context.references.get(line.source)}]`,
6789
+ ...included.map((pair) => `Accepted later amendment [Ledger source ${context.references.get(pair.later)}] is fully included in this briefing. Sentence scope is unresolved.`),
6790
+ ...amendments.some((pair) => !context.complete.has(pair.later)) ? ["Accepted later amendment text is not fully included in this briefing. Sentence scope is unresolved."] : []
6791
+ ].join("\n");
6785
6792
  }
6786
6793
  /**
6787
6794
  * Splits a recall topic at its joints.
@@ -6977,74 +6984,62 @@ function placeMember(input, links, amending, id, seen, settled) {
6977
6984
  return keys;
6978
6985
  }
6979
6986
  /**
6980
- * Collects the sentences that live messages made stale.
6987
+ * Collects accepted direct amendments of live messages.
6981
6988
  *
6982
6989
  * @remarks
6983
- * A sentence of a live message is stale when it shares an id or a number with a message that
6984
- * amends it. An amending message takes effect while it is live, and keeps its effect after another
6985
- * message supersedes it, so the value it replaced never revives. A user or tool message that the
6986
- * input excludes or files quiet never takes effect.
6990
+ * An accepted edge relates an earlier live message to an amender without claiming which sentences
6991
+ * changed. An amender takes effect while live and retains its edge after another message supersedes
6992
+ * it, without restoring the superseded text. An excluded or quiet user or tool message has no effect.
6987
6993
  *
6988
6994
  * @param input - The exclusions and classification to read
6989
6995
  * @param byId - The messages by id
6990
6996
  * @param live - The live message ids from {@link collectLive}
6991
- * @returns The stale sentences in conversation order, each with the tokens it shares
6997
+ * @returns The distinct accepted direct edges in conversation order
6992
6998
  *
6993
6999
  * @example
6994
7000
  * ```ts
6995
- * collectStale(input, byId, ['user-1', 'user-3']) // [{ source: 'user-1', sentence: 1, tokens: ['ESC-2291'] }]
7001
+ * collectAmendments(input, byId, ['user-1', 'user-3']) // [{ earlier: 'user-1', later: 'user-3' }]
6996
7002
  * ```
6997
7003
  */
6998
- function collectStale(input, byId, live) {
7004
+ function collectAmendments(input, byId, live) {
6999
7005
  const { classification } = input;
7000
7006
  const excluded = new Set(input.exclusions);
7007
+ const living = new Set(live);
7008
+ const ordered = [...new Set(input.messages.map((message) => message.id))];
7009
+ const positions = new Map(ordered.map((id, index) => [id, index]));
7001
7010
  const effective = /* @__PURE__ */ new Set([...live, ...[...byId.values()].filter((message) => message.role !== "assistant" && !excluded.has(message.id) && !classification.quiet.has(message.id) && (classification.supersessions.get(message.id) ?? []).length > 0).map((message) => message.id)]);
7002
- return live.flatMap((id) => {
7003
- const laters = (classification.amendments.get(id) ?? []).filter((later) => effective.has(later)).flatMap((later) => {
7004
- const message = byId.get(later);
7005
- return message === void 0 ? [] : [extractTokens(message.content)];
7006
- });
7007
- if (laters.length === 0) return [];
7008
- return splitSentences(byId.get(id)?.content ?? "").flatMap((text, sentence) => {
7009
- const own = extractTokens(text);
7010
- const tokens = new Set(laters.flatMap((other) => [...[...own.ids].filter((token) => other.ids.has(token)), ...[...own.numbers].filter((token) => other.numbers.has(token)).map(String)]));
7011
- return tokens.size > 0 ? [{
7012
- source: id,
7013
- sentence,
7014
- tokens: [...tokens]
7015
- }] : [];
7016
- });
7017
- });
7011
+ return ordered.filter((id) => living.has(id)).flatMap((earlier) => [...new Set(classification.amendments.get(earlier) ?? [])].filter((later) => effective.has(later) && positions.has(later)).sort((a, b) => (positions.get(a) ?? 0) - (positions.get(b) ?? 0)).map((later) => ({
7012
+ earlier,
7013
+ later
7014
+ })));
7018
7015
  }
7019
7016
  /**
7020
7017
  * Builds the record lines of one message.
7021
7018
  *
7022
7019
  * @remarks
7023
- * Each sentence that is not stale becomes a line. A sentence that opens with a pronoun and follows
7020
+ * Each original indexed sentence becomes a line. A sentence that opens with a pronoun and follows
7024
7021
  * another sentence takes the last name of the sentence before it that is neither an owner name nor
7025
7022
  * a system name, and its line text opens with that party and a colon.
7026
7023
  *
7027
7024
  * @param input - The classification whose topics the lines carry
7028
7025
  * @param byId - The messages by id
7029
7026
  * @param id - The message id
7030
- * @param dead - The stale sentences as `SOURCE SENTENCE` keys
7031
7027
  * @param holders - The owner names, which never serve as a party
7032
7028
  * @param system - The system text's names, which never serve as a party
7033
7029
  * @returns The lines in sentence order; empty when the message is absent
7034
7030
  *
7035
7031
  * @example
7036
7032
  * ```ts
7037
- * buildLines(input, byId, 'user-1', new Set(), [], []).map((line) => line.text)
7033
+ * buildLines(input, byId, 'user-1', [], []).map((line) => line.text)
7038
7034
  * // ['Odile Marlow phoned about BW-5512.', 'Odile Marlow: She wants a refund.']
7039
7035
  * ```
7040
7036
  */
7041
- function buildLines(input, byId, id, dead, holders, system) {
7037
+ function buildLines(input, byId, id, holders, system) {
7042
7038
  const message = byId.get(id);
7043
7039
  if (message === void 0) return [];
7044
7040
  const sentences = splitSentences(message.content);
7045
7041
  const topics = input.classification.topics.get(id) ?? [];
7046
7042
  return sentences.flatMap((sentence, at) => {
7047
- if (dead.has(`${id} ${at}`)) return [];
7048
7043
  const party = /^(?:He|She|They|His|Her|Their)(?![\p{L}\p{N}])/u.test(sentence) && at > 0 ? collectNames(sentences[at - 1] ?? "").filter((name) => !holders.includes(name) && !system.includes(name)).at(-1) : void 0;
7049
7044
  const line = {
7050
7045
  text: party === void 0 ? sentence : `${party}: ${sentence}`,
@@ -7059,8 +7054,7 @@ function buildLines(input, byId, id, dead, holders, system) {
7059
7054
  }];
7060
7055
  });
7061
7056
  }
7062
- //#endregion
7063
- //#region src/core/ledgers/Classifier.ts
7057
+ // src/core/ledgers/Classifier.ts
7064
7058
  /**
7065
7059
  * Files messages through the conversation's judgment manager and reads their categories and corrections.
7066
7060
  *
@@ -7346,8 +7340,7 @@ var Classifier = class {
7346
7340
  }
7347
7341
  }
7348
7342
  };
7349
- //#endregion
7350
- //#region src/core/ledgers/validators.ts
7343
+ // src/core/ledgers/validators.ts
7351
7344
  /**
7352
7345
  * Checks whether a value is finite and lies in the interval (0, 1].
7353
7346
  * @param value - The value to inspect
@@ -7372,8 +7365,7 @@ function isFraction(value) {
7372
7365
  function isPositiveSafeInteger(value) {
7373
7366
  return (0, _orkestrel_contract.isFiniteNumber)(value) && Number.isSafeInteger(value) && value > 0;
7374
7367
  }
7375
- //#endregion
7376
- //#region src/core/ledgers/Gauge.ts
7368
+ // src/core/ledgers/Gauge.ts
7377
7369
  /**
7378
7370
  * Prices prompts in tokens from a measured scale and overhead cost, and measures the room a request
7379
7371
  * has left.
@@ -7466,8 +7458,7 @@ var Gauge = class {
7466
7458
  if ((0, _orkestrel_contract.isFiniteNumber)(reply?.completion)) this.#reply = Math.max(this.#reply, reply.completion - (reply.thinking ?? 0));
7467
7459
  }
7468
7460
  };
7469
- //#endregion
7470
- //#region src/core/ledgers/LedgerPass.ts
7461
+ // src/core/ledgers/LedgerPass.ts
7471
7462
  /**
7472
7463
  * Holds what one pass of a ledger request keeps: the selection its run adopted last, the
7473
7464
  * conversation boundary its calls count additions from, its summed usage, and its gauge calls.
@@ -7611,8 +7602,7 @@ var LedgerPass = class {
7611
7602
  this.#log = [...this.#log, { thinking }];
7612
7603
  }
7613
7604
  };
7614
- //#endregion
7615
- //#region src/core/ledgers/LedgerRequest.ts
7605
+ // src/core/ledgers/LedgerRequest.ts
7616
7606
  /**
7617
7607
  * Holds what one ledger request keeps while it is served: its message, its filing readings and
7618
7608
  * plan, the gauge calls of its passes, and its repeat and recall stops.
@@ -7765,8 +7755,7 @@ var LedgerRequest = class {
7765
7755
  return this.#listings.get(result);
7766
7756
  }
7767
7757
  };
7768
- //#endregion
7769
- //#region src/core/ledgers/Ledger.ts
7758
+ // src/core/ledgers/Ledger.ts
7770
7759
  /**
7771
7760
  * Serves one conversation through classified records, a bounded briefing, and a final answer pass.
7772
7761
  * @example
@@ -8124,17 +8113,17 @@ var Ledger = class {
8124
8113
  projection: buildRecords(input)
8125
8114
  };
8126
8115
  }
8127
- #projectLines(input, projection, id) {
8128
- return buildLines(input, new Map(input.messages.map((message) => [message.id, message])), id, new Set(projection.stale.map((line) => `${line.source} ${line.sentence}`)), [...input.owners.values()].flat(), collectNames(this.#options.system));
8116
+ #projectLines(input, id) {
8117
+ return buildLines(input, new Map(input.messages.map((message) => [message.id, message])), id, [...input.owners.values()].flat(), collectNames(this.#options.system));
8129
8118
  }
8130
- #renderSource(id, lines) {
8119
+ #renderSource(id, lines, context) {
8131
8120
  const message = this.#conversation.message(id);
8132
8121
  if (message === void 0) return "";
8133
8122
  const sentences = splitSentences(message.content);
8134
- const text = sentences.length === lines.length ? message.content : lines.map((line) => sentences[line.sentence] ?? "").join(" ");
8135
- if (text === "" || message.role !== "tool") return text;
8123
+ const text = sentences.every((_, index) => lines.some((line) => line.sentence === index)) ? message.content : lines.map((line) => sentences[line.sentence] ?? "").join(" ");
8124
+ if (text === "") return "";
8136
8125
  const reading = this.#readLookups().find((one) => one.id === id);
8137
- return reading === void 0 ? text : `${renderLookupCall(reading.name, reading.arguments)}: ${text}`;
8126
+ return [...lines.map((line) => renderLedgerAnnotation(line, context)), message.role !== "tool" || reading === void 0 ? text : `${renderLookupCall(reading.name, reading.arguments)}: ${text}`].filter((part) => part !== "").join("\n");
8138
8127
  }
8139
8128
  #collectAfter(request) {
8140
8129
  const messages = this.#conversation.messages();
@@ -8217,7 +8206,7 @@ var Ledger = class {
8217
8206
  const score = [...words].filter((word) => asked?.words.has(word)).reduce((sum, word) => sum + Math.log(texts.length / (counts.get(word) ?? 1)), 0);
8218
8207
  return [{
8219
8208
  source: message.id,
8220
- lines: this.#projectLines(input, projection, message.id),
8209
+ lines: this.#projectLines(input, message.id),
8221
8210
  position,
8222
8211
  group,
8223
8212
  ruled,
@@ -8251,7 +8240,7 @@ var Ledger = class {
8251
8240
  source: unit.source,
8252
8241
  record: this.#buildUnitRecord(unit.source, unit.category, input, projection, held)
8253
8242
  }));
8254
- const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), cap);
8243
+ const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), cap, projection.amendments);
8255
8244
  const briefing = trimmed.briefing;
8256
8245
  const shown = /* @__PURE__ */ new Set([...trimmed.included, ...records.flatMap((record) => record.members.filter((source) => {
8257
8246
  const full = record.lines.filter((line) => line.source === source);
@@ -8263,10 +8252,10 @@ var Ledger = class {
8263
8252
  ...briefing === "" ? {} : { briefing }
8264
8253
  };
8265
8254
  }
8266
- #trim(steps, records, mapped, included, cap) {
8255
+ #trim(steps, records, mapped, included, cap, amendments) {
8267
8256
  const trimmed = steps.reduce((cut, step) => {
8268
8257
  if (cut.briefing !== void 0) return cut;
8269
- const briefing = this.#render(cut.records, mapped, cut.included);
8258
+ const briefing = this.#render(cut.records, mapped, cut.included, amendments);
8270
8259
  const content = [this.#options.system, briefing].filter((part) => part !== "").join("\n\n");
8271
8260
  if (this.#price([{
8272
8261
  id: "system",
@@ -8292,7 +8281,7 @@ var Ledger = class {
8292
8281
  return {
8293
8282
  records: trimmed.records,
8294
8283
  included: trimmed.included,
8295
- briefing: trimmed.briefing ?? this.#render(trimmed.records, mapped, trimmed.included)
8284
+ briefing: trimmed.briefing ?? this.#render(trimmed.records, mapped, trimmed.included, amendments)
8296
8285
  };
8297
8286
  }
8298
8287
  #buildUnitRecord(source, category, input, projection, held) {
@@ -8305,25 +8294,33 @@ var Ledger = class {
8305
8294
  }
8306
8295
  #collectAmended(input, projection, source, held) {
8307
8296
  const live = collectProjectionIds(projection);
8308
- return scanAmendments(input.classification.amendments, source, (id) => id === source || !held.has(id) && live.has(id)).flatMap((id) => this.#projectLines(input, projection, id));
8297
+ return scanAmendments(input.classification.amendments, source, (id) => id === source || !held.has(id) && live.has(id)).flatMap((id) => this.#projectLines(input, id));
8309
8298
  }
8310
- #render(records, mapped, included) {
8311
- const owners = records.filter((record) => record.key !== "rules" && record.lines.length > 0).map(renderLedgerPinned).join("\n\n");
8299
+ #render(records, mapped, included, amendments) {
8312
8300
  const entries = mapped.filter((unit) => included.has(unit.source)).flatMap(({ record: unit }) => [...Map.groupBy(unit.lines, (line) => line.source)].map(([source, lines]) => ({
8313
8301
  unit,
8314
8302
  source,
8315
8303
  lines
8316
8304
  })));
8317
8305
  const first = new Map(entries.toReversed().map((entry) => [entry.source, entry]));
8318
- const rendered = entries.filter((entry) => first.get(entry.source) === entry).map(({ unit, source, lines }) => ({
8306
+ const unique = entries.filter((entry) => first.get(entry.source) === entry);
8307
+ const record = records.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
8308
+ const ownerRecords = records.filter((candidate) => candidate.key !== "rules" && candidate.lines.length > 0);
8309
+ const context = buildLedgerRenderContext(this.#conversation.messages(), [
8310
+ ...ownerRecords.flatMap((candidate) => candidate.lines),
8311
+ ...unique.filter((entry) => entry.unit.key !== LEDGER_RULES_KEY).flatMap((entry) => entry.lines),
8312
+ ...record?.lines ?? [],
8313
+ ...unique.filter((entry) => entry.unit.key === LEDGER_RULES_KEY).flatMap((entry) => entry.lines)
8314
+ ], amendments);
8315
+ const owners = ownerRecords.map((owner) => renderLedgerPinned(owner, context)).join("\n\n");
8316
+ const rendered = unique.map(({ unit, source, lines }) => ({
8319
8317
  rules: unit.key === LEDGER_RULES_KEY,
8320
- texts: unit.key === "rules" && source === unit.members[0] ? lines.map((line) => this.#renderSource(source, [line])) : [this.#renderSource(source, lines)]
8318
+ texts: unit.key === "rules" && source === unit.members[0] ? lines.map((line) => this.#renderSource(source, [line], context)) : [this.#renderSource(source, lines, context)]
8321
8319
  }));
8322
8320
  const pinned = rendered.filter((one) => !one.rules).flatMap((one) => one.texts);
8323
8321
  const rules = rendered.filter((one) => one.rules).flatMap((one) => one.texts);
8324
8322
  const body = [owners, pinned.join("\n")].filter((text) => text !== "").join("\n\n");
8325
- const record = records.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
8326
- return [body === "" ? "" : `## Pinned\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record), ...rules].join("\n")].filter((text) => text !== "").join("\n\n");
8323
+ return [body === "" ? "" : `## Pinned\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record, context), ...rules].join("\n")].filter((text) => text !== "").join("\n\n");
8327
8324
  }
8328
8325
  #selectTail(request, cap, input) {
8329
8326
  const first = input.messages.findIndex((message) => this.#requests.has(message.id));
@@ -8463,8 +8460,7 @@ var Ledger = class {
8463
8460
  return lines.length === 0 ? void 0 : `${LEDGER_NOTES.results}\n${lines.join("\n")}`;
8464
8461
  }
8465
8462
  };
8466
- //#endregion
8467
- //#region src/core/ledgers/factories.ts
8463
+ // src/core/ledgers/factories.ts
8468
8464
  /**
8469
8465
  * Creates a conversation ledger after checking its thresholds, allocation, and tool names.
8470
8466
  * @param provider - The provider that answers requests
@@ -8480,7 +8476,6 @@ var Ledger = class {
8480
8476
  function createLedger(provider, options) {
8481
8477
  return new Ledger(provider, options);
8482
8478
  }
8483
- //#endregion
8484
8479
  exports.Agent = Agent;
8485
8480
  exports.AgentContext = AgentContext;
8486
8481
  exports.AgentError = AgentError;
@@ -8554,6 +8549,7 @@ exports.attachImages = attachImages;
8554
8549
  exports.attachUserImages = attachUserImages;
8555
8550
  exports.buildJudgeResult = buildJudgeResult;
8556
8551
  exports.buildJudgments = buildJudgments;
8552
+ exports.buildLedgerRenderContext = buildLedgerRenderContext;
8557
8553
  exports.buildLines = buildLines;
8558
8554
  exports.buildProviderHeaders = buildProviderHeaders;
8559
8555
  exports.buildProviderResult = buildProviderResult;
@@ -8562,13 +8558,13 @@ exports.buildRecapMessage = buildRecapMessage;
8562
8558
  exports.buildRecords = buildRecords;
8563
8559
  exports.buildSummaryMessage = buildSummaryMessage;
8564
8560
  exports.chargeUsage = chargeUsage;
8561
+ exports.collectAmendments = collectAmendments;
8565
8562
  exports.collectExchanges = collectExchanges;
8566
8563
  exports.collectImageData = collectImageData;
8567
8564
  exports.collectLive = collectLive;
8568
8565
  exports.collectNames = collectNames;
8569
8566
  exports.collectProjectionIds = collectProjectionIds;
8570
8567
  exports.collectRegistry = collectRegistry;
8571
- exports.collectStale = collectStale;
8572
8568
  exports.collectToolGroups = collectToolGroups;
8573
8569
  exports.computeReading = computeReading;
8574
8570
  exports.computeThinking = computeThinking;
@@ -8658,6 +8654,7 @@ exports.removeEntries = removeEntries;
8658
8654
  exports.renderCauseChain = renderCauseChain;
8659
8655
  exports.renderFencedFile = renderFencedFile;
8660
8656
  exports.renderJSON = renderJSON;
8657
+ exports.renderLedgerAnnotation = renderLedgerAnnotation;
8661
8658
  exports.renderLedgerPinned = renderLedgerPinned;
8662
8659
  exports.renderLedgerRecord = renderLedgerRecord;
8663
8660
  exports.renderLookupCall = renderLookupCall;