@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.
@@ -1,13 +1,14 @@
1
- import { S as STATE_CUSTOM_TYPE, _ as withCanonicalFileSections, a as createInitialState, b as RESUME_MESSAGE_TYPE, c as fileDetailsFromUnknown, d as latestCheckpointArtifactEntry, f as mergeFileDetails, h as projectContextMessages, i as contextDetailsFromUnknown, l as fileOperationsFromMessages, m as parseState, n as checkpointRequestDetails, o as createRequestId, p as parseCheckpointDecision, r as checkpointSummaryFromEntry, s as effectiveThresholds, t as baselineUsageIsSettled, u as isStructuredCheckpoint, v as CHECKPOINT_MESSAGE_TYPE, x as RUNTIME_STATE_MESSAGE_TYPE, y as CONTEXT_MESSAGE_TYPE } from "../compactionPolicy-CDCYTj2b.mjs";
2
- import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/serverFacet";
3
- import { composeRootHooks, defineHook, defineRoot } from "@agimon-ai/po-core/extensionFile";
4
- import { DOOM_CONTEXT_CONTRIBUTIONS_SERVICE, requireDoomContextContributions } from "@agimon-ai/po-core/contextContributions";
5
- import { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from "@agimon-ai/po-core/uiHub";
6
- import { loadDoomConfig } from "@agimon-ai/po-config";
7
- import { createDoomTelemetry } from "@agimon-ai/po-telemetry";
1
+ import { C as STATE_CUSTOM_TYPE, S as RUNTIME_STATE_MESSAGE_TYPE, a as createInitialState, b as CONTEXT_MESSAGE_TYPE, c as effectiveThresholds, d as isStructuredCheckpoint, f as latestCheckpointArtifactEntry, g as projectContextMessages, h as parseState, i as contextDetailsFromUnknown, l as fileDetailsFromUnknown, m as parseCheckpointDecision, n as checkpointRequestDetails, o as createRequestId, p as mergeFileDetails, r as checkpointSummaryFromEntry, s as customMessage, t as baselineUsageIsSettled, u as fileOperationsFromMessages, v as withCanonicalFileSections, x as RESUME_MESSAGE_TYPE, y as CHECKPOINT_MESSAGE_TYPE } from "../compactionPolicy-_WTvdEQ2.mjs";
2
+ import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/serverPlugin";
3
+ import { composeRootHooks, composeRootInjects, defineHook, defineRoot } from "@agimon-ai/po-core/extensionFile";
4
+ import { ArtifactAccessError, COMPACTION_ARTIFACT_DIRECTORY, artifactRoot, listArtifacts, openArtifact, readArtifactBytes, removeArtifact, writeArtifactText } from "@agimon-ai/po-artifact/artifactFiles";
5
+ import { PO_CONTEXT_CONTRIBUTIONS_SERVICE, requirePoContextContributions } from "@agimon-ai/po-core/contextContributions";
6
+ import { PO_UI_HUB_SERVICE, requirePoUiHub } from "@agimon-ai/po-core/uiHub";
7
+ import { loadPoConfig } from "@agimon-ai/po-config";
8
+ import { createPoTelemetry } from "@agimon-ai/po-telemetry";
8
9
  import { minimatch } from "minimatch";
9
- const FOOTER_SOURCE = "doom-autocompact";
10
- const STATUS_KEY = "doom-autocompact";
10
+ const FOOTER_SOURCE = "po-autocompact";
11
+ const STATUS_KEY = "po-autocompact";
11
12
  //#endregion
12
13
  //#region src/services/autocompactRuntime/index.ts
13
14
  function errorMessage(error) {
@@ -37,7 +38,7 @@ function readContextContributionsSnapshot(service) {
37
38
  return {
38
39
  entries: [],
39
40
  errors: [{
40
- source: DOOM_CONTEXT_CONTRIBUTIONS_SERVICE,
41
+ source: PO_CONTEXT_CONTRIBUTIONS_SERVICE,
41
42
  id: "service-snapshot",
42
43
  label: "Context contributions",
43
44
  order: 0,
@@ -63,7 +64,7 @@ function formatRuntimeState(snapshot) {
63
64
  return `<compaction-runtime-state>
64
65
  Authoritative runtime state captured when compaction committed. Use it to resume coordination without reconstructing state from the summary.
65
66
  <active-plan>
66
- ${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by Doom Plan.` : "(no active plan document)"}
67
+ ${snapshot.planPath ? `Source: ${snapshot.planPath}\nExact plan content is restored separately by Po Plan.` : "(no active plan document)"}
67
68
  </active-plan>
68
69
  <context-contributions>
69
70
  ${formatContextContributions({
@@ -93,7 +94,7 @@ ${importantContext.length > 0 ? importantContext.join("\n") : "(none recorded ou
93
94
  }
94
95
  function checkpointInstructions(pass, steering) {
95
96
  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" : "";
96
- return `Create Doom autocompact checkpoint pass ${pass}.
97
+ return `Create Po autocompact checkpoint pass ${pass}.
97
98
 
98
99
  ${steeringEnvelope(steering)}
99
100
 
@@ -117,7 +118,7 @@ const DEFAULT_RUNTIME_CONFIG = {
117
118
  overrides: []
118
119
  };
119
120
  /**
120
- * What the Doom config says about this package.
121
+ * What the Po config says about this package.
121
122
  *
122
123
  * `modes.autocompact` is read first and `modes.planning.subagents` is the
123
124
  * fallback, because summarization borrowed the planning subagent model before
@@ -126,9 +127,9 @@ const DEFAULT_RUNTIME_CONFIG = {
126
127
  function autocompactRuntimeConfig(root, onLoadFailure) {
127
128
  let modes;
128
129
  try {
129
- modes = loadDoomConfig(root).modes;
130
+ modes = loadPoConfig(root).modes;
130
131
  } catch (error) {
131
- process.emitWarning("Doom autocompact configuration could not be loaded; using the active session model instead.");
132
+ process.emitWarning("Po autocompact configuration could not be loaded; using the active session model instead.");
132
133
  onLoadFailure?.(error);
133
134
  return DEFAULT_RUNTIME_CONFIG;
134
135
  }
@@ -151,23 +152,24 @@ function autocompactRuntimeConfig(root, onLoadFailure) {
151
152
  }
152
153
  //#endregion
153
154
  //#region src/services/autocompactTelemetry/index.ts
154
- const SERVICE_NAME = "doom-autocompact";
155
+ const SERVICE_NAME = "po-autocompact";
155
156
  const PACKAGE_NAME = "@agimon-ai/po-autocompact";
156
157
  const AUTOCOMPACT_EVENT = {
157
- checkpointStarted: "doom_autocompact.checkpoint_started",
158
- checkpointCompleted: "doom_autocompact.checkpoint_completed",
159
- checkpointFailed: "doom_autocompact.checkpoint_failed",
160
- checkpointInvalid: "doom_autocompact.checkpoint_invalid",
161
- configurationLoadFailed: "doom_autocompact.configuration_load_failed",
162
- contextContributionDegraded: "doom_autocompact.context_contribution_degraded",
163
- contextCommitted: "doom_autocompact.context_committed",
164
- contextApplied: "doom_autocompact.context_applied",
165
- contextMarkerInvalid: "doom_autocompact.context_marker_invalid",
166
- contextHookSlow: "doom_autocompact.context_hook_slow",
167
- nativeCompactionCompleted: "doom_autocompact.native_compaction_completed"
158
+ checkpointStarted: "po_autocompact.checkpoint_started",
159
+ checkpointCompleted: "po_autocompact.checkpoint_completed",
160
+ checkpointFailed: "po_autocompact.checkpoint_failed",
161
+ checkpointInvalid: "po_autocompact.checkpoint_invalid",
162
+ configurationLoadFailed: "po_autocompact.configuration_load_failed",
163
+ contextContributionDegraded: "po_autocompact.context_contribution_degraded",
164
+ contextCommitted: "po_autocompact.context_committed",
165
+ contextApplied: "po_autocompact.context_applied",
166
+ contextMarkerInvalid: "po_autocompact.context_marker_invalid",
167
+ contextHookSlow: "po_autocompact.context_hook_slow",
168
+ nativeCompactionCompleted: "po_autocompact.native_compaction_completed",
169
+ historyWriteFailed: "po_autocompact.history_write_failed"
168
170
  };
169
171
  function createAutocompactTelemetry(options = {}) {
170
- const telemetry = createDoomTelemetry({
172
+ const telemetry = createPoTelemetry({
171
173
  serviceName: SERVICE_NAME,
172
174
  packageName: PACKAGE_NAME,
173
175
  cwd: options.cwd,
@@ -188,6 +190,119 @@ function createAutocompactTelemetry(options = {}) {
188
190
  };
189
191
  }
190
192
  //#endregion
193
+ //#region src/services/compactionHistory/index.ts
194
+ const FORMAT = "po-compaction/1";
195
+ const HEADER = `---\nformat: ${JSON.stringify(FORMAT)}\n`;
196
+ const HISTORY_PATH = new RegExp(`^${COMPACTION_ARTIFACT_DIRECTORY}/(?:epoch-\\d+/(?:summary|checkpoint-\\d+)|in-epoch/checkpoint-\\d+)\\.md$`);
197
+ const NATIVE_PREFIX = "The conversation history before this point was compacted into the following summary:\n\n<summary>\n";
198
+ const NATIVE_SUFFIX = "\n</summary>";
199
+ function historyFile(path, fields, body) {
200
+ const header = Object.entries({
201
+ format: FORMAT,
202
+ ...fields
203
+ }).flatMap(([key, value]) => value === void 0 ? [] : [`${key}: ${JSON.stringify(value)}`]);
204
+ return {
205
+ path: `${COMPACTION_ARTIFACT_DIRECTORY}/${path}`,
206
+ text: `---\n${header.join("\n")}\n---\n\n${body}\n`
207
+ };
208
+ }
209
+ function isoTime(value) {
210
+ const time = new Date(value);
211
+ return Number.isFinite(time.getTime()) ? time.toISOString() : void 0;
212
+ }
213
+ function passOf(value) {
214
+ if (typeof value !== "object" || value === null || !("pass" in value)) return void 0;
215
+ return value.pass === 1 || value.pass === 2 || value.pass === 3 ? value.pass : void 0;
216
+ }
217
+ function committedFields(entry) {
218
+ if (entry.type === "compaction") {
219
+ const summary = entry.summary.trim();
220
+ return {
221
+ body: summary.startsWith(NATIVE_PREFIX) && summary.endsWith(NATIVE_SUFFIX) ? summary.slice(96, -11).trim() : summary,
222
+ fields: {
223
+ source: "compact",
224
+ tokensBefore: entry.tokensBefore > 0 ? entry.tokensBefore : void 0
225
+ }
226
+ };
227
+ }
228
+ const marker = customMessage(entry);
229
+ const details = marker?.customType === "po-autocompact-context" ? contextDetailsFromUnknown(marker.details) : void 0;
230
+ if (!details) return void 0;
231
+ return {
232
+ body: checkpointSummaryFromEntry(entry) ?? "",
233
+ fields: {
234
+ source: "autocompact",
235
+ pass: details.poAutocompact.pass,
236
+ tokensBefore: details.poAutocompact.tokensBefore
237
+ }
238
+ };
239
+ }
240
+ /** Number commits along the active branch so a rewind rewrites the same epoch folders. */
241
+ function wantedHistory(entries) {
242
+ const files = [];
243
+ let staged = [];
244
+ let epoch = 1;
245
+ const checkpoints = (folder) => staged.map(({ entry, summary, pass }, index) => historyFile(`${folder}/checkpoint-${index + 1}.md`, {
246
+ kind: "checkpoint",
247
+ epoch,
248
+ checkpoint: index + 1,
249
+ entryId: entry.id,
250
+ source: "autocompact",
251
+ pass,
252
+ timestamp: isoTime(entry.timestamp)
253
+ }, summary));
254
+ for (const entry of entries) {
255
+ const marker = customMessage(entry);
256
+ if (entry.type === "custom" && entry.customType === "po-autocompact-checkpoint" || marker?.customType === "po-autocompact-checkpoint") {
257
+ const summary = checkpointSummaryFromEntry(entry);
258
+ if (summary) staged.push({
259
+ entry,
260
+ summary,
261
+ pass: passOf(entry.type === "custom" ? entry.data : marker?.details)
262
+ });
263
+ continue;
264
+ }
265
+ const committed = committedFields(entry);
266
+ if (!committed) continue;
267
+ files.push(...checkpoints(`epoch-${epoch}`), historyFile(`epoch-${epoch}/summary.md`, {
268
+ kind: "summary",
269
+ epoch,
270
+ entryId: entry.id,
271
+ ...committed.fields,
272
+ timestamp: isoTime(entry.timestamp)
273
+ }, committed.body));
274
+ staged = [];
275
+ epoch += 1;
276
+ }
277
+ files.push(...checkpoints("in-epoch"));
278
+ return files;
279
+ }
280
+ async function ownedHistory(root, path) {
281
+ const file = await openArtifact(root, path).catch((error) => {
282
+ if (error instanceof ArtifactAccessError && error.status === 404) return void 0;
283
+ throw error;
284
+ });
285
+ if (!file) return false;
286
+ try {
287
+ const bytes = await readArtifactBytes(file.handle, Math.min(file.stat.size, HEADER.length));
288
+ return new TextDecoder().decode(bytes) === HEADER;
289
+ } finally {
290
+ await file.handle.close();
291
+ }
292
+ }
293
+ /** Mirror history into the session artifact folder. Pruning touches only files carrying this mirror's header. */
294
+ async function mirrorCompactionHistory(root, entries) {
295
+ const files = wantedHistory(entries);
296
+ if (files.length === 0) return;
297
+ for (const file of files) await writeArtifactText(root, file.path, file.text);
298
+ const listed = await listArtifacts(root);
299
+ if (listed.error) throw new Error(listed.error);
300
+ const wanted = new Set(files.map((file) => file.path));
301
+ const stale = listed.items.filter((item) => HISTORY_PATH.test(item.path) && !wanted.has(item.path));
302
+ for (const item of stale) if (await ownedHistory(root, item.path)) await removeArtifact(root, item.path);
303
+ for (const folder of new Set(stale.map((item) => item.path.slice(0, item.path.lastIndexOf("/"))))) await removeArtifact(root, folder);
304
+ }
305
+ //#endregion
191
306
  //#region src/services/modelOverrides/index.ts
192
307
  /**
193
308
  * A pattern naming a provider is matched against `provider/id`, anything else
@@ -233,7 +348,7 @@ function tailAfter(snapshot, current) {
233
348
  return current.slice(snapshot.length);
234
349
  }
235
350
  function leaf(entries) {
236
- return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "doom-autocompact-state" && entry.customType !== "doom-autocompact-checkpoint")?.id ?? "root";
351
+ return entries.findLast((entry) => entry.type !== "custom" || entry.customType !== "po-autocompact-state" && entry.customType !== "po-autocompact-checkpoint")?.id ?? "root";
237
352
  }
238
353
  function createNativeAutocompact(dependencies = {}) {
239
354
  const telemetry = dependencies.telemetry ?? createAutocompactTelemetry();
@@ -252,8 +367,11 @@ function createNativeAutocompact(dependencies = {}) {
252
367
  let configFailureReported = false;
253
368
  let footer;
254
369
  let navigating = false;
370
+ let degraded = false;
255
371
  let lastNativeCompactionId;
256
372
  let checkpointBoundary;
373
+ let mirrorQueued = false;
374
+ let historyWarnedSession;
257
375
  const attributes = () => ({
258
376
  "pi.session.id": context?.sessionId ?? "",
259
377
  "autocompact.cycle": state.cycle,
@@ -289,8 +407,6 @@ function createNativeAutocompact(dependencies = {}) {
289
407
  if (!alive(version)) return;
290
408
  await execution.session.appendCustomEntry(STATE_CUSTOM_TYPE, {
291
409
  ...state,
292
- nativeSnapshot: snapshot,
293
- nativePreviousSnapshot: previousSnapshot,
294
410
  nativeLastCompactionId: lastNativeCompactionId
295
411
  });
296
412
  if (alive(version)) refreshStatus(execution);
@@ -305,6 +421,7 @@ function createNativeAutocompact(dependencies = {}) {
305
421
  };
306
422
  const fail = async (execution, version, error, malformed = false) => {
307
423
  if (!alive(version)) return;
424
+ degraded = true;
308
425
  const eventAttributes = attributes();
309
426
  const attempts = state.invalidAttempts + 1;
310
427
  const pass = state.pass;
@@ -318,28 +435,51 @@ function createNativeAutocompact(dependencies = {}) {
318
435
  state.phase = "waiting";
319
436
  clear();
320
437
  state.lastAttemptLeafId = failedLeaf;
321
- await persist(execution, version);
438
+ const errors = [error];
439
+ try {
440
+ await persist(execution, version);
441
+ } catch (persistError) {
442
+ errors.push(persistError);
443
+ }
322
444
  if (!alive(version)) return;
323
- await execution.client.notify({
324
- body: `Doom autocompact summarization pass ${pass} failed: ${error instanceof Error ? error.message : String(error)}`,
445
+ await Promise.allSettled([Promise.resolve().then(() => execution.client.notify({
446
+ body: `Po autocompact summarization pass ${pass} failed: ${error instanceof Error ? error.message : String(error)}`,
325
447
  level: "error"
326
- });
327
- await telemetry.recordError(malformed ? AUTOCOMPACT_EVENT.checkpointInvalid : AUTOCOMPACT_EVENT.checkpointFailed, error, {
448
+ })), ...errors.map((failure) => Promise.resolve().then(() => telemetry.recordError(malformed ? AUTOCOMPACT_EVENT.checkpointInvalid : AUTOCOMPACT_EVENT.checkpointFailed, failure, {
328
449
  ...eventAttributes,
329
450
  "autocompact.checkpoint.attempts": attempts,
330
451
  "autocompact.checkpoint.exhausted": attempts >= 3
331
- });
452
+ })))]);
332
453
  };
333
454
  const branch = async (execution) => await execution.session.entries();
334
455
  const canonical = async (execution, entries) => {
335
456
  if (!execution.session.contextMessages) throw new Error("Canonical context is unavailable for autocompact.");
336
457
  return projectContextMessages(await execution.session.contextMessages(), entries).messages;
337
458
  };
459
+ const scheduleMirror = (execution) => {
460
+ if (mirrorQueued) return;
461
+ mirrorQueued = true;
462
+ enqueue(async () => {
463
+ mirrorQueued = false;
464
+ try {
465
+ await mirrorCompactionHistory(artifactRoot(execution.sessionId, execution.environment), await branch(execution));
466
+ } catch (error) {
467
+ const warn = historyWarnedSession !== execution.sessionId;
468
+ historyWarnedSession = execution.sessionId;
469
+ await Promise.allSettled([Promise.resolve().then(() => telemetry.recordWarning(AUTOCOMPACT_EVENT.historyWriteFailed, error, attributes())), ...warn ? [Promise.resolve().then(() => execution.client.notify({
470
+ body: `Po autocompact could not save compaction history: ${error instanceof Error ? error.message : String(error)}`,
471
+ level: "warning"
472
+ }))] : []]);
473
+ }
474
+ }).finally(() => {
475
+ mirrorQueued = false;
476
+ });
477
+ };
338
478
  const contributionSnapshot = async (execution) => {
339
479
  const result = readContextContributionsSnapshot(contributions);
340
480
  for (const error of result.errors) {
341
481
  await execution.client.notify({
342
- body: `Doom autocompact context contribution degraded (${error.source}/${error.id}): ${error.message}`,
482
+ body: `Po autocompact context contribution degraded (${error.source}/${error.id}): ${error.message}`,
343
483
  level: "warning"
344
484
  });
345
485
  await telemetry.recordWarning(AUTOCOMPACT_EVENT.contextContributionDegraded, new Error(error.message), {
@@ -369,6 +509,54 @@ function createNativeAutocompact(dependencies = {}) {
369
509
  "autocompact.runtime.contribution_error_count": saved.contributionErrors.length
370
510
  };
371
511
  };
512
+ const summaryModel = async (execution, configuration) => {
513
+ const ownReference = configuration.agent?.model ? parseModelReference(configuration.agent.model) : void 0;
514
+ const candidate = ownReference ? `${ownReference.provider}/${ownReference.modelId}` : void 0;
515
+ const reference = candidate && execution.textCompletion.available(candidate) ? candidate : execution.model ? `${execution.model.provider}/${execution.model.id}` : "";
516
+ return {
517
+ reference,
518
+ thinking: configuration.agent?.thinking ?? (reference === candidate ? ownReference?.thinking : void 0) ?? (await execution.session.readModelSettings?.())?.thinkingLevel
519
+ };
520
+ };
521
+ const manualCompaction = async (event, execution) => {
522
+ const configuration = configured(execution);
523
+ if (!configuration.enabled || !execution.textCompletion?.summarize) return;
524
+ try {
525
+ const entries = await branch(execution);
526
+ const messages = await canonical(execution, entries);
527
+ const delta = state.pass > 1 && previousSnapshot ? tailAfter(previousSnapshot, messages) : void 0;
528
+ const previous = state.pass > 1 ? checkpointSummaryFromEntry(latestCheckpointArtifactEntry(entries)) : void 0;
529
+ const { reference, thinking } = await summaryModel(execution, configuration);
530
+ const instructions = checkpointInstructions(3, {
531
+ plan: latestPlanSnapshot(entries),
532
+ contextContributions: await contributionSnapshot(execution),
533
+ readFiles: state.readFiles,
534
+ modifiedFiles: state.modifiedFiles
535
+ });
536
+ const { summary } = parseCheckpointDecision(await execution.textCompletion.summarize(reference, {
537
+ messages: delta ?? messages,
538
+ instructions: typeof event.instructions === "string" && event.instructions.trim() ? `${instructions}\n\n${event.instructions}` : instructions,
539
+ ...previous ? { previousSummary: previous } : {},
540
+ ...thinking ? { thinkingLevel: thinking } : {},
541
+ ...execution.signal ? { signal: execution.signal } : {}
542
+ }));
543
+ if (!isStructuredCheckpoint(summary)) throw new Error("Summarization returned an incomplete checkpoint.");
544
+ const files = mergeFileDetails(state, fileOperationsFromMessages(messages));
545
+ const usage = await execution.session.contextUsage?.();
546
+ return { compaction: {
547
+ summary: withCanonicalFileSections(summary, files),
548
+ tokensBefore: usage?.tokens ?? 0,
549
+ retainedTail: [],
550
+ details: files
551
+ } };
552
+ } catch (error) {
553
+ await execution.client.notify({
554
+ body: `Po autocompact manual compaction failed: ${error instanceof Error ? error.message : String(error)}`,
555
+ level: "error"
556
+ });
557
+ throw error;
558
+ }
559
+ };
372
560
  const resetCycle = () => {
373
561
  state.phase = "waiting";
374
562
  state.checkpointQueue = [];
@@ -412,13 +600,14 @@ function createNativeAutocompact(dependencies = {}) {
412
600
  state.invalidAttempts = 0;
413
601
  clear();
414
602
  await persist(execution, version);
603
+ scheduleMirror(execution);
415
604
  return false;
416
605
  }
417
606
  if (!execution.session.appendMessage) throw new Error("Checkpoint messages are unavailable.");
418
607
  const files = mergeFileDetails(state, fileOperationsFromMessages(messages));
419
608
  const details = {
420
609
  ...files,
421
- doomAutocompact: {
610
+ poAutocompact: {
422
611
  version: 2,
423
612
  cycle: state.cycle,
424
613
  pass,
@@ -446,6 +635,7 @@ function createNativeAutocompact(dependencies = {}) {
446
635
  state.modifiedFiles = files.modifiedFiles;
447
636
  resetCycle();
448
637
  await persist(execution, version);
638
+ scheduleMirror(execution);
449
639
  if (!alive(version)) return false;
450
640
  await telemetry.recordEvent(AUTOCOMPACT_EVENT.contextCommitted, {
451
641
  ...committedAttributes,
@@ -454,10 +644,19 @@ function createNativeAutocompact(dependencies = {}) {
454
644
  "autocompact.apply_mode": idle ? "idle" : "turn_end",
455
645
  ...runtimeAttributes
456
646
  });
457
- 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, `${RESUME_MESSAGE_TYPE}:${details.doomAutocompact.requestId}`);
647
+ 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, `${RESUME_MESSAGE_TYPE}:${details.poAutocompact.requestId}`);
458
648
  return true;
459
649
  };
460
- const progress = async (execution, allowBusy = false, appendMessage = checkpointBoundary?.appendMessage.bind(checkpointBoundary)) => {
650
+ const ensureCheckpointBoundary = (execution) => {
651
+ if (checkpointBoundary) return;
652
+ if (!execution.session.registerCheckpointBoundary) throw new Error("Native checkpoint boundaries are unavailable.");
653
+ checkpointBoundary = execution.session.registerCheckpointBoundary(async (boundary) => {
654
+ if (!active || navigating || boundary.signal?.aborted) return;
655
+ const current = context ?? execution;
656
+ await enqueue(() => boundary.signal?.aborted ? Promise.resolve() : progress(current, true, boundary.appendMessage.bind(boundary)));
657
+ });
658
+ };
659
+ const advance = async (execution, allowBusy = false, appendMessage = checkpointBoundary?.appendMessage.bind(checkpointBoundary)) => {
461
660
  const version = generation;
462
661
  context = execution;
463
662
  const activity = await execution.session.activity();
@@ -510,20 +709,18 @@ function createNativeAutocompact(dependencies = {}) {
510
709
  delete state.pendingCheckpoint;
511
710
  await persist(execution, version);
512
711
  if (!alive(version)) return;
712
+ degraded = false;
513
713
  controller?.abort();
514
714
  controller = new AbortController();
515
715
  const signal = controller.signal;
516
- const ownReference = configuration.agent?.model ? parseModelReference(configuration.agent.model) : void 0;
517
- const candidate = ownReference ? `${ownReference.provider}/${ownReference.modelId}` : void 0;
518
- const reference = candidate && execution.textCompletion.available(candidate) ? candidate : execution.model ? `${execution.model.provider}/${execution.model.id}` : "";
519
- const thinking = configuration.agent?.thinking ?? (reference === candidate ? ownReference?.thinking : void 0) ?? (await execution.session.readModelSettings?.())?.thinkingLevel;
520
- if (!alive(version)) return;
521
716
  const requestAttributes = {
522
717
  ...attributes(),
523
718
  "autocompact.message_count.before": messages.length
524
719
  };
525
720
  const delta = previousSnapshot ? tailAfter(previousSnapshot, messages) : void 0;
526
- const completion = telemetry.runInSpan("doom_autocompact.checkpoint", requestAttributes, async () => {
721
+ const completion = telemetry.runInSpan("po_autocompact.checkpoint", requestAttributes, async () => {
722
+ const { reference, thinking } = await summaryModel(execution, configuration);
723
+ if (!alive(version) || signal.aborted) return "";
527
724
  await telemetry.recordEvent(AUTOCOMPACT_EVENT.checkpointStarted, requestAttributes);
528
725
  return execution.textCompletion.summarize(reference, {
529
726
  messages: pass > 1 && delta ? delta : messages,
@@ -562,16 +759,21 @@ function createNativeAutocompact(dependencies = {}) {
562
759
  work.add(completion);
563
760
  completion.then(() => work.delete(completion), () => work.delete(completion));
564
761
  };
565
- const restore = async (execution) => {
566
- if (!active) return;
567
- if (!checkpointBoundary) {
568
- if (!execution.session.registerCheckpointBoundary) throw new Error("Native checkpoint boundaries are unavailable.");
569
- checkpointBoundary = execution.session.registerCheckpointBoundary(async (boundary) => {
570
- if (!active || navigating || boundary.signal?.aborted) return;
571
- const current = context ?? execution;
572
- await enqueue(() => boundary.signal?.aborted ? Promise.resolve() : progress(current, true, boundary.appendMessage.bind(boundary)));
573
- });
762
+ const progress = async (execution, allowBusy = false, appendMessage) => {
763
+ const version = generation;
764
+ try {
765
+ ensureCheckpointBoundary(execution);
766
+ await advance(execution, allowBusy, appendMessage);
767
+ } catch (error) {
768
+ try {
769
+ await fail(execution, version, error);
770
+ } finally {
771
+ if (alive(version)) delete state.lastAttemptLeafId;
772
+ }
574
773
  }
774
+ };
775
+ const load = async (execution) => {
776
+ if (!active) return;
575
777
  navigating = false;
576
778
  generation += 1;
577
779
  const version = generation;
@@ -582,7 +784,7 @@ function createNativeAutocompact(dependencies = {}) {
582
784
  invalid.clear();
583
785
  const entries = await branch(execution);
584
786
  if (!alive(version)) return;
585
- const entry = entries.findLast((item) => item.type === "custom" && item.customType === "doom-autocompact-state");
787
+ const entry = entries.findLast((item) => item.type === "custom" && item.customType === "po-autocompact-state");
586
788
  const data = entry?.type === "custom" && entry.data && typeof entry.data === "object" ? entry.data : void 0;
587
789
  state = parseState(data) ?? createInitialState();
588
790
  lastNativeCompactionId = typeof data?.nativeLastCompactionId === "string" ? data.nativeLastCompactionId : void 0;
@@ -593,9 +795,9 @@ function createNativeAutocompact(dependencies = {}) {
593
795
  const artifacts = entries.slice(entry ? entries.indexOf(entry) + 1 : 0);
594
796
  const committed = artifacts.findLast((item) => {
595
797
  const message = item.type === "message" ? item.message : void 0;
596
- if (message?.role !== "custom" || message.customType !== "doom-autocompact-context") return false;
798
+ if (message?.role !== "custom" || message.customType !== "po-autocompact-context") return false;
597
799
  const details = contextDetailsFromUnknown(message.details);
598
- return details !== void 0 && details.doomAutocompact.requestId === state.requestId && details.doomAutocompact.cycle === state.cycle && details.doomAutocompact.pass === state.pass && details.doomAutocompact.snapshotLeafId === state.snapshotLeafId && isStructuredCheckpoint(checkpointSummaryFromEntry(item) ?? "");
800
+ return details !== void 0 && details.poAutocompact.requestId === state.requestId && details.poAutocompact.cycle === state.cycle && details.poAutocompact.pass === state.pass && details.poAutocompact.snapshotLeafId === state.snapshotLeafId && isStructuredCheckpoint(checkpointSummaryFromEntry(item) ?? "");
599
801
  });
600
802
  if (committed?.type === "message" && committed.message.role === "custom") {
601
803
  const details = contextDetailsFromUnknown(committed.message.details);
@@ -604,7 +806,7 @@ function createNativeAutocompact(dependencies = {}) {
604
806
  resetCycle();
605
807
  await persist(execution, version);
606
808
  } else if (artifacts.findLast((item) => {
607
- if (item.type !== "custom" || item.customType !== "doom-autocompact-checkpoint") return false;
809
+ if (item.type !== "custom" || item.customType !== "po-autocompact-checkpoint") return false;
608
810
  const details = item.data;
609
811
  return details?.version === 2 && details.requestId === state.requestId && details.cycle === state.cycle && details.pass === state.pass && isStructuredCheckpoint(checkpointSummaryFromEntry(item) ?? "");
610
812
  }) && (state.pass === 1 || state.pass === 2)) {
@@ -618,12 +820,24 @@ function createNativeAutocompact(dependencies = {}) {
618
820
  await persist(execution, version);
619
821
  }
620
822
  }
621
- if (state.phase !== "waiting" && state.phase !== "checkpoint_ready") {
823
+ if (state.phase !== "waiting" && (state.phase !== "checkpoint_ready" || !snapshot)) {
622
824
  state.phase = "waiting";
623
825
  clear();
826
+ delete state.lastAttemptLeafId;
624
827
  await persist(execution, version);
625
828
  }
626
- if (alive(version)) await enqueue(() => progress(execution));
829
+ if (!alive(version)) return;
830
+ const progressed = enqueue(() => progress(execution));
831
+ scheduleMirror(execution);
832
+ await progressed;
833
+ };
834
+ const restore = async (execution) => {
835
+ const version = generation + 1;
836
+ try {
837
+ await load(execution);
838
+ } catch (error) {
839
+ await fail(execution, version, error);
840
+ }
627
841
  };
628
842
  return {
629
843
  hooks: [
@@ -654,7 +868,11 @@ function createNativeAutocompact(dependencies = {}) {
654
868
  },
655
869
  {
656
870
  event: "session_before_compact",
657
- handle: (event, execution) => active && !navigating && configured(execution).enabled && event.reason === "threshold" && (state.phase === "checkpoint_pending" || state.phase === "checkpoint_ready" || state.baselinePending) ? { cancel: true } : void 0
871
+ handle: (event, execution) => {
872
+ if (!active || navigating) return;
873
+ if (event.reason === "manual") return manualCompaction(event, execution);
874
+ return !degraded && configured(execution).enabled && event.reason === "threshold" && (state.phase === "checkpoint_pending" || state.phase === "checkpoint_ready") ? { cancel: true } : void 0;
875
+ }
658
876
  },
659
877
  {
660
878
  event: "context",
@@ -670,7 +888,7 @@ function createNativeAutocompact(dependencies = {}) {
670
888
  const id = leaf(entries);
671
889
  if (!invalid.has(id)) {
672
890
  invalid.add(id);
673
- await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("Doom autocompact context marker is malformed."), {
891
+ await telemetry.recordError(AUTOCOMPACT_EVENT.contextMarkerInvalid, /* @__PURE__ */ new Error("Po autocompact context marker is malformed."), {
674
892
  ...attributes(),
675
893
  "autocompact.leaf_id": id
676
894
  });
@@ -727,6 +945,7 @@ function createNativeAutocompact(dependencies = {}) {
727
945
  const nativeAttributes = attributes();
728
946
  resetCycle();
729
947
  await persist(execution, version);
948
+ scheduleMirror(execution);
730
949
  if (alive(version)) await telemetry.recordEvent(AUTOCOMPACT_EVENT.nativeCompactionCompleted, {
731
950
  ...nativeAttributes,
732
951
  "autocompact.native.reason": typeof event.reason === "string" ? event.reason : "unknown",
@@ -739,8 +958,8 @@ function createNativeAutocompact(dependencies = {}) {
739
958
  }
740
959
  ],
741
960
  plugin(cordis) {
742
- cordis.inject([DOOM_UI_HUB_SERVICE], (injected) => {
743
- const contribution = requireDoomUiHub(injected).registerFooter({
961
+ cordis.inject([PO_UI_HUB_SERVICE], (injected) => {
962
+ const contribution = requirePoUiHub(injected).registerFooter({
744
963
  source: FOOTER_SOURCE,
745
964
  id: "autocompact",
746
965
  order: 20
@@ -752,8 +971,8 @@ function createNativeAutocompact(dependencies = {}) {
752
971
  if (footer === contribution) footer = void 0;
753
972
  };
754
973
  });
755
- cordis.inject([DOOM_CONTEXT_CONTRIBUTIONS_SERVICE], (injected) => {
756
- const service = requireDoomContextContributions(injected);
974
+ cordis.inject([PO_CONTEXT_CONTRIBUTIONS_SERVICE], (injected) => {
975
+ const service = requirePoContextContributions(injected);
757
976
  contributions = service;
758
977
  return () => {
759
978
  if (contributions === service) contributions = void 0;
@@ -815,11 +1034,12 @@ const via = (identity, value) => value === void 0 ? void 0 : {
815
1034
  ...identity,
816
1035
  ...value
817
1036
  };
818
- const facet = defineServerPlugin({
1037
+ const serverPlugin = defineServerPlugin({
819
1038
  name: "@agimon-ai/po-autocompact",
820
1039
  providerOverrides: composeServerProviderOverrides(root_server_default),
1040
+ injects: composeRootInjects({ session: [root_server_default] }),
821
1041
  session: async (context) => {
822
- const scopeSession = await root_server_default(context);
1042
+ const scopeSession = await context.scopeRoot("session", root_server_default, context);
823
1043
  const contextSession = {
824
1044
  ...context,
825
1045
  root: scopeSession.value
@@ -845,6 +1065,6 @@ const facet = defineServerPlugin({
845
1065
  }
846
1066
  });
847
1067
  //#endregion
848
- export { facet as default, facet };
1068
+ export { serverPlugin as default, serverPlugin };
849
1069
 
850
1070
  //# sourceMappingURL=server.mjs.map