@mindstudio-ai/remy 0.1.215 → 0.1.217
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.js +71 -18
- package/dist/index.js +74 -19
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -3631,7 +3631,8 @@ var ALLOWED_MODELS_BY_TYPE = {
|
|
|
3631
3631
|
"gemini-3.1-pro",
|
|
3632
3632
|
"gemini-3-flash",
|
|
3633
3633
|
"gemini-3.5-flash",
|
|
3634
|
-
"grok-build-0.1"
|
|
3634
|
+
"grok-build-0.1",
|
|
3635
|
+
"grok-4.5"
|
|
3635
3636
|
]
|
|
3636
3637
|
// vision: undefined — unconstrained
|
|
3637
3638
|
// image_generation: undefined — unconstrained
|
|
@@ -5722,8 +5723,8 @@ async function compactConversation(messages, apiConfig, system, tools2, model) {
|
|
|
5722
5723
|
log8.info("Compaction complete", { summaries: summaries.length });
|
|
5723
5724
|
return checkpointMessages;
|
|
5724
5725
|
}
|
|
5725
|
-
function findSafeInsertionPoint(messages) {
|
|
5726
|
-
let idx =
|
|
5726
|
+
function findSafeInsertionPoint(messages, fromIndex = messages.length) {
|
|
5727
|
+
let idx = fromIndex;
|
|
5727
5728
|
while (idx > 0) {
|
|
5728
5729
|
const msg = messages[idx - 1];
|
|
5729
5730
|
if (msg.role === "user" && msg.toolCallId) {
|
|
@@ -5732,7 +5733,7 @@ function findSafeInsertionPoint(messages) {
|
|
|
5732
5733
|
break;
|
|
5733
5734
|
}
|
|
5734
5735
|
}
|
|
5735
|
-
if (idx <
|
|
5736
|
+
if (idx < fromIndex && idx > 0) {
|
|
5736
5737
|
const msg = messages[idx - 1];
|
|
5737
5738
|
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
5738
5739
|
const hasToolUse = msg.content.some(
|
|
@@ -6278,6 +6279,8 @@ import path11 from "path";
|
|
|
6278
6279
|
var log12 = createLogger("session");
|
|
6279
6280
|
var SESSION_FILE = ".remy-session.json";
|
|
6280
6281
|
var ARCHIVE_DIR = ".logs/sessions";
|
|
6282
|
+
var ROTATE_THRESHOLD_BYTES = 32 * 1024 * 1024;
|
|
6283
|
+
var RETAIN_TAIL_BYTES = 16 * 1024 * 1024;
|
|
6281
6284
|
function loadSession(state) {
|
|
6282
6285
|
try {
|
|
6283
6286
|
const raw = fs22.readFileSync(SESSION_FILE, "utf-8");
|
|
@@ -6333,36 +6336,86 @@ function sanitizeMessages(messages) {
|
|
|
6333
6336
|
}
|
|
6334
6337
|
return result;
|
|
6335
6338
|
}
|
|
6339
|
+
function buildPayload(state) {
|
|
6340
|
+
const payload = { messages: state.messages };
|
|
6341
|
+
if (state.models && Object.keys(state.models).length > 0) {
|
|
6342
|
+
payload.models = state.models;
|
|
6343
|
+
}
|
|
6344
|
+
return payload;
|
|
6345
|
+
}
|
|
6346
|
+
function archiveMessages(messages, label, models) {
|
|
6347
|
+
fs22.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
6348
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6349
|
+
let dest = path11.join(ARCHIVE_DIR, `${label}-${ts}.json`);
|
|
6350
|
+
let n = 1;
|
|
6351
|
+
while (fs22.existsSync(dest)) {
|
|
6352
|
+
dest = path11.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
|
|
6353
|
+
}
|
|
6354
|
+
const payload = { messages };
|
|
6355
|
+
if (models && Object.keys(models).length > 0) {
|
|
6356
|
+
payload.models = models;
|
|
6357
|
+
}
|
|
6358
|
+
fs22.writeFileSync(dest, JSON.stringify(payload), "utf-8");
|
|
6359
|
+
log12.info("Session archived", { label, dest, messageCount: messages.length });
|
|
6360
|
+
return dest;
|
|
6361
|
+
}
|
|
6362
|
+
function rotate(state) {
|
|
6363
|
+
const messages = state.messages;
|
|
6364
|
+
if (messages.length === 0) {
|
|
6365
|
+
return false;
|
|
6366
|
+
}
|
|
6367
|
+
let tailBytes = 0;
|
|
6368
|
+
let scrollbackStart = 0;
|
|
6369
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
6370
|
+
tailBytes += Buffer.byteLength(JSON.stringify(messages[i]), "utf-8") + 1;
|
|
6371
|
+
if (tailBytes >= RETAIN_TAIL_BYTES) {
|
|
6372
|
+
scrollbackStart = i;
|
|
6373
|
+
break;
|
|
6374
|
+
}
|
|
6375
|
+
}
|
|
6376
|
+
const checkpointIdx = findLastSummaryCheckpoint(messages, "conversation");
|
|
6377
|
+
let cut = checkpointIdx === -1 ? scrollbackStart : Math.min(scrollbackStart, checkpointIdx);
|
|
6378
|
+
cut = findSafeInsertionPoint(messages, cut);
|
|
6379
|
+
if (cut <= 0) {
|
|
6380
|
+
return false;
|
|
6381
|
+
}
|
|
6382
|
+
archiveMessages(messages.slice(0, cut), "rotated", state.models);
|
|
6383
|
+
state.messages = messages.slice(cut);
|
|
6384
|
+
log12.info("Session rotated", {
|
|
6385
|
+
archived: cut,
|
|
6386
|
+
retained: state.messages.length
|
|
6387
|
+
});
|
|
6388
|
+
return true;
|
|
6389
|
+
}
|
|
6336
6390
|
function saveSession(state) {
|
|
6337
6391
|
try {
|
|
6338
|
-
|
|
6339
|
-
if (
|
|
6340
|
-
|
|
6392
|
+
let serialized = JSON.stringify(buildPayload(state));
|
|
6393
|
+
if (Buffer.byteLength(serialized, "utf-8") > ROTATE_THRESHOLD_BYTES && rotate(state)) {
|
|
6394
|
+
serialized = JSON.stringify(buildPayload(state));
|
|
6341
6395
|
}
|
|
6342
|
-
fs22.writeFileSync(SESSION_FILE,
|
|
6396
|
+
fs22.writeFileSync(SESSION_FILE, serialized, "utf-8");
|
|
6343
6397
|
log12.info("Session saved", { messageCount: state.messages.length });
|
|
6344
6398
|
} catch (err) {
|
|
6345
6399
|
log12.warn("Session save failed", { error: err.message });
|
|
6346
6400
|
}
|
|
6347
6401
|
}
|
|
6348
6402
|
function clearSession(state) {
|
|
6403
|
+
try {
|
|
6404
|
+
if (state.messages.length > 0) {
|
|
6405
|
+
archiveMessages(state.messages, "cleared", state.models);
|
|
6406
|
+
}
|
|
6407
|
+
} catch (err) {
|
|
6408
|
+
log12.warn("Session archive on clear failed", { error: err.message });
|
|
6409
|
+
}
|
|
6349
6410
|
state.messages = [];
|
|
6350
6411
|
try {
|
|
6351
6412
|
if (fs22.existsSync(SESSION_FILE)) {
|
|
6352
|
-
fs22.
|
|
6353
|
-
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6354
|
-
const dest = path11.join(ARCHIVE_DIR, `cleared-${ts}.json`);
|
|
6355
|
-
fs22.renameSync(SESSION_FILE, dest);
|
|
6356
|
-
log12.info("Session archived on clear", { dest });
|
|
6413
|
+
fs22.unlinkSync(SESSION_FILE);
|
|
6357
6414
|
}
|
|
6358
6415
|
} catch (err) {
|
|
6359
|
-
log12.warn("Session
|
|
6416
|
+
log12.warn("Session clear: could not remove live file", {
|
|
6360
6417
|
error: err.message
|
|
6361
6418
|
});
|
|
6362
|
-
try {
|
|
6363
|
-
fs22.unlinkSync(SESSION_FILE);
|
|
6364
|
-
} catch {
|
|
6365
|
-
}
|
|
6366
6419
|
}
|
|
6367
6420
|
}
|
|
6368
6421
|
|
package/dist/index.js
CHANGED
|
@@ -1584,8 +1584,8 @@ async function compactConversation(messages, apiConfig, system, tools2, model) {
|
|
|
1584
1584
|
log2.info("Compaction complete", { summaries: summaries.length });
|
|
1585
1585
|
return checkpointMessages;
|
|
1586
1586
|
}
|
|
1587
|
-
function findSafeInsertionPoint(messages) {
|
|
1588
|
-
let idx =
|
|
1587
|
+
function findSafeInsertionPoint(messages, fromIndex = messages.length) {
|
|
1588
|
+
let idx = fromIndex;
|
|
1589
1589
|
while (idx > 0) {
|
|
1590
1590
|
const msg = messages[idx - 1];
|
|
1591
1591
|
if (msg.role === "user" && msg.toolCallId) {
|
|
@@ -1594,7 +1594,7 @@ function findSafeInsertionPoint(messages) {
|
|
|
1594
1594
|
break;
|
|
1595
1595
|
}
|
|
1596
1596
|
}
|
|
1597
|
-
if (idx <
|
|
1597
|
+
if (idx < fromIndex && idx > 0) {
|
|
1598
1598
|
const msg = messages[idx - 1];
|
|
1599
1599
|
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
1600
1600
|
const hasToolUse = msg.content.some(
|
|
@@ -2250,7 +2250,8 @@ var init_surfaces = __esm({
|
|
|
2250
2250
|
"gemini-3.1-pro",
|
|
2251
2251
|
"gemini-3-flash",
|
|
2252
2252
|
"gemini-3.5-flash",
|
|
2253
|
-
"grok-build-0.1"
|
|
2253
|
+
"grok-build-0.1",
|
|
2254
|
+
"grok-4.5"
|
|
2254
2255
|
]
|
|
2255
2256
|
// vision: undefined — unconstrained
|
|
2256
2257
|
// image_generation: undefined — unconstrained
|
|
@@ -6705,46 +6706,100 @@ function sanitizeMessages(messages) {
|
|
|
6705
6706
|
}
|
|
6706
6707
|
return result;
|
|
6707
6708
|
}
|
|
6709
|
+
function buildPayload(state) {
|
|
6710
|
+
const payload = { messages: state.messages };
|
|
6711
|
+
if (state.models && Object.keys(state.models).length > 0) {
|
|
6712
|
+
payload.models = state.models;
|
|
6713
|
+
}
|
|
6714
|
+
return payload;
|
|
6715
|
+
}
|
|
6716
|
+
function archiveMessages(messages, label, models) {
|
|
6717
|
+
fs20.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
6718
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6719
|
+
let dest = path9.join(ARCHIVE_DIR, `${label}-${ts}.json`);
|
|
6720
|
+
let n = 1;
|
|
6721
|
+
while (fs20.existsSync(dest)) {
|
|
6722
|
+
dest = path9.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.json`);
|
|
6723
|
+
}
|
|
6724
|
+
const payload = { messages };
|
|
6725
|
+
if (models && Object.keys(models).length > 0) {
|
|
6726
|
+
payload.models = models;
|
|
6727
|
+
}
|
|
6728
|
+
fs20.writeFileSync(dest, JSON.stringify(payload), "utf-8");
|
|
6729
|
+
log9.info("Session archived", { label, dest, messageCount: messages.length });
|
|
6730
|
+
return dest;
|
|
6731
|
+
}
|
|
6732
|
+
function rotate(state) {
|
|
6733
|
+
const messages = state.messages;
|
|
6734
|
+
if (messages.length === 0) {
|
|
6735
|
+
return false;
|
|
6736
|
+
}
|
|
6737
|
+
let tailBytes = 0;
|
|
6738
|
+
let scrollbackStart = 0;
|
|
6739
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
6740
|
+
tailBytes += Buffer.byteLength(JSON.stringify(messages[i]), "utf-8") + 1;
|
|
6741
|
+
if (tailBytes >= RETAIN_TAIL_BYTES) {
|
|
6742
|
+
scrollbackStart = i;
|
|
6743
|
+
break;
|
|
6744
|
+
}
|
|
6745
|
+
}
|
|
6746
|
+
const checkpointIdx = findLastSummaryCheckpoint(messages, "conversation");
|
|
6747
|
+
let cut = checkpointIdx === -1 ? scrollbackStart : Math.min(scrollbackStart, checkpointIdx);
|
|
6748
|
+
cut = findSafeInsertionPoint(messages, cut);
|
|
6749
|
+
if (cut <= 0) {
|
|
6750
|
+
return false;
|
|
6751
|
+
}
|
|
6752
|
+
archiveMessages(messages.slice(0, cut), "rotated", state.models);
|
|
6753
|
+
state.messages = messages.slice(cut);
|
|
6754
|
+
log9.info("Session rotated", {
|
|
6755
|
+
archived: cut,
|
|
6756
|
+
retained: state.messages.length
|
|
6757
|
+
});
|
|
6758
|
+
return true;
|
|
6759
|
+
}
|
|
6708
6760
|
function saveSession(state) {
|
|
6709
6761
|
try {
|
|
6710
|
-
|
|
6711
|
-
if (
|
|
6712
|
-
|
|
6762
|
+
let serialized = JSON.stringify(buildPayload(state));
|
|
6763
|
+
if (Buffer.byteLength(serialized, "utf-8") > ROTATE_THRESHOLD_BYTES && rotate(state)) {
|
|
6764
|
+
serialized = JSON.stringify(buildPayload(state));
|
|
6713
6765
|
}
|
|
6714
|
-
fs20.writeFileSync(SESSION_FILE,
|
|
6766
|
+
fs20.writeFileSync(SESSION_FILE, serialized, "utf-8");
|
|
6715
6767
|
log9.info("Session saved", { messageCount: state.messages.length });
|
|
6716
6768
|
} catch (err) {
|
|
6717
6769
|
log9.warn("Session save failed", { error: err.message });
|
|
6718
6770
|
}
|
|
6719
6771
|
}
|
|
6720
6772
|
function clearSession(state) {
|
|
6773
|
+
try {
|
|
6774
|
+
if (state.messages.length > 0) {
|
|
6775
|
+
archiveMessages(state.messages, "cleared", state.models);
|
|
6776
|
+
}
|
|
6777
|
+
} catch (err) {
|
|
6778
|
+
log9.warn("Session archive on clear failed", { error: err.message });
|
|
6779
|
+
}
|
|
6721
6780
|
state.messages = [];
|
|
6722
6781
|
try {
|
|
6723
6782
|
if (fs20.existsSync(SESSION_FILE)) {
|
|
6724
|
-
fs20.
|
|
6725
|
-
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6726
|
-
const dest = path9.join(ARCHIVE_DIR, `cleared-${ts}.json`);
|
|
6727
|
-
fs20.renameSync(SESSION_FILE, dest);
|
|
6728
|
-
log9.info("Session archived on clear", { dest });
|
|
6783
|
+
fs20.unlinkSync(SESSION_FILE);
|
|
6729
6784
|
}
|
|
6730
6785
|
} catch (err) {
|
|
6731
|
-
log9.warn("Session
|
|
6786
|
+
log9.warn("Session clear: could not remove live file", {
|
|
6732
6787
|
error: err.message
|
|
6733
6788
|
});
|
|
6734
|
-
try {
|
|
6735
|
-
fs20.unlinkSync(SESSION_FILE);
|
|
6736
|
-
} catch {
|
|
6737
|
-
}
|
|
6738
6789
|
}
|
|
6739
6790
|
}
|
|
6740
|
-
var log9, SESSION_FILE, ARCHIVE_DIR;
|
|
6791
|
+
var log9, SESSION_FILE, ARCHIVE_DIR, ROTATE_THRESHOLD_BYTES, RETAIN_TAIL_BYTES;
|
|
6741
6792
|
var init_session = __esm({
|
|
6742
6793
|
"src/session.ts"() {
|
|
6743
6794
|
"use strict";
|
|
6744
6795
|
init_logger();
|
|
6796
|
+
init_compaction();
|
|
6797
|
+
init_cleanMessages();
|
|
6745
6798
|
log9 = createLogger("session");
|
|
6746
6799
|
SESSION_FILE = ".remy-session.json";
|
|
6747
6800
|
ARCHIVE_DIR = ".logs/sessions";
|
|
6801
|
+
ROTATE_THRESHOLD_BYTES = 32 * 1024 * 1024;
|
|
6802
|
+
RETAIN_TAIL_BYTES = 16 * 1024 * 1024;
|
|
6748
6803
|
}
|
|
6749
6804
|
});
|
|
6750
6805
|
|