@bastani/atomic 0.8.27 → 0.8.28-alpha.1
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.md +22 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +14 -0
- package/dist/builtin/workflows/README.md +11 -9
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/authoring.d.ts +5 -2
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +3 -1
- package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +17 -25
- package/dist/builtin/workflows/src/extension/index.ts +133 -18
- package/dist/builtin/workflows/src/extension/render-result.ts +22 -2
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -3
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +210 -16
- package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
- package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +42 -5
- package/dist/builtin/workflows/src/shared/store-types.ts +8 -2
- package/dist/builtin/workflows/src/shared/store.ts +51 -0
- package/dist/builtin/workflows/src/shared/types.ts +14 -4
- package/dist/builtin/workflows/src/tui/graph-view.ts +4 -1
- package/dist/builtin/workflows/src/tui/prompt-card.ts +6 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +11 -1
- package/dist/core/agent-session.d.ts +4 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +147 -31
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts +10 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +26 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -2
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +7 -7
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -84
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +3 -479
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-compaction.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction.js +39 -82
- package/dist/core/compaction/context-compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +10 -8
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +1 -11
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +10 -25
- package/dist/core/messages.js.map +1 -1
- package/dist/core/session-manager.d.ts +5 -8
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -76
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +0 -4
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -5
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +5 -9
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +0 -3
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +4 -27
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +2 -2
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +0 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/compaction.md +210 -181
- package/docs/extensions.md +31 -20
- package/docs/json.md +3 -4
- package/docs/session-format.md +12 -21
- package/docs/sessions.md +3 -1
- package/docs/settings.md +2 -5
- package/docs/workflows.md +11 -9
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-compaction.ts +43 -106
- package/examples/extensions/handoff.ts +6 -44
- package/examples/extensions/trigger-compact.ts +5 -4
- package/package.json +5 -5
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +0 -43
- package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
|
@@ -4,7 +4,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { Type } from "typebox";
|
|
7
|
-
import { createBranchSummaryMessage,
|
|
7
|
+
import { createBranchSummaryMessage, createCustomMessage } from "../messages.js";
|
|
8
8
|
import { buildContextDeletionFilteredPath, buildContextDeletionFilters, } from "../session-manager.js";
|
|
9
9
|
import { estimateTokens } from "./compaction.js";
|
|
10
10
|
export const CONTEXT_COMPACTION_PROMPT_VERSION = 1;
|
|
@@ -216,19 +216,6 @@ function getToolResultCallId(message) {
|
|
|
216
216
|
return typeof callId === "string" ? callId : undefined;
|
|
217
217
|
}
|
|
218
218
|
function contentBlocksForEntry(entryId, message, protectedEntry, existingDeletedBlocks) {
|
|
219
|
-
if (message.role === "compactionSummary") {
|
|
220
|
-
const text = message.summary;
|
|
221
|
-
return [
|
|
222
|
-
{
|
|
223
|
-
entryId,
|
|
224
|
-
blockIndex: 0,
|
|
225
|
-
type: "summary",
|
|
226
|
-
text,
|
|
227
|
-
tokenEstimate: estimateTextTokens(text),
|
|
228
|
-
protected: protectedEntry,
|
|
229
|
-
},
|
|
230
|
-
];
|
|
231
|
-
}
|
|
232
219
|
const content = message.content;
|
|
233
220
|
if (!Array.isArray(content))
|
|
234
221
|
return [];
|
|
@@ -256,7 +243,6 @@ function messageText(message) {
|
|
|
256
243
|
case "bashExecution":
|
|
257
244
|
return `Ran ${message.command}\n${message.output}`;
|
|
258
245
|
case "branchSummary":
|
|
259
|
-
case "compactionSummary":
|
|
260
246
|
return message.summary;
|
|
261
247
|
case "custom":
|
|
262
248
|
case "toolResult":
|
|
@@ -264,6 +250,17 @@ function messageText(message) {
|
|
|
264
250
|
return textFromUnknownContent(message.content);
|
|
265
251
|
case "assistant":
|
|
266
252
|
return textFromUnknownContent(message.content);
|
|
253
|
+
case "compactionSummary":
|
|
254
|
+
// Legacy summary-compaction message type retained in the upstream AgentMessage union
|
|
255
|
+
// after summary compaction was removed; surface its archival summary text.
|
|
256
|
+
return message.summary;
|
|
257
|
+
default: {
|
|
258
|
+
// Exhaustiveness guard: adding a new AgentMessage role must fail the build here instead
|
|
259
|
+
// of silently degrading to an empty string.
|
|
260
|
+
const _exhaustiveCheck = message;
|
|
261
|
+
void _exhaustiveCheck;
|
|
262
|
+
return "";
|
|
263
|
+
}
|
|
267
264
|
}
|
|
268
265
|
}
|
|
269
266
|
function hasAssistantError(message) {
|
|
@@ -275,35 +272,6 @@ function hasToolResultError(message) {
|
|
|
275
272
|
function hasFailedBashExecution(message) {
|
|
276
273
|
return message.role === "bashExecution" && typeof message.exitCode === "number" && message.exitCode !== 0;
|
|
277
274
|
}
|
|
278
|
-
function collectLatestSummaryCompactionIndex(pathEntries) {
|
|
279
|
-
for (let i = pathEntries.length - 1; i >= 0; i--) {
|
|
280
|
-
if (pathEntries[i].type === "compaction")
|
|
281
|
-
return i;
|
|
282
|
-
}
|
|
283
|
-
return -1;
|
|
284
|
-
}
|
|
285
|
-
function collectActiveEntryIndices(pathEntries, latestCompactionIndex) {
|
|
286
|
-
if (latestCompactionIndex < 0) {
|
|
287
|
-
return pathEntries.map((_, index) => index);
|
|
288
|
-
}
|
|
289
|
-
const latestCompaction = pathEntries[latestCompactionIndex];
|
|
290
|
-
if (latestCompaction.type !== "compaction")
|
|
291
|
-
return pathEntries.map((_, index) => index);
|
|
292
|
-
const indices = [];
|
|
293
|
-
let foundFirstKept = false;
|
|
294
|
-
for (let i = 0; i < latestCompactionIndex; i++) {
|
|
295
|
-
const entry = pathEntries[i];
|
|
296
|
-
if (entry.id === latestCompaction.firstKeptEntryId) {
|
|
297
|
-
foundFirstKept = true;
|
|
298
|
-
}
|
|
299
|
-
if (foundFirstKept)
|
|
300
|
-
indices.push(i);
|
|
301
|
-
}
|
|
302
|
-
for (let i = latestCompactionIndex + 1; i < pathEntries.length; i++) {
|
|
303
|
-
indices.push(i);
|
|
304
|
-
}
|
|
305
|
-
return indices;
|
|
306
|
-
}
|
|
307
275
|
function isProtectedEntry(entry, message, recentEntryIds) {
|
|
308
276
|
if (recentEntryIds.has(entry.id))
|
|
309
277
|
return true;
|
|
@@ -311,7 +279,7 @@ function isProtectedEntry(entry, message, recentEntryIds) {
|
|
|
311
279
|
return true;
|
|
312
280
|
if (message.role === "custom")
|
|
313
281
|
return true;
|
|
314
|
-
if (message.role === "branchSummary"
|
|
282
|
+
if (message.role === "branchSummary")
|
|
315
283
|
return true;
|
|
316
284
|
if (hasAssistantError(message) || hasToolResultError(message))
|
|
317
285
|
return true;
|
|
@@ -324,46 +292,22 @@ function isProtectedEntry(entry, message, recentEntryIds) {
|
|
|
324
292
|
export function prepareContextCompaction(pathEntries, settings, options = {}) {
|
|
325
293
|
if (pathEntries.length === 0)
|
|
326
294
|
return undefined;
|
|
327
|
-
const latestCompactionIndex = collectLatestSummaryCompactionIndex(pathEntries);
|
|
328
295
|
const deletionFilters = buildContextDeletionFilters(pathEntries);
|
|
329
296
|
const filteredPathEntries = buildContextDeletionFilteredPath(pathEntries, deletionFilters);
|
|
330
|
-
const
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
.map((index) => filteredEntryById.get(pathEntries[index].id))
|
|
334
|
-
.filter((entry) => entry !== undefined && getContextEligibleMessageFromEntry(entry) !== undefined)
|
|
297
|
+
const rawEntryById = new Map(pathEntries.map((entry) => [entry.id, entry]));
|
|
298
|
+
const messageEntryIds = filteredPathEntries
|
|
299
|
+
.filter((entry) => entry.type !== "context_compaction" && getContextEligibleMessageFromEntry(entry) !== undefined)
|
|
335
300
|
.map((entry) => entry.id);
|
|
336
301
|
const recentEntryIds = new Set(messageEntryIds.slice(-CONTEXT_CRITICAL_OVERFLOW_RECENT_ENTRY_COUNT));
|
|
337
302
|
const protectedEntryIds = new Set();
|
|
338
303
|
const entries = [];
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (latestCompaction.type === "compaction") {
|
|
342
|
-
const message = createCompactionSummaryMessage(latestCompaction.summary, latestCompaction.tokensBefore, latestCompaction.timestamp);
|
|
343
|
-
const contentBlocks = contentBlocksForEntry(latestCompaction.id, message, true, undefined);
|
|
344
|
-
protectedEntryIds.add(latestCompaction.id);
|
|
345
|
-
entries.push({
|
|
346
|
-
entryId: latestCompaction.id,
|
|
347
|
-
entryType: latestCompaction.type,
|
|
348
|
-
role: message.role,
|
|
349
|
-
text: messageText(message),
|
|
350
|
-
tokenEstimate: estimateTokens(message),
|
|
351
|
-
protected: true,
|
|
352
|
-
contentBlocks,
|
|
353
|
-
message,
|
|
354
|
-
toolCallIds: [],
|
|
355
|
-
toolResultFor: undefined,
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
for (const index of activeEntryIndices) {
|
|
360
|
-
const rawEntry = pathEntries[index];
|
|
361
|
-
const entry = filteredEntryById.get(rawEntry.id);
|
|
362
|
-
if (!entry || entry.type === "context_compaction")
|
|
304
|
+
for (const entry of filteredPathEntries) {
|
|
305
|
+
if (entry.type === "context_compaction")
|
|
363
306
|
continue;
|
|
364
307
|
const message = getContextEligibleMessageFromEntry(entry);
|
|
365
308
|
if (!message)
|
|
366
309
|
continue;
|
|
310
|
+
const rawEntry = rawEntryById.get(entry.id) ?? entry;
|
|
367
311
|
const protectedEntry = isProtectedEntry(entry, message, recentEntryIds);
|
|
368
312
|
if (protectedEntry)
|
|
369
313
|
protectedEntryIds.add(entry.id);
|
|
@@ -653,6 +597,23 @@ function computeContextCompactionStats(transcript, targets) {
|
|
|
653
597
|
percentReduction,
|
|
654
598
|
};
|
|
655
599
|
}
|
|
600
|
+
/**
|
|
601
|
+
* An entry "bears task context" when it carries the user's intent for the session: a real `user`
|
|
602
|
+
* message, an extension-injected `custom` message, or a branch summary (`branchSummary` role /
|
|
603
|
+
* `branch_summary` entry type) that recaps an earlier branch's task.
|
|
604
|
+
*
|
|
605
|
+
* Verbatim compaction must always leave at least one task-bearing entry in context. The same set
|
|
606
|
+
* also defines which protected entries `critical_overflow` may delete, because the intent each one
|
|
607
|
+
* carries is recoverable from any other surviving task-bearing entry. As a deliberate consequence,
|
|
608
|
+
* `critical_overflow` MAY delete every literal `user` message as long as a branch summary or custom
|
|
609
|
+
* entry survives — branch summaries intentionally carry the task forward.
|
|
610
|
+
*/
|
|
611
|
+
function isTaskBearingEntry(entry) {
|
|
612
|
+
return (entry.role === "user" ||
|
|
613
|
+
entry.role === "custom" ||
|
|
614
|
+
entry.role === "branchSummary" ||
|
|
615
|
+
entry.entryType === "branch_summary");
|
|
616
|
+
}
|
|
656
617
|
function isCriticalOverflowProtectedEntryDeletable(entry, transcript) {
|
|
657
618
|
if (!entry.protected)
|
|
658
619
|
return true;
|
|
@@ -665,11 +626,7 @@ function isCriticalOverflowProtectedEntryDeletable(entry, transcript) {
|
|
|
665
626
|
if (hasAssistantError(entry.message) || hasToolResultError(entry.message) || hasFailedBashExecution(entry.message)) {
|
|
666
627
|
return false;
|
|
667
628
|
}
|
|
668
|
-
return (entry
|
|
669
|
-
entry.role === "custom" ||
|
|
670
|
-
entry.role === "branchSummary" ||
|
|
671
|
-
entry.role === "compactionSummary" ||
|
|
672
|
-
entry.entryType === "branch_summary");
|
|
629
|
+
return isTaskBearingEntry(entry);
|
|
673
630
|
}
|
|
674
631
|
function canDeleteProtectedTargetInMode(transcript, target, mode) {
|
|
675
632
|
if (mode !== "critical_overflow")
|
|
@@ -749,7 +706,7 @@ export function validateContextDeletionRequest(request, transcript, options = {}
|
|
|
749
706
|
if (remainingEntries.length === 0) {
|
|
750
707
|
throw new Error("Deletion request would remove all context entries");
|
|
751
708
|
}
|
|
752
|
-
const hasTaskBearingContext = remainingEntries.some(
|
|
709
|
+
const hasTaskBearingContext = remainingEntries.some(isTaskBearingEntry);
|
|
753
710
|
if (!hasTaskBearingContext) {
|
|
754
711
|
throw new Error("Deletion request would leave no user task in context");
|
|
755
712
|
}
|
|
@@ -1465,7 +1422,7 @@ function contextCompactionTranscriptManifest(transcript, transcriptFilePath) {
|
|
|
1465
1422
|
}
|
|
1466
1423
|
function contextCompactionModePrompt(mode) {
|
|
1467
1424
|
if (mode === "critical_overflow") {
|
|
1468
|
-
return `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest protected entries or protected content shown in the manifest,
|
|
1425
|
+
return `\n<critical-overflow-mode>\nThe previous model request overflowed its context window. This is a critical LRU-style compaction pass. First delete stale unprotected context. If that is not enough, you may also delete the earliest protected entries or protected content shown in the manifest. Evict in priority order: remove old reasoning traces first, then old user/custom/summary context, while preserving recent entries, unresolved errors, failed commands, and enough task-bearing context for the assistant to continue.\n</critical-overflow-mode>`;
|
|
1469
1426
|
}
|
|
1470
1427
|
return `\n<standard-mode>\nDo not delete entries or content blocks marked protected. Protected context is only eligible during critical overflow recovery, not during standard compaction.\n</standard-mode>`;
|
|
1471
1428
|
}
|