@orkestrel/agent 0.0.36 → 0.0.37

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.
@@ -8805,6 +8805,11 @@ var PLACED_CATEGORIES = Object.freeze(["rule", "correction"]);
8805
8805
  var LEDGER_RULES_KEY = "rules";
8806
8806
  /** Prefixes the key of an owner's record, which the owner's id follows. */
8807
8807
  var LEDGER_OWNER_PREFIX = "owner:";
8808
+ /** Labels recalled conversation text by its origin. */
8809
+ var LEDGER_RECALL_LABELS = Object.freeze({
8810
+ request: "Earlier request:",
8811
+ reply: "Earlier reply:"
8812
+ });
8808
8813
  /**
8809
8814
  * Supplies the wording of every question the ledger asks its judge.
8810
8815
  *
@@ -8952,6 +8957,108 @@ function isLedgerError(value) {
8952
8957
  }
8953
8958
  // src/core/ledgers/helpers.ts
8954
8959
  /**
8960
+ * Digests held messages, lookup call context, stored copies, and sentence receipts using canonical text.
8961
+ * This non-cryptographic checksum detects host edits and makes no security claim.
8962
+ * @param exchanges - The stored exchange entries
8963
+ * @param messages - The conversation holding their messages
8964
+ * @returns The hexadecimal checksum, or undefined when a required message is absent or canonical encoding fails
8965
+ * @example
8966
+ * ```ts
8967
+ * digestLedgerWindow([], []) // a deterministic hexadecimal checksum
8968
+ * ```
8969
+ */
8970
+ function digestLedgerWindow(exchanges, messages) {
8971
+ const byId = new Map(messages.map((message) => [message.id, message]));
8972
+ const held = [...new Set(exchanges.flatMap((entry) => [
8973
+ entry.request,
8974
+ entry.reply,
8975
+ ...entry.lines.map((line) => line.source)
8976
+ ]))].map((id) => byId.get(id));
8977
+ const callers = messages.filter((message) => message.role === "tool" || message.calls !== void 0);
8978
+ const encoded = attempt(() => {
8979
+ const values = [...held, ...callers].map((message) => canonicalStringify(message));
8980
+ return values.some((value) => value === void 0) ? void 0 : canonicalStringify([values, exchanges.map((entry) => [entry.copy ?? null, entry.lines])]);
8981
+ });
8982
+ if (!encoded.success || encoded.value === void 0) return void 0;
8983
+ const hash = [...encoded.value].reduce((prior, character) => {
8984
+ const code = character.codePointAt(0) ?? 0;
8985
+ return {
8986
+ first: Math.imul(prior.first ^ code, 16777619) >>> 0,
8987
+ second: Math.imul(prior.second ^ code, 16777619) >>> 0
8988
+ };
8989
+ }, {
8990
+ first: 2166136261,
8991
+ second: 3335557771
8992
+ });
8993
+ return hash.first.toString(16).padStart(8, "0") + hash.second.toString(16).padStart(8, "0");
8994
+ }
8995
+ /**
8996
+ * Collects stored messages eligible to open the recall offer.
8997
+ * @remarks
8998
+ * Notes and findings without a result do not open the offer. User statements, including quiet
8999
+ * statements available through recall's word route, can open it; this helper does not filter results.
9000
+ * @param input - The messages, findings, and classification
9001
+ * @param requests - The marked request ids
9002
+ * @param notes - The annotation ids to exclude
9003
+ * @returns User statements, lookup findings with results, marked requests, and nonblank call-free replies
9004
+ * @example
9005
+ * ```ts
9006
+ * collectRecallMessages(input, new Set(), new Set()) // eligible stored messages
9007
+ * ```
9008
+ */
9009
+ function collectRecallMessages(input, requests, notes) {
9010
+ const findings = new Set(input.findings.filter((finding) => finding.result !== void 0).map((finding) => finding.id));
9011
+ return input.messages.filter((message) => !notes.has(message.id) && (requests.has(message.id) || message.role === "assistant" && !hasCalls(message) && message.content.trim() !== "" || message.role === "user" && !hasCalls(message) || message.role === "tool" && findings.has(message.id)));
9012
+ }
9013
+ /**
9014
+ * Checks whether an eligible earlier message is absent from the prompt or incompletely covered.
9015
+ * A successful finding is held when a finding with the same canonical identity and text is fully received.
9016
+ * @param input - The messages, findings, and classification
9017
+ * @param request - The current request id; only messages before it count
9018
+ * @param requests - The marked request ids
9019
+ * @param notes - The annotation ids to exclude
9020
+ * @param messages - The seed tail and held exchange messages; lookup stubs retain their rendered text
9021
+ * @param lines - The receipts held by the window and the request copy together
9022
+ * @returns True if an eligible earlier message is absent or only partly covered; false otherwise
9023
+ * @example
9024
+ * ```ts
9025
+ * hasHiddenRecall(input, request.id, requests, notes, tail, lines) // whether to offer recall
9026
+ * ```
9027
+ */
9028
+ function hasHiddenRecall(input, request, requests, notes, messages, lines) {
9029
+ const start = input.messages.findIndex((message) => message.id === request);
9030
+ const before = new Set(input.messages.slice(0, Math.max(0, start)).map((message) => message.id));
9031
+ const present = new Map(messages.map((message) => [message.id, message]));
9032
+ const receipts = Map.groupBy(lines, (line) => line.source);
9033
+ return collectRecallMessages(input, requests, notes).some((message) => {
9034
+ if (!before.has(message.id)) return false;
9035
+ if (requests.has(message.id) || message.role === "assistant") return !present.has(message.id);
9036
+ if (present.get(message.id)?.content === message.content) return false;
9037
+ const finding = input.findings.find((one) => one.id === message.id);
9038
+ return !(finding === void 0 ? [message.id] : input.findings.filter((one) => before.has(one.id) && matchesLookup(finding, one)).map((one) => one.id)).some((id) => {
9039
+ if (present.get(id)?.content === message.content) return true;
9040
+ const held = new Set((receipts.get(id) ?? []).map((line) => line.sentence));
9041
+ return splitSentences(message.content).every((_, at) => held.has(at));
9042
+ });
9043
+ });
9044
+ }
9045
+ /**
9046
+ * Checks whether two successful findings carry the same text for the same canonical lookup.
9047
+ * @param left - The finding to compare
9048
+ * @param right - The candidate copy
9049
+ * @returns True for the same finding or equal canonical identities and text; unkeyable findings match only themselves
9050
+ * @example
9051
+ * ```ts
9052
+ * matchesLookup(finding, finding) // true when it has a result
9053
+ * ```
9054
+ */
9055
+ function matchesLookup(left, right) {
9056
+ if (left.result === void 0 || right.result === void 0 || left.text !== right.text) return false;
9057
+ if (left.id === right.id) return true;
9058
+ const identity = identifyLookup(left.name, left.arguments);
9059
+ return identity !== void 0 && identity === identifyLookup(right.name, right.arguments);
9060
+ }
9061
+ /**
8955
9062
  * Collects the live message ids placed in records or left without a record.
8956
9063
  * @param projection - The projected records and unplaced ids
8957
9064
  * @returns The distinct live message ids
@@ -9507,17 +9614,17 @@ function matchEntities(index, text, partial) {
9507
9614
  * Projects the owner records and the rules record from a conversation's messages.
9508
9615
  *
9509
9616
  * @remarks
9510
- * Each line is a sentence of a live message, verbatim except that a sentence that opens with a pronoun opens with its party and a colon. A message is live when it is a user message,
9511
- * or a tool message whose finding is the last finding of its call, and the input neither excludes it nor
9512
- * files it quiet or replaced. A finding with an undefined `result` still replaces the earlier
9513
- * finding of the same call, so the earlier result leaves every record.
9617
+ * Each line is a sentence of a live message, verbatim except that a sentence that opens with a
9618
+ * pronoun opens with its party and a colon. {@link collectLive} retains user messages and the
9619
+ * earliest finding in each call identity's last run of identical text, subject to exclusions,
9620
+ * quiet classification, and supersessions. An undefined result still replaces the earlier finding.
9514
9621
  *
9515
9622
  * A live message joins the owner records its entities name, directly or through a linked lookup
9516
9623
  * argument. A message that names no owner joins where its earlier side of an amendment pair joins,
9517
9624
  * or on the rules record when it is filed as a rule or a correction, and is an orphan otherwise.
9518
9625
  *
9519
- * Every live sentence is retained. Accepted direct edges are listed in `amendments`. An amending message
9520
- * that is itself superseded retains its accepted edge without restoring its text.
9626
+ * Every live sentence is retained. Accepted edges are listed in `amendments`. An amender that is
9627
+ * superseded points to its newest live successor, or retains its endpoint when none exists.
9521
9628
  *
9522
9629
  * A sentence that opens with a pronoun takes the party named in the sentence before it. The reading
9523
9630
  * trusts capitals, so a capitalized word that is no person, such as a carrier named mid-sentence,
@@ -9727,10 +9834,12 @@ function splitTopic(topic) {
9727
9834
  * @remarks
9728
9835
  * The cut keeps at least one entry. When it leaves entries out, its last line reads
9729
9836
  * `N older items not shown; name a narrower topic to narrow the recall`, which
9730
- * {@link matchesCutLine} recognizes.
9837
+ * {@link matchesCutLine} recognizes. Pass `more` when the entries aren't in age order, so the line
9838
+ * doesn't claim an omitted entry is older than a kept one.
9731
9839
  *
9732
9840
  * @param entries - The entries in the order they are kept
9733
9841
  * @param room - The estimate units the joined entries can take
9842
+ * @param kind - What the cut line calls an omitted entry. Default: `older`
9734
9843
  * @returns The kept entries followed by the cut line when any were left out, joined by newlines
9735
9844
  *
9736
9845
  * @example
@@ -9738,7 +9847,7 @@ function splitTopic(topic) {
9738
9847
  * cutListing(['first entry', 'second entry'], 1) // 'first entry\n1 older item not shown; name a narrower topic to narrow the recall'
9739
9848
  * ```
9740
9849
  */
9741
- function cutListing(entries, room) {
9850
+ function cutListing(entries, room, kind = "older") {
9742
9851
  const stop = [...entries.keys()].findIndex((at) => at > 0 && estimateMessages([{
9743
9852
  id: "recall",
9744
9853
  role: "tool",
@@ -9746,7 +9855,7 @@ function cutListing(entries, room) {
9746
9855
  }]) > room);
9747
9856
  const kept = entries.slice(0, stop === -1 ? void 0 : stop);
9748
9857
  const left = entries.length - kept.length;
9749
- return [...kept, ...left > 0 ? [`${left} older item${left === 1 ? "" : "s"} not shown; name a narrower topic to narrow the recall`] : []].join("\n");
9858
+ return [...kept, ...left > 0 ? [`${left} ${kind} item${left === 1 ? "" : "s"} not shown; name a narrower topic to narrow the recall`] : []].join("\n");
9750
9859
  }
9751
9860
  /**
9752
9861
  * Checks whether a line is the cut line {@link cutListing} writes.
@@ -9760,7 +9869,7 @@ function cutListing(entries, room) {
9760
9869
  * ```
9761
9870
  */
9762
9871
  function matchesCutLine(line) {
9763
- return /^\d+ older items? not shown; /.test(line);
9872
+ return /^\d+ (?:older|more) items? not shown; /.test(line);
9764
9873
  }
9765
9874
  /**
9766
9875
  * Renders the tail stub of a lookup result from an earlier request.
@@ -9821,11 +9930,12 @@ function fitSlope(groups) {
9821
9930
  * Collects the ids of the live messages in conversation order.
9822
9931
  *
9823
9932
  * @remarks
9824
- * A message is live when it is a user message, or a tool message whose finding is the last finding of its
9825
- * call, and the input neither excludes it nor files it quiet or replaced. A finding replaces any
9826
- * earlier finding of the same call, an empty one included, so an empty lookup leaves the earlier
9827
- * result out of every record. A finding with no canonical identity stays live as its own source
9828
- * and participates in no replacement.
9933
+ * A message is live when it is a user message or the first unsuperseded finding in its canonical
9934
+ * call identity's last run of identical text, and the input neither excludes it nor files it quiet
9935
+ * or superseded. When the whole run is superseded, its first finding reaches that final filter.
9936
+ * Different text or an undefined result replaces the earlier run, so an empty lookup leaves the
9937
+ * earlier result out of every record. A thrown lookup leaves the earlier result live. A finding
9938
+ * with no canonical identity participates in no replacement.
9829
9939
  *
9830
9940
  * @param input - The messages, findings, and classification to read
9831
9941
  * @returns The live message ids
@@ -9841,7 +9951,14 @@ function collectLive(input) {
9841
9951
  const position = new Map(input.messages.map((message, at) => [message.id, at]));
9842
9952
  const findings = input.findings.filter((finding) => position.has(finding.id));
9843
9953
  const identities = new Map(findings.map((finding) => [finding.id, identifyLookup(finding.name, finding.arguments)]));
9844
- const current = new Set(findings.filter((finding) => finding.result !== void 0 && !findings.some((later) => identities.get(finding.id) !== void 0 && (position.get(later.id) ?? -1) > (position.get(finding.id) ?? -1) && identities.get(later.id) === identities.get(finding.id))).map((finding) => finding.id));
9954
+ const current = new Set([...Map.groupBy(findings, (finding) => identities.get(finding.id) ?? finding).values()].flatMap((group) => {
9955
+ const ordered = group.toSorted((left, right) => (position.get(left.id) ?? -1) - (position.get(right.id) ?? -1));
9956
+ const last = ordered.at(-1);
9957
+ if (last?.result === void 0) return [];
9958
+ const boundary = ordered.findLastIndex((finding) => finding.result === void 0 || finding.text !== last.text);
9959
+ const first = ordered.slice(boundary + 1).find((finding) => (classification.supersessions.get(finding.id) ?? []).length === 0) ?? ordered[boundary + 1];
9960
+ return first === void 0 ? [] : [first.id];
9961
+ }));
9845
9962
  return [...new Map(input.messages.map((message) => [message.id, message])).values()].filter((message) => message.role === "user" || message.role === "tool" && current.has(message.id)).map((message) => message.id).filter((id) => !excluded.has(id) && !classification.quiet.has(id) && (classification.supersessions.get(id) ?? []).length === 0);
9846
9963
  }
9847
9964
  /**
@@ -9896,17 +10013,18 @@ function placeMember(input, links, amended, id, seen, settled) {
9896
10013
  return keys;
9897
10014
  }
9898
10015
  /**
9899
- * Collects accepted direct amendments of live messages.
10016
+ * Collects accepted amendments of live messages, following superseded amenders to live successors.
9900
10017
  *
9901
10018
  * @remarks
9902
10019
  * An accepted edge relates an earlier live message to an amender without claiming which sentences
9903
- * changed. An amender takes effect while live and retains its edge after another message supersedes
9904
- * it, without restoring the superseded text. An excluded or quiet user or tool message has no effect.
10020
+ * changed. A superseded amender points to its newest reachable live successor in conversation order,
10021
+ * with cycles guarded and duplicate endpoints removed. With no live successor, its endpoint stays.
10022
+ * This never restores superseded text. An excluded or quiet user or tool message has no effect.
9905
10023
  *
9906
10024
  * @param input - The exclusions and classification to read
9907
10025
  * @param byId - The messages by id
9908
10026
  * @param live - The live message ids from {@link collectLive}
9909
- * @returns The distinct accepted direct edges in conversation order
10027
+ * @returns The distinct accepted edges in conversation order
9910
10028
  *
9911
10029
  * @example
9912
10030
  * ```ts
@@ -9920,7 +10038,10 @@ function collectAmendments(input, byId, live) {
9920
10038
  const ordered = [...new Set(input.messages.map((message) => message.id))];
9921
10039
  const positions = new Map(ordered.map((id, index) => [id, index]));
9922
10040
  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)]);
9923
- 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) => ({
10041
+ return ordered.filter((id) => living.has(id)).flatMap((earlier) => [...new Set((classification.amendments.get(earlier) ?? []).filter((later) => effective.has(later) && positions.has(later)).map((later) => {
10042
+ const successors = new Set(scanAmendments(classification.supersessions, later, () => true));
10043
+ return ordered.findLast((id) => living.has(id) && successors.has(id)) ?? later;
10044
+ }))].sort((a, b) => (positions.get(a) ?? 0) - (positions.get(b) ?? 0)).map((later) => ({
9924
10045
  earlier,
9925
10046
  later
9926
10047
  })));
@@ -9966,6 +10087,83 @@ function buildLines(input, byId, id, holders, system) {
9966
10087
  }];
9967
10088
  });
9968
10089
  }
10090
+ /**
10091
+ * Encodes a sentence's record placement without comparing rendered text.
10092
+ * @param line - The record key, title, source, and zero-based sentence index
10093
+ * @returns The serialized placement identity
10094
+ * @example
10095
+ * ```ts
10096
+ * buildLedgerLineKey({ key: 'rules', title: 'Rules', source: 'one', sentence: 0 })
10097
+ * ```
10098
+ */
10099
+ function buildLedgerLineKey(line) {
10100
+ return JSON.stringify([
10101
+ line.key,
10102
+ line.title,
10103
+ line.source,
10104
+ line.sentence
10105
+ ]);
10106
+ }
10107
+ /**
10108
+ * Collects the record's sentence receipts not already held by a window.
10109
+ * @param record - The selected record with its original sentence identities
10110
+ * @param held - Placement identities already rendered in the window
10111
+ * @returns The remaining sentences with their record placement
10112
+ * @example
10113
+ * ```ts
10114
+ * collectLedgerLines({ key: 'rules', title: 'Rules', members: [], lines: [] }, new Set()) // []
10115
+ * ```
10116
+ */
10117
+ function collectLedgerLines(record, held) {
10118
+ return record.lines.map((line) => ({
10119
+ ...line,
10120
+ key: record.key,
10121
+ title: record.title
10122
+ })).filter((line) => !held.has(buildLedgerLineKey(line)));
10123
+ }
10124
+ /**
10125
+ * Selects each marked request's unambiguous final call-free reply.
10126
+ * @param messages - Stored conversation messages in order
10127
+ * @param requests - Marked request ids delimiting reply intervals
10128
+ * @param notes - Ledger notes that separate answer passes
10129
+ * @returns Eligible final replies keyed by request id
10130
+ * @example
10131
+ * ```ts
10132
+ * collectLedgerReplies([], new Set(), new Set()).size // 0
10133
+ * ```
10134
+ */
10135
+ function collectLedgerReplies(messages, requests, notes) {
10136
+ const positions = messages.flatMap((message, at) => requests.has(message.id) ? [at] : []);
10137
+ return new Map(positions.flatMap((position, index) => {
10138
+ const request = messages[position];
10139
+ const turns = messages.slice(position + 1, positions[index + 1]);
10140
+ const reply = turns.findLast((message) => message.role === "assistant" && !hasCalls(message));
10141
+ const answers = turns.flatMap((message, at) => message.role === "assistant" && !hasCalls(message) && message.content.trim() !== "" ? [at] : []);
10142
+ const certain = answers.every((at, offset) => offset === 0 || turns.slice((answers[offset - 1] ?? -1) + 1, at).some((message) => notes.has(message.id)));
10143
+ return request !== void 0 && certain && reply !== void 0 && reply.content.trim() !== "" ? [[request.id, reply]] : [];
10144
+ }));
10145
+ }
10146
+ /**
10147
+ * Captures source bytes and direct amendment edges for a held window.
10148
+ * @param messages - Current stored messages
10149
+ * @param sources - Requests, replies, and record sources the window holds
10150
+ * @param amendments - Accepted direct amendment edges from the current projection
10151
+ * @returns Source and edge identities for stale detection
10152
+ * @example
10153
+ * ```ts
10154
+ * collectLedgerEvidence([], new Set(), []).messages.size // 0
10155
+ * ```
10156
+ */
10157
+ function collectLedgerEvidence(messages, sources, amendments) {
10158
+ return {
10159
+ messages: new Set(messages.filter((message) => sources.has(message.id)).map((message) => JSON.stringify(["message", message]))),
10160
+ amendments: new Map(amendments.filter((edge) => sources.has(edge.earlier) || sources.has(edge.later)).map((edge) => [JSON.stringify([
10161
+ "edge",
10162
+ edge.earlier,
10163
+ edge.later
10164
+ ]), { ...edge }]))
10165
+ };
10166
+ }
9969
10167
  // src/core/ledgers/Classifier.ts
9970
10168
  /**
9971
10169
  * Files messages through the conversation's judgment manager and reads their categories and corrections.
@@ -10010,7 +10208,7 @@ var Classifier = class {
10010
10208
  /**
10011
10209
  * Reads the category a message is filed under.
10012
10210
  * @param id - The message id
10013
- * @returns The assigned category, the recorded category at the cutoff, or `undefined`
10211
+ * @returns The assigned category, the recorded category at the cutoff, or `undefined`; a quiet winner suppressed by the user literal floor remains undecided
10014
10212
  */
10015
10213
  category(id) {
10016
10214
  const message = this.#options.conversation.message(id);
@@ -10019,25 +10217,29 @@ var Classifier = class {
10019
10217
  if (assigned !== void 0) return assigned;
10020
10218
  const answer = this.#readCategories(id);
10021
10219
  const cutoff = this.#options.thresholds.category;
10022
- return LEDGER_CATEGORIES.flatMap((category) => {
10220
+ const winner = LEDGER_CATEGORIES.flatMap((category) => {
10023
10221
  const probability = answer?.probabilities[category];
10024
10222
  return probability !== void 0 && probability >= cutoff ? [{
10025
10223
  category,
10026
10224
  probability
10027
10225
  }] : [];
10028
10226
  }).reduce((best, candidate) => best === void 0 || candidate.probability > best.probability ? candidate : best, void 0)?.category;
10227
+ return winner !== void 0 && QUIET_CATEGORIES.includes(winner) && !this.quiet(id) ? void 0 : winner;
10029
10228
  }
10030
10229
  /**
10031
10230
  * Reports whether a message files under a quiet category.
10032
10231
  * @param id - The message id
10033
- * @returns True if the assigned or recorded category is quiet; false otherwise.
10232
+ * @returns True if the assigned category is quiet or the recorded quiet weight reaches the cutoff, except for a user message carrying an id or number; false otherwise
10034
10233
  */
10035
10234
  quiet(id) {
10036
10235
  const message = this.#options.conversation.message(id);
10037
10236
  if (message === void 0) return false;
10038
10237
  const assigned = this.#options.assign(message);
10039
10238
  if (assigned !== void 0) return QUIET_CATEGORIES.includes(assigned);
10040
- return this.#weigh(id, QUIET_CATEGORIES) >= this.#options.thresholds.category;
10239
+ if (this.#weigh(id, QUIET_CATEGORIES) < this.#options.thresholds.category) return false;
10240
+ if (message.role !== "user") return true;
10241
+ const literals = extractLiterals(message.content);
10242
+ return literals.ids.size + literals.numbers.size === 0;
10041
10243
  }
10042
10244
  /**
10043
10245
  * Reports whether a message files under a decisive category.
@@ -10076,7 +10278,7 @@ var Classifier = class {
10076
10278
  if (head !== "amends" && head !== "supersedes" || !isString(earlier) || !isString(later)) return [];
10077
10279
  const before = this.#options.conversation.message(earlier);
10078
10280
  const after = this.#options.conversation.message(later);
10079
- if (before === void 0 || after === void 0 || (this.#readNoul(this.#buildPair(head, earlier, later)) ?? 0) < this.#options.thresholds[head]) return [];
10281
+ if (before === void 0 || after === void 0 || (this.#readNoul(this.#buildPair(head, earlier, later)) ?? 0) < this.#options.thresholds[head] || this.quiet(later)) return [];
10080
10282
  return head === "amends" && !this.#sharesLiteral(extractLiterals(before.content), extractLiterals(after.content)) ? [] : [{
10081
10283
  head,
10082
10284
  earlier,
@@ -10328,8 +10530,9 @@ var Classifier = class {
10328
10530
  * has left.
10329
10531
  *
10330
10532
  * @remarks
10331
- * `observe` rescales from the first call of each finished request with the overhead cost taken out,
10332
- * and keeps that request's calls for the marginal rate and the longest final completion for the reply
10533
+ * `observe` rescales from the first call only when `spared` is absent, zero, or at least `overhead`,
10534
+ * with `max(0, overhead - spared)` taken out. A partially spared call keeps the existing scale.
10535
+ * It keeps that request's calls for the marginal rate and the longest final completion for the reply
10333
10536
  * reserve after subtracting its thinking. `overhead` never changes after construction.
10334
10537
  * {@link GaugeOptions} defines the measured use, reply reserve, and recall-room formulas.
10335
10538
  * {@link LedgerOptions} defines the ledger's plan budget and recall close rule.
@@ -10387,7 +10590,7 @@ var Gauge = class {
10387
10590
  }
10388
10591
  remainder(calls) {
10389
10592
  const call = calls.at(-1);
10390
- const used = isFiniteNumber(call?.prompt) ? call.prompt + (call.completion ?? 0) - (this.#replay === "none" ? call.thinking ?? 0 : 0) : this.#overhead + this.#scale * (call?.estimate ?? 0);
10593
+ const used = isFiniteNumber(call?.prompt) ? call.prompt + (call.completion ?? 0) - (this.#replay === "none" ? call.thinking ?? 0 : 0) : Math.max(0, this.#overhead - (call?.spared ?? 0)) + this.#scale * (call?.estimate ?? 0);
10391
10594
  return Math.max(0, this.#capacity - used);
10392
10595
  }
10393
10596
  reserve(calls, longest) {
@@ -10407,8 +10610,8 @@ var Gauge = class {
10407
10610
  }
10408
10611
  observe(calls, reply) {
10409
10612
  const first = calls[0];
10410
- if (first !== void 0 && isFiniteNumber(first.prompt) && first.estimate > 0) {
10411
- const priced = first.prompt - this.#overhead;
10613
+ if (first !== void 0 && isFiniteNumber(first.prompt) && first.estimate > 0 && ((first.spared ?? 0) === 0 || (first.spared ?? 0) >= this.#overhead)) {
10614
+ const priced = first.prompt - Math.max(0, this.#overhead - (first.spared ?? 0));
10412
10615
  if (priced > 0) this.#scale = priced / first.estimate;
10413
10616
  }
10414
10617
  this.#history = [...this.#history, [...calls]];
@@ -10585,6 +10788,9 @@ var LedgerRequest = class {
10585
10788
  #faults = /* @__PURE__ */ new Set();
10586
10789
  #message;
10587
10790
  #plan;
10791
+ #scope;
10792
+ #draft;
10793
+ #sent;
10588
10794
  #passes = [];
10589
10795
  #attempts = [];
10590
10796
  #admitted = /* @__PURE__ */ new Set();
@@ -10619,6 +10825,16 @@ var LedgerRequest = class {
10619
10825
  get plan() {
10620
10826
  return this.#plan;
10621
10827
  }
10828
+ get scope() {
10829
+ return this.#scope;
10830
+ }
10831
+ apply(scope) {
10832
+ this.#scope = scope;
10833
+ }
10834
+ /** Returns the copy and receipts adopted by the last provider turn. */
10835
+ get sent() {
10836
+ return this.#sent;
10837
+ }
10622
10838
  /**
10623
10839
  * Returns the selection the current pass's run adopted last.
10624
10840
  *
@@ -10674,6 +10890,8 @@ var LedgerRequest = class {
10674
10890
  this.#passes.at(-1)?.adopt(selection, boundary);
10675
10891
  }
10676
10892
  observe(call, position) {
10893
+ const draft = this.#draft;
10894
+ this.#sent = draft !== void 0 && this.selection?.messages.some((message) => message.id === draft.copy.id && message.content === draft.copy.content) ? draft : void 0;
10677
10895
  this.#passes.at(-1)?.observe(call, position);
10678
10896
  }
10679
10897
  spend(usage) {
@@ -10694,8 +10912,9 @@ var LedgerRequest = class {
10694
10912
  faulted(error) {
10695
10913
  return this.#faults.has(error);
10696
10914
  }
10697
- file(attempts, plan) {
10915
+ file(attempts, plan, draft) {
10698
10916
  this.#attempts = [...this.#attempts, ...attempts];
10917
+ this.#draft = draft;
10699
10918
  if (plan !== void 0) this.#plan = plan;
10700
10919
  }
10701
10920
  admit(name, args) {
@@ -10827,6 +11046,29 @@ var LedgerScan = class {
10827
11046
  }
10828
11047
  };
10829
11048
  // src/core/ledgers/shapers.ts
11049
+ /** Describes the minimal serialized evidence of a nonempty exchange window. */
11050
+ var ledgerWindowShape = objectShape({
11051
+ digest: stringShape(),
11052
+ exchanges: arrayShape(objectShape({
11053
+ request: stringShape(),
11054
+ copy: optionalShape(stringShape()),
11055
+ reply: stringShape(),
11056
+ lines: arrayShape(objectShape({
11057
+ key: stringShape(),
11058
+ title: stringShape(),
11059
+ source: stringShape(),
11060
+ sentence: numberShape({
11061
+ integer: true,
11062
+ min: 0,
11063
+ max: Number.MAX_SAFE_INTEGER
11064
+ })
11065
+ }))
11066
+ }), { min: 1 }),
11067
+ amendments: arrayShape(objectShape({
11068
+ earlier: stringShape(),
11069
+ later: stringShape()
11070
+ }))
11071
+ });
10830
11072
  /**
10831
11073
  * Describes a ledger snapshot exactly: an unknown key refuses, so a key a later version adds never reads
10832
11074
  * as absent.
@@ -10844,13 +11086,36 @@ var ledgerSnapshotShape = objectShape({
10844
11086
  gauge: optionalShape(objectShape({
10845
11087
  scale: numberShape(),
10846
11088
  overhead: numberShape()
10847
- }))
11089
+ })),
11090
+ window: optionalShape(ledgerWindowShape)
10848
11091
  });
10849
11092
  // src/core/ledgers/contracts.ts
10850
- /** Reads the faults of a refused ledger snapshot. */
11093
+ /** Reads structural faults of a serialized exchange window. */
11094
+ var ledgerWindowContract = createContract(ledgerWindowShape);
11095
+ /** Reads structural faults of a ledger snapshot, including its optional held exchange window. */
10851
11096
  var ledgerSnapshotContract = createContract(ledgerSnapshotShape);
10852
11097
  // src/core/ledgers/validators.ts
10853
11098
  /**
11099
+ * Checks whether a value has the exact shape of a nonempty exchange window.
11100
+ * @param value - The untrusted window
11101
+ * @returns True if the window and its members are well shaped; false otherwise
11102
+ * @example
11103
+ * ```ts
11104
+ * isLedgerWindowSnapshot({ digest: 'checksum', exchanges: [{ request: 'request', reply: 'reply', lines: [] }], amendments: [] }) // true
11105
+ * ```
11106
+ */
11107
+ function isLedgerWindowSnapshot(value) {
11108
+ return holds(() => {
11109
+ if (!isRecord(value) || Object.keys(value).length !== 3 || !isString(value.digest)) return false;
11110
+ const { exchanges, amendments } = value;
11111
+ if (!arrayOf(isRecord)(exchanges) || exchanges.length === 0 || !arrayOf(isRecord)(amendments)) return false;
11112
+ return exchanges.every((entry) => {
11113
+ const { request, reply, copy, lines } = entry;
11114
+ return Object.keys(entry).length === 3 + Number(copy !== void 0) && isString(request) && isString(reply) && (copy === void 0 || isString(copy)) && arrayOf(isRecord)(lines) && lines.every((line) => Object.keys(line).length === 4 && isString(line.key) && isString(line.title) && isString(line.source) && isNonNegativeSafeInteger(line.sentence));
11115
+ }) && amendments.every((edge) => Object.keys(edge).length === 2 && isString(edge.earlier) && isString(edge.later));
11116
+ });
11117
+ }
11118
+ /**
10854
11119
  * Checks whether a value is finite and lies in the interval (0, 1].
10855
11120
  * @param value - The value to inspect
10856
11121
  * @returns True if the value is a valid ledger fraction; false otherwise
@@ -10901,6 +11166,8 @@ function isLedgerQuestion(value) {
10901
11166
  * guard is structural: it admits a conversation holding a stored `system` role
10902
11167
  * or a repeated id, which `requireConversationSnapshot` and the `Conversation` constructor then
10903
11168
  * refuse as the stored-data check a ledger's hydrate runs.
11169
+ * A present `window` must be nonempty and exactly shaped. This guard does not audit its references
11170
+ * or sentence ranges. Hydration discards the window when its digest disagrees or cannot be computed.
10904
11171
  *
10905
11172
  * @param value - The value to inspect, such as a parsed checkpoint
10906
11173
  * @returns True if the value has the shape of a ledger snapshot whose marked ids name messages of its own conversation; false otherwise
@@ -10914,8 +11181,8 @@ function isLedgerQuestion(value) {
10914
11181
  function isLedgerSnapshot(value) {
10915
11182
  return holds(() => {
10916
11183
  if (!isRecord(value)) return false;
10917
- const { conversation, requests, notes, failures, gauge } = value;
10918
- if (Object.keys(value).length !== (gauge === void 0 ? 4 : 5)) return false;
11184
+ const { conversation, requests, notes, failures, gauge, window } = value;
11185
+ if (Object.keys(value).length !== 4 + Number(gauge !== void 0) + Number(window !== void 0)) return false;
10919
11186
  if (!isConversationSnapshot(conversation)) return false;
10920
11187
  const isIds = arrayOf(isString);
10921
11188
  if (!isIds(requests) || !isIds(notes) || !isIds(failures)) return false;
@@ -10925,7 +11192,7 @@ function isLedgerSnapshot(value) {
10925
11192
  if (!isFiniteNumber(scale) || scale <= 0 || !isFiniteNumber(overhead) || overhead < 0) return false;
10926
11193
  }
10927
11194
  const roles = new Map(conversation.messages.map((message) => [message.id, message.role]));
10928
- return requests.every((id) => roles.get(id) === "user") && notes.every((id) => roles.get(id) === "user") && failures.every((id) => roles.get(id) === "tool");
11195
+ return requests.every((id) => roles.get(id) === "user") && notes.every((id) => roles.get(id) === "user") && failures.every((id) => roles.get(id) === "tool") && (window === void 0 || isLedgerWindowSnapshot(window));
10929
11196
  });
10930
11197
  }
10931
11198
  // src/core/ledgers/Ledger.ts
@@ -10955,6 +11222,8 @@ var Ledger = class {
10955
11222
  #scans = /* @__PURE__ */ new Set();
10956
11223
  #calibrations = /* @__PURE__ */ new Set();
10957
11224
  #gauge;
11225
+ #window = [];
11226
+ #evidence = collectLedgerEvidence([], /* @__PURE__ */ new Set(), []);
10958
11227
  /**
10959
11228
  * Composes the conversation, classifier, tools, and agent.
10960
11229
  * @param provider - The provider that serves the conversation
@@ -10988,7 +11257,8 @@ var Ledger = class {
10988
11257
  if (!isLedgerQuestion(options.questions)) throw new LedgerError("QUESTION", "questions must hold a choice category question whose criteria describe every category, a non-empty topic string, and noul amends and supersedes questions; pass the LEDGER_QUESTIONS constant for the measured wording");
10989
11258
  const snapshot = options.snapshot;
10990
11259
  if (snapshot !== void 0 && !isLedgerSnapshot(snapshot)) {
10991
- const faults = ledgerSnapshotContract.audit(snapshot);
11260
+ const candidate = options.snapshot;
11261
+ const faults = ledgerSnapshotContract.audit(candidate);
10992
11262
  throw new LedgerError("SNAPSHOT", `snapshot must be well formed and mark only messages of its conversation; pass what snapshot() returned${faults.length === 0 ? "" : `\n${describeFaults(faults, ledgerSnapshotContract.schema)}`}`, { context: { faults } });
10993
11263
  }
10994
11264
  this.#provider = provider;
@@ -11036,7 +11306,7 @@ var Ledger = class {
11036
11306
  }));
11037
11307
  tools.add(createTool({
11038
11308
  name: "recall",
11039
- description: `Recall what the full conversation record holds on a topic: an owner name, an id, or one of the topics ${renderTopicNames(options.topics)}. Returns source lines, newest first.`,
11309
+ description: `Find something said earlier that isn't in the messages you can see, by an owner name, an id, or one of the topics ${renderTopicNames(options.topics)}. Returns statements and lookup findings first, then earlier requests and replies labeled by origin; newest first within each group.`,
11040
11310
  contract: objectShape({ topic: stringShape({
11041
11311
  min: 1,
11042
11312
  description: "An owner name, an id, or a topic"
@@ -11120,8 +11390,8 @@ var Ledger = class {
11120
11390
  }
11121
11391
  }
11122
11392
  /**
11123
- * Serializes the conversation, the marked ids, and the gauge into a snapshot a later ledger hydrates from.
11124
- * @returns The snapshot, each id list in conversation order and `gauge` present after the ledger holds one
11393
+ * Serializes the conversation, marked ids, gauge, and completed exchange window for a later ledger.
11394
+ * @returns The snapshot, each id list in conversation order, with a gauge and window only when held
11125
11395
  * @throws {AgentError} Thrown when a request or calibration is active (code `'CONCURRENCY'`)
11126
11396
  */
11127
11397
  snapshot() {
@@ -11130,12 +11400,31 @@ var Ledger = class {
11130
11400
  const conversation = this.#conversation.snapshot();
11131
11401
  const ids = conversation.messages.map((message) => message.id);
11132
11402
  const gauge = this.gauge;
11403
+ const window = {
11404
+ exchanges: this.#window.map((entry) => ({
11405
+ request: entry.request.id,
11406
+ ...entry.request.content === this.#conversation.message(entry.request.id)?.content ? {} : { copy: entry.request.content },
11407
+ reply: entry.reply.id,
11408
+ lines: entry.lines.map(({ key, title, source, sentence }) => ({
11409
+ key,
11410
+ title,
11411
+ source,
11412
+ sentence
11413
+ }))
11414
+ })),
11415
+ amendments: [...this.#evidence.amendments.values()].map((edge) => ({ ...edge }))
11416
+ };
11417
+ const digest = window.exchanges.length === 0 ? void 0 : digestLedgerWindow(window.exchanges, conversation.messages);
11133
11418
  return {
11134
11419
  conversation,
11135
11420
  requests: ids.filter((id) => this.#requests.has(id)),
11136
11421
  notes: ids.filter((id) => this.#annotations.has(id)),
11137
11422
  failures: ids.filter((id) => this.#results.get(id)?.success === false),
11138
- ...gauge === void 0 ? {} : { gauge }
11423
+ ...gauge === void 0 ? {} : { gauge },
11424
+ ...window.exchanges.length === 0 || digest === void 0 ? {} : { window: {
11425
+ ...window,
11426
+ digest
11427
+ } }
11139
11428
  };
11140
11429
  }
11141
11430
  /**
@@ -11153,6 +11442,7 @@ var Ledger = class {
11153
11442
  if (this.#busy()) throw new AgentError("CONCURRENCY", "a ledger request is already active");
11154
11443
  const caller = createAbort({ ...signal === void 0 ? {} : { signal } }).signal;
11155
11444
  const request = new LedgerRequest(content, this.#options.recall?.limit);
11445
+ const scope = this.#agent.context.scope;
11156
11446
  this.#live.add(request);
11157
11447
  try {
11158
11448
  if (this.#gauge === void 0) await this.#measureGauge(caller);
@@ -11178,7 +11468,8 @@ var Ledger = class {
11178
11468
  content: LEDGER_NOTES.cue
11179
11469
  }).id);
11180
11470
  const previous = this.#agent.context.scope;
11181
- this.#agent.context.apply(createScope({
11471
+ const answer = createScope({
11472
+ ...previous,
11182
11473
  name: "answer",
11183
11474
  tools: [],
11184
11475
  select: async (conversation, message, runSignal) => {
@@ -11189,11 +11480,12 @@ var Ledger = class {
11189
11480
  messages: selection.messages.filter((one) => one.role !== "tool" && !hasCalls(one))
11190
11481
  };
11191
11482
  }
11192
- }));
11483
+ });
11484
+ this.#agent.context.apply(answer);
11193
11485
  try {
11194
11486
  passes.push(await this.#generatePass(request, caller, false));
11195
11487
  } finally {
11196
- this.#agent.context.apply(previous);
11488
+ if (this.#agent.context.scope === answer) this.#agent.context.apply(previous);
11197
11489
  }
11198
11490
  }
11199
11491
  const last = passes.at(-1) ?? first;
@@ -11212,7 +11504,9 @@ var Ledger = class {
11212
11504
  ...last.stop === void 0 ? {} : { stop: last.stop }
11213
11505
  };
11214
11506
  } finally {
11507
+ if (request.scope !== void 0 && this.#agent.context.scope === request.scope) this.#agent.context.apply(scope);
11215
11508
  this.#flush();
11509
+ this.#commitExchange(request);
11216
11510
  this.#live.delete(request);
11217
11511
  }
11218
11512
  }
@@ -11275,6 +11569,37 @@ var Ledger = class {
11275
11569
  for (const id of snapshot.requests) this.#requests.add(id);
11276
11570
  for (const id of snapshot.notes) this.#annotations.add(id);
11277
11571
  const messages = this.#conversation.messages();
11572
+ if (snapshot.window !== void 0 && digestLedgerWindow(snapshot.window.exchanges, messages) === snapshot.window.digest) {
11573
+ const window = snapshot.window.exchanges.map((entry) => {
11574
+ const request = this.#conversation.message(entry.request);
11575
+ const reply = this.#conversation.message(entry.reply);
11576
+ if (request === void 0 || reply === void 0) throw new LedgerError("SNAPSHOT", "window pair must belong to its conversation");
11577
+ const lines = entry.lines.map((line) => {
11578
+ const source = this.#conversation.message(line.source);
11579
+ if (source === void 0) throw new LedgerError("SNAPSHOT", "window source must belong to its conversation");
11580
+ return {
11581
+ ...line,
11582
+ text: splitSentences(source.content)[line.sentence] ?? "",
11583
+ topics: [],
11584
+ role: source.role
11585
+ };
11586
+ });
11587
+ return {
11588
+ request: {
11589
+ ...request,
11590
+ content: entry.copy ?? request.content
11591
+ },
11592
+ reply,
11593
+ lines
11594
+ };
11595
+ });
11596
+ this.#window = window;
11597
+ this.#evidence = collectLedgerEvidence(messages, new Set(this.#window.flatMap((entry) => [
11598
+ entry.request.id,
11599
+ entry.reply.id,
11600
+ ...entry.lines.map((line) => line.source)
11601
+ ])), snapshot.window.amendments);
11602
+ }
11278
11603
  const groups = collectToolGroups(messages);
11279
11604
  for (const message of messages) {
11280
11605
  if (!snapshot.failures.includes(message.id)) continue;
@@ -11405,20 +11730,26 @@ var Ledger = class {
11405
11730
  const { attempts, failure, ...filed } = classified;
11406
11731
  const planned = attempt(() => {
11407
11732
  if (filed.fault !== void 0) throw filed.fault;
11733
+ const { draft, ...plan } = this.#plan(selected, this.#rescan());
11408
11734
  return {
11409
- ...this.#plan(selected, this.#rescan()),
11410
- ...filed,
11411
- ...failure === void 0 ? {} : { fault: failure }
11735
+ draft,
11736
+ selection: {
11737
+ ...plan,
11738
+ ...filed,
11739
+ ...failure === void 0 ? {} : { fault: failure }
11740
+ }
11412
11741
  };
11413
11742
  });
11414
- request.file(attempts, planned.success ? planned.value : void 0);
11743
+ request.file(attempts, planned.success ? planned.value.selection : void 0, planned.success ? planned.value.draft : void 0);
11415
11744
  if (!planned.success) return this.#refuse(planned.error, filed, this.#conversation);
11745
+ const selection = planned.value.selection;
11416
11746
  return this.#annotations.has(message.id) ? {
11417
- ...planned.value,
11418
- messages: [...planned.value.messages, ...this.#collectAfter(selected)]
11419
- } : planned.value;
11747
+ ...selection,
11748
+ messages: [...selection.messages, ...this.#collectAfter(selected)]
11749
+ } : selection;
11420
11750
  }
11421
11751
  #refuse(error, filed, conversation) {
11752
+ if (conversation === this.#conversation && !(isLedgerError(error) && error.code === "REQUEST")) this.#current()?.file([]);
11422
11753
  return {
11423
11754
  ...filed,
11424
11755
  messages: conversation.view(),
@@ -11445,7 +11776,11 @@ var Ledger = class {
11445
11776
  topics: [...near]
11446
11777
  });
11447
11778
  const total = Math.max(0, (this.#options.capacity - this.#predict) * this.#share.prompt - (this.#gauge?.overhead ?? 0)) / (1 + LEDGER_SCALE_DRIFT);
11448
- const tail = this.#selectTail(request, total * this.#share.tail, input, scan);
11779
+ const built = this.#agent.context.build({
11780
+ messages: [request],
11781
+ judgments: []
11782
+ });
11783
+ const tail = this.#selectTail(request, total, input, scan);
11449
11784
  const tailIds = new Set(tail.map((message) => message.id));
11450
11785
  const scoped = records.some((record) => record.key !== LEDGER_RULES_KEY);
11451
11786
  const held = /* @__PURE__ */ new Set([...projection.records.filter((record) => scoped || record.key === "rules").flatMap((record) => record.members), ...records.length > 0 ? projection.records.flatMap((record) => record.members.filter((id) => this.#conversation.message(id)?.role === "user" && this.#classifier.category(id) === "rule" && this.#classifier.decisive(id))) : []]);
@@ -11493,25 +11828,121 @@ var Ledger = class {
11493
11828
  source: unit.source,
11494
11829
  record: this.#buildUnitRecord(unit.source, unit.category, input, projection, held)
11495
11830
  }));
11496
- const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), request, tail, total, projection.amendments, scan);
11497
- const shown = /* @__PURE__ */ new Set([...trimmed.included, ...records.flatMap((record) => record.members.filter((source) => {
11498
- const full = record.lines.filter((line) => line.source === source);
11499
- const visible = trimmed.records.find((one) => one.key === record.key)?.lines.filter((line) => line.source === source) ?? [];
11500
- return full.length > 0 && full.length === visible.length;
11501
- }))]);
11502
- return { messages: [...tail.slice(0, -1).map((message) => message.role === "tool" ? this.#renderTailStub(message, scan, shown) : message), buildRequestMessage(request, trimmed.rendered)] };
11503
- }
11504
- #trim(steps, records, mapped, included, request, tail, total, amendments, scan) {
11505
- const built = this.#agent.context.build({
11506
- messages: [request],
11507
- judgments: []
11831
+ const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), built, tail, total, projection.amendments, scan);
11832
+ const replies = collectLedgerReplies(scan.messages, this.#requests, this.#annotations);
11833
+ const sources = new Set(this.#window.flatMap((entry) => [
11834
+ entry.request.id,
11835
+ entry.reply.id,
11836
+ ...entry.lines.map((line) => line.source)
11837
+ ]));
11838
+ const evidence = collectLedgerEvidence(scan.messages, sources, projection.amendments);
11839
+ const prefix = this.#window.flatMap((entry) => entry.lines);
11840
+ const prior = buildLedgerRenderContext(scan.messages, prefix, projection.amendments);
11841
+ const combined = buildLedgerRenderContext(scan.messages, [...prefix, ...trimmed.rendered.lines], projection.amendments);
11842
+ const stale = evidence.messages.size !== this.#evidence.messages.size || [...evidence.messages].some((receipt) => !this.#evidence.messages.has(receipt)) || evidence.amendments.size !== this.#evidence.amendments.size || [...evidence.amendments.keys()].some((receipt) => !this.#evidence.amendments.has(receipt)) || this.#window.some((entry) => replies.get(entry.request.id)?.id !== entry.reply.id || entry.lines.some((line) => !live.has(line.source))) || projection.amendments.some((edge) => prior.first.has(edge.earlier) && prior.complete.has(edge.later) !== combined.complete.has(edge.later) || prior.first.has(edge.later) && combined.complete.has(edge.later) && !prior.first.has(edge.earlier) && combined.first.has(edge.earlier));
11843
+ const last = stale ? this.#window.at(-1) : void 0;
11844
+ const retained = last === void 0 || replies.get(last.request.id)?.id !== last.reply.id ? void 0 : this.#conversation.message(last.request.id);
11845
+ if (stale) this.#window = [];
11846
+ const [previous, reply] = this.#window.length === 0 ? this.#selectExchange(request, input) : [];
11847
+ const window = this.#window.length > 0 ? this.#window : previous !== void 0 && reply !== void 0 ? [{
11848
+ request: previous,
11849
+ reply,
11850
+ lines: []
11851
+ }] : retained !== void 0 && last !== void 0 ? [{
11852
+ request: retained,
11853
+ reply: last.reply,
11854
+ lines: []
11855
+ }] : [];
11856
+ if (this.#window.length === 0) {
11857
+ const derived = collectLedgerEvidence(scan.messages, new Set(window.flatMap((entry) => [entry.request.id, entry.reply.id])), projection.amendments);
11858
+ this.#window = window;
11859
+ this.#evidence = derived;
11860
+ }
11861
+ const carried = window.flatMap((entry) => entry.lines);
11862
+ const delta = this.#render(trimmed.records, mapped, trimmed.included, projection.amendments, scan, new Set(carried.map(buildLedgerLineKey)), carried);
11863
+ const newest = window.at(-1);
11864
+ const plain = newest === void 0 ? void 0 : this.#conversation.message(newest.request.id);
11865
+ const fallback = newest === void 0 || plain === void 0 ? [] : [{
11866
+ request: plain,
11867
+ reply: newest.reply,
11868
+ lines: []
11869
+ }];
11870
+ const empty = {
11871
+ window: [],
11872
+ rendered: trimmed.rendered
11873
+ };
11874
+ const rungs = [
11875
+ {
11876
+ window,
11877
+ rendered: delta
11878
+ },
11879
+ {
11880
+ window: fallback,
11881
+ rendered: trimmed.rendered
11882
+ },
11883
+ empty
11884
+ ];
11885
+ const probes = rungs.map((rung) => [...built.slice(0, -1), ...stripThinking([
11886
+ ...tail.slice(0, -1),
11887
+ ...rung.window.flatMap((entry) => [entry.request, entry.reply]),
11888
+ buildRequestMessage(built.at(-1) ?? request, rung.rendered.text)
11889
+ ], this.#replay)]);
11890
+ const names = this.#agent.context.scope?.tools;
11891
+ const definitions = this.#agent.context.tools.definitions();
11892
+ const offered = rungs.map((rung) => hasHiddenRecall(input, request.id, this.#requests, this.#annotations, [...tail.slice(0, -1), ...rung.window.flatMap((entry) => [entry.request, entry.reply])], [...rung.window.flatMap((entry) => entry.lines), ...rung.rendered.lines]));
11893
+ const longest = this.#findLongest();
11894
+ const closed = probes.map((messages, at) => {
11895
+ const tools = definitions.filter((tool) => (names === void 0 || names.includes(tool.name)) && (tool.name !== "recall" || offered[at]));
11896
+ const calls = [{
11897
+ estimate: estimateMessages(messages),
11898
+ tools: tools.length,
11899
+ spared: this.#spared(tools)
11900
+ }];
11901
+ return offered[at] === true && this.#gauge !== void 0 && this.#gauge.remainder(calls) - this.#predict < 2 * this.#gauge.reserve(calls, longest);
11508
11902
  });
11903
+ const prices = probes.map((messages) => this.#price(messages));
11904
+ const admitted = rungs.find((_rung, at) => (prices[at] ?? Infinity) <= total && (closed[2] === true || closed[at] === false)) ?? empty;
11905
+ if (offered[rungs.indexOf(admitted)] === false && (names === void 0 || names.includes("recall"))) {
11906
+ const tools = definitions.filter((tool) => tool.name !== "recall").map((tool) => tool.name);
11907
+ const narrowed = this.#agent.context.scope?.narrow({ tools }) ?? createScope({
11908
+ name: "ledger",
11909
+ tools
11910
+ });
11911
+ this.#current()?.apply(narrowed);
11912
+ this.#agent.context.apply(narrowed);
11913
+ }
11914
+ const copy = buildRequestMessage(request, admitted.rendered.text);
11915
+ const kept = admitted.window.flatMap((entry) => entry.lines);
11916
+ const origins = /* @__PURE__ */ new Set([
11917
+ request.id,
11918
+ ...admitted.window.flatMap((entry) => [entry.request.id, entry.reply.id]),
11919
+ ...kept.map((line) => line.source),
11920
+ ...admitted.rendered.lines.map((line) => line.source)
11921
+ ]);
11922
+ const draft = {
11923
+ copy,
11924
+ lines: admitted.rendered.lines,
11925
+ evidence: collectLedgerEvidence(scan.messages, origins, projection.amendments),
11926
+ window: admitted.window
11927
+ };
11928
+ const shown = buildLedgerRenderContext(scan.messages, [...kept, ...admitted.rendered.lines], []).complete;
11929
+ return {
11930
+ draft,
11931
+ messages: [
11932
+ ...tail.slice(0, -1).map((message) => message.role === "tool" ? this.#renderTailStub(message, scan, shown) : message),
11933
+ ...admitted.window.flatMap((entry) => [entry.request, entry.reply]),
11934
+ copy
11935
+ ]
11936
+ };
11937
+ }
11938
+ #trim(steps, records, mapped, included, built, tail, total, amendments, scan) {
11509
11939
  const head = built.slice(0, -1);
11510
- const priced = built.at(-1) ?? request;
11940
+ const priced = built.at(-1);
11941
+ if (priced === void 0) throw new Error("a built plan holds its request");
11511
11942
  const found = findLedgerCut(0, steps.length, (count) => {
11512
11943
  const cut = buildLedgerCut(steps.slice(0, count), records, included);
11513
11944
  const rendered = this.#render(cut.records, mapped, cut.included, amendments, scan);
11514
- const copy = buildRequestMessage(priced, rendered);
11945
+ const copy = buildRequestMessage(priced, rendered.text);
11515
11946
  return this.#price([...head, ...stripThinking([...tail.slice(0, -1), copy], this.#replay)]) <= total ? {
11516
11947
  ...cut,
11517
11948
  rendered
@@ -11536,36 +11967,48 @@ var Ledger = class {
11536
11967
  const live = collectProjectionIds(projection);
11537
11968
  return scanAmendments(input.classification.amendments, source, (id) => id === source || !held.has(id) && live.has(id)).flatMap((id) => this.#projectLines(input, id));
11538
11969
  }
11539
- #render(records, mapped, included, amendments, scan) {
11540
- const entries = mapped.filter((unit) => included.has(unit.source)).flatMap(({ record: unit }) => [...Map.groupBy(unit.lines, (line) => line.source)].map(([source, lines]) => ({
11970
+ #render(records, mapped, included, amendments, scan, held = /* @__PURE__ */ new Set(), prefix = []) {
11971
+ const population = records.map((record) => ({
11972
+ ...record,
11973
+ lines: collectLedgerLines(record, held)
11974
+ }));
11975
+ const entries = mapped.filter((unit) => included.has(unit.source)).flatMap(({ record: unit }) => [...Map.groupBy(collectLedgerLines(unit, /* @__PURE__ */ new Set()), (line) => line.source)].map(([source, lines]) => ({
11541
11976
  unit,
11542
11977
  source,
11543
11978
  lines
11544
11979
  })));
11545
11980
  const first = new Map(entries.toReversed().map((entry) => [entry.source, entry]));
11546
- const unique = entries.filter((entry) => first.get(entry.source) === entry);
11547
- const record = records.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
11548
- const ownerRecords = records.filter((candidate) => candidate.key !== "rules" && candidate.lines.length > 0);
11549
- const context = buildLedgerRenderContext(this.#conversation.messages(), [
11981
+ const unique = entries.filter((entry) => first.get(entry.source) === entry).map((entry) => ({
11982
+ ...entry,
11983
+ lines: entry.lines.filter((line) => !prefix.some((prior) => prior.source === line.source && prior.sentence === line.sentence))
11984
+ })).filter((entry) => entry.lines.length > 0);
11985
+ const record = population.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
11986
+ const ownerRecords = population.filter((candidate) => candidate.key !== "rules" && candidate.lines.length > 0);
11987
+ const lines = [
11550
11988
  ...ownerRecords.flatMap((candidate) => candidate.lines),
11551
11989
  ...unique.filter((entry) => entry.unit.key !== LEDGER_RULES_KEY).flatMap((entry) => entry.lines),
11552
11990
  ...record?.lines ?? [],
11553
11991
  ...unique.filter((entry) => entry.unit.key === LEDGER_RULES_KEY).flatMap((entry) => entry.lines)
11554
- ], amendments);
11992
+ ];
11993
+ const context = buildLedgerRenderContext(scan.messages, [...prefix, ...lines], amendments);
11555
11994
  const owners = ownerRecords.map((owner) => renderLedgerPinned(owner, context)).join("\n\n");
11556
- const rendered = unique.map(({ unit, source, lines }) => {
11995
+ const rendered = unique.map(({ unit, source, lines: retained }) => {
11557
11996
  const sentences = splitSentences(this.#conversation.message(source)?.content ?? "");
11558
11997
  return {
11559
11998
  rules: unit.key === LEDGER_RULES_KEY,
11560
- texts: unit.key === "rules" && source === unit.members[0] ? lines.map((line) => this.#renderSource(source, sentences, [line], context, scan)) : [this.#renderSource(source, sentences, lines, context, scan)]
11999
+ texts: unit.key === "rules" && source === unit.members[0] ? retained.map((line) => this.#renderSource(source, sentences, [line], context, scan)) : [this.#renderSource(source, sentences, retained, context, scan)]
11561
12000
  };
11562
12001
  });
11563
12002
  const pinned = rendered.filter((one) => !one.rules).flatMap((one) => one.texts);
11564
12003
  const rules = rendered.filter((one) => one.rules).flatMap((one) => one.texts);
11565
12004
  const body = [owners, pinned.join("\n")].filter((text) => text !== "").join("\n\n");
11566
- return [body === "" ? "" : `## Records\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record, context), ...rules].join("\n")].filter((text) => text !== "").join("\n\n");
12005
+ return {
12006
+ text: [body === "" ? "" : `## Records\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record, context), ...rules].join("\n")].filter((part) => part !== "").join("\n\n"),
12007
+ lines
12008
+ };
11567
12009
  }
11568
- #selectTail(request, cap, input, scan) {
12010
+ #selectTail(request, total, input, scan) {
12011
+ const cap = total * this.#share.tail;
11569
12012
  const first = input.messages.findIndex((message) => this.#requests.has(message.id));
11570
12013
  const seed = input.messages.slice(0, first < 0 ? input.messages.findIndex((message) => message.id === request.id) : first);
11571
12014
  const groups = collectToolGroups(seed).flatMap((group) => {
@@ -11596,6 +12039,29 @@ var Ledger = class {
11596
12039
  const stop = exchanges.findIndex((_exchange, index) => this.#price(stripThinking([...exchanges.slice(0, index + 1).toReversed().flat(), request], this.#replay)) > cap);
11597
12040
  return [...exchanges.slice(0, stop === -1 ? exchanges.length : stop).toReversed().flat(), request];
11598
12041
  }
12042
+ #selectExchange(request, input) {
12043
+ const before = input.messages.slice(0, input.messages.findIndex((message) => message.id === request.id));
12044
+ const previous = before.findLast((message) => this.#requests.has(message.id));
12045
+ const reply = previous === void 0 ? void 0 : collectLedgerReplies(before, this.#requests, this.#annotations).get(previous.id);
12046
+ return previous !== void 0 && reply !== void 0 ? [previous, reply] : [];
12047
+ }
12048
+ #commitExchange(request) {
12049
+ const draft = request.sent;
12050
+ const message = request.message;
12051
+ if (message === void 0) return;
12052
+ const reply = collectLedgerReplies(this.#conversation.messages(), this.#requests, this.#annotations).get(message.id);
12053
+ if (reply === void 0) return;
12054
+ this.#window = [...draft?.window ?? this.#window, {
12055
+ request: draft?.copy ?? message,
12056
+ reply,
12057
+ lines: draft?.lines ?? []
12058
+ }];
12059
+ const evidence = draft?.evidence ?? this.#evidence;
12060
+ this.#evidence = {
12061
+ messages: /* @__PURE__ */ new Set([...evidence.messages, ...collectLedgerEvidence([message, reply], /* @__PURE__ */ new Set([message.id, reply.id]), []).messages]),
12062
+ amendments: evidence.amendments
12063
+ };
12064
+ }
11599
12065
  #renderTailStub(message, scan, shown) {
11600
12066
  const group = scan.group(message.id);
11601
12067
  const call = group === void 0 ? void 0 : findLedgerCall(group, message);
@@ -11604,7 +12070,7 @@ var Ledger = class {
11604
12070
  const visible = renderStub(call?.name ?? "tool", call?.arguments ?? {}, "shown");
11605
12071
  return {
11606
12072
  ...message,
11607
- content: renderStub(call?.name ?? "tool", call?.arguments ?? {}, this.#results.get(message.id)?.success === false ? "failed" : finding?.result === void 0 ? "empty" : shown === void 0 ? hidden.length > visible.length ? "hidden" : "shown" : shown.has(message.id) ? "shown" : "hidden")
12073
+ content: renderStub(call?.name ?? "tool", call?.arguments ?? {}, this.#results.get(message.id)?.success === false ? "failed" : finding?.result === void 0 ? "empty" : shown === void 0 ? hidden.length > visible.length ? "hidden" : "shown" : scan.findings.some((other) => shown.has(other.id) && matchesLookup(finding, other)) ? "shown" : "hidden")
11608
12074
  };
11609
12075
  }
11610
12076
  #observeTurn() {
@@ -11615,11 +12081,19 @@ var Ledger = class {
11615
12081
  const additions = this.#conversation.messages().slice(boundary);
11616
12082
  const messages = this.#agent.context.build(request.selection);
11617
12083
  const names = this.#agent.context.scope?.tools;
12084
+ const tools = this.#agent.context.tools.definitions().filter((tool) => names === void 0 || names.includes(tool.name));
11618
12085
  request.observe({
11619
12086
  estimate: estimateMessages(stripThinking([...messages, ...additions], this.#replay)),
11620
- tools: this.#agent.context.tools.definitions().filter((tool) => names === void 0 || names.includes(tool.name)).length
12087
+ tools: tools.length,
12088
+ spared: this.#spared(tools)
11621
12089
  }, this.#conversation.messages().length);
11622
12090
  }
12091
+ #spared(tools) {
12092
+ const overhead = this.#gauge?.overhead ?? 0;
12093
+ if (tools.length === 0) return overhead;
12094
+ const missing = this.#agent.context.tools.definitions().filter((tool) => !tools.some((one) => one.name === tool.name));
12095
+ return missing.length === 0 ? 0 : Math.min(overhead, estimateTokens(JSON.stringify(missing)) * (this.#gauge?.scale ?? 1));
12096
+ }
11623
12097
  #findLongest() {
11624
12098
  return this.#conversation.messages().filter((message) => message.role === "assistant").reduce((longest, message) => message.content.length > longest.length ? message.content : longest, "");
11625
12099
  }
@@ -11672,11 +12146,12 @@ var Ledger = class {
11672
12146
  const source = listable.get(id);
11673
12147
  if (source === void 0) return [];
11674
12148
  const lookup = scan.finding(id);
11675
- const text = lookup === void 0 ? source.content : `${renderLookupCall(lookup.name, lookup.arguments)}: ${source.content}`;
12149
+ const content = source.content.replace(/(^|[\n\v\f\r\u0085\u2028\u2029])(?=Earlier (?:request|reply):)/g, "$1 ");
12150
+ const text = lookup === void 0 ? content : `${renderLookupCall(lookup.name, lookup.arguments)}: ${content}`;
11676
12151
  return [{
11677
12152
  id,
11678
12153
  text,
11679
- stored: lookup === void 0 ? [] : [[splitResultLines(text)[0] ?? "", splitResultLines(source.content)[0] ?? ""]]
12154
+ stored: lookup === void 0 ? [] : [[splitResultLines(text)[0] ?? "", splitResultLines(content)[0] ?? ""]]
11680
12155
  }];
11681
12156
  });
11682
12157
  return {
@@ -11689,7 +12164,14 @@ var Ledger = class {
11689
12164
  listed: [],
11690
12165
  recalled: /* @__PURE__ */ new Map()
11691
12166
  });
11692
- const result = gathered.listed.length === 0 ? `nothing on "${topic}"; recall ${guidance}` : cutListing(gathered.listed, room);
12167
+ const earlier = input.messages.slice(0, Math.max(0, start)).reverse().flatMap((message) => {
12168
+ if (gathered.done.has(message.id) || this.#annotations.has(message.id)) return [];
12169
+ const label = this.#requests.has(message.id) ? LEDGER_RECALL_LABELS.request : message.role === "assistant" && !hasCalls(message) && message.content.trim() !== "" ? LEDGER_RECALL_LABELS.reply : void 0;
12170
+ if (label === void 0 || !searches.some((search) => search.words.length > 0 && search.words.every((word) => message.content.toLowerCase().includes(word)))) return [];
12171
+ return [`${label} ${message.content.replace(/[\n\v\f\r\u0085\u2028\u2029]+/g, "\n ")}`];
12172
+ });
12173
+ const listed = [...gathered.listed, ...earlier];
12174
+ const result = listed.length === 0 ? `nothing earlier on "${topic}"; answer from the messages you can see` : cutListing(listed, room, earlier.length > 0 ? "more" : "older");
11693
12175
  request?.list(result, gathered.recalled);
11694
12176
  return result;
11695
12177
  } finally {
@@ -11702,7 +12184,7 @@ var Ledger = class {
11702
12184
  const result = this.#results.get(message.id);
11703
12185
  if (message.role !== "tool" || result?.success !== true) return [];
11704
12186
  const recalled = result.name === "recall";
11705
- if (recalled && /^nothing on /.test(message.content)) return [];
12187
+ if (recalled && /^nothing earlier on /.test(message.content)) return [];
11706
12188
  const stored = recalled ? request.lines(message.content) : void 0;
11707
12189
  return splitResultLines(message.content).filter((line) => !recalled || !matchesCutLine(line)).map((line) => stored?.get(line) ?? line);
11708
12190
  }))];
@@ -11725,6 +12207,6 @@ var Ledger = class {
11725
12207
  function createLedger(provider, options) {
11726
12208
  return new Ledger(provider, options);
11727
12209
  }
11728
- export { AUTHORITY_NOTES, Agent, AgentContext, AgentError, AgentFanout, AgentJobError, AgentJudge, AgentProvider, AgentRegistry, Approver, Authority, CONVERSATION_RECAP_PREFIX, CONVERSATION_ROLES, Channel, Classifier, ContextError, Conversation, ConversationError, ConversationManager, DECISIVE_CATEGORIES, DEFAULT_AGENT_LIMIT, DEFAULT_CONVERSATION_KEEP, DEFAULT_LEDGER_LIMIT, DEFAULT_LEDGER_SHARE, DEFAULT_PROVIDER_TIMEOUT, DEFAULT_RECALL_LIMIT, DEFAULT_RELAY_LIMIT, DETERMINISTIC_JUDGE_ERROR, DatabaseConversationStore, DatabaseMemoStore, Gauge, IMAGE_TOKEN_ESTIMATE, INVALID_RELAY_STATUS, Instruction, InstructionManager, JudgeAbortError, JudgeError, JudgmentManager, LEDGER_CATEGORIES, LEDGER_NOTES, LEDGER_OWNER_PREFIX, LEDGER_QUESTIONS, LEDGER_RULES_KEY, LEDGER_SCALE_DRIFT, LEDGER_SLICE, LEDGER_WORD, Ledger, LedgerError, LedgerRequest, MAX_ERROR_BODY_LENGTH, MEMO_SECTION_HEADER, MESSAGE_ROLES, MESSAGE_TOKEN_OVERHEAD, MemoManager, MemoryConversationStore, MemoryMemoStore, OVERSIZED_RELAY_STATUS, PLACED_CATEGORIES, ProviderAbortError, ProviderError, QUIET_CATEGORIES, REFUSED_RELAY_CONTENT_TYPE, REFUSED_RELAY_STATUS, RELAY_CONTENT_TYPE, RELAY_PROVIDER_MESSAGE, RelayProvider, RelayStream, SCOPE_NOTE, SKILL_SECTION_HEADER, SYSTEM_ONE_PATH, Scope, ScopeManager, SkillManager, SystemOneJudge, THINK_CLOSE, THINK_OPEN, ThinkSplitter, UNAUTHORIZED_RELAY_STATUS, UPSTREAM_RELAY_STATUS, WORKSPACE_SECTION_HEADER, agentAnswerContract, agentAnswerShape, agentChunkToFrame, agentFrameContract, agentFrameShape, agentJobContract, agentJobShape, agentPromptContract, agentPromptShape, agentResultToFrame, agentResultToJSON, agentStreamToFrames, armReaderAbort, assembleResult, attachImages, attachUserImages, buildJudgeResult, buildJudgments, buildLedgerCut, buildLedgerIndex, buildLedgerRenderContext, buildLines, buildProviderHeaders, buildProviderResult, buildRecallMessage, buildRecapMessage, buildRecords, buildRelayRequest, buildRequestMessage, buildSummaryMessage, chargeUsage, collectAmendments, collectExchanges, collectImageData, collectLive, collectNames, collectProjectionIds, collectRegistry, collectToolGroups, computeThinking, conversationSnapshotContract, conversationSnapshotShape, copyJSON, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createApprover, createAuthority, createChannel, createConversation, createConversationManager, createDatabaseConversationStore, createDatabaseMemoStore, createInstruction, createInstructionManager, createLedger, createMemoManager, createMemoryConversationStore, createMemoryMemoStore, createRelay, createRelayProvider, createScope, createScopeManager, createSkillManager, createSystemOneJudge, createThinkSplitter, cutListing, denyCall, describeQuestionRefusal, describeRelayRefusal, describeSnapshotRefusal, estimateMessages, estimateRequest, estimateTokens, extractLiterals, extractQueueOptions, extractSystemOneAnswer, extractSystemOneUsage, extractWords, filterAllowList, findLedgerCall, findLedgerCut, fitSlope, freezeJSON, handleAgentQueueJob, hasCalls, identifyLookup, inferStop, intersectKeys, isAgentError, isAgentJobError, isAuthorityDecision, isAuthorityVerdict, isContextError, isConversation, isConversationError, isConversationSnapshot, isFraction, isJudgeAbortError, isJudgeAnswer, isJudgeEntry, isJudgeError, isJudgeQuestion, isJudgment, isLedgerError, isLedgerQuestion, isLedgerSnapshot, isMemo, isMemoOrigin, isMemoSnapshot, isMessage, isMessageInput, isNonNegativeSafeInteger, isPositiveSafeInteger, isProviderAbortError, isProviderError, isProviderResult, isSection, isSystemOneAnswer, isSystemOneResponse, joinThinking, judgeAnswerContract, judgeAnswerShape, judgeEntryShape, judgeQuestionContract, judgeQuestionShape, judgmentContract, judgmentShape, ledgerSnapshotContract, ledgerSnapshotShape, linkOwners, matchEntities, matchesCutLine, matchesJSON, matchesJudgment, measureAnswer, measureMessage, measureRequest, memoContract, memoShape, memoSnapshotContract, memoSnapshotShape, messageContract, messageInputContract, messageInputShape, messageShape, normalizeArgument, normalizeWord, placeMember, providerRequestContract, providerRequestShape, providerResultContract, providerResultShape, questionToSystemOne, raceSignal, rankLedgerCut, readBodyText, readChunks, readFailure, readJudgeOutcome, readProviderDelta, relayFrameContract, relayFrameShape, releaseReader, removeEntries, renderArguments, renderCauseChain, renderFencedFile, renderIndexEntry, renderJSON, renderLedgerAnnotation, renderLedgerPinned, renderLedgerRecord, renderLookupCall, renderSection, renderStub, renderToolValue, renderTopicNames, requestToRelay, requireAnswer, requireBudget, requireConversation, requireConversationSnapshot, requireCumulative, requireEntry, requireFallback, requireJudgeResult, requireJudgment, requireKeep, requireLimit, requireMessageInput, requireProviderResult, requireRole, requireRules, requireSectionsCap, requireSummary, resolveDecision, resolvePredict, sanitizeToken, sanitizeUsage, scanAmendments, scanJudgmentTies, scanProbability, sectionContract, sectionShape, selectRecords, settleAgentJob, settleToolResult, splitResultLines, splitSentences, splitTopic, splitWords, stripThinking, sumUsage, tokenUsageShape, tokenUsageToJSON, toolCallShape };
12210
+ export { AUTHORITY_NOTES, Agent, AgentContext, AgentError, AgentFanout, AgentJobError, AgentJudge, AgentProvider, AgentRegistry, Approver, Authority, CONVERSATION_RECAP_PREFIX, CONVERSATION_ROLES, Channel, Classifier, ContextError, Conversation, ConversationError, ConversationManager, DECISIVE_CATEGORIES, DEFAULT_AGENT_LIMIT, DEFAULT_CONVERSATION_KEEP, DEFAULT_LEDGER_LIMIT, DEFAULT_LEDGER_SHARE, DEFAULT_PROVIDER_TIMEOUT, DEFAULT_RECALL_LIMIT, DEFAULT_RELAY_LIMIT, DETERMINISTIC_JUDGE_ERROR, DatabaseConversationStore, DatabaseMemoStore, Gauge, IMAGE_TOKEN_ESTIMATE, INVALID_RELAY_STATUS, Instruction, InstructionManager, JudgeAbortError, JudgeError, JudgmentManager, LEDGER_CATEGORIES, LEDGER_NOTES, LEDGER_OWNER_PREFIX, LEDGER_QUESTIONS, LEDGER_RECALL_LABELS, LEDGER_RULES_KEY, LEDGER_SCALE_DRIFT, LEDGER_SLICE, LEDGER_WORD, Ledger, LedgerError, LedgerRequest, MAX_ERROR_BODY_LENGTH, MEMO_SECTION_HEADER, MESSAGE_ROLES, MESSAGE_TOKEN_OVERHEAD, MemoManager, MemoryConversationStore, MemoryMemoStore, OVERSIZED_RELAY_STATUS, PLACED_CATEGORIES, ProviderAbortError, ProviderError, QUIET_CATEGORIES, REFUSED_RELAY_CONTENT_TYPE, REFUSED_RELAY_STATUS, RELAY_CONTENT_TYPE, RELAY_PROVIDER_MESSAGE, RelayProvider, RelayStream, SCOPE_NOTE, SKILL_SECTION_HEADER, SYSTEM_ONE_PATH, Scope, ScopeManager, SkillManager, SystemOneJudge, THINK_CLOSE, THINK_OPEN, ThinkSplitter, UNAUTHORIZED_RELAY_STATUS, UPSTREAM_RELAY_STATUS, WORKSPACE_SECTION_HEADER, agentAnswerContract, agentAnswerShape, agentChunkToFrame, agentFrameContract, agentFrameShape, agentJobContract, agentJobShape, agentPromptContract, agentPromptShape, agentResultToFrame, agentResultToJSON, agentStreamToFrames, armReaderAbort, assembleResult, attachImages, attachUserImages, buildJudgeResult, buildJudgments, buildLedgerCut, buildLedgerIndex, buildLedgerLineKey, buildLedgerRenderContext, buildLines, buildProviderHeaders, buildProviderResult, buildRecallMessage, buildRecapMessage, buildRecords, buildRelayRequest, buildRequestMessage, buildSummaryMessage, chargeUsage, collectAmendments, collectExchanges, collectImageData, collectLedgerEvidence, collectLedgerLines, collectLedgerReplies, collectLive, collectNames, collectProjectionIds, collectRecallMessages, collectRegistry, collectToolGroups, computeThinking, conversationSnapshotContract, conversationSnapshotShape, copyJSON, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createApprover, createAuthority, createChannel, createConversation, createConversationManager, createDatabaseConversationStore, createDatabaseMemoStore, createInstruction, createInstructionManager, createLedger, createMemoManager, createMemoryConversationStore, createMemoryMemoStore, createRelay, createRelayProvider, createScope, createScopeManager, createSkillManager, createSystemOneJudge, createThinkSplitter, cutListing, denyCall, describeQuestionRefusal, describeRelayRefusal, describeSnapshotRefusal, digestLedgerWindow, estimateMessages, estimateRequest, estimateTokens, extractLiterals, extractQueueOptions, extractSystemOneAnswer, extractSystemOneUsage, extractWords, filterAllowList, findLedgerCall, findLedgerCut, fitSlope, freezeJSON, handleAgentQueueJob, hasCalls, hasHiddenRecall, identifyLookup, inferStop, intersectKeys, isAgentError, isAgentJobError, isAuthorityDecision, isAuthorityVerdict, isContextError, isConversation, isConversationError, isConversationSnapshot, isFraction, isJudgeAbortError, isJudgeAnswer, isJudgeEntry, isJudgeError, isJudgeQuestion, isJudgment, isLedgerError, isLedgerQuestion, isLedgerSnapshot, isLedgerWindowSnapshot, isMemo, isMemoOrigin, isMemoSnapshot, isMessage, isMessageInput, isNonNegativeSafeInteger, isPositiveSafeInteger, isProviderAbortError, isProviderError, isProviderResult, isSection, isSystemOneAnswer, isSystemOneResponse, joinThinking, judgeAnswerContract, judgeAnswerShape, judgeEntryShape, judgeQuestionContract, judgeQuestionShape, judgmentContract, judgmentShape, ledgerSnapshotContract, ledgerSnapshotShape, ledgerWindowContract, ledgerWindowShape, linkOwners, matchEntities, matchesCutLine, matchesJSON, matchesJudgment, matchesLookup, measureAnswer, measureMessage, measureRequest, memoContract, memoShape, memoSnapshotContract, memoSnapshotShape, messageContract, messageInputContract, messageInputShape, messageShape, normalizeArgument, normalizeWord, placeMember, providerRequestContract, providerRequestShape, providerResultContract, providerResultShape, questionToSystemOne, raceSignal, rankLedgerCut, readBodyText, readChunks, readFailure, readJudgeOutcome, readProviderDelta, relayFrameContract, relayFrameShape, releaseReader, removeEntries, renderArguments, renderCauseChain, renderFencedFile, renderIndexEntry, renderJSON, renderLedgerAnnotation, renderLedgerPinned, renderLedgerRecord, renderLookupCall, renderSection, renderStub, renderToolValue, renderTopicNames, requestToRelay, requireAnswer, requireBudget, requireConversation, requireConversationSnapshot, requireCumulative, requireEntry, requireFallback, requireJudgeResult, requireJudgment, requireKeep, requireLimit, requireMessageInput, requireProviderResult, requireRole, requireRules, requireSectionsCap, requireSummary, resolveDecision, resolvePredict, sanitizeToken, sanitizeUsage, scanAmendments, scanJudgmentTies, scanProbability, sectionContract, sectionShape, selectRecords, settleAgentJob, settleToolResult, splitResultLines, splitSentences, splitTopic, splitWords, stripThinking, sumUsage, tokenUsageShape, tokenUsageToJSON, toolCallShape };
11729
12211
 
11730
12212
  //# sourceMappingURL=index.js.map