maka-agent 0.2.0-dev.68.20261003 → 0.2.0-dev.70.20261005
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/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/recall.js +13 -14
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +0 -3
- package/node_modules/@maka/runtime/dist/model-history.js +4 -14
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +23 -4
- package/node_modules/@maka/storage/dist/execution-stores.js +10 -0
- package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +74 -5
- package/package.json +1 -1
|
Binary file
|
|
@@ -682,6 +682,18 @@ async function collectHits(deps, input) {
|
|
|
682
682
|
scannedFully = false;
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
|
+
// A narrowed scan needs the corpus count to rank the same way as a full
|
|
686
|
+
// scan. Resolve it before reading transcripts so a declined count cannot
|
|
687
|
+
// discard work and reread every candidate during fallback.
|
|
688
|
+
const storedCorpusSize = deps.countSearchableMessages
|
|
689
|
+
? await deps.countSearchableMessages({ sessionIds: input.sessionIds })
|
|
690
|
+
: null;
|
|
691
|
+
if (input.abortSignal?.aborted)
|
|
692
|
+
return null;
|
|
693
|
+
if (storedCorpusSize === null && !scannedFully) {
|
|
694
|
+
sessionIds = input.sessionIds;
|
|
695
|
+
scannedFully = true;
|
|
696
|
+
}
|
|
685
697
|
const hits = [];
|
|
686
698
|
let counted = 0;
|
|
687
699
|
for (const sessionId of sessionIds) {
|
|
@@ -711,20 +723,7 @@ async function collectHits(deps, input) {
|
|
|
711
723
|
hits.push(hit);
|
|
712
724
|
}
|
|
713
725
|
}
|
|
714
|
-
|
|
715
|
-
// has to come from the store. The full scan takes the same number when the
|
|
716
|
-
// store offers one, which is what keeps a score independent of the path.
|
|
717
|
-
let corpusSize = counted;
|
|
718
|
-
if (deps.countSearchableMessages) {
|
|
719
|
-
corpusSize = await deps.countSearchableMessages({ sessionIds: input.sessionIds });
|
|
720
|
-
if (input.abortSignal?.aborted)
|
|
721
|
-
return null;
|
|
722
|
-
if (corpusSize === null) {
|
|
723
|
-
if (!scannedFully)
|
|
724
|
-
return collectHits(deps, { ...input, forceFullScan: true });
|
|
725
|
-
corpusSize = counted;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
726
|
+
const corpusSize = storedCorpusSize ?? counted;
|
|
728
727
|
return { hits, corpusSize, scannedFully, transcripts };
|
|
729
728
|
}
|
|
730
729
|
/**
|
|
@@ -1127,9 +1127,6 @@ export class AiSdkTurn {
|
|
|
1127
1127
|
}
|
|
1128
1128
|
const requestSystemPromptBase = joinPromptFragments([
|
|
1129
1129
|
systemPrompt,
|
|
1130
|
-
priorUnknownProjection.kind === 'projected'
|
|
1131
|
-
? priorUnknownProjection.systemNotice
|
|
1132
|
-
: undefined,
|
|
1133
1130
|
finalChildSummaryStep ? CHILD_STEP_BUDGET_FINALIZATION_PROMPT : undefined,
|
|
1134
1131
|
toolRuntime.hasSandboxBoundaryDenial() ? SANDBOX_BOUNDARY_DENIED_FOR_TURN : undefined,
|
|
1135
1132
|
sandboxBoundaryFinalizationStep ? SANDBOX_BOUNDARY_FINALIZATION_PROMPT : undefined,
|
|
@@ -177,20 +177,10 @@ export function inspectPriorUnknownToolOutcomes(events, invocations) {
|
|
|
177
177
|
}
|
|
178
178
|
if (outcomes.length === 0)
|
|
179
179
|
return { kind: 'none' };
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
rows.push(`- and ${outcomes.length - 64} more unknown operations`);
|
|
185
|
-
return {
|
|
186
|
-
kind: 'projected',
|
|
187
|
-
outcomes,
|
|
188
|
-
systemNotice: [
|
|
189
|
-
'A prior execution was interrupted after these tools were dispatched. No durable tool results were recorded; their side effects may or may not have happened.',
|
|
190
|
-
'The outcome_unknown tool responses in history are temporary context, not proof of success or failure. Inspect current state before repeating any action.',
|
|
191
|
-
...rows,
|
|
192
|
-
].join('\n'),
|
|
193
|
-
};
|
|
180
|
+
// The unknown is carried only by the request-local tool responses below
|
|
181
|
+
// (appendPriorUnknownToolResponses): the system prompt stays byte-stable,
|
|
182
|
+
// so the provider's cached request prefix is never churned per event.
|
|
183
|
+
return { kind: 'projected', outcomes };
|
|
194
184
|
}
|
|
195
185
|
/** Insert request-only tool responses beside their calls so provider history stays well-formed. */
|
|
196
186
|
export function appendPriorUnknownToolResponses(events, projection) {
|
|
@@ -42,9 +42,23 @@ export class RuntimeReadModel {
|
|
|
42
42
|
async getSessionView(sessionId) {
|
|
43
43
|
const diagnostics = [];
|
|
44
44
|
const inFlightTurnIds = new Set();
|
|
45
|
+
let snapshot;
|
|
46
|
+
if (this.deps.runtimeEventStore.readSessionRuntimeSnapshot) {
|
|
47
|
+
try {
|
|
48
|
+
snapshot = await this.deps.runtimeEventStore.readSessionRuntimeSnapshot(sessionId);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new RuntimeReadModelError('RuntimeEvent Session snapshot read failed', [
|
|
52
|
+
readModelDiagnostic('unsupported_event', 'RuntimeEventStore.readSessionRuntimeSnapshot failed', {
|
|
53
|
+
error: errorMessage(error),
|
|
54
|
+
}),
|
|
55
|
+
]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
45
58
|
let invocations;
|
|
46
59
|
try {
|
|
47
|
-
invocations = (
|
|
60
|
+
invocations = (snapshot?.invocations ??
|
|
61
|
+
(await this.deps.runtimeEventStore.listSessionInvocations(sessionId))).filter((invocation) => isSessionInlineInvocation(invocation.opening));
|
|
48
62
|
}
|
|
49
63
|
catch (error) {
|
|
50
64
|
throw new RuntimeReadModelError('RuntimeReadModel could not list Session invocations', [
|
|
@@ -56,15 +70,20 @@ export class RuntimeReadModel {
|
|
|
56
70
|
if (invocations.length === 0) {
|
|
57
71
|
return this.buildView({ invocations, events: [], diagnostics });
|
|
58
72
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
73
|
+
const durableEventOrdinalById = snapshot?.durableEventOrdinalById ??
|
|
74
|
+
new Map((await this.readSessionRuntimeEventOrdinals(sessionId)).map(({ event, ordinal }) => [
|
|
75
|
+
event.id,
|
|
76
|
+
ordinal,
|
|
77
|
+
]));
|
|
61
78
|
const ordered = [];
|
|
62
79
|
const terminalFacts = [];
|
|
63
80
|
for (let runIndex = 0; runIndex < invocations.length; runIndex += 1) {
|
|
64
81
|
const invocation = invocations[runIndex];
|
|
65
82
|
let runEvents;
|
|
66
83
|
try {
|
|
67
|
-
runEvents =
|
|
84
|
+
runEvents = snapshot
|
|
85
|
+
? (snapshot.eventsByRun.get(invocation.runId) ?? [])
|
|
86
|
+
: await this.deps.runtimeEventStore.readRuntimeEvents(sessionId, invocation.runId);
|
|
68
87
|
}
|
|
69
88
|
catch (error) {
|
|
70
89
|
throw new RuntimeReadModelError('RuntimeEvent ledger read failed', [
|
|
@@ -354,6 +354,11 @@ async function createExecutionStoresForWrite(lease, provider) {
|
|
|
354
354
|
ensureTerminalRuntimeEventDurable: (sessionId, runId, event) => run(() => runtimeEventStore.ensureTerminalRuntimeEventDurable(sessionId, runId, event)),
|
|
355
355
|
ensureRecoveredTerminalRuntimeEventDurable: (sessionId, runId, event, operationIds) => run(() => runtimeEventStore.ensureRecoveredTerminalRuntimeEventDurable(sessionId, runId, event, operationIds)),
|
|
356
356
|
readRuntimeEvents: (sessionId, runId) => run(() => runtimeEventStore.readRuntimeEvents(sessionId, runId)),
|
|
357
|
+
...(runtimeEventStore.readSessionRuntimeSnapshot
|
|
358
|
+
? {
|
|
359
|
+
readSessionRuntimeSnapshot: (sessionId) => run(() => runtimeEventStore.readSessionRuntimeSnapshot(sessionId)),
|
|
360
|
+
}
|
|
361
|
+
: {}),
|
|
357
362
|
scanRuntimeEvents: (sessionId, runId, budget, visit) => run(() => runtimeEventStore.scanRuntimeEvents(sessionId, runId, budget, visit)),
|
|
358
363
|
readRuntimeEventsBounded: (sessionId, runId, budget) => run(() => runtimeEventStore.readRuntimeEventsBounded(sessionId, runId, budget)),
|
|
359
364
|
readImmutableRuntimeEvents: (sessionId, runId) => run(() => runtimeEventStore.readImmutableRuntimeEvents(sessionId, runId)),
|
|
@@ -466,6 +471,11 @@ async function openExecutionStoresForRead(lease, kind, extension) {
|
|
|
466
471
|
},
|
|
467
472
|
runtimeEventStore: {
|
|
468
473
|
readRuntimeEvents: (sessionId, runId) => run(() => runtimeEventStore.readRuntimeEvents(sessionId, runId)),
|
|
474
|
+
...(runtimeEventStore.readSessionRuntimeSnapshot
|
|
475
|
+
? {
|
|
476
|
+
readSessionRuntimeSnapshot: (sessionId) => run(() => runtimeEventStore.readSessionRuntimeSnapshot(sessionId)),
|
|
477
|
+
}
|
|
478
|
+
: {}),
|
|
469
479
|
readRuntimeEventsBounded: (sessionId, runId, budget) => run(() => runtimeEventStore.readRuntimeEventsBounded(sessionId, runId, budget)),
|
|
470
480
|
readImmutableRuntimeEvents: (sessionId, runId) => run(() => runtimeEventStore.readImmutableRuntimeEvents(sessionId, runId)),
|
|
471
481
|
listSessionInvocations: (sessionId) => run(() => runtimeEventStore.listSessionInvocations(sessionId)),
|
|
@@ -39,6 +39,7 @@ export async function openRuntimeEventReadPersistence(input) {
|
|
|
39
39
|
return {
|
|
40
40
|
kind: 'sqlite',
|
|
41
41
|
runtimeEventStore: Object.freeze({
|
|
42
|
+
readSessionRuntimeSnapshot: (sessionId) => store.readSessionRuntimeSnapshot(sessionId),
|
|
42
43
|
listSessionInvocations: (sessionId) => store.listSessionInvocations(sessionId),
|
|
43
44
|
listInvocationRecoveryInventory: (sessionIds) => store.listInvocationRecoveryInventory(sessionIds),
|
|
44
45
|
readRunInvocation: (sessionId, runId) => store.readRunInvocation(sessionId, runId),
|
|
@@ -369,6 +369,74 @@ export class SqliteRuntimeStore {
|
|
|
369
369
|
async readRuntimeEvents(sessionId, runId) {
|
|
370
370
|
return this.readRuntimeEventsSync(sessionId, runId);
|
|
371
371
|
}
|
|
372
|
+
async readSessionRuntimeSnapshot(sessionId) {
|
|
373
|
+
assertRuntimeStorageSafeId(sessionId, 'Invalid session id');
|
|
374
|
+
return this.readTransaction(() => {
|
|
375
|
+
const decodedEvents = new Map();
|
|
376
|
+
const openings = this.readInvocationOpeningsSync(sessionId, { direction: 'asc' }, decodedEvents);
|
|
377
|
+
const eventsByRun = new Map();
|
|
378
|
+
const durableEventOrdinalById = new Map();
|
|
379
|
+
if (openings.length === 0) {
|
|
380
|
+
return { invocations: [], eventsByRun, durableEventOrdinalById };
|
|
381
|
+
}
|
|
382
|
+
// Read each payload once. The opening query already decoded its events;
|
|
383
|
+
// reuse those same objects. Global event_seq order also gives each run
|
|
384
|
+
// its immutable order and each invocation its first terminal fact.
|
|
385
|
+
const rows = this.db
|
|
386
|
+
.prepare(`
|
|
387
|
+
SELECT event_id, session_id, invocation_id, run_id, turn_id,
|
|
388
|
+
CASE WHEN event_kind = 'invocation_opened' THEN '' ELSE payload_json END AS payload_json
|
|
389
|
+
FROM runtime_events
|
|
390
|
+
WHERE session_id = ?
|
|
391
|
+
ORDER BY event_seq ASC, event_id ASC
|
|
392
|
+
`)
|
|
393
|
+
.all(sessionId);
|
|
394
|
+
const terminalByInvocation = new Map();
|
|
395
|
+
for (const row of rows) {
|
|
396
|
+
const event = decodedEvents.get(row.event_id) ?? decodeRuntimeEventStorageRow(row);
|
|
397
|
+
const events = eventsByRun.get(event.runId) ?? [];
|
|
398
|
+
events.push(event);
|
|
399
|
+
eventsByRun.set(event.runId, events);
|
|
400
|
+
if (isTerminalRuntimeEvent(event) && !terminalByInvocation.has(event.invocationId)) {
|
|
401
|
+
terminalByInvocation.set(event.invocationId, event);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Only identities and ordinals are needed here, not a second copy of
|
|
405
|
+
// every payload. Keep the same join and identity checks as the entry reader.
|
|
406
|
+
const ordinals = this.db
|
|
407
|
+
.prepare(`
|
|
408
|
+
SELECT o.ordinal, e.event_id, e.session_id
|
|
409
|
+
FROM runtime_session_event_ordinals o
|
|
410
|
+
JOIN runtime_events e ON e.event_id = o.event_id
|
|
411
|
+
WHERE o.session_id = ?
|
|
412
|
+
ORDER BY o.ordinal ASC
|
|
413
|
+
`)
|
|
414
|
+
.all(sessionId);
|
|
415
|
+
for (const row of ordinals) {
|
|
416
|
+
if (!Number.isSafeInteger(row.ordinal) || row.ordinal < 1) {
|
|
417
|
+
throw new Error(`Invalid RuntimeEvent Session ordinal for ${sessionId}`);
|
|
418
|
+
}
|
|
419
|
+
if (row.session_id !== sessionId) {
|
|
420
|
+
throw new Error(`RuntimeEvent Session ordinal identity mismatch for ${row.event_id}`);
|
|
421
|
+
}
|
|
422
|
+
durableEventOrdinalById.set(row.event_id, row.ordinal);
|
|
423
|
+
}
|
|
424
|
+
const partialsByRun = new Map();
|
|
425
|
+
for (const partial of this.readRuntimePartialSnapshotsSync(sessionId)) {
|
|
426
|
+
const partials = partialsByRun.get(partial.event.runId) ?? [];
|
|
427
|
+
partials.push(partial);
|
|
428
|
+
partialsByRun.set(partial.event.runId, partials);
|
|
429
|
+
}
|
|
430
|
+
for (const [runId, partials] of partialsByRun) {
|
|
431
|
+
eventsByRun.set(runId, mergeRuntimePartialSnapshots(eventsByRun.get(runId) ?? [], partials));
|
|
432
|
+
}
|
|
433
|
+
const invocations = openings.map((opening) => {
|
|
434
|
+
const terminalEvent = terminalByInvocation.get(opening.invocationId);
|
|
435
|
+
return { ...opening, ...(terminalEvent ? { terminalEvent } : {}) };
|
|
436
|
+
});
|
|
437
|
+
return { invocations, eventsByRun, durableEventOrdinalById };
|
|
438
|
+
});
|
|
439
|
+
}
|
|
372
440
|
transcriptQuery() {
|
|
373
441
|
return new RuntimeTranscriptQuery(this.db, (sessionId, invocationId) => {
|
|
374
442
|
// By invocation rather than by run: both shelves key their opening on it,
|
|
@@ -692,7 +760,7 @@ export class SqliteRuntimeStore {
|
|
|
692
760
|
* Ordering and paging therefore happen in SQL, and a bounded caller decodes
|
|
693
761
|
* only the openings it asked for.
|
|
694
762
|
*/
|
|
695
|
-
readInvocationOpeningsSync(sessionId, options) {
|
|
763
|
+
readInvocationOpeningsSync(sessionId, options, decodedEvents) {
|
|
696
764
|
const order = options.direction === 'desc' ? 'DESC' : 'ASC';
|
|
697
765
|
const rows = this.db
|
|
698
766
|
.prepare(`
|
|
@@ -767,6 +835,7 @@ export class SqliteRuntimeStore {
|
|
|
767
835
|
if (!opening) {
|
|
768
836
|
throw new Error(`RuntimeEvent ${event.id} is indexed as an opening fact but is not one`);
|
|
769
837
|
}
|
|
838
|
+
decodedEvents?.set(event.id, event);
|
|
770
839
|
return {
|
|
771
840
|
sessionId: event.sessionId,
|
|
772
841
|
invocationId: event.invocationId,
|
|
@@ -958,10 +1027,10 @@ export class SqliteRuntimeStore {
|
|
|
958
1027
|
SELECT stream_key, session_id, invocation_id, run_id, turn_id,
|
|
959
1028
|
payload_json, text_content, after_event_id
|
|
960
1029
|
FROM runtime_partial_snapshots
|
|
961
|
-
WHERE session_id = ? AND run_id = ?
|
|
1030
|
+
WHERE session_id = ? ${runId === undefined ? '' : 'AND run_id = ?'}
|
|
962
1031
|
ORDER BY updated_at ASC, stream_key ASC
|
|
963
1032
|
`)
|
|
964
|
-
.all(sessionId, runId);
|
|
1033
|
+
.all(...(runId === undefined ? [sessionId] : [sessionId, runId]));
|
|
965
1034
|
const segmentText = new Map();
|
|
966
1035
|
const segments = this.db
|
|
967
1036
|
.prepare(`
|
|
@@ -969,10 +1038,10 @@ export class SqliteRuntimeStore {
|
|
|
969
1038
|
FROM runtime_partial_segments AS segment
|
|
970
1039
|
INNER JOIN runtime_partial_snapshots AS snapshot
|
|
971
1040
|
ON snapshot.stream_key = segment.stream_key
|
|
972
|
-
WHERE snapshot.session_id = ? AND snapshot.run_id = ?
|
|
1041
|
+
WHERE snapshot.session_id = ? ${runId === undefined ? '' : 'AND snapshot.run_id = ?'}
|
|
973
1042
|
ORDER BY segment.stream_key ASC, segment.segment_seq ASC
|
|
974
1043
|
`)
|
|
975
|
-
.iterate(sessionId, runId);
|
|
1044
|
+
.iterate(...(runId === undefined ? [sessionId] : [sessionId, runId]));
|
|
976
1045
|
let streamKey;
|
|
977
1046
|
let chunks = [];
|
|
978
1047
|
let tail = [];
|