@ouro.bot/cli 0.1.0-alpha.346 → 0.1.0-alpha.347
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.json +6 -0
- package/dist/heart/session-events.js +5 -5
- package/dist/mind/context.js +56 -6
- package/dist/senses/cli.js +14 -6
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.347",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Post-turn session persist functions now return the events array directly, eliminating a redundant `loadSession` file read after every CLI TUI turn. `postTurnPersist` returns `SessionEvent[]` and `deferPostTurnPersist` returns `Promise<SessionEvent[]>`, so the CLI sense uses the returned data instead of re-reading the file it just wrote."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.346",
|
|
6
12
|
"changes": [
|
|
@@ -676,11 +676,11 @@ function selectProjectedEventIds(currentMessages, currentEventIds, trimmedMessag
|
|
|
676
676
|
}
|
|
677
677
|
function buildCanonicalSessionEnvelope(options) {
|
|
678
678
|
const existing = options.existing;
|
|
679
|
-
//
|
|
680
|
-
const currentIngressTimes = options.currentMessages.map(getIngressTime);
|
|
681
|
-
const previousMessages =
|
|
682
|
-
const currentMessages =
|
|
683
|
-
const trimmedMessages =
|
|
679
|
+
// Callers pass pre-sanitized messages + pre-captured ingress times.
|
|
680
|
+
const currentIngressTimes = options.currentIngressTimes ?? options.currentMessages.map(getIngressTime);
|
|
681
|
+
const previousMessages = options.previousMessages;
|
|
682
|
+
const currentMessages = options.currentMessages;
|
|
683
|
+
const trimmedMessages = options.trimmedMessages;
|
|
684
684
|
const previousProjectionIds = existing?.projection.eventIds.length
|
|
685
685
|
? [...existing.projection.eventIds]
|
|
686
686
|
: existing?.events.map((event) => event.id) ?? [];
|
package/dist/mind/context.js
CHANGED
|
@@ -39,6 +39,9 @@ exports.saveSession = saveSession;
|
|
|
39
39
|
exports.appendSyntheticAssistantMessage = appendSyntheticAssistantMessage;
|
|
40
40
|
exports.loadSession = loadSession;
|
|
41
41
|
exports.postTurn = postTurn;
|
|
42
|
+
exports.postTurnTrim = postTurnTrim;
|
|
43
|
+
exports.postTurnPersist = postTurnPersist;
|
|
44
|
+
exports.deferPostTurnPersist = deferPostTurnPersist;
|
|
42
45
|
exports.deleteSession = deleteSession;
|
|
43
46
|
const config_1 = require("../heart/config");
|
|
44
47
|
const session_events_1 = require("../heart/session-events");
|
|
@@ -193,12 +196,14 @@ function writeSessionEnvelope(filePath, envelope) {
|
|
|
193
196
|
function saveSession(filePath, messages, lastUsage, state) {
|
|
194
197
|
const existing = (0, session_events_1.loadSessionEnvelopeFile)(filePath);
|
|
195
198
|
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
199
|
+
const currentIngressTimes = messages.map(session_events_1.getIngressTime);
|
|
196
200
|
const sanitized = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
197
201
|
const envelope = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
198
202
|
existing,
|
|
199
203
|
previousMessages,
|
|
200
204
|
currentMessages: sanitized,
|
|
201
205
|
trimmedMessages: sanitized,
|
|
206
|
+
currentIngressTimes,
|
|
202
207
|
recordedAt: new Date().toISOString(),
|
|
203
208
|
lastUsage: lastUsage ?? null,
|
|
204
209
|
state,
|
|
@@ -247,7 +252,19 @@ function loadSession(filePath) {
|
|
|
247
252
|
return null;
|
|
248
253
|
}
|
|
249
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Synchronous post-turn: sanitize, trim (mutates messages in place), and persist to disk.
|
|
257
|
+
* For non-blocking persist, use postTurnTrim() + deferPostTurnPersist() instead.
|
|
258
|
+
*/
|
|
250
259
|
function postTurn(messages, sessPath, usage, hooks, state) {
|
|
260
|
+
const prepared = postTurnTrim(messages, usage, hooks);
|
|
261
|
+
postTurnPersist(sessPath, prepared, usage, state);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Synchronous phase: run hooks, sanitize, trim, and mutate the messages array in place.
|
|
265
|
+
* Returns the data needed by postTurnPersist / deferPostTurnPersist.
|
|
266
|
+
*/
|
|
267
|
+
function postTurnTrim(messages, usage, hooks) {
|
|
251
268
|
const preTrimMessages = [...messages];
|
|
252
269
|
if (hooks?.beforeTrim) {
|
|
253
270
|
try {
|
|
@@ -266,26 +283,59 @@ function postTurn(messages, sessPath, usage, hooks, state) {
|
|
|
266
283
|
}
|
|
267
284
|
}
|
|
268
285
|
const { maxTokens, contextMargin } = (0, config_1.getContextConfig)();
|
|
286
|
+
const currentIngressTimes = messages.map(session_events_1.getIngressTime);
|
|
269
287
|
const currentMessages = (0, session_events_1.sanitizeProviderMessages)(messages);
|
|
270
|
-
const
|
|
271
|
-
messages.splice(0, messages.length, ...
|
|
288
|
+
const trimmedMessages = trimMessages(currentMessages, maxTokens, contextMargin, usage?.input_tokens);
|
|
289
|
+
messages.splice(0, messages.length, ...trimmedMessages);
|
|
290
|
+
return { currentMessages, trimmedMessages, currentIngressTimes, maxTokens, contextMargin };
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Synchronous persist: load existing envelope, build canonical envelope, write to disk.
|
|
294
|
+
*/
|
|
295
|
+
function postTurnPersist(sessPath, prepared, usage, state) {
|
|
272
296
|
const existing = (0, session_events_1.loadSessionEnvelopeFile)(sessPath);
|
|
273
297
|
const previousMessages = existing ? (0, session_events_1.projectProviderMessages)(existing) : [];
|
|
274
298
|
const envelope = (0, session_events_1.buildCanonicalSessionEnvelope)({
|
|
275
299
|
existing,
|
|
276
300
|
previousMessages,
|
|
277
|
-
currentMessages,
|
|
278
|
-
trimmedMessages:
|
|
301
|
+
currentMessages: prepared.currentMessages,
|
|
302
|
+
trimmedMessages: prepared.trimmedMessages,
|
|
303
|
+
currentIngressTimes: prepared.currentIngressTimes,
|
|
279
304
|
recordedAt: new Date().toISOString(),
|
|
280
305
|
lastUsage: usage ?? null,
|
|
281
306
|
state,
|
|
282
307
|
projectionBasis: {
|
|
283
|
-
maxTokens,
|
|
284
|
-
contextMargin,
|
|
308
|
+
maxTokens: prepared.maxTokens,
|
|
309
|
+
contextMargin: prepared.contextMargin,
|
|
285
310
|
inputTokens: usage?.input_tokens ?? null,
|
|
286
311
|
},
|
|
287
312
|
});
|
|
288
313
|
writeSessionEnvelope(sessPath, envelope);
|
|
314
|
+
return envelope.events;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Deferred persist: same as postTurnPersist but runs on the next event loop tick.
|
|
318
|
+
* Returns a promise that resolves when the persist completes.
|
|
319
|
+
*/
|
|
320
|
+
function deferPostTurnPersist(sessPath, prepared, usage, state) {
|
|
321
|
+
return new Promise((resolve) => {
|
|
322
|
+
setImmediate(() => {
|
|
323
|
+
try {
|
|
324
|
+
const events = postTurnPersist(sessPath, prepared, usage, state);
|
|
325
|
+
resolve(events);
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
(0, runtime_1.emitNervesEvent)({
|
|
329
|
+
level: "warn",
|
|
330
|
+
component: "mind",
|
|
331
|
+
event: "mind.deferred_persist_error",
|
|
332
|
+
message: "deferred session persist failed",
|
|
333
|
+
meta: { error: err instanceof Error ? err.message : String(err) },
|
|
334
|
+
});
|
|
335
|
+
resolve([]);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
});
|
|
289
339
|
}
|
|
290
340
|
function deleteSession(filePath) {
|
|
291
341
|
try {
|
package/dist/senses/cli.js
CHANGED
|
@@ -1009,8 +1009,10 @@ async function main(agentName, options) {
|
|
|
1009
1009
|
lastActivityAt: sessionState?.lastFriendActivityAt,
|
|
1010
1010
|
_testInputSource: options?._testInputSource,
|
|
1011
1011
|
onAsyncAssistantMessage: async (messages, _assistantMessage) => {
|
|
1012
|
-
(0, context_1.
|
|
1013
|
-
|
|
1012
|
+
const prepared = (0, context_1.postTurnTrim)(messages);
|
|
1013
|
+
const events = (0, context_1.postTurnPersist)(sessPath, prepared, undefined, sessionState);
|
|
1014
|
+
/* v8 ignore next -- defensive: postTurnPersist always returns events in practice @preserve */
|
|
1015
|
+
sessionEvents = events.length > 0 ? events : sessionEvents;
|
|
1014
1016
|
},
|
|
1015
1017
|
runTurn: async (messages, userInput, callbacks, signal, toolContext, userContent) => {
|
|
1016
1018
|
// Run the full per-turn pipeline: resolve -> gate -> session -> drain -> runAgent -> postTurn -> tokens
|
|
@@ -1022,9 +1024,10 @@ async function main(agentName, options) {
|
|
|
1022
1024
|
/* v8 ignore start -- failover-aware callback wrapper: tested via pipeline integration @preserve */
|
|
1023
1025
|
const failoverAwareCallbacks = {
|
|
1024
1026
|
...callbacks,
|
|
1025
|
-
// Save session after each tool result for crash recovery
|
|
1027
|
+
// Save session after each tool result for crash recovery (deferred to avoid blocking)
|
|
1026
1028
|
onToolResult: (turnMessages) => {
|
|
1027
|
-
(0, context_1.
|
|
1029
|
+
const prepared = (0, context_1.postTurnTrim)(turnMessages);
|
|
1030
|
+
(0, context_1.deferPostTurnPersist)(sessPath, prepared, undefined, sessionState);
|
|
1028
1031
|
},
|
|
1029
1032
|
onError: (error, severity) => {
|
|
1030
1033
|
if (severity === "terminal" && failoverState) {
|
|
@@ -1069,9 +1072,14 @@ async function main(agentName, options) {
|
|
|
1069
1072
|
},
|
|
1070
1073
|
}),
|
|
1071
1074
|
postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
|
|
1072
|
-
(
|
|
1075
|
+
// Trim synchronously (mutates turnMessages for next turn),
|
|
1076
|
+
// then defer envelope build + disk I/O to avoid blocking the TUI.
|
|
1077
|
+
const prepared = (0, context_1.postTurnTrim)(turnMessages, usage, hooks);
|
|
1073
1078
|
sessionState = state;
|
|
1074
|
-
|
|
1079
|
+
(0, context_1.deferPostTurnPersist)(sessionPathArg, prepared, usage, state).then((events) => {
|
|
1080
|
+
/* v8 ignore next -- defensive: deferPostTurnPersist always resolves events in practice @preserve */
|
|
1081
|
+
sessionEvents = events.length > 0 ? events : sessionEvents;
|
|
1082
|
+
});
|
|
1075
1083
|
},
|
|
1076
1084
|
accumulateFriendTokens: tokens_1.accumulateFriendTokens,
|
|
1077
1085
|
signal,
|