@ponythewhite/base-context 1.0.9 → 1.0.11
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/CHANGELOG.md +19 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/{bundled-modules-5JRM6P4T.js → bundled-modules-PEFT72QN.js} +2 -2
- package/dist/bundle/{chunk-VVI3UKGR.js → chunk-JZHGOOFM.js} +87 -57
- package/dist/bundle/{chunk-NEHLB7JV.js → chunk-TOOVREMP.js} +596 -102
- package/dist/bundle/{cli-main-YUDBEYE2.js → cli-main-BRXGYTGK.js} +2 -2
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{main-ZLGGAAGU.js → main-POUXGEL6.js} +2 -2
- package/dist/core/agent-session.d.ts +0 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +85 -45
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/canonical-context.d.ts +19 -3
- package/dist/core/canonical-context.d.ts.map +1 -1
- package/dist/core/canonical-context.js +245 -39
- package/dist/core/canonical-context.js.map +1 -1
- package/dist/core/context-epoch-copy.d.ts +1 -1
- package/dist/core/context-epoch-copy.d.ts.map +1 -1
- package/dist/core/context-epoch-copy.js +18 -7
- package/dist/core/context-epoch-copy.js.map +1 -1
- package/dist/core/context-epoch.d.ts +18 -3
- package/dist/core/context-epoch.d.ts.map +1 -1
- package/dist/core/context-epoch.js +13 -2
- package/dist/core/context-epoch.js.map +1 -1
- package/dist/core/context-tree.d.ts +1 -1
- package/dist/core/context-tree.d.ts.map +1 -1
- package/dist/core/context-tree.js +98 -8
- package/dist/core/context-tree.js.map +1 -1
- package/dist/core/history-index-worker.d.ts.map +1 -1
- package/dist/core/history-index-worker.js +59 -6
- package/dist/core/history-index-worker.js.map +1 -1
- package/dist/core/history-index.d.ts +17 -0
- package/dist/core/history-index.d.ts.map +1 -1
- package/dist/core/history-index.js +22 -0
- package/dist/core/history-index.js.map +1 -1
- package/dist/core/inference-coordinator.d.ts.map +1 -1
- package/dist/core/inference-coordinator.js +5 -1
- package/dist/core/inference-coordinator.js.map +1 -1
- package/dist/core/public-context.d.ts.map +1 -1
- package/dist/core/public-context.js +20 -8
- package/dist/core/public-context.js.map +1 -1
- package/dist/core/request-view-selection.d.ts +2 -1
- package/dist/core/request-view-selection.d.ts.map +1 -1
- package/dist/core/request-view-selection.js +29 -2
- package/dist/core/request-view-selection.js.map +1 -1
- package/dist/core/session-fork-messages.d.ts +5 -0
- package/dist/core/session-fork-messages.d.ts.map +1 -1
- package/dist/core/session-fork-messages.js +44 -0
- package/dist/core/session-fork-messages.js.map +1 -1
- package/dist/core/session-history-index.d.ts +5 -0
- package/dist/core/session-history-index.d.ts.map +1 -1
- package/dist/core/session-history-index.js +7 -0
- package/dist/core/session-history-index.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +155 -13
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-tree.d.ts +9 -0
- package/dist/core/session-tree.d.ts.map +1 -1
- package/dist/core/session-tree.js +71 -11
- package/dist/core/session-tree.js.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.js +4 -4
- package/dist/modes/agent-connection/in-process-agent-connection.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +19 -34
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-socket.d.ts +5 -0
- package/dist/modes/daemon/daemon-socket.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-socket.js +19 -0
- package/dist/modes/daemon/daemon-socket.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +6 -7
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-client.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-client.js +5 -5
- package/dist/modes/daemon/daemon-worker-client.js.map +1 -1
- package/package.json +4 -4
|
@@ -927,6 +927,8 @@ const DEFAULT_MANAGER_HISTORY_LIMITS = {
|
|
|
927
927
|
maxEntries: 16_384,
|
|
928
928
|
maxSourceBytes: 64 * 1024 * 1024,
|
|
929
929
|
};
|
|
930
|
+
// Selected forks bound compact original-reference metadata separately from selected payload/output limits.
|
|
931
|
+
const FORK_SOURCE_METADATA_MAX_BYTES = 64 * 1024 * 1024;
|
|
930
932
|
async function readOwnedSessionHeader(snapshot) {
|
|
931
933
|
const handle = await openFile(snapshot.journalPath, "r");
|
|
932
934
|
let capturedHeader;
|
|
@@ -1476,6 +1478,20 @@ export class SessionManager {
|
|
|
1476
1478
|
readSourceHistory(read) {
|
|
1477
1479
|
return this._runHistoryRead(this._bindHistorySource((index, source, query) => createSessionHistoryReadScope(index, source, query, "source")), read);
|
|
1478
1480
|
}
|
|
1481
|
+
/** Read the owner-maintained own-spend projection without hydrating the source. */
|
|
1482
|
+
async readOwnUsageSummary() {
|
|
1483
|
+
this._assertMutable();
|
|
1484
|
+
if (!this.supportsCapturedHistoryReads())
|
|
1485
|
+
throw new Error("Own usage projection requires an owned native source");
|
|
1486
|
+
const state = this.writeState;
|
|
1487
|
+
return this._enqueue(state, 0, async () => {
|
|
1488
|
+
await state.owner.flush();
|
|
1489
|
+
const snapshot = state.owner.getSnapshot();
|
|
1490
|
+
await this._acknowledgedHistory(state, snapshot);
|
|
1491
|
+
// Keep later appends queued: the catalog holds current totals, not historical versions.
|
|
1492
|
+
return state.history.currentSourceUsage(snapshot);
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1479
1495
|
/** Complete bounded structured task reduction on one captured native branch. */
|
|
1480
1496
|
async readTaskState(limits = {}) {
|
|
1481
1497
|
const captured = taskStateReadLimits(limits);
|
|
@@ -3330,6 +3346,11 @@ export class SessionManager {
|
|
|
3330
3346
|
}
|
|
3331
3347
|
async _captureForkInput(target, options) {
|
|
3332
3348
|
const limits = { ...(options.limits ?? DEFAULT_MANAGER_HISTORY_LIMITS) };
|
|
3349
|
+
if (!Number.isSafeInteger(limits.maxEntries) ||
|
|
3350
|
+
limits.maxEntries <= 0 ||
|
|
3351
|
+
!Number.isSafeInteger(limits.maxSourceBytes) ||
|
|
3352
|
+
limits.maxSourceBytes <= 0)
|
|
3353
|
+
throw new Error("Invalid fork source limits");
|
|
3333
3354
|
const sourceFile = this.sessionFile;
|
|
3334
3355
|
const header = JSON.parse(stringifyBoundedJson(this.getHeader(), limits.maxSourceBytes));
|
|
3335
3356
|
const settings = {
|
|
@@ -3448,34 +3469,155 @@ export class SessionManager {
|
|
|
3448
3469
|
if (headerBytes >= limits.maxSourceBytes)
|
|
3449
3470
|
throw new Error("Fork source byte budget exceeded");
|
|
3450
3471
|
return this.readSourceHistory(async (history) => {
|
|
3451
|
-
const
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3472
|
+
const metadata = new Map();
|
|
3473
|
+
let metadataBytes = 0;
|
|
3474
|
+
let after = 0;
|
|
3475
|
+
for (;;) {
|
|
3476
|
+
const page = await history.page(after, 128);
|
|
3477
|
+
if (page.indexedThrough < history.source.sourceSequence)
|
|
3478
|
+
throw new Error("Captured fork history has incomplete index coverage");
|
|
3479
|
+
for (const reference of page.events) {
|
|
3480
|
+
// Prefix/revision remapping needs original refs, not text previews or unselected bodies.
|
|
3481
|
+
const source = {
|
|
3482
|
+
id: reference.id,
|
|
3483
|
+
parentId: reference.parentId,
|
|
3484
|
+
kind: reference.kind,
|
|
3485
|
+
sequence: reference.sequence,
|
|
3486
|
+
revision: reference.revision,
|
|
3487
|
+
locator: { ...reference.locator },
|
|
3488
|
+
retention: reference.retention,
|
|
3489
|
+
qualification: reference.qualification,
|
|
3490
|
+
};
|
|
3491
|
+
metadataBytes += Buffer.byteLength(JSON.stringify(source)) + 1;
|
|
3492
|
+
if (metadataBytes > FORK_SOURCE_METADATA_MAX_BYTES)
|
|
3493
|
+
throw new Error("Fork source metadata byte budget exceeded");
|
|
3494
|
+
metadata.set(source.id, source);
|
|
3495
|
+
}
|
|
3496
|
+
if (page.nextAfter === null)
|
|
3497
|
+
break;
|
|
3498
|
+
after = page.nextAfter;
|
|
3499
|
+
}
|
|
3500
|
+
const hasEpoch = [...metadata.values()].some((entry) => entry.kind === "compaction" && entry.qualification === "native-context-epoch");
|
|
3501
|
+
const loaded = new Map();
|
|
3502
|
+
let sourceBytes = headerBytes;
|
|
3503
|
+
const load = async (id) => {
|
|
3504
|
+
const existing = loaded.get(id);
|
|
3505
|
+
if (existing)
|
|
3506
|
+
return existing;
|
|
3507
|
+
const reference = metadata.get(id);
|
|
3508
|
+
if (!reference)
|
|
3509
|
+
throw new Error("Fork selected source is unavailable");
|
|
3510
|
+
if (loaded.size >= limits.maxEntries)
|
|
3511
|
+
throw new Error("Fork entry budget exceeded");
|
|
3512
|
+
const remaining = limits.maxSourceBytes - sourceBytes;
|
|
3513
|
+
if (reference.locator.length > remaining)
|
|
3514
|
+
throw new Error("Fork source byte budget exceeded");
|
|
3515
|
+
const hydrated = await history.hydrateEntry(id, remaining);
|
|
3516
|
+
if (!hydrated)
|
|
3517
|
+
throw new Error("Fork selected source is unavailable");
|
|
3518
|
+
const entry = withEntryRetention(hydrated.entry, hydrated.source.retention, hydrated.source.qualification);
|
|
3519
|
+
loaded.set(id, entry);
|
|
3520
|
+
metadata.set(id, captureEpochCopyEntry(entry, hydrated.source));
|
|
3521
|
+
sourceBytes += reference.locator.length;
|
|
3522
|
+
return entry;
|
|
3523
|
+
};
|
|
3524
|
+
if ("entryId" in target && !metadata.has(target.entryId))
|
|
3525
|
+
throw new Error("Invalid entry ID for forking");
|
|
3526
|
+
const selected = "entryId" in target ? await load(target.entryId) : undefined;
|
|
3527
|
+
if ("entryId" in target &&
|
|
3528
|
+
target.position === "before" &&
|
|
3529
|
+
(selected?.type !== "message" || selected.message.role !== "user"))
|
|
3530
|
+
throw new Error("Invalid entry ID for forking");
|
|
3531
|
+
const leafId = "entryId" in target ? (target.position === "at" ? selected.id : selected.parentId) : target.leafId;
|
|
3532
|
+
const path = [];
|
|
3533
|
+
let page = await history.parentPathFrom(leafId);
|
|
3534
|
+
for (;;) {
|
|
3535
|
+
if (page.totalEntries > limits.maxEntries)
|
|
3536
|
+
throw new Error("Fork entry budget exceeded");
|
|
3537
|
+
for (const reference of page.events)
|
|
3538
|
+
path.push(await load(reference.id));
|
|
3539
|
+
if (!page.nextCursor)
|
|
3540
|
+
break;
|
|
3541
|
+
page = await history.parentPathFrom(leafId, { cursor: page.nextCursor });
|
|
3542
|
+
}
|
|
3543
|
+
const copied = path.filter((entry) => entry.type !== "label");
|
|
3544
|
+
const ids = new Set(copied.map((entry) => entry.id));
|
|
3545
|
+
if (hasEpoch) {
|
|
3546
|
+
for (const entry of copied) {
|
|
3547
|
+
if (entry.type !== "message")
|
|
3548
|
+
continue;
|
|
3549
|
+
if (entry.execution && "invocationId" in entry.execution)
|
|
3550
|
+
ids.add(entry.execution.invocationId);
|
|
3551
|
+
const updateTarget = entry.message.role === "assistant"
|
|
3552
|
+
? { kind: "assistant-usage", targetId: entry.id }
|
|
3553
|
+
: entry.message.role === "toolResult"
|
|
3554
|
+
? { kind: "ipython-sent-message", toolCallId: entry.message.toolCallId }
|
|
3555
|
+
: undefined;
|
|
3556
|
+
if (!updateTarget)
|
|
3557
|
+
continue;
|
|
3558
|
+
let after = 0;
|
|
3559
|
+
for (;;) {
|
|
3560
|
+
const updates = await history.sourceContextUpdates(updateTarget, after);
|
|
3561
|
+
if (updates.indexedThrough < history.source.sourceSequence)
|
|
3562
|
+
throw new Error("Captured fork updates have incomplete index coverage");
|
|
3563
|
+
for (const reference of updates.events)
|
|
3564
|
+
ids.add(reference.id);
|
|
3565
|
+
if (updates.nextAfter === null)
|
|
3566
|
+
break;
|
|
3567
|
+
after = updates.nextAfter;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
// Keep every actual related ancestor, including private intent/request rows when necessary.
|
|
3571
|
+
for (const id of ids) {
|
|
3572
|
+
const reference = metadata.get(id);
|
|
3573
|
+
if (!reference)
|
|
3574
|
+
throw new Error("Fork related source is unavailable");
|
|
3575
|
+
if (reference.parentId !== null)
|
|
3576
|
+
ids.add(reference.parentId);
|
|
3577
|
+
}
|
|
3578
|
+
for (const id of ids)
|
|
3579
|
+
await load(id);
|
|
3580
|
+
}
|
|
3581
|
+
else {
|
|
3582
|
+
// Preserve the existing non-epoch copy's resolved whole-source assistant usage overlay.
|
|
3583
|
+
for (const entry of copied) {
|
|
3584
|
+
if (entry.type !== "message" || entry.message.role !== "assistant")
|
|
3585
|
+
continue;
|
|
3586
|
+
const latest = await history.sourceAssistantUsage(entry.id);
|
|
3587
|
+
if (latest)
|
|
3588
|
+
await load(latest.id);
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
for (const id of ids) {
|
|
3592
|
+
const label = await history.sourceLabel(id);
|
|
3593
|
+
if (label)
|
|
3594
|
+
await load(label.id);
|
|
3595
|
+
}
|
|
3596
|
+
const entries = [...loaded.values()].sort((left, right) => metadata.get(left.id).sequence - metadata.get(right.id).sequence);
|
|
3458
3597
|
if (!hasEpoch)
|
|
3459
3598
|
applyChildUsageAttributions(entries);
|
|
3460
|
-
|
|
3599
|
+
const epochCopy = hasEpoch
|
|
3461
3600
|
? {
|
|
3462
3601
|
sessionId: history.source.sessionId,
|
|
3463
3602
|
sessionFile: history.source.sessionFile,
|
|
3464
3603
|
through: history.source.sourceSequence,
|
|
3465
|
-
entries:
|
|
3604
|
+
entries: [...metadata.values()],
|
|
3466
3605
|
retained: false,
|
|
3467
3606
|
}
|
|
3468
|
-
: undefined
|
|
3607
|
+
: undefined;
|
|
3608
|
+
if (epochCopy)
|
|
3609
|
+
stringifyBoundedJson(epochCopy, FORK_SOURCE_METADATA_MAX_BYTES);
|
|
3610
|
+
return finish(entries, history, epochCopy);
|
|
3469
3611
|
});
|
|
3470
3612
|
}
|
|
3471
|
-
async _rebuildCopiedEpoch(copied, limits) {
|
|
3613
|
+
async _rebuildCopiedEpoch(copied, limits, metadataMaxBytes = limits.maxSourceBytes) {
|
|
3472
3614
|
if (!copied.entries.some((entry) => entry.kind === "compaction" && entry.qualification === "native-context-epoch"))
|
|
3473
3615
|
return;
|
|
3474
3616
|
if (!this.supportsCapturedHistoryReads())
|
|
3475
3617
|
throw new Error("Copied context epochs require an owned persistent source");
|
|
3476
3618
|
const sink = this.bindCompactionSink(limits);
|
|
3477
3619
|
await this._runHistoryRead({ ...sink, readHistory: (read) => sink[readCopiedEpochSource](read) }, async (history) => {
|
|
3478
|
-
const rebuilt = await rebuildCopiedContextEpoch(history, copied, limits);
|
|
3620
|
+
const rebuilt = await rebuildCopiedContextEpoch(history, copied, limits, metadataMaxBytes);
|
|
3479
3621
|
if (rebuilt)
|
|
3480
3622
|
await sink[appendContextEpoch](rebuilt.checkpoint, rebuilt.tokensBefore, rebuilt.summary);
|
|
3481
3623
|
});
|
|
@@ -3512,7 +3654,7 @@ export class SessionManager {
|
|
|
3512
3654
|
if (input.epochCopy) {
|
|
3513
3655
|
try {
|
|
3514
3656
|
await next.branchTo(input.leafId ?? null);
|
|
3515
|
-
await next._rebuildCopiedEpoch(input.epochCopy, input.limits);
|
|
3657
|
+
await next._rebuildCopiedEpoch(input.epochCopy, input.limits, FORK_SOURCE_METADATA_MAX_BYTES);
|
|
3516
3658
|
}
|
|
3517
3659
|
catch (error) {
|
|
3518
3660
|
try {
|