@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.
- package/dist/src/core/index.cjs +578 -84
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +324 -32
- package/dist/src/core/index.d.ts +324 -32
- package/dist/src/core/index.js +567 -85
- package/dist/src/core/index.js.map +1 -1
- package/package.json +7 -7
package/dist/src/core/index.js
CHANGED
|
@@ -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
|
|
9511
|
-
*
|
|
9512
|
-
*
|
|
9513
|
-
*
|
|
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
|
|
9520
|
-
*
|
|
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}
|
|
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
|
|
9825
|
-
* call, and the input neither excludes it nor files it quiet
|
|
9826
|
-
*
|
|
9827
|
-
*
|
|
9828
|
-
*
|
|
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(
|
|
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
|
|
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.
|
|
9904
|
-
*
|
|
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
|
|
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) ?? [])
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
10332
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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: `
|
|
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,
|
|
11124
|
-
* @returns The snapshot, each id list in conversation order
|
|
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
|
-
|
|
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
|
-
|
|
11410
|
-
|
|
11411
|
-
|
|
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
|
-
...
|
|
11418
|
-
messages: [...
|
|
11419
|
-
} :
|
|
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
|
|
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)),
|
|
11497
|
-
const
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
const
|
|
11506
|
-
|
|
11507
|
-
|
|
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)
|
|
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
|
|
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
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
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
|
-
]
|
|
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] ?
|
|
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
|
|
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,
|
|
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(
|
|
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:
|
|
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
|
|
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(
|
|
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
|
|
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
|