@mindstudio-ai/remy 0.1.245 → 0.1.246
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/headless.d.ts +4 -1
- package/dist/headless.js +154 -28
- package/dist/index.js +156 -30
- package/package.json +1 -1
package/dist/headless.d.ts
CHANGED
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
* page size (default 500, hard cap 2000). Response: {event:"history",
|
|
20
20
|
* messages, startIndex, endIndex, totalMessageCount, ...}. Walk backward by
|
|
21
21
|
* passing the previous response's `startIndex` as the next `before`. When
|
|
22
|
-
* `startIndex === 0`, no older messages remain.
|
|
22
|
+
* `startIndex === 0`, no older messages remain. Indices are GLOBAL — they span
|
|
23
|
+
* the sealed session archives followed by the live tail (see getHistoryPage in
|
|
24
|
+
* session.ts), so scrollback continues past a rotation to the conversation
|
|
25
|
+
* start, not just to the start of the live (post-rotation) array.
|
|
23
26
|
*/
|
|
24
27
|
interface HeadlessOptions {
|
|
25
28
|
apiKey?: string;
|
package/dist/headless.js
CHANGED
|
@@ -6309,6 +6309,14 @@ var ARCHIVE_DIR = ".logs/sessions";
|
|
|
6309
6309
|
var ROTATE_THRESHOLD_BYTES = 32 * 1024 * 1024;
|
|
6310
6310
|
var RETAIN_TAIL_BYTES = 16 * 1024 * 1024;
|
|
6311
6311
|
var ARCHIVE_RETENTION_BYTES = 64 * 1024 * 1024;
|
|
6312
|
+
var ARCHIVE_NAME_RE = /^(cleared|rotated)-.*\.json$/;
|
|
6313
|
+
var archiveSortKey = (name) => name.replace(/^(cleared|rotated)-/, "");
|
|
6314
|
+
var ARCHIVE_COUNT_RE = /\.c(\d+)\.json$/;
|
|
6315
|
+
var HISTORY_DEFAULT_LIMIT = 500;
|
|
6316
|
+
var HISTORY_MAX_LIMIT = 2e3;
|
|
6317
|
+
var archiveCountCache = /* @__PURE__ */ new Map();
|
|
6318
|
+
var archiveMsgCache = /* @__PURE__ */ new Map();
|
|
6319
|
+
var ARCHIVE_MSG_CACHE_MAX = 3;
|
|
6312
6320
|
function loadSession(state) {
|
|
6313
6321
|
pruneArchives();
|
|
6314
6322
|
try {
|
|
@@ -6387,31 +6395,34 @@ function buildPayload(state) {
|
|
|
6387
6395
|
function archiveMessages(messages, label, models) {
|
|
6388
6396
|
fs21.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
6389
6397
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6390
|
-
|
|
6398
|
+
const count = messages.length;
|
|
6399
|
+
let dest = path11.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
|
|
6391
6400
|
let n = 1;
|
|
6392
6401
|
while (fs21.existsSync(dest)) {
|
|
6393
|
-
dest = path11.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
|
|
6402
|
+
dest = path11.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
|
|
6394
6403
|
}
|
|
6395
6404
|
const payload = { messages };
|
|
6396
6405
|
if (models && Object.keys(models).length > 0) {
|
|
6397
6406
|
payload.models = models;
|
|
6398
6407
|
}
|
|
6399
6408
|
fs21.writeFileSync(dest, JSON.stringify(payload), "utf-8");
|
|
6400
|
-
|
|
6409
|
+
archiveCountCache.set(path11.basename(dest), count);
|
|
6410
|
+
log9.info("Session archived", { label, dest, messageCount: count });
|
|
6401
6411
|
pruneArchives();
|
|
6402
6412
|
return dest;
|
|
6403
6413
|
}
|
|
6404
6414
|
function pruneArchives() {
|
|
6405
6415
|
try {
|
|
6406
|
-
const entries = fs21.readdirSync(ARCHIVE_DIR).filter((name) =>
|
|
6416
|
+
const entries = fs21.readdirSync(ARCHIVE_DIR).filter((name) => ARCHIVE_NAME_RE.test(name));
|
|
6407
6417
|
if (entries.length <= 1) {
|
|
6408
6418
|
return;
|
|
6409
6419
|
}
|
|
6410
|
-
const sortKey = (name) => name.replace(/^(cleared|rotated)-/, "");
|
|
6411
6420
|
const archives = entries.map((name) => ({
|
|
6412
6421
|
name,
|
|
6413
6422
|
size: fs21.statSync(path11.join(ARCHIVE_DIR, name)).size
|
|
6414
|
-
})).sort(
|
|
6423
|
+
})).sort(
|
|
6424
|
+
(a, b) => archiveSortKey(b.name).localeCompare(archiveSortKey(a.name))
|
|
6425
|
+
);
|
|
6415
6426
|
let kept = 0;
|
|
6416
6427
|
let cut = archives.length;
|
|
6417
6428
|
for (let i = 0; i < archives.length; i++) {
|
|
@@ -6442,6 +6453,129 @@ function pruneArchives() {
|
|
|
6442
6453
|
} catch {
|
|
6443
6454
|
}
|
|
6444
6455
|
}
|
|
6456
|
+
function parseArchive(name) {
|
|
6457
|
+
const cached3 = archiveMsgCache.get(name);
|
|
6458
|
+
if (cached3) {
|
|
6459
|
+
archiveMsgCache.delete(name);
|
|
6460
|
+
archiveMsgCache.set(name, cached3);
|
|
6461
|
+
return cached3;
|
|
6462
|
+
}
|
|
6463
|
+
try {
|
|
6464
|
+
const raw = fs21.readFileSync(path11.join(ARCHIVE_DIR, name), "utf-8");
|
|
6465
|
+
const data = JSON.parse(raw);
|
|
6466
|
+
const messages = Array.isArray(data?.messages) ? data.messages : [];
|
|
6467
|
+
archiveCountCache.set(name, messages.length);
|
|
6468
|
+
archiveMsgCache.set(name, messages);
|
|
6469
|
+
while (archiveMsgCache.size > ARCHIVE_MSG_CACHE_MAX) {
|
|
6470
|
+
const oldest = archiveMsgCache.keys().next().value;
|
|
6471
|
+
if (oldest === void 0) {
|
|
6472
|
+
break;
|
|
6473
|
+
}
|
|
6474
|
+
archiveMsgCache.delete(oldest);
|
|
6475
|
+
}
|
|
6476
|
+
return messages;
|
|
6477
|
+
} catch (err) {
|
|
6478
|
+
log9.warn("Session archive unreadable", { name, error: err?.message });
|
|
6479
|
+
return null;
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6482
|
+
function archiveCount(name) {
|
|
6483
|
+
const cached3 = archiveCountCache.get(name);
|
|
6484
|
+
if (cached3 !== void 0) {
|
|
6485
|
+
return cached3;
|
|
6486
|
+
}
|
|
6487
|
+
const m = ARCHIVE_COUNT_RE.exec(name);
|
|
6488
|
+
if (m) {
|
|
6489
|
+
const n = Number(m[1]);
|
|
6490
|
+
archiveCountCache.set(name, n);
|
|
6491
|
+
return n;
|
|
6492
|
+
}
|
|
6493
|
+
const msgs = parseArchive(name);
|
|
6494
|
+
return msgs ? msgs.length : null;
|
|
6495
|
+
}
|
|
6496
|
+
function readArchiveMessages(name) {
|
|
6497
|
+
return parseArchive(name) ?? [];
|
|
6498
|
+
}
|
|
6499
|
+
function listConversationArchives() {
|
|
6500
|
+
let names;
|
|
6501
|
+
try {
|
|
6502
|
+
names = fs21.readdirSync(ARCHIVE_DIR).filter((n) => ARCHIVE_NAME_RE.test(n));
|
|
6503
|
+
} catch {
|
|
6504
|
+
return { slots: [], archivedCount: 0 };
|
|
6505
|
+
}
|
|
6506
|
+
let maxClearedKey = null;
|
|
6507
|
+
for (const name of names) {
|
|
6508
|
+
if (name.startsWith("cleared-")) {
|
|
6509
|
+
const key = archiveSortKey(name);
|
|
6510
|
+
if (maxClearedKey === null || key > maxClearedKey) {
|
|
6511
|
+
maxClearedKey = key;
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
}
|
|
6515
|
+
const rotated = names.filter((n) => n.startsWith("rotated-")).filter((n) => maxClearedKey === null || archiveSortKey(n) > maxClearedKey).sort((a, b) => archiveSortKey(a).localeCompare(archiveSortKey(b)));
|
|
6516
|
+
const slots = [];
|
|
6517
|
+
let offset = 0;
|
|
6518
|
+
for (const name of rotated) {
|
|
6519
|
+
const count = archiveCount(name);
|
|
6520
|
+
if (count === null || count <= 0) {
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
slots.push({ name, count, offset });
|
|
6524
|
+
offset += count;
|
|
6525
|
+
}
|
|
6526
|
+
return { slots, archivedCount: offset };
|
|
6527
|
+
}
|
|
6528
|
+
function getHistoryPage(state, opts) {
|
|
6529
|
+
const { slots, archivedCount } = listConversationArchives();
|
|
6530
|
+
const liveLen = state.messages.length;
|
|
6531
|
+
const total = archivedCount + liveLen;
|
|
6532
|
+
const rawLimit = opts?.limit;
|
|
6533
|
+
const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(Math.max(1, rawLimit | 0), HISTORY_MAX_LIMIT) : HISTORY_DEFAULT_LIMIT;
|
|
6534
|
+
const rawBefore = opts?.before;
|
|
6535
|
+
const before = typeof rawBefore === "number" && Number.isFinite(rawBefore) ? Math.max(0, Math.min(rawBefore | 0, total)) : total;
|
|
6536
|
+
const peekGlobal = (i) => {
|
|
6537
|
+
if (i >= archivedCount) {
|
|
6538
|
+
return state.messages[i - archivedCount];
|
|
6539
|
+
}
|
|
6540
|
+
for (const slot of slots) {
|
|
6541
|
+
if (i < slot.offset + slot.count) {
|
|
6542
|
+
return readArchiveMessages(slot.name)[i - slot.offset];
|
|
6543
|
+
}
|
|
6544
|
+
}
|
|
6545
|
+
return void 0;
|
|
6546
|
+
};
|
|
6547
|
+
let startIndex = Math.max(0, before - limit);
|
|
6548
|
+
while (startIndex > 0) {
|
|
6549
|
+
const msg = peekGlobal(startIndex);
|
|
6550
|
+
if (msg && msg.role === "user" && msg.toolCallId) {
|
|
6551
|
+
startIndex--;
|
|
6552
|
+
} else {
|
|
6553
|
+
break;
|
|
6554
|
+
}
|
|
6555
|
+
}
|
|
6556
|
+
const endIndex = before;
|
|
6557
|
+
const messages = [];
|
|
6558
|
+
for (const slot of slots) {
|
|
6559
|
+
const slotEnd = slot.offset + slot.count;
|
|
6560
|
+
if (slotEnd <= startIndex || slot.offset >= endIndex) {
|
|
6561
|
+
continue;
|
|
6562
|
+
}
|
|
6563
|
+
const from = Math.max(startIndex, slot.offset) - slot.offset;
|
|
6564
|
+
const to = Math.min(endIndex, slotEnd) - slot.offset;
|
|
6565
|
+
const msgs = readArchiveMessages(slot.name);
|
|
6566
|
+
for (let i = from; i < to; i++) {
|
|
6567
|
+
messages.push(msgs[i]);
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6570
|
+
if (endIndex > archivedCount) {
|
|
6571
|
+
const from = Math.max(startIndex, archivedCount) - archivedCount;
|
|
6572
|
+
const to = endIndex - archivedCount;
|
|
6573
|
+
for (let i = from; i < to; i++) {
|
|
6574
|
+
messages.push(state.messages[i]);
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
return { messages, startIndex, endIndex, totalMessageCount: total };
|
|
6578
|
+
}
|
|
6445
6579
|
function rotate(state) {
|
|
6446
6580
|
const messages = state.messages;
|
|
6447
6581
|
if (messages.length === 0) {
|
|
@@ -7979,8 +8113,6 @@ var USER_FACING_TOOLS = /* @__PURE__ */ new Set([
|
|
|
7979
8113
|
"presentPublishPlan"
|
|
7980
8114
|
]);
|
|
7981
8115
|
var FORCED_COMPACTION_THRESHOLD_TOKENS = 85e4;
|
|
7982
|
-
var HISTORY_DEFAULT_LIMIT = 500;
|
|
7983
|
-
var HISTORY_MAX_LIMIT = 2e3;
|
|
7984
8116
|
var HeadlessSession = class {
|
|
7985
8117
|
// Configuration
|
|
7986
8118
|
opts;
|
|
@@ -8726,30 +8858,24 @@ var HeadlessSession = class {
|
|
|
8726
8858
|
}
|
|
8727
8859
|
if (action === "get_history") {
|
|
8728
8860
|
this.applyPendingBlockUpdates();
|
|
8729
|
-
const
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
const before = typeof rawBefore === "number" && Number.isFinite(rawBefore) ? Math.max(0, Math.min(rawBefore | 0, total)) : total;
|
|
8734
|
-
let startIndex = Math.max(0, before - limit);
|
|
8735
|
-
while (startIndex > 0 && this.state.messages[startIndex].role === "user" && this.state.messages[startIndex].toolCallId) {
|
|
8736
|
-
startIndex--;
|
|
8737
|
-
}
|
|
8738
|
-
const endIndex = before;
|
|
8861
|
+
const page = getHistoryPage(this.state, {
|
|
8862
|
+
...typeof parsed.before === "number" ? { before: parsed.before } : {},
|
|
8863
|
+
...typeof parsed.limit === "number" ? { limit: parsed.limit } : {}
|
|
8864
|
+
});
|
|
8739
8865
|
log15.info("History response", {
|
|
8740
8866
|
requestId,
|
|
8741
|
-
startIndex,
|
|
8742
|
-
endIndex,
|
|
8743
|
-
count: endIndex - startIndex,
|
|
8744
|
-
totalMessageCount:
|
|
8745
|
-
beforeParam:
|
|
8746
|
-
limitParam:
|
|
8867
|
+
startIndex: page.startIndex,
|
|
8868
|
+
endIndex: page.endIndex,
|
|
8869
|
+
count: page.endIndex - page.startIndex,
|
|
8870
|
+
totalMessageCount: page.totalMessageCount,
|
|
8871
|
+
beforeParam: parsed.before,
|
|
8872
|
+
limitParam: parsed.limit
|
|
8747
8873
|
});
|
|
8748
8874
|
this.dispatchSimple(requestId, "history", () => ({
|
|
8749
|
-
messages:
|
|
8750
|
-
startIndex,
|
|
8751
|
-
endIndex,
|
|
8752
|
-
totalMessageCount:
|
|
8875
|
+
messages: page.messages,
|
|
8876
|
+
startIndex: page.startIndex,
|
|
8877
|
+
endIndex: page.endIndex,
|
|
8878
|
+
totalMessageCount: page.totalMessageCount,
|
|
8753
8879
|
running: this.running,
|
|
8754
8880
|
...this.running && this.currentRequestId ? { currentRequestId: this.currentRequestId } : {},
|
|
8755
8881
|
...this.state.models && { models: this.state.models },
|
package/dist/index.js
CHANGED
|
@@ -2314,31 +2314,34 @@ function buildPayload(state) {
|
|
|
2314
2314
|
function archiveMessages(messages, label, models) {
|
|
2315
2315
|
fs10.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
2316
2316
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2317
|
-
|
|
2317
|
+
const count = messages.length;
|
|
2318
|
+
let dest = path4.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
|
|
2318
2319
|
let n = 1;
|
|
2319
2320
|
while (fs10.existsSync(dest)) {
|
|
2320
|
-
dest = path4.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
|
|
2321
|
+
dest = path4.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
|
|
2321
2322
|
}
|
|
2322
2323
|
const payload = { messages };
|
|
2323
2324
|
if (models && Object.keys(models).length > 0) {
|
|
2324
2325
|
payload.models = models;
|
|
2325
2326
|
}
|
|
2326
2327
|
fs10.writeFileSync(dest, JSON.stringify(payload), "utf-8");
|
|
2327
|
-
|
|
2328
|
+
archiveCountCache.set(path4.basename(dest), count);
|
|
2329
|
+
log3.info("Session archived", { label, dest, messageCount: count });
|
|
2328
2330
|
pruneArchives();
|
|
2329
2331
|
return dest;
|
|
2330
2332
|
}
|
|
2331
2333
|
function pruneArchives() {
|
|
2332
2334
|
try {
|
|
2333
|
-
const entries = fs10.readdirSync(ARCHIVE_DIR).filter((name) =>
|
|
2335
|
+
const entries = fs10.readdirSync(ARCHIVE_DIR).filter((name) => ARCHIVE_NAME_RE.test(name));
|
|
2334
2336
|
if (entries.length <= 1) {
|
|
2335
2337
|
return;
|
|
2336
2338
|
}
|
|
2337
|
-
const sortKey = (name) => name.replace(/^(cleared|rotated)-/, "");
|
|
2338
2339
|
const archives = entries.map((name) => ({
|
|
2339
2340
|
name,
|
|
2340
2341
|
size: fs10.statSync(path4.join(ARCHIVE_DIR, name)).size
|
|
2341
|
-
})).sort(
|
|
2342
|
+
})).sort(
|
|
2343
|
+
(a, b) => archiveSortKey(b.name).localeCompare(archiveSortKey(a.name))
|
|
2344
|
+
);
|
|
2342
2345
|
let kept = 0;
|
|
2343
2346
|
let cut = archives.length;
|
|
2344
2347
|
for (let i = 0; i < archives.length; i++) {
|
|
@@ -2369,6 +2372,129 @@ function pruneArchives() {
|
|
|
2369
2372
|
} catch {
|
|
2370
2373
|
}
|
|
2371
2374
|
}
|
|
2375
|
+
function parseArchive(name) {
|
|
2376
|
+
const cached3 = archiveMsgCache.get(name);
|
|
2377
|
+
if (cached3) {
|
|
2378
|
+
archiveMsgCache.delete(name);
|
|
2379
|
+
archiveMsgCache.set(name, cached3);
|
|
2380
|
+
return cached3;
|
|
2381
|
+
}
|
|
2382
|
+
try {
|
|
2383
|
+
const raw = fs10.readFileSync(path4.join(ARCHIVE_DIR, name), "utf-8");
|
|
2384
|
+
const data = JSON.parse(raw);
|
|
2385
|
+
const messages = Array.isArray(data?.messages) ? data.messages : [];
|
|
2386
|
+
archiveCountCache.set(name, messages.length);
|
|
2387
|
+
archiveMsgCache.set(name, messages);
|
|
2388
|
+
while (archiveMsgCache.size > ARCHIVE_MSG_CACHE_MAX) {
|
|
2389
|
+
const oldest = archiveMsgCache.keys().next().value;
|
|
2390
|
+
if (oldest === void 0) {
|
|
2391
|
+
break;
|
|
2392
|
+
}
|
|
2393
|
+
archiveMsgCache.delete(oldest);
|
|
2394
|
+
}
|
|
2395
|
+
return messages;
|
|
2396
|
+
} catch (err) {
|
|
2397
|
+
log3.warn("Session archive unreadable", { name, error: err?.message });
|
|
2398
|
+
return null;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
function archiveCount(name) {
|
|
2402
|
+
const cached3 = archiveCountCache.get(name);
|
|
2403
|
+
if (cached3 !== void 0) {
|
|
2404
|
+
return cached3;
|
|
2405
|
+
}
|
|
2406
|
+
const m = ARCHIVE_COUNT_RE.exec(name);
|
|
2407
|
+
if (m) {
|
|
2408
|
+
const n = Number(m[1]);
|
|
2409
|
+
archiveCountCache.set(name, n);
|
|
2410
|
+
return n;
|
|
2411
|
+
}
|
|
2412
|
+
const msgs = parseArchive(name);
|
|
2413
|
+
return msgs ? msgs.length : null;
|
|
2414
|
+
}
|
|
2415
|
+
function readArchiveMessages(name) {
|
|
2416
|
+
return parseArchive(name) ?? [];
|
|
2417
|
+
}
|
|
2418
|
+
function listConversationArchives() {
|
|
2419
|
+
let names;
|
|
2420
|
+
try {
|
|
2421
|
+
names = fs10.readdirSync(ARCHIVE_DIR).filter((n) => ARCHIVE_NAME_RE.test(n));
|
|
2422
|
+
} catch {
|
|
2423
|
+
return { slots: [], archivedCount: 0 };
|
|
2424
|
+
}
|
|
2425
|
+
let maxClearedKey = null;
|
|
2426
|
+
for (const name of names) {
|
|
2427
|
+
if (name.startsWith("cleared-")) {
|
|
2428
|
+
const key = archiveSortKey(name);
|
|
2429
|
+
if (maxClearedKey === null || key > maxClearedKey) {
|
|
2430
|
+
maxClearedKey = key;
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
const rotated = names.filter((n) => n.startsWith("rotated-")).filter((n) => maxClearedKey === null || archiveSortKey(n) > maxClearedKey).sort((a, b) => archiveSortKey(a).localeCompare(archiveSortKey(b)));
|
|
2435
|
+
const slots = [];
|
|
2436
|
+
let offset = 0;
|
|
2437
|
+
for (const name of rotated) {
|
|
2438
|
+
const count = archiveCount(name);
|
|
2439
|
+
if (count === null || count <= 0) {
|
|
2440
|
+
continue;
|
|
2441
|
+
}
|
|
2442
|
+
slots.push({ name, count, offset });
|
|
2443
|
+
offset += count;
|
|
2444
|
+
}
|
|
2445
|
+
return { slots, archivedCount: offset };
|
|
2446
|
+
}
|
|
2447
|
+
function getHistoryPage(state, opts) {
|
|
2448
|
+
const { slots, archivedCount } = listConversationArchives();
|
|
2449
|
+
const liveLen = state.messages.length;
|
|
2450
|
+
const total = archivedCount + liveLen;
|
|
2451
|
+
const rawLimit = opts?.limit;
|
|
2452
|
+
const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(Math.max(1, rawLimit | 0), HISTORY_MAX_LIMIT) : HISTORY_DEFAULT_LIMIT;
|
|
2453
|
+
const rawBefore = opts?.before;
|
|
2454
|
+
const before = typeof rawBefore === "number" && Number.isFinite(rawBefore) ? Math.max(0, Math.min(rawBefore | 0, total)) : total;
|
|
2455
|
+
const peekGlobal = (i) => {
|
|
2456
|
+
if (i >= archivedCount) {
|
|
2457
|
+
return state.messages[i - archivedCount];
|
|
2458
|
+
}
|
|
2459
|
+
for (const slot of slots) {
|
|
2460
|
+
if (i < slot.offset + slot.count) {
|
|
2461
|
+
return readArchiveMessages(slot.name)[i - slot.offset];
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
return void 0;
|
|
2465
|
+
};
|
|
2466
|
+
let startIndex = Math.max(0, before - limit);
|
|
2467
|
+
while (startIndex > 0) {
|
|
2468
|
+
const msg = peekGlobal(startIndex);
|
|
2469
|
+
if (msg && msg.role === "user" && msg.toolCallId) {
|
|
2470
|
+
startIndex--;
|
|
2471
|
+
} else {
|
|
2472
|
+
break;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
const endIndex = before;
|
|
2476
|
+
const messages = [];
|
|
2477
|
+
for (const slot of slots) {
|
|
2478
|
+
const slotEnd = slot.offset + slot.count;
|
|
2479
|
+
if (slotEnd <= startIndex || slot.offset >= endIndex) {
|
|
2480
|
+
continue;
|
|
2481
|
+
}
|
|
2482
|
+
const from = Math.max(startIndex, slot.offset) - slot.offset;
|
|
2483
|
+
const to = Math.min(endIndex, slotEnd) - slot.offset;
|
|
2484
|
+
const msgs = readArchiveMessages(slot.name);
|
|
2485
|
+
for (let i = from; i < to; i++) {
|
|
2486
|
+
messages.push(msgs[i]);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
if (endIndex > archivedCount) {
|
|
2490
|
+
const from = Math.max(startIndex, archivedCount) - archivedCount;
|
|
2491
|
+
const to = endIndex - archivedCount;
|
|
2492
|
+
for (let i = from; i < to; i++) {
|
|
2493
|
+
messages.push(state.messages[i]);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
return { messages, startIndex, endIndex, totalMessageCount: total };
|
|
2497
|
+
}
|
|
2372
2498
|
function rotate(state) {
|
|
2373
2499
|
const messages = state.messages;
|
|
2374
2500
|
if (messages.length === 0) {
|
|
@@ -2428,7 +2554,7 @@ function clearSession(state) {
|
|
|
2428
2554
|
});
|
|
2429
2555
|
}
|
|
2430
2556
|
}
|
|
2431
|
-
var log3, SESSION_FILE, ARCHIVE_DIR, ROTATE_THRESHOLD_BYTES, RETAIN_TAIL_BYTES, ARCHIVE_RETENTION_BYTES;
|
|
2557
|
+
var log3, SESSION_FILE, ARCHIVE_DIR, ROTATE_THRESHOLD_BYTES, RETAIN_TAIL_BYTES, ARCHIVE_RETENTION_BYTES, ARCHIVE_NAME_RE, archiveSortKey, ARCHIVE_COUNT_RE, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, archiveCountCache, archiveMsgCache, ARCHIVE_MSG_CACHE_MAX;
|
|
2432
2558
|
var init_session = __esm({
|
|
2433
2559
|
"src/session.ts"() {
|
|
2434
2560
|
"use strict";
|
|
@@ -2442,6 +2568,14 @@ var init_session = __esm({
|
|
|
2442
2568
|
ROTATE_THRESHOLD_BYTES = 32 * 1024 * 1024;
|
|
2443
2569
|
RETAIN_TAIL_BYTES = 16 * 1024 * 1024;
|
|
2444
2570
|
ARCHIVE_RETENTION_BYTES = 64 * 1024 * 1024;
|
|
2571
|
+
ARCHIVE_NAME_RE = /^(cleared|rotated)-.*\.json$/;
|
|
2572
|
+
archiveSortKey = (name) => name.replace(/^(cleared|rotated)-/, "");
|
|
2573
|
+
ARCHIVE_COUNT_RE = /\.c(\d+)\.json$/;
|
|
2574
|
+
HISTORY_DEFAULT_LIMIT = 500;
|
|
2575
|
+
HISTORY_MAX_LIMIT = 2e3;
|
|
2576
|
+
archiveCountCache = /* @__PURE__ */ new Map();
|
|
2577
|
+
archiveMsgCache = /* @__PURE__ */ new Map();
|
|
2578
|
+
ARCHIVE_MSG_CACHE_MAX = 3;
|
|
2445
2579
|
}
|
|
2446
2580
|
});
|
|
2447
2581
|
|
|
@@ -8839,7 +8973,7 @@ var headless_exports = {};
|
|
|
8839
8973
|
__export(headless_exports, {
|
|
8840
8974
|
HeadlessSession: () => HeadlessSession
|
|
8841
8975
|
});
|
|
8842
|
-
var log15, EXTERNAL_TOOL_TIMEOUT_MS, USER_FACING_TOOLS, FORCED_COMPACTION_THRESHOLD_TOKENS,
|
|
8976
|
+
var log15, EXTERNAL_TOOL_TIMEOUT_MS, USER_FACING_TOOLS, FORCED_COMPACTION_THRESHOLD_TOKENS, HeadlessSession;
|
|
8843
8977
|
var init_headless = __esm({
|
|
8844
8978
|
"src/headless/index.ts"() {
|
|
8845
8979
|
"use strict";
|
|
@@ -8868,8 +9002,6 @@ var init_headless = __esm({
|
|
|
8868
9002
|
"presentPublishPlan"
|
|
8869
9003
|
]);
|
|
8870
9004
|
FORCED_COMPACTION_THRESHOLD_TOKENS = 85e4;
|
|
8871
|
-
HISTORY_DEFAULT_LIMIT = 500;
|
|
8872
|
-
HISTORY_MAX_LIMIT = 2e3;
|
|
8873
9005
|
HeadlessSession = class {
|
|
8874
9006
|
// Configuration
|
|
8875
9007
|
opts;
|
|
@@ -9615,30 +9747,24 @@ var init_headless = __esm({
|
|
|
9615
9747
|
}
|
|
9616
9748
|
if (action === "get_history") {
|
|
9617
9749
|
this.applyPendingBlockUpdates();
|
|
9618
|
-
const
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
const before = typeof rawBefore === "number" && Number.isFinite(rawBefore) ? Math.max(0, Math.min(rawBefore | 0, total)) : total;
|
|
9623
|
-
let startIndex = Math.max(0, before - limit);
|
|
9624
|
-
while (startIndex > 0 && this.state.messages[startIndex].role === "user" && this.state.messages[startIndex].toolCallId) {
|
|
9625
|
-
startIndex--;
|
|
9626
|
-
}
|
|
9627
|
-
const endIndex = before;
|
|
9750
|
+
const page = getHistoryPage(this.state, {
|
|
9751
|
+
...typeof parsed.before === "number" ? { before: parsed.before } : {},
|
|
9752
|
+
...typeof parsed.limit === "number" ? { limit: parsed.limit } : {}
|
|
9753
|
+
});
|
|
9628
9754
|
log15.info("History response", {
|
|
9629
9755
|
requestId,
|
|
9630
|
-
startIndex,
|
|
9631
|
-
endIndex,
|
|
9632
|
-
count: endIndex - startIndex,
|
|
9633
|
-
totalMessageCount:
|
|
9634
|
-
beforeParam:
|
|
9635
|
-
limitParam:
|
|
9756
|
+
startIndex: page.startIndex,
|
|
9757
|
+
endIndex: page.endIndex,
|
|
9758
|
+
count: page.endIndex - page.startIndex,
|
|
9759
|
+
totalMessageCount: page.totalMessageCount,
|
|
9760
|
+
beforeParam: parsed.before,
|
|
9761
|
+
limitParam: parsed.limit
|
|
9636
9762
|
});
|
|
9637
9763
|
this.dispatchSimple(requestId, "history", () => ({
|
|
9638
|
-
messages:
|
|
9639
|
-
startIndex,
|
|
9640
|
-
endIndex,
|
|
9641
|
-
totalMessageCount:
|
|
9764
|
+
messages: page.messages,
|
|
9765
|
+
startIndex: page.startIndex,
|
|
9766
|
+
endIndex: page.endIndex,
|
|
9767
|
+
totalMessageCount: page.totalMessageCount,
|
|
9642
9768
|
running: this.running,
|
|
9643
9769
|
...this.running && this.currentRequestId ? { currentRequestId: this.currentRequestId } : {},
|
|
9644
9770
|
...this.state.models && { models: this.state.models },
|