@agimon-ai/po-autocompact 0.0.0-alpha.2 → 0.0.0-alpha.21
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/LICENSE +149 -21
- package/README.md +4 -4
- package/dist/apiContracts.cjs +1 -1
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.d.mts +1 -1
- package/dist/apiContracts.mjs +1 -1
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/{compactionPolicy-BIJJHcBP.cjs → compactionPolicy-C76UDULA.cjs} +20 -14
- package/dist/compactionPolicy-C76UDULA.cjs.map +1 -0
- package/dist/{compactionPolicy-CDCYTj2b.mjs → compactionPolicy-_WTvdEQ2.mjs} +15 -15
- package/dist/compactionPolicy-_WTvdEQ2.mjs.map +1 -0
- package/dist/extensions/server.cjs +288 -68
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +291 -71
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +1 -1
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/package.json +13 -12
- package/dist/compactionPolicy-BIJJHcBP.cjs.map +0 -1
- package/dist/compactionPolicy-CDCYTj2b.mjs.map +0 -1
|
@@ -2,16 +2,17 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_compactionPolicy = require("../compactionPolicy-
|
|
6
|
-
let
|
|
5
|
+
const require_compactionPolicy = require("../compactionPolicy-C76UDULA.cjs");
|
|
6
|
+
let _agimon_ai_po_core_serverPlugin = require("@agimon-ai/po-core/serverPlugin");
|
|
7
7
|
let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
|
|
8
|
+
let _agimon_ai_po_artifact_artifactFiles = require("@agimon-ai/po-artifact/artifactFiles");
|
|
8
9
|
let _agimon_ai_po_core_contextContributions = require("@agimon-ai/po-core/contextContributions");
|
|
9
10
|
let _agimon_ai_po_core_uiHub = require("@agimon-ai/po-core/uiHub");
|
|
10
11
|
let _agimon_ai_po_config = require("@agimon-ai/po-config");
|
|
11
12
|
let _agimon_ai_po_telemetry = require("@agimon-ai/po-telemetry");
|
|
12
13
|
let minimatch = require("minimatch");
|
|
13
|
-
const FOOTER_SOURCE = "
|
|
14
|
-
const STATUS_KEY = "
|
|
14
|
+
const FOOTER_SOURCE = "po-autocompact";
|
|
15
|
+
const STATUS_KEY = "po-autocompact";
|
|
15
16
|
//#endregion
|
|
16
17
|
//#region src/services/autocompactRuntime/index.ts
|
|
17
18
|
function errorMessage(error) {
|
|
@@ -41,7 +42,7 @@ function readContextContributionsSnapshot(service) {
|
|
|
41
42
|
return {
|
|
42
43
|
entries: [],
|
|
43
44
|
errors: [{
|
|
44
|
-
source: _agimon_ai_po_core_contextContributions.
|
|
45
|
+
source: _agimon_ai_po_core_contextContributions.PO_CONTEXT_CONTRIBUTIONS_SERVICE,
|
|
45
46
|
id: "service-snapshot",
|
|
46
47
|
label: "Context contributions",
|
|
47
48
|
order: 0,
|
|
@@ -67,7 +68,7 @@ function formatRuntimeState(snapshot) {
|
|
|
67
68
|
return `<compaction-runtime-state>
|
|
68
69
|
Authoritative runtime state captured when compaction committed. Use it to resume coordination without reconstructing state from the summary.
|
|
69
70
|
<active-plan>
|
|
70
|
-
${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by
|
|
71
|
+
${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by Po Plan.` : "(no active plan document)"}
|
|
71
72
|
</active-plan>
|
|
72
73
|
<context-contributions>
|
|
73
74
|
${formatContextContributions({
|
|
@@ -97,7 +98,7 @@ ${importantContext.length > 0 ? importantContext.join("\n") : "(none recorded ou
|
|
|
97
98
|
}
|
|
98
99
|
function checkpointInstructions(pass, steering) {
|
|
99
100
|
const decision = pass === 2 ? "Start with exactly <shouldCompact>true</shouldCompact> or <shouldCompact>false</shouldCompact>. Use true when the staged summary safely retains the important parent context. Use false only when it is not yet sufficient for safe compaction.\n\n" : "";
|
|
100
|
-
return `Create
|
|
101
|
+
return `Create Po autocompact checkpoint pass ${pass}.
|
|
101
102
|
|
|
102
103
|
${steeringEnvelope(steering)}
|
|
103
104
|
|
|
@@ -121,7 +122,7 @@ const DEFAULT_RUNTIME_CONFIG = {
|
|
|
121
122
|
overrides: []
|
|
122
123
|
};
|
|
123
124
|
/**
|
|
124
|
-
* What the
|
|
125
|
+
* What the Po config says about this package.
|
|
125
126
|
*
|
|
126
127
|
* `modes.autocompact` is read first and `modes.planning.subagents` is the
|
|
127
128
|
* fallback, because summarization borrowed the planning subagent model before
|
|
@@ -130,9 +131,9 @@ const DEFAULT_RUNTIME_CONFIG = {
|
|
|
130
131
|
function autocompactRuntimeConfig(root, onLoadFailure) {
|
|
131
132
|
let modes;
|
|
132
133
|
try {
|
|
133
|
-
modes = (0, _agimon_ai_po_config.
|
|
134
|
+
modes = (0, _agimon_ai_po_config.loadPoConfig)(root).modes;
|
|
134
135
|
} catch (error) {
|
|
135
|
-
process.emitWarning("
|
|
136
|
+
process.emitWarning("Po autocompact configuration could not be loaded; using the active session model instead.");
|
|
136
137
|
onLoadFailure?.(error);
|
|
137
138
|
return DEFAULT_RUNTIME_CONFIG;
|
|
138
139
|
}
|
|
@@ -155,23 +156,24 @@ function autocompactRuntimeConfig(root, onLoadFailure) {
|
|
|
155
156
|
}
|
|
156
157
|
//#endregion
|
|
157
158
|
//#region src/services/autocompactTelemetry/index.ts
|
|
158
|
-
const SERVICE_NAME = "
|
|
159
|
+
const SERVICE_NAME = "po-autocompact";
|
|
159
160
|
const PACKAGE_NAME = "@agimon-ai/po-autocompact";
|
|
160
161
|
const AUTOCOMPACT_EVENT = {
|
|
161
|
-
checkpointStarted: "
|
|
162
|
-
checkpointCompleted: "
|
|
163
|
-
checkpointFailed: "
|
|
164
|
-
checkpointInvalid: "
|
|
165
|
-
configurationLoadFailed: "
|
|
166
|
-
contextContributionDegraded: "
|
|
167
|
-
contextCommitted: "
|
|
168
|
-
contextApplied: "
|
|
169
|
-
contextMarkerInvalid: "
|
|
170
|
-
contextHookSlow: "
|
|
171
|
-
nativeCompactionCompleted: "
|
|
162
|
+
checkpointStarted: "po_autocompact.checkpoint_started",
|
|
163
|
+
checkpointCompleted: "po_autocompact.checkpoint_completed",
|
|
164
|
+
checkpointFailed: "po_autocompact.checkpoint_failed",
|
|
165
|
+
checkpointInvalid: "po_autocompact.checkpoint_invalid",
|
|
166
|
+
configurationLoadFailed: "po_autocompact.configuration_load_failed",
|
|
167
|
+
contextContributionDegraded: "po_autocompact.context_contribution_degraded",
|
|
168
|
+
contextCommitted: "po_autocompact.context_committed",
|
|
169
|
+
contextApplied: "po_autocompact.context_applied",
|
|
170
|
+
contextMarkerInvalid: "po_autocompact.context_marker_invalid",
|
|
171
|
+
contextHookSlow: "po_autocompact.context_hook_slow",
|
|
172
|
+
nativeCompactionCompleted: "po_autocompact.native_compaction_completed",
|
|
173
|
+
historyWriteFailed: "po_autocompact.history_write_failed"
|
|
172
174
|
};
|
|
173
175
|
function createAutocompactTelemetry(options = {}) {
|
|
174
|
-
const telemetry = (0, _agimon_ai_po_telemetry.
|
|
176
|
+
const telemetry = (0, _agimon_ai_po_telemetry.createPoTelemetry)({
|
|
175
177
|
serviceName: SERVICE_NAME,
|
|
176
178
|
packageName: PACKAGE_NAME,
|
|
177
179
|
cwd: options.cwd,
|
|
@@ -192,6 +194,119 @@ function createAutocompactTelemetry(options = {}) {
|
|
|
192
194
|
};
|
|
193
195
|
}
|
|
194
196
|
//#endregion
|
|
197
|
+
//#region src/services/compactionHistory/index.ts
|
|
198
|
+
const FORMAT = "po-compaction/1";
|
|
199
|
+
const HEADER = `---\nformat: ${JSON.stringify(FORMAT)}\n`;
|
|
200
|
+
const HISTORY_PATH = new RegExp(`^${_agimon_ai_po_artifact_artifactFiles.COMPACTION_ARTIFACT_DIRECTORY}/(?:epoch-\\d+/(?:summary|checkpoint-\\d+)|in-epoch/checkpoint-\\d+)\\.md$`);
|
|
201
|
+
const NATIVE_PREFIX = "The conversation history before this point was compacted into the following summary:\n\n<summary>\n";
|
|
202
|
+
const NATIVE_SUFFIX = "\n</summary>";
|
|
203
|
+
function historyFile(path, fields, body) {
|
|
204
|
+
const header = Object.entries({
|
|
205
|
+
format: FORMAT,
|
|
206
|
+
...fields
|
|
207
|
+
}).flatMap(([key, value]) => value === void 0 ? [] : [`${key}: ${JSON.stringify(value)}`]);
|
|
208
|
+
return {
|
|
209
|
+
path: `${_agimon_ai_po_artifact_artifactFiles.COMPACTION_ARTIFACT_DIRECTORY}/${path}`,
|
|
210
|
+
text: `---\n${header.join("\n")}\n---\n\n${body}\n`
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function isoTime(value) {
|
|
214
|
+
const time = new Date(value);
|
|
215
|
+
return Number.isFinite(time.getTime()) ? time.toISOString() : void 0;
|
|
216
|
+
}
|
|
217
|
+
function passOf(value) {
|
|
218
|
+
if (typeof value !== "object" || value === null || !("pass" in value)) return void 0;
|
|
219
|
+
return value.pass === 1 || value.pass === 2 || value.pass === 3 ? value.pass : void 0;
|
|
220
|
+
}
|
|
221
|
+
function committedFields(entry) {
|
|
222
|
+
if (entry.type === "compaction") {
|
|
223
|
+
const summary = entry.summary.trim();
|
|
224
|
+
return {
|
|
225
|
+
body: summary.startsWith(NATIVE_PREFIX) && summary.endsWith(NATIVE_SUFFIX) ? summary.slice(96, -11).trim() : summary,
|
|
226
|
+
fields: {
|
|
227
|
+
source: "compact",
|
|
228
|
+
tokensBefore: entry.tokensBefore > 0 ? entry.tokensBefore : void 0
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const marker = require_compactionPolicy.customMessage(entry);
|
|
233
|
+
const details = marker?.customType === "po-autocompact-context" ? require_compactionPolicy.contextDetailsFromUnknown(marker.details) : void 0;
|
|
234
|
+
if (!details) return void 0;
|
|
235
|
+
return {
|
|
236
|
+
body: require_compactionPolicy.checkpointSummaryFromEntry(entry) ?? "",
|
|
237
|
+
fields: {
|
|
238
|
+
source: "autocompact",
|
|
239
|
+
pass: details.poAutocompact.pass,
|
|
240
|
+
tokensBefore: details.poAutocompact.tokensBefore
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Number commits along the active branch so a rewind rewrites the same epoch folders. */
|
|
245
|
+
function wantedHistory(entries) {
|
|
246
|
+
const files = [];
|
|
247
|
+
let staged = [];
|
|
248
|
+
let epoch = 1;
|
|
249
|
+
const checkpoints = (folder) => staged.map(({ entry, summary, pass }, index) => historyFile(`${folder}/checkpoint-${index + 1}.md`, {
|
|
250
|
+
kind: "checkpoint",
|
|
251
|
+
epoch,
|
|
252
|
+
checkpoint: index + 1,
|
|
253
|
+
entryId: entry.id,
|
|
254
|
+
source: "autocompact",
|
|
255
|
+
pass,
|
|
256
|
+
timestamp: isoTime(entry.timestamp)
|
|
257
|
+
}, summary));
|
|
258
|
+
for (const entry of entries) {
|
|
259
|
+
const marker = require_compactionPolicy.customMessage(entry);
|
|
260
|
+
if (entry.type === "custom" && entry.customType === "po-autocompact-checkpoint" || marker?.customType === "po-autocompact-checkpoint") {
|
|
261
|
+
const summary = require_compactionPolicy.checkpointSummaryFromEntry(entry);
|
|
262
|
+
if (summary) staged.push({
|
|
263
|
+
entry,
|
|
264
|
+
summary,
|
|
265
|
+
pass: passOf(entry.type === "custom" ? entry.data : marker?.details)
|
|
266
|
+
});
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const committed = committedFields(entry);
|
|
270
|
+
if (!committed) continue;
|
|
271
|
+
files.push(...checkpoints(`epoch-${epoch}`), historyFile(`epoch-${epoch}/summary.md`, {
|
|
272
|
+
kind: "summary",
|
|
273
|
+
epoch,
|
|
274
|
+
entryId: entry.id,
|
|
275
|
+
...committed.fields,
|
|
276
|
+
timestamp: isoTime(entry.timestamp)
|
|
277
|
+
}, committed.body));
|
|
278
|
+
staged = [];
|
|
279
|
+
epoch += 1;
|
|
280
|
+
}
|
|
281
|
+
files.push(...checkpoints("in-epoch"));
|
|
282
|
+
return files;
|
|
283
|
+
}
|
|
284
|
+
async function ownedHistory(root, path) {
|
|
285
|
+
const file = await (0, _agimon_ai_po_artifact_artifactFiles.openArtifact)(root, path).catch((error) => {
|
|
286
|
+
if (error instanceof _agimon_ai_po_artifact_artifactFiles.ArtifactAccessError && error.status === 404) return void 0;
|
|
287
|
+
throw error;
|
|
288
|
+
});
|
|
289
|
+
if (!file) return false;
|
|
290
|
+
try {
|
|
291
|
+
const bytes = await (0, _agimon_ai_po_artifact_artifactFiles.readArtifactBytes)(file.handle, Math.min(file.stat.size, HEADER.length));
|
|
292
|
+
return new TextDecoder().decode(bytes) === HEADER;
|
|
293
|
+
} finally {
|
|
294
|
+
await file.handle.close();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/** Mirror history into the session artifact folder. Pruning touches only files carrying this mirror's header. */
|
|
298
|
+
async function mirrorCompactionHistory(root, entries) {
|
|
299
|
+
const files = wantedHistory(entries);
|
|
300
|
+
if (files.length === 0) return;
|
|
301
|
+
for (const file of files) await (0, _agimon_ai_po_artifact_artifactFiles.writeArtifactText)(root, file.path, file.text);
|
|
302
|
+
const listed = await (0, _agimon_ai_po_artifact_artifactFiles.listArtifacts)(root);
|
|
303
|
+
if (listed.error) throw new Error(listed.error);
|
|
304
|
+
const wanted = new Set(files.map((file) => file.path));
|
|
305
|
+
const stale = listed.items.filter((item) => HISTORY_PATH.test(item.path) && !wanted.has(item.path));
|
|
306
|
+
for (const item of stale) if (await ownedHistory(root, item.path)) await (0, _agimon_ai_po_artifact_artifactFiles.removeArtifact)(root, item.path);
|
|
307
|
+
for (const folder of new Set(stale.map((item) => item.path.slice(0, item.path.lastIndexOf("/"))))) await (0, _agimon_ai_po_artifact_artifactFiles.removeArtifact)(root, folder);
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
195
310
|
//#region src/services/modelOverrides/index.ts
|
|
196
311
|
/**
|
|
197
312
|
* A pattern naming a provider is matched against `provider/id`, anything else
|
|
@@ -237,7 +352,7 @@ function tailAfter(snapshot, current) {
|
|
|
237
352
|
return current.slice(snapshot.length);
|
|
238
353
|
}
|
|
239
354
|
function leaf(entries) {
|
|
240
|
-
return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "
|
|
355
|
+
return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "po-autocompact-state" && entry.customType !== "po-autocompact-checkpoint")?.id ?? "root";
|
|
241
356
|
}
|
|
242
357
|
function createNativeAutocompact(dependencies = {}) {
|
|
243
358
|
const telemetry = dependencies.telemetry ?? createAutocompactTelemetry();
|
|
@@ -256,8 +371,11 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
256
371
|
let configFailureReported = false;
|
|
257
372
|
let footer;
|
|
258
373
|
let navigating = false;
|
|
374
|
+
let degraded = false;
|
|
259
375
|
let lastNativeCompactionId;
|
|
260
376
|
let checkpointBoundary;
|
|
377
|
+
let mirrorQueued = false;
|
|
378
|
+
let historyWarnedSession;
|
|
261
379
|
const attributes = () => ({
|
|
262
380
|
"pi.session.id": context?.sessionId ?? "",
|
|
263
381
|
"autocompact.cycle": state.cycle,
|
|
@@ -293,8 +411,6 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
293
411
|
if (!alive(version)) return;
|
|
294
412
|
await execution.session.appendCustomEntry(require_compactionPolicy.STATE_CUSTOM_TYPE, {
|
|
295
413
|
...state,
|
|
296
|
-
nativeSnapshot: snapshot,
|
|
297
|
-
nativePreviousSnapshot: previousSnapshot,
|
|
298
414
|
nativeLastCompactionId: lastNativeCompactionId
|
|
299
415
|
});
|
|
300
416
|
if (alive(version)) refreshStatus(execution);
|
|
@@ -309,6 +425,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
309
425
|
};
|
|
310
426
|
const fail = async (execution, version, error, malformed = false) => {
|
|
311
427
|
if (!alive(version)) return;
|
|
428
|
+
degraded = true;
|
|
312
429
|
const eventAttributes = attributes();
|
|
313
430
|
const attempts = state.invalidAttempts + 1;
|
|
314
431
|
const pass = state.pass;
|
|
@@ -322,28 +439,51 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
322
439
|
state.phase = "waiting";
|
|
323
440
|
clear();
|
|
324
441
|
state.lastAttemptLeafId = failedLeaf;
|
|
325
|
-
|
|
442
|
+
const errors = [error];
|
|
443
|
+
try {
|
|
444
|
+
await persist(execution, version);
|
|
445
|
+
} catch (persistError) {
|
|
446
|
+
errors.push(persistError);
|
|
447
|
+
}
|
|
326
448
|
if (!alive(version)) return;
|
|
327
|
-
await execution.client.notify({
|
|
328
|
-
body: `
|
|
449
|
+
await Promise.allSettled([Promise.resolve().then(() => execution.client.notify({
|
|
450
|
+
body: `Po autocompact summarization pass ${pass} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
329
451
|
level: "error"
|
|
330
|
-
})
|
|
331
|
-
await telemetry.recordError(malformed ? AUTOCOMPACT_EVENT.checkpointInvalid : AUTOCOMPACT_EVENT.checkpointFailed, error, {
|
|
452
|
+
})), ...errors.map((failure) => Promise.resolve().then(() => telemetry.recordError(malformed ? AUTOCOMPACT_EVENT.checkpointInvalid : AUTOCOMPACT_EVENT.checkpointFailed, failure, {
|
|
332
453
|
...eventAttributes,
|
|
333
454
|
"autocompact.checkpoint.attempts": attempts,
|
|
334
455
|
"autocompact.checkpoint.exhausted": attempts >= 3
|
|
335
|
-
});
|
|
456
|
+
})))]);
|
|
336
457
|
};
|
|
337
458
|
const branch = async (execution) => await execution.session.entries();
|
|
338
459
|
const canonical = async (execution, entries) => {
|
|
339
460
|
if (!execution.session.contextMessages) throw new Error("Canonical context is unavailable for autocompact.");
|
|
340
461
|
return require_compactionPolicy.projectContextMessages(await execution.session.contextMessages(), entries).messages;
|
|
341
462
|
};
|
|
463
|
+
const scheduleMirror = (execution) => {
|
|
464
|
+
if (mirrorQueued) return;
|
|
465
|
+
mirrorQueued = true;
|
|
466
|
+
enqueue(async () => {
|
|
467
|
+
mirrorQueued = false;
|
|
468
|
+
try {
|
|
469
|
+
await mirrorCompactionHistory((0, _agimon_ai_po_artifact_artifactFiles.artifactRoot)(execution.sessionId, execution.environment), await branch(execution));
|
|
470
|
+
} catch (error) {
|
|
471
|
+
const warn = historyWarnedSession !== execution.sessionId;
|
|
472
|
+
historyWarnedSession = execution.sessionId;
|
|
473
|
+
await Promise.allSettled([Promise.resolve().then(() => telemetry.recordWarning(AUTOCOMPACT_EVENT.historyWriteFailed, error, attributes())), ...warn ? [Promise.resolve().then(() => execution.client.notify({
|
|
474
|
+
body: `Po autocompact could not save compaction history: ${error instanceof Error ? error.message : String(error)}`,
|
|
475
|
+
level: "warning"
|
|
476
|
+
}))] : []]);
|
|
477
|
+
}
|
|
478
|
+
}).finally(() => {
|
|
479
|
+
mirrorQueued = false;
|
|
480
|
+
});
|
|
481
|
+
};
|
|
342
482
|
const contributionSnapshot = async (execution) => {
|
|
343
483
|
const result = readContextContributionsSnapshot(contributions);
|
|
344
484
|
for (const error of result.errors) {
|
|
345
485
|
await execution.client.notify({
|
|
346
|
-
body: `
|
|
486
|
+
body: `Po autocompact context contribution degraded (${error.source}/${error.id}): ${error.message}`,
|
|
347
487
|
level: "warning"
|
|
348
488
|
});
|
|
349
489
|
await telemetry.recordWarning(AUTOCOMPACT_EVENT.contextContributionDegraded, new Error(error.message), {
|
|
@@ -373,6 +513,54 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
373
513
|
"autocompact.runtime.contribution_error_count": saved.contributionErrors.length
|
|
374
514
|
};
|
|
375
515
|
};
|
|
516
|
+
const summaryModel = async (execution, configuration) => {
|
|
517
|
+
const ownReference = configuration.agent?.model ? parseModelReference(configuration.agent.model) : void 0;
|
|
518
|
+
const candidate = ownReference ? `${ownReference.provider}/${ownReference.modelId}` : void 0;
|
|
519
|
+
const reference = candidate && execution.textCompletion.available(candidate) ? candidate : execution.model ? `${execution.model.provider}/${execution.model.id}` : "";
|
|
520
|
+
return {
|
|
521
|
+
reference,
|
|
522
|
+
thinking: configuration.agent?.thinking ?? (reference === candidate ? ownReference?.thinking : void 0) ?? (await execution.session.readModelSettings?.())?.thinkingLevel
|
|
523
|
+
};
|
|
524
|
+
};
|
|
525
|
+
const manualCompaction = async (event, execution) => {
|
|
526
|
+
const configuration = configured(execution);
|
|
527
|
+
if (!configuration.enabled || !execution.textCompletion?.summarize) return;
|
|
528
|
+
try {
|
|
529
|
+
const entries = await branch(execution);
|
|
530
|
+
const messages = await canonical(execution, entries);
|
|
531
|
+
const delta = state.pass > 1 && previousSnapshot ? tailAfter(previousSnapshot, messages) : void 0;
|
|
532
|
+
const previous = state.pass > 1 ? require_compactionPolicy.checkpointSummaryFromEntry(require_compactionPolicy.latestCheckpointArtifactEntry(entries)) : void 0;
|
|
533
|
+
const { reference, thinking } = await summaryModel(execution, configuration);
|
|
534
|
+
const instructions = checkpointInstructions(3, {
|
|
535
|
+
plan: latestPlanSnapshot(entries),
|
|
536
|
+
contextContributions: await contributionSnapshot(execution),
|
|
537
|
+
readFiles: state.readFiles,
|
|
538
|
+
modifiedFiles: state.modifiedFiles
|
|
539
|
+
});
|
|
540
|
+
const { summary } = require_compactionPolicy.parseCheckpointDecision(await execution.textCompletion.summarize(reference, {
|
|
541
|
+
messages: delta ?? messages,
|
|
542
|
+
instructions: typeof event.instructions === "string" && event.instructions.trim() ? `${instructions}\n\n${event.instructions}` : instructions,
|
|
543
|
+
...previous ? { previousSummary: previous } : {},
|
|
544
|
+
...thinking ? { thinkingLevel: thinking } : {},
|
|
545
|
+
...execution.signal ? { signal: execution.signal } : {}
|
|
546
|
+
}));
|
|
547
|
+
if (!require_compactionPolicy.isStructuredCheckpoint(summary)) throw new Error("Summarization returned an incomplete checkpoint.");
|
|
548
|
+
const files = require_compactionPolicy.mergeFileDetails(state, require_compactionPolicy.fileOperationsFromMessages(messages));
|
|
549
|
+
const usage = await execution.session.contextUsage?.();
|
|
550
|
+
return { compaction: {
|
|
551
|
+
summary: require_compactionPolicy.withCanonicalFileSections(summary, files),
|
|
552
|
+
tokensBefore: usage?.tokens ?? 0,
|
|
553
|
+
retainedTail: [],
|
|
554
|
+
details: files
|
|
555
|
+
} };
|
|
556
|
+
} catch (error) {
|
|
557
|
+
await execution.client.notify({
|
|
558
|
+
body: `Po autocompact manual compaction failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
559
|
+
level: "error"
|
|
560
|
+
});
|
|
561
|
+
throw error;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
376
564
|
const resetCycle = () => {
|
|
377
565
|
state.phase = "waiting";
|
|
378
566
|
state.checkpointQueue = [];
|
|
@@ -416,13 +604,14 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
416
604
|
state.invalidAttempts = 0;
|
|
417
605
|
clear();
|
|
418
606
|
await persist(execution, version);
|
|
607
|
+
scheduleMirror(execution);
|
|
419
608
|
return false;
|
|
420
609
|
}
|
|
421
610
|
if (!execution.session.appendMessage) throw new Error("Checkpoint messages are unavailable.");
|
|
422
611
|
const files = require_compactionPolicy.mergeFileDetails(state, require_compactionPolicy.fileOperationsFromMessages(messages));
|
|
423
612
|
const details = {
|
|
424
613
|
...files,
|
|
425
|
-
|
|
614
|
+
poAutocompact: {
|
|
426
615
|
version: 2,
|
|
427
616
|
cycle: state.cycle,
|
|
428
617
|
pass,
|
|
@@ -450,6 +639,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
450
639
|
state.modifiedFiles = files.modifiedFiles;
|
|
451
640
|
resetCycle();
|
|
452
641
|
await persist(execution, version);
|
|
642
|
+
scheduleMirror(execution);
|
|
453
643
|
if (!alive(version)) return false;
|
|
454
644
|
await telemetry.recordEvent(AUTOCOMPACT_EVENT.contextCommitted, {
|
|
455
645
|
...committedAttributes,
|
|
@@ -458,10 +648,19 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
458
648
|
"autocompact.apply_mode": idle ? "idle" : "turn_end",
|
|
459
649
|
...runtimeAttributes
|
|
460
650
|
});
|
|
461
|
-
if (idle && alive(version)) await execution.session.admitPrompt?.("Asynchronous compaction completed. Continue from the compacted checkpoint's immediate next action without repeating completed work.", "steer", void 0, `${require_compactionPolicy.RESUME_MESSAGE_TYPE}:${details.
|
|
651
|
+
if (idle && alive(version)) await execution.session.admitPrompt?.("Asynchronous compaction completed. Continue from the compacted checkpoint's immediate next action without repeating completed work.", "steer", void 0, `${require_compactionPolicy.RESUME_MESSAGE_TYPE}:${details.poAutocompact.requestId}`);
|
|
462
652
|
return true;
|
|
463
653
|
};
|
|
464
|
-
const
|
|
654
|
+
const ensureCheckpointBoundary = (execution) => {
|
|
655
|
+
if (checkpointBoundary) return;
|
|
656
|
+
if (!execution.session.registerCheckpointBoundary) throw new Error("Native checkpoint boundaries are unavailable.");
|
|
657
|
+
checkpointBoundary = execution.session.registerCheckpointBoundary(async (boundary) => {
|
|
658
|
+
if (!active || navigating || boundary.signal?.aborted) return;
|
|
659
|
+
const current = context ?? execution;
|
|
660
|
+
await enqueue(() => boundary.signal?.aborted ? Promise.resolve() : progress(current, true, boundary.appendMessage.bind(boundary)));
|
|
661
|
+
});
|
|
662
|
+
};
|
|
663
|
+
const advance = async (execution, allowBusy = false, appendMessage = checkpointBoundary?.appendMessage.bind(checkpointBoundary)) => {
|
|
465
664
|
const version = generation;
|
|
466
665
|
context = execution;
|
|
467
666
|
const activity = await execution.session.activity();
|
|
@@ -514,20 +713,18 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
514
713
|
delete state.pendingCheckpoint;
|
|
515
714
|
await persist(execution, version);
|
|
516
715
|
if (!alive(version)) return;
|
|
716
|
+
degraded = false;
|
|
517
717
|
controller?.abort();
|
|
518
718
|
controller = new AbortController();
|
|
519
719
|
const signal = controller.signal;
|
|
520
|
-
const ownReference = configuration.agent?.model ? parseModelReference(configuration.agent.model) : void 0;
|
|
521
|
-
const candidate = ownReference ? `${ownReference.provider}/${ownReference.modelId}` : void 0;
|
|
522
|
-
const reference = candidate && execution.textCompletion.available(candidate) ? candidate : execution.model ? `${execution.model.provider}/${execution.model.id}` : "";
|
|
523
|
-
const thinking = configuration.agent?.thinking ?? (reference === candidate ? ownReference?.thinking : void 0) ?? (await execution.session.readModelSettings?.())?.thinkingLevel;
|
|
524
|
-
if (!alive(version)) return;
|
|
525
720
|
const requestAttributes = {
|
|
526
721
|
...attributes(),
|
|
527
722
|
"autocompact.message_count.before": messages.length
|
|
528
723
|
};
|
|
529
724
|
const delta = previousSnapshot ? tailAfter(previousSnapshot, messages) : void 0;
|
|
530
|
-
const completion = telemetry.runInSpan("
|
|
725
|
+
const completion = telemetry.runInSpan("po_autocompact.checkpoint", requestAttributes, async () => {
|
|
726
|
+
const { reference, thinking } = await summaryModel(execution, configuration);
|
|
727
|
+
if (!alive(version) || signal.aborted) return "";
|
|
531
728
|
await telemetry.recordEvent(AUTOCOMPACT_EVENT.checkpointStarted, requestAttributes);
|
|
532
729
|
return execution.textCompletion.summarize(reference, {
|
|
533
730
|
messages: pass > 1 && delta ? delta : messages,
|
|
@@ -566,16 +763,21 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
566
763
|
work.add(completion);
|
|
567
764
|
completion.then(() => work.delete(completion), () => work.delete(completion));
|
|
568
765
|
};
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
await
|
|
577
|
-
}
|
|
766
|
+
const progress = async (execution, allowBusy = false, appendMessage) => {
|
|
767
|
+
const version = generation;
|
|
768
|
+
try {
|
|
769
|
+
ensureCheckpointBoundary(execution);
|
|
770
|
+
await advance(execution, allowBusy, appendMessage);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
try {
|
|
773
|
+
await fail(execution, version, error);
|
|
774
|
+
} finally {
|
|
775
|
+
if (alive(version)) delete state.lastAttemptLeafId;
|
|
776
|
+
}
|
|
578
777
|
}
|
|
778
|
+
};
|
|
779
|
+
const load = async (execution) => {
|
|
780
|
+
if (!active) return;
|
|
579
781
|
navigating = false;
|
|
580
782
|
generation += 1;
|
|
581
783
|
const version = generation;
|
|
@@ -586,7 +788,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
586
788
|
invalid.clear();
|
|
587
789
|
const entries = await branch(execution);
|
|
588
790
|
if (!alive(version)) return;
|
|
589
|
-
const entry = entries.findLast((item) => item.type === "custom" && item.customType === "
|
|
791
|
+
const entry = entries.findLast((item) => item.type === "custom" && item.customType === "po-autocompact-state");
|
|
590
792
|
const data = entry?.type === "custom" && entry.data && typeof entry.data === "object" ? entry.data : void 0;
|
|
591
793
|
state = require_compactionPolicy.parseState(data) ?? require_compactionPolicy.createInitialState();
|
|
592
794
|
lastNativeCompactionId = typeof data?.nativeLastCompactionId === "string" ? data.nativeLastCompactionId : void 0;
|
|
@@ -597,9 +799,9 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
597
799
|
const artifacts = entries.slice(entry ? entries.indexOf(entry) + 1 : 0);
|
|
598
800
|
const committed = artifacts.findLast((item) => {
|
|
599
801
|
const message = item.type === "message" ? item.message : void 0;
|
|
600
|
-
if (message?.role !== "custom" || message.customType !== "
|
|
802
|
+
if (message?.role !== "custom" || message.customType !== "po-autocompact-context") return false;
|
|
601
803
|
const details = require_compactionPolicy.contextDetailsFromUnknown(message.details);
|
|
602
|
-
return details !== void 0 && details.
|
|
804
|
+
return details !== void 0 && details.poAutocompact.requestId === state.requestId && details.poAutocompact.cycle === state.cycle && details.poAutocompact.pass === state.pass && details.poAutocompact.snapshotLeafId === state.snapshotLeafId && require_compactionPolicy.isStructuredCheckpoint(require_compactionPolicy.checkpointSummaryFromEntry(item) ?? "");
|
|
603
805
|
});
|
|
604
806
|
if (committed?.type === "message" && committed.message.role === "custom") {
|
|
605
807
|
const details = require_compactionPolicy.contextDetailsFromUnknown(committed.message.details);
|
|
@@ -608,7 +810,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
608
810
|
resetCycle();
|
|
609
811
|
await persist(execution, version);
|
|
610
812
|
} else if (artifacts.findLast((item) => {
|
|
611
|
-
if (item.type !== "custom" || item.customType !== "
|
|
813
|
+
if (item.type !== "custom" || item.customType !== "po-autocompact-checkpoint") return false;
|
|
612
814
|
const details = item.data;
|
|
613
815
|
return details?.version === 2 && details.requestId === state.requestId && details.cycle === state.cycle && details.pass === state.pass && require_compactionPolicy.isStructuredCheckpoint(require_compactionPolicy.checkpointSummaryFromEntry(item) ?? "");
|
|
614
816
|
}) && (state.pass === 1 || state.pass === 2)) {
|
|
@@ -622,12 +824,24 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
622
824
|
await persist(execution, version);
|
|
623
825
|
}
|
|
624
826
|
}
|
|
625
|
-
if (state.phase !== "waiting" && state.phase !== "checkpoint_ready") {
|
|
827
|
+
if (state.phase !== "waiting" && (state.phase !== "checkpoint_ready" || !snapshot)) {
|
|
626
828
|
state.phase = "waiting";
|
|
627
829
|
clear();
|
|
830
|
+
delete state.lastAttemptLeafId;
|
|
628
831
|
await persist(execution, version);
|
|
629
832
|
}
|
|
630
|
-
if (alive(version))
|
|
833
|
+
if (!alive(version)) return;
|
|
834
|
+
const progressed = enqueue(() => progress(execution));
|
|
835
|
+
scheduleMirror(execution);
|
|
836
|
+
await progressed;
|
|
837
|
+
};
|
|
838
|
+
const restore = async (execution) => {
|
|
839
|
+
const version = generation + 1;
|
|
840
|
+
try {
|
|
841
|
+
await load(execution);
|
|
842
|
+
} catch (error) {
|
|
843
|
+
await fail(execution, version, error);
|
|
844
|
+
}
|
|
631
845
|
};
|
|
632
846
|
return {
|
|
633
847
|
hooks: [
|
|
@@ -658,7 +872,11 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
658
872
|
},
|
|
659
873
|
{
|
|
660
874
|
event: "session_before_compact",
|
|
661
|
-
handle: (event, execution) =>
|
|
875
|
+
handle: (event, execution) => {
|
|
876
|
+
if (!active || navigating) return;
|
|
877
|
+
if (event.reason === "manual") return manualCompaction(event, execution);
|
|
878
|
+
return !degraded && configured(execution).enabled && event.reason === "threshold" && (state.phase === "checkpoint_pending" || state.phase === "checkpoint_ready") ? { cancel: true } : void 0;
|
|
879
|
+
}
|
|
662
880
|
},
|
|
663
881
|
{
|
|
664
882
|
event: "context",
|
|
@@ -674,7 +892,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
674
892
|
const id = leaf(entries);
|
|
675
893
|
if (!invalid.has(id)) {
|
|
676
894
|
invalid.add(id);
|
|
677
|
-
await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("
|
|
895
|
+
await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("Po autocompact context marker is malformed."), {
|
|
678
896
|
...attributes(),
|
|
679
897
|
"autocompact.leaf_id": id
|
|
680
898
|
});
|
|
@@ -731,6 +949,7 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
731
949
|
const nativeAttributes = attributes();
|
|
732
950
|
resetCycle();
|
|
733
951
|
await persist(execution, version);
|
|
952
|
+
scheduleMirror(execution);
|
|
734
953
|
if (alive(version)) await telemetry.recordEvent(AUTOCOMPACT_EVENT.nativeCompactionCompleted, {
|
|
735
954
|
...nativeAttributes,
|
|
736
955
|
"autocompact.native.reason": typeof event.reason === "string" ? event.reason : "unknown",
|
|
@@ -743,8 +962,8 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
743
962
|
}
|
|
744
963
|
],
|
|
745
964
|
plugin(cordis) {
|
|
746
|
-
cordis.inject([_agimon_ai_po_core_uiHub.
|
|
747
|
-
const contribution = (0, _agimon_ai_po_core_uiHub.
|
|
965
|
+
cordis.inject([_agimon_ai_po_core_uiHub.PO_UI_HUB_SERVICE], (injected) => {
|
|
966
|
+
const contribution = (0, _agimon_ai_po_core_uiHub.requirePoUiHub)(injected).registerFooter({
|
|
748
967
|
source: FOOTER_SOURCE,
|
|
749
968
|
id: "autocompact",
|
|
750
969
|
order: 20
|
|
@@ -756,8 +975,8 @@ function createNativeAutocompact(dependencies = {}) {
|
|
|
756
975
|
if (footer === contribution) footer = void 0;
|
|
757
976
|
};
|
|
758
977
|
});
|
|
759
|
-
cordis.inject([_agimon_ai_po_core_contextContributions.
|
|
760
|
-
const service = (0, _agimon_ai_po_core_contextContributions.
|
|
978
|
+
cordis.inject([_agimon_ai_po_core_contextContributions.PO_CONTEXT_CONTRIBUTIONS_SERVICE], (injected) => {
|
|
979
|
+
const service = (0, _agimon_ai_po_core_contextContributions.requirePoContextContributions)(injected);
|
|
761
980
|
contributions = service;
|
|
762
981
|
return () => {
|
|
763
982
|
if (contributions === service) contributions = void 0;
|
|
@@ -819,11 +1038,12 @@ const via = (identity, value) => value === void 0 ? void 0 : {
|
|
|
819
1038
|
...identity,
|
|
820
1039
|
...value
|
|
821
1040
|
};
|
|
822
|
-
const
|
|
1041
|
+
const serverPlugin = (0, _agimon_ai_po_core_serverPlugin.defineServerPlugin)({
|
|
823
1042
|
name: "@agimon-ai/po-autocompact",
|
|
824
|
-
providerOverrides: (0,
|
|
1043
|
+
providerOverrides: (0, _agimon_ai_po_core_serverPlugin.composeServerProviderOverrides)(root_server_default),
|
|
1044
|
+
injects: (0, _agimon_ai_po_core_extensionFile.composeRootInjects)({ session: [root_server_default] }),
|
|
825
1045
|
session: async (context) => {
|
|
826
|
-
const scopeSession = await root_server_default
|
|
1046
|
+
const scopeSession = await context.scopeRoot("session", root_server_default, context);
|
|
827
1047
|
const contextSession = {
|
|
828
1048
|
...context,
|
|
829
1049
|
root: scopeSession.value
|
|
@@ -849,7 +1069,7 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
|
|
|
849
1069
|
}
|
|
850
1070
|
});
|
|
851
1071
|
//#endregion
|
|
852
|
-
exports.default =
|
|
853
|
-
exports.
|
|
1072
|
+
exports.default = serverPlugin;
|
|
1073
|
+
exports.serverPlugin = serverPlugin;
|
|
854
1074
|
|
|
855
1075
|
//# sourceMappingURL=server.cjs.map
|