@nghyane/arcane 0.1.29 → 0.1.30

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.
Files changed (50) hide show
  1. package/package.json +4 -4
  2. package/src/cli/config-cli.ts +1 -1
  3. package/src/config/settings-schema.ts +19 -27
  4. package/src/config/settings.ts +3 -4
  5. package/src/extensibility/custom-tools/types.ts +0 -12
  6. package/src/extensibility/extensions/index.ts +0 -5
  7. package/src/extensibility/extensions/runner.ts +6 -26
  8. package/src/extensibility/extensions/types.ts +1 -77
  9. package/src/extensibility/hooks/runner.ts +5 -24
  10. package/src/extensibility/hooks/types.ts +1 -77
  11. package/src/index.ts +2 -13
  12. package/src/modes/components/footer.ts +4 -11
  13. package/src/modes/components/index.ts +0 -1
  14. package/src/modes/components/status-line/segments.ts +1 -2
  15. package/src/modes/components/status-line/types.ts +0 -1
  16. package/src/modes/components/status-line.ts +0 -6
  17. package/src/modes/components/tree-selector.ts +0 -8
  18. package/src/modes/controllers/command-controller.ts +2 -98
  19. package/src/modes/controllers/event-controller.ts +46 -52
  20. package/src/modes/controllers/extension-ui-controller.ts +0 -42
  21. package/src/modes/controllers/input-controller.ts +0 -23
  22. package/src/modes/controllers/selector-controller.ts +0 -5
  23. package/src/modes/interactive-mode.ts +3 -24
  24. package/src/modes/print-mode.ts +0 -16
  25. package/src/modes/rpc/rpc-client.ts +0 -16
  26. package/src/modes/rpc/rpc-mode.ts +0 -32
  27. package/src/modes/rpc/rpc-types.ts +0 -9
  28. package/src/modes/types.ts +1 -13
  29. package/src/modes/utils/ui-helpers.ts +2 -118
  30. package/src/sdk.ts +0 -15
  31. package/src/session/agent-session.ts +89 -650
  32. package/src/session/compaction/branch-summarization.ts +5 -13
  33. package/src/session/compaction/index.ts +0 -1
  34. package/src/session/compaction/utils.ts +94 -2
  35. package/src/session/messages.ts +0 -37
  36. package/src/session/retry-utils.ts +1 -1
  37. package/src/session/session-manager.ts +8 -108
  38. package/src/session/session-types.ts +4 -25
  39. package/src/session/stats.ts +2 -39
  40. package/src/slash-commands/builtin-registry.ts +0 -11
  41. package/src/task/executor.ts +0 -8
  42. package/examples/hooks/custom-compaction.ts +0 -116
  43. package/src/modes/components/compaction-summary-message.ts +0 -59
  44. package/src/prompts/compaction/compaction-short-summary.md +0 -9
  45. package/src/prompts/compaction/compaction-summary-context.md +0 -5
  46. package/src/prompts/compaction/compaction-summary.md +0 -41
  47. package/src/prompts/compaction/compaction-turn-prefix.md +0 -17
  48. package/src/prompts/compaction/compaction-update-summary.md +0 -45
  49. package/src/session/compaction/compaction.ts +0 -864
  50. package/src/session/compaction/pruning.ts +0 -91
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@ export { ModelRegistry } from "./config/model-registry";
13
13
  // Prompt templates
14
14
  export type { PromptTemplate } from "./config/prompt-templates";
15
15
  export { renderPromptTemplate } from "./config/prompt-templates";
16
- export type { CompactionSettings, RetrySettings, SkillsSettings } from "./config/settings";
16
+ export type { RetrySettings, SkillsSettings } from "./config/settings";
17
17
  export { Settings, settings } from "./config/settings";
18
18
  // Custom commands
19
19
  export type {
@@ -114,7 +114,6 @@ export {
114
114
  BashExecutionComponent,
115
115
  BorderedLoader,
116
116
  BranchSummaryMessageComponent,
117
- CompactionSummaryMessageComponent,
118
117
  CustomEditor,
119
118
  CustomMessageComponent,
120
119
  DynamicBorder,
@@ -181,39 +180,29 @@ export {
181
180
  } from "./session/agent-session";
182
181
  // Auth and model registry
183
182
  export { type ApiKeyCredential, type AuthCredential, AuthStorage, type OAuthCredential } from "./session/auth-storage";
184
- // Compaction
183
+ // Branch summarization and utilities
185
184
  export {
186
185
  type BranchPreparation,
187
186
  type BranchSummaryResult,
188
187
  type CollectEntriesResult,
189
- type CompactionResult,
190
- type CutPointResult,
191
188
  calculateContextTokens,
192
189
  collectEntriesForBranchSummary,
193
- compact,
194
- DEFAULT_COMPACTION_SETTINGS,
195
190
  estimateTokens,
196
191
  type FileOperations,
197
- findCutPoint,
198
- findTurnStartIndex,
199
192
  type GenerateBranchSummaryOptions,
200
193
  generateBranchSummary,
201
- generateSummary,
202
194
  getLastAssistantUsage,
203
195
  prepareBranchEntries,
204
196
  serializeConversation,
205
- shouldCompact,
206
197
  } from "./session/compaction";
207
198
  export { convertToLlm } from "./session/messages";
208
199
  export {
209
200
  type BranchSummaryEntry,
210
201
  buildSessionContext,
211
- type CompactionEntry,
212
202
  CURRENT_SESSION_VERSION,
213
203
  type CustomEntry,
214
204
  type CustomMessageEntry,
215
205
  type FileEntry,
216
- getLatestCompactionEntry,
217
206
  type ModeChangeEntry,
218
207
  type ModelChangeEntry,
219
208
  migrateSessionEntries,
@@ -45,15 +45,10 @@ export class FooterComponent implements Component {
45
45
  #cachedBranch: string | null | undefined = undefined; // undefined = not checked yet, null = not in git repo, string = branch name
46
46
  #gitWatcher: fs.FSWatcher | null = null;
47
47
  #onBranchChange: (() => void) | null = null;
48
- #autoCompactEnabled: boolean = true;
49
48
  #extensionStatuses: Map<string, string> = new Map();
50
49
 
51
50
  constructor(private readonly session: AgentSession) {}
52
51
 
53
- setAutoCompactEnabled(enabled: boolean): void {
54
- this.#autoCompactEnabled = enabled;
55
- }
56
-
57
52
  /**
58
53
  * Set extension status text to display in the footer.
59
54
  * Text is sanitized (newlines/tabs replaced with spaces) and truncated to terminal width.
@@ -157,7 +152,7 @@ export class FooterComponent implements Component {
157
152
  render(width: number): string[] {
158
153
  const state = this.session.state;
159
154
 
160
- // Calculate cumulative usage from ALL session entries (not just post-compaction messages)
155
+ // Calculate cumulative usage from ALL session entries
161
156
  let totalInput = 0;
162
157
  let totalOutput = 0;
163
158
  let totalCacheRead = 0;
@@ -174,8 +169,7 @@ export class FooterComponent implements Component {
174
169
  }
175
170
  }
176
171
 
177
- // Calculate context usage from session (handles compaction correctly).
178
- // After compaction, tokens are unknown until the next LLM response.
172
+ // Calculate context usage from session.
179
173
  const contextUsage = this.session.getContextUsage();
180
174
  const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
181
175
  const contextPercentValue = contextUsage?.percent ?? 0;
@@ -227,11 +221,10 @@ export class FooterComponent implements Component {
227
221
 
228
222
  // Colorize context percentage based on usage
229
223
  let contextPercentStr: string;
230
- const autoIndicator = this.#autoCompactEnabled ? " (auto)" : "";
231
224
  const contextPercentDisplay =
232
225
  contextPercent === "?"
233
- ? `?/${formatTokens(contextWindow)}${autoIndicator}`
234
- : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
226
+ ? `?/${formatTokens(contextWindow)}`
227
+ : `${contextPercent}%/${formatTokens(contextWindow)}`;
235
228
  if (contextPercentValue > 90) {
236
229
  contextPercentStr = theme.fg("error", contextPercentDisplay);
237
230
  } else if (contextPercentValue > 70) {
@@ -3,7 +3,6 @@ export { AssistantMessageComponent } from "./assistant-message";
3
3
  export { BashExecutionComponent } from "./bash-execution";
4
4
  export { BorderedLoader } from "./bordered-loader";
5
5
  export { BranchSummaryMessageComponent } from "./branch-summary-message";
6
- export { CompactionSummaryMessageComponent } from "./compaction-summary-message";
7
6
  export { CountdownTimer } from "./countdown-timer";
8
7
  export { CustomEditor } from "./custom-editor";
9
8
  export { CustomMessageComponent } from "./custom-message";
@@ -211,8 +211,7 @@ const contextPctSegment: StatusLineSegment = {
211
211
  const pct = ctx.contextPercent;
212
212
  const window = ctx.contextWindow;
213
213
 
214
- const autoIcon = ctx.autoCompactEnabled && theme.icon.auto ? ` ${theme.icon.auto}` : "";
215
- const text = `${pct.toFixed(1)}%/${formatTokens(window)}${autoIcon}`;
214
+ const text = `${pct.toFixed(1)}%/${formatTokens(window)}`;
216
215
 
217
216
  let content: string;
218
217
  if (pct > 90) {
@@ -30,7 +30,6 @@ export interface SegmentContext {
30
30
  };
31
31
  contextPercent: number;
32
32
  contextWindow: number;
33
- autoCompactEnabled: boolean;
34
33
  subagentCount: number;
35
34
  sessionStartTime: number;
36
35
  git: {
@@ -65,7 +65,6 @@ export class StatusLineComponent implements Component {
65
65
  #cachedBranch: string | null | undefined = undefined;
66
66
  #gitWatcher: fs.FSWatcher | null = null;
67
67
  #onBranchChange: (() => void) | null = null;
68
- #autoCompactEnabled: boolean = true;
69
68
  #hookStatuses: Map<string, string> = new Map();
70
69
  #subagentCount: number = 0;
71
70
  #sessionStartTime: number = Date.now();
@@ -89,10 +88,6 @@ export class StatusLineComponent implements Component {
89
88
  this.#settings = settings;
90
89
  }
91
90
 
92
- setAutoCompactEnabled(enabled: boolean): void {
93
- this.#autoCompactEnabled = enabled;
94
- }
95
-
96
91
  setSubagentCount(count: number): void {
97
92
  this.#subagentCount = count;
98
93
  }
@@ -258,7 +253,6 @@ export class StatusLineComponent implements Component {
258
253
  usageStats,
259
254
  contextPercent,
260
255
  contextWindow,
261
- autoCompactEnabled: this.#autoCompactEnabled,
262
256
  subagentCount: this.#subagentCount,
263
257
  sessionStartTime: this.#sessionStartTime,
264
258
  git: {
@@ -372,9 +372,6 @@ class TreeList implements Component {
372
372
  }
373
373
  break;
374
374
  }
375
- case "compaction":
376
- parts.push("compaction");
377
- break;
378
375
  case "branch_summary":
379
376
  parts.push("branch summary", entry.summary);
380
377
  break;
@@ -573,11 +570,6 @@ class TreeList implements Component {
573
570
  result = theme.fg("customMessageLabel", `[${entry.customType}]: `) + normalize(content);
574
571
  break;
575
572
  }
576
- case "compaction": {
577
- const tokens = Math.round(entry.tokensBefore / 1000);
578
- result = theme.fg("borderAccent", `[compaction: ${tokens}k tokens]`);
579
- break;
580
- }
581
573
  case "branch_summary":
582
574
  result = theme.fg("warning", `[branch summary]: `) + normalize(entry.summary);
583
575
  break;
@@ -9,14 +9,13 @@ import {
9
9
  type UsageReport,
10
10
  } from "@nghyane/arcane-ai";
11
11
  import { copyToClipboard } from "@nghyane/arcane-natives";
12
- import { Loader, Markdown, padding, Spacer, Text, visibleWidth } from "@nghyane/arcane-tui";
12
+ import { Markdown, padding, Spacer, Text, visibleWidth } from "@nghyane/arcane-tui";
13
13
  import { Snowflake } from "@nghyane/arcane-utils";
14
14
  import { setProjectDir } from "@nghyane/arcane-utils/dirs";
15
15
  import { $ } from "bun";
16
16
  import { reset as resetCapabilities } from "../../capability";
17
17
  import { formatKeyHint, type KeyId } from "../../config/keybindings";
18
18
  import { loadCustomShare } from "../../export/custom-share";
19
- import type { CompactOptions } from "../../extensibility/extensions/types";
20
19
  import { getGatewayStatus } from "../../ipy/gateway-coordinator";
21
20
  import { BashExecutionComponent } from "../../modes/components/bash-execution";
22
21
  import { BorderedLoader } from "../../modes/components/bordered-loader";
@@ -24,8 +23,7 @@ import { DynamicBorder } from "../../modes/components/dynamic-border";
24
23
  import { PythonExecutionComponent } from "../../modes/components/python-execution";
25
24
  import type { InteractiveModeContext } from "../../modes/types";
26
25
  import type { AuthStorage } from "../../session/auth-storage";
27
- import { createCompactionSummaryMessage } from "../../session/messages";
28
- import { getMarkdownTheme, getSymbolTheme, theme } from "../../theme/theme";
26
+ import { getMarkdownTheme, theme } from "../../theme/theme";
29
27
  import { outputMeta } from "../../tools/output-meta";
30
28
  import { resolveToCwd } from "../../tools/path-utils";
31
29
  import { getChangelogPath, parseChangelog } from "../../utils/changelog";
@@ -425,12 +423,6 @@ export class CommandController {
425
423
  }
426
424
  this.ctx.statusContainer.clear();
427
425
 
428
- if (this.ctx.session.isCompacting) {
429
- this.ctx.session.abortCompaction();
430
- while (this.ctx.session.isCompacting) {
431
- await Bun.sleep(10);
432
- }
433
- }
434
426
  await this.ctx.session.newSession();
435
427
 
436
428
  this.ctx.statusLine.invalidate();
@@ -438,7 +430,6 @@ export class CommandController {
438
430
 
439
431
  this.ctx.chatContainer.clear();
440
432
  this.ctx.pendingMessagesContainer.clear();
441
- this.ctx.compactionQueuedMessages = [];
442
433
  this.ctx.streamingComponent = undefined;
443
434
  this.ctx.streamingMessage = undefined;
444
435
  this.ctx.pendingTools.clear();
@@ -604,92 +595,6 @@ export class CommandController {
604
595
  this.ctx.ui.requestRender();
605
596
  }
606
597
 
607
- async handleCompactCommand(customInstructions?: string): Promise<void> {
608
- const entries = this.ctx.sessionManager.getEntries();
609
- const messageCount = entries.filter(e => e.type === "message").length;
610
-
611
- if (messageCount < 2) {
612
- this.ctx.showWarning("Nothing to compact (no messages yet)");
613
- return;
614
- }
615
-
616
- await this.executeCompaction(customInstructions, false);
617
- }
618
-
619
- async handleSkillCommand(skillPath: string, args: string): Promise<void> {
620
- try {
621
- const content = await Bun.file(skillPath).text();
622
- const body = content.replace(/^---\n[\s\S]*?\n---\n/, "").trim();
623
- const metaLines = [`Skill: ${skillPath}`];
624
- if (args) {
625
- metaLines.push(`User: ${args}`);
626
- }
627
- const message = `${body}\n\n---\n\n${metaLines.join("\n")}`;
628
- await this.ctx.session.prompt(message);
629
- } catch (err) {
630
- this.ctx.showError(`Failed to load skill: ${err instanceof Error ? err.message : String(err)}`);
631
- }
632
- }
633
-
634
- async executeCompaction(customInstructionsOrOptions?: string | CompactOptions, isAuto = false): Promise<void> {
635
- if (this.ctx.loadingAnimation) {
636
- this.ctx.loadingAnimation.stop();
637
- this.ctx.loadingAnimation = undefined;
638
- }
639
- this.ctx.statusContainer.clear();
640
-
641
- const originalOnEscape = this.ctx.editor.onEscape;
642
- this.ctx.editor.onEscape = () => {
643
- this.ctx.session.abortCompaction();
644
- };
645
-
646
- this.ctx.chatContainer.addChild(new Spacer(1));
647
- const label = isAuto ? "Auto-compacting context... (esc to cancel)" : "Compacting context... (esc to cancel)";
648
- const compactingLoader = new Loader(
649
- this.ctx.ui,
650
- spinner => theme.fg("accent", spinner),
651
- text => theme.fg("muted", text),
652
- label,
653
- getSymbolTheme().spinnerFrames,
654
- );
655
- this.ctx.statusContainer.addChild(compactingLoader);
656
- this.ctx.ui.requestRender();
657
-
658
- try {
659
- const instructions = typeof customInstructionsOrOptions === "string" ? customInstructionsOrOptions : undefined;
660
- const options =
661
- customInstructionsOrOptions && typeof customInstructionsOrOptions === "object"
662
- ? customInstructionsOrOptions
663
- : undefined;
664
- const result = await this.ctx.session.compact(instructions, options);
665
-
666
- this.ctx.rebuildChatFromMessages();
667
-
668
- const msg = createCompactionSummaryMessage(
669
- result.summary,
670
- result.tokensBefore,
671
- new Date().toISOString(),
672
- result.shortSummary,
673
- );
674
- this.ctx.addMessageToChat(msg);
675
-
676
- this.ctx.statusLine.invalidate();
677
- this.ctx.updateEditorTopBorder();
678
- } catch (error) {
679
- const message = error instanceof Error ? error.message : String(error);
680
- if (message === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError")) {
681
- this.ctx.showError("Compaction cancelled");
682
- } else {
683
- this.ctx.showError(`Compaction failed: ${message}`);
684
- }
685
- } finally {
686
- compactingLoader.stop();
687
- this.ctx.statusContainer.clear();
688
- this.ctx.editor.onEscape = originalOnEscape;
689
- }
690
- await this.ctx.flushCompactionQueue({ willRetry: false });
691
- }
692
-
693
598
  async handleHandoffCommand(customInstructions?: string): Promise<void> {
694
599
  const entries = this.ctx.sessionManager.getEntries();
695
600
  const messageCount = entries.filter(e => e.type === "message").length;
@@ -772,7 +677,6 @@ function formatDurationShort(ms: number): string {
772
677
  const hrs = hours % 24;
773
678
  if (days > 0) return `${days}d${hrs > 0 ? ` ${hrs}h` : ""}`;
774
679
  if (hours > 0) return `${hours}h${mins > 0 ? ` ${mins}m` : ""}`;
775
- if (minutes > 0) return `${minutes}m`;
776
680
  return `${totalSeconds}s`;
777
681
  }
778
682
 
@@ -1,5 +1,5 @@
1
1
  import { type AgentTool, toolDetails } from "@nghyane/arcane-agent";
2
- import { Loader, TERMINAL } from "@nghyane/arcane-tui";
2
+ import { Loader, TERMINAL, Text } from "@nghyane/arcane-tui";
3
3
  import { settings } from "../../config/settings";
4
4
  import { AssistantMessageComponent } from "../../modes/components/assistant-message";
5
5
  import { ContextGroupComponent } from "../../modes/components/context-group";
@@ -259,57 +259,6 @@ export class EventController {
259
259
  this.sendCompletionNotification();
260
260
  break;
261
261
 
262
- case "auto_compaction_start": {
263
- this.ctx.autoCompactionEscapeHandler = this.ctx.editor.onEscape;
264
- this.ctx.editor.onEscape = () => {
265
- this.ctx.session.abortCompaction();
266
- };
267
- this.ctx.statusContainer.clear();
268
- const reasonText = event.reason === "overflow" ? "Context overflow detected, " : "";
269
- this.ctx.autoCompactionLoader = new Loader(
270
- this.ctx.ui,
271
- spinner => theme.fg("accent", spinner),
272
- text => theme.fg("muted", text),
273
- `${reasonText}Auto-compacting… (esc to cancel)`,
274
- getSymbolTheme().spinnerFrames,
275
- );
276
- this.ctx.statusContainer.addChild(this.ctx.autoCompactionLoader);
277
- this.ctx.ui.requestRender();
278
- break;
279
- }
280
-
281
- case "auto_compaction_end": {
282
- if (this.ctx.autoCompactionEscapeHandler) {
283
- this.ctx.editor.onEscape = this.ctx.autoCompactionEscapeHandler;
284
- this.ctx.autoCompactionEscapeHandler = undefined;
285
- }
286
- if (this.ctx.autoCompactionLoader) {
287
- this.ctx.autoCompactionLoader.stop();
288
- this.ctx.autoCompactionLoader = undefined;
289
- this.ctx.statusContainer.clear();
290
- }
291
- if (event.aborted) {
292
- this.ctx.showStatus("Auto-compaction cancelled");
293
- } else if (event.result) {
294
- this.ctx.chatContainer.clear();
295
- this.ctx.rebuildChatFromMessages();
296
- this.ctx.addMessageToChat({
297
- role: "compactionSummary",
298
- tokensBefore: event.result.tokensBefore,
299
- summary: event.result.summary,
300
- shortSummary: event.result.shortSummary,
301
- timestamp: Date.now(),
302
- });
303
- this.ctx.statusLine.invalidate();
304
- this.ctx.updateEditorTopBorder();
305
- } else {
306
- this.ctx.showWarning("Auto-compaction failed; continuing without compaction");
307
- }
308
- await this.ctx.flushCompactionQueue({ willRetry: event.willRetry });
309
- this.ctx.ui.requestRender();
310
- break;
311
- }
312
-
313
262
  case "auto_retry_start": {
314
263
  this.ctx.retryEscapeHandler = this.ctx.editor.onEscape;
315
264
  this.ctx.editor.onEscape = () => {
@@ -348,6 +297,51 @@ export class EventController {
348
297
  break;
349
298
  }
350
299
 
300
+ case "context_warning": {
301
+ this.ctx.statusContainer.clear();
302
+ const warningMsg = `Context usage at ${event.percent}% — session will auto-handoff soon`;
303
+ this.ctx.statusContainer.addChild(
304
+ new Text(theme.fg("warning", `${theme.status.warning} ${warningMsg}`), 0, 0),
305
+ );
306
+ this.ctx.ui.requestRender();
307
+ break;
308
+ }
309
+
310
+ case "auto_handoff_start": {
311
+ this.ctx.statusContainer.clear();
312
+ this.ctx.handoffLoader = new Loader(
313
+ this.ctx.ui,
314
+ spinner => theme.fg("warning", spinner),
315
+ text => theme.fg("muted", text),
316
+ "Auto-handoff in progress…",
317
+ getSymbolTheme().spinnerFrames,
318
+ );
319
+ this.ctx.statusContainer.addChild(this.ctx.handoffLoader);
320
+ this.ctx.ui.requestRender();
321
+ break;
322
+ }
323
+
324
+ case "auto_handoff_end": {
325
+ if (this.ctx.handoffLoader) {
326
+ this.ctx.handoffLoader.stop();
327
+ this.ctx.handoffLoader = undefined;
328
+ this.ctx.statusContainer.clear();
329
+ }
330
+ if (event.success) {
331
+ this.ctx.statusContainer.addChild(
332
+ new Text(
333
+ theme.fg("success", `${theme.status.success} Session handed off — continuing in new session`),
334
+ 0,
335
+ 0,
336
+ ),
337
+ );
338
+ } else if (event.error) {
339
+ this.ctx.showError(`Auto-handoff failed: ${event.error}`);
340
+ }
341
+ this.ctx.ui.requestRender();
342
+ break;
343
+ }
344
+
351
345
  case "ttsr_triggered": {
352
346
  this.#finalizeContextGroup();
353
347
  const component = new TtsrNotificationComponent(event.rules);
@@ -133,12 +133,6 @@ export class ExtensionUiController {
133
133
  // Signal shutdown request (will be handled by main loop)
134
134
  },
135
135
  getContextUsage: () => this.ctx.session.getContextUsage(),
136
- compact: async instructionsOrOptions => {
137
- const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
138
- const options =
139
- instructionsOrOptions && typeof instructionsOrOptions === "object" ? instructionsOrOptions : undefined;
140
- await this.ctx.session.compact(instructions, options);
141
- },
142
136
  getSystemPrompt: () => this.ctx.session.systemPrompt,
143
137
  };
144
138
  const commandActions: ExtensionCommandContextActions = {
@@ -174,7 +168,6 @@ export class ExtensionUiController {
174
168
  // Clear UI state
175
169
  this.ctx.chatContainer.clear();
176
170
  this.ctx.pendingMessagesContainer.clear();
177
- this.ctx.compactionQueuedMessages = [];
178
171
  this.ctx.streamingComponent = undefined;
179
172
  this.ctx.streamingMessage = undefined;
180
173
  this.ctx.pendingTools.clear();
@@ -220,16 +213,6 @@ export class ExtensionUiController {
220
213
 
221
214
  return { cancelled: false };
222
215
  },
223
- compact: async instructionsOrOptions => {
224
- const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
225
- const options =
226
- instructionsOrOptions && typeof instructionsOrOptions === "object" ? instructionsOrOptions : undefined;
227
- if (this.ctx.isBackgrounded) {
228
- await this.ctx.session.compact(instructions, options);
229
- return;
230
- }
231
- await this.ctx.executeCompaction(instructionsOrOptions, false);
232
- },
233
216
  switchSession: async sessionPath => {
234
217
  const result = await this.ctx.session.switchSession(sessionPath);
235
218
  if (!result) {
@@ -322,12 +305,6 @@ export class ExtensionUiController {
322
305
  // Signal shutdown request (will be handled by main loop)
323
306
  },
324
307
  getContextUsage: () => this.ctx.session.getContextUsage(),
325
- compact: async instructionsOrOptions => {
326
- const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
327
- const options =
328
- instructionsOrOptions && typeof instructionsOrOptions === "object" ? instructionsOrOptions : undefined;
329
- await this.ctx.session.compact(instructions, options);
330
- },
331
308
  getSystemPrompt: () => this.ctx.session.systemPrompt,
332
309
  };
333
310
  const commandActions: ExtensionCommandContextActions = {
@@ -369,7 +346,6 @@ export class ExtensionUiController {
369
346
  // Clear UI state
370
347
  this.ctx.chatContainer.clear();
371
348
  this.ctx.pendingMessagesContainer.clear();
372
- this.ctx.compactionQueuedMessages = [];
373
349
  this.ctx.streamingComponent = undefined;
374
350
  this.ctx.streamingMessage = undefined;
375
351
  this.ctx.pendingTools.clear();
@@ -421,16 +397,6 @@ export class ExtensionUiController {
421
397
 
422
398
  return { cancelled: false };
423
399
  },
424
- compact: async instructionsOrOptions => {
425
- const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
426
- const options =
427
- instructionsOrOptions && typeof instructionsOrOptions === "object" ? instructionsOrOptions : undefined;
428
- if (this.ctx.isBackgrounded) {
429
- await this.ctx.session.compact(instructions, options);
430
- return;
431
- }
432
- await this.ctx.executeCompaction(instructionsOrOptions, false);
433
- },
434
400
  switchSession: async sessionPath => {
435
401
  if (this.ctx.isBackgrounded) {
436
402
  return { cancelled: true };
@@ -497,14 +463,6 @@ export class ExtensionUiController {
497
463
  await registeredTool.definition.onSession(event, {
498
464
  ui: uiContext,
499
465
  getContextUsage: () => this.ctx.session.getContextUsage(),
500
- compact: async instructionsOrOptions => {
501
- const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
502
- const options =
503
- instructionsOrOptions && typeof instructionsOrOptions === "object"
504
- ? instructionsOrOptions
505
- : undefined;
506
- await this.ctx.session.compact(instructions, options);
507
- },
508
466
  hasUI: !this.ctx.isBackgrounded,
509
467
  cwd: this.ctx.sessionManager.getCwd(),
510
468
  sessionManager: this.ctx.session.sessionManager,
@@ -30,13 +30,9 @@ export class InputController {
30
30
  Boolean(
31
31
  this.ctx.loadingAnimation ||
32
32
  this.ctx.session.isStreaming ||
33
- this.ctx.session.isCompacting ||
34
33
  this.ctx.session.isGeneratingHandoff ||
35
34
  this.ctx.session.isBashRunning ||
36
35
  this.ctx.session.isPythonRunning ||
37
- this.ctx.autoCompactionLoader ||
38
- this.ctx.retryLoader ||
39
- this.ctx.autoCompactionEscapeHandler ||
40
36
  this.ctx.retryEscapeHandler,
41
37
  );
42
38
  this.ctx.editor.onEscape = () => {
@@ -270,16 +266,6 @@ export class InputController {
270
266
  }
271
267
  }
272
268
 
273
- // Queue input during compaction
274
- if (this.ctx.session.isCompacting) {
275
- if (this.ctx.pendingImages.length > 0) {
276
- this.ctx.showStatus("Compaction in progress. Retry after it completes to send images.");
277
- return;
278
- }
279
- this.ctx.queueCompactionMessage(text, "steer");
280
- return;
281
- }
282
-
283
269
  // If streaming, use prompt() with steer behavior
284
270
  // This handles extension commands (execute immediately), prompt template expansion, and queueing
285
271
  if (this.ctx.session.isStreaming) {
@@ -365,11 +351,6 @@ export class InputController {
365
351
  const text = this.ctx.editor.getText().trim();
366
352
  if (!text) return;
367
353
 
368
- if (this.ctx.session.isCompacting) {
369
- this.ctx.queueCompactionMessage(text, "followUp");
370
- return;
371
- }
372
-
373
354
  if (this.ctx.session.isStreaming) {
374
355
  this.ctx.editor.addToHistory(text);
375
356
  this.ctx.editor.setText("");
@@ -427,10 +408,6 @@ export class InputController {
427
408
  this.ctx.loadingAnimation.stop();
428
409
  this.ctx.loadingAnimation = undefined;
429
410
  }
430
- if (this.ctx.autoCompactionLoader) {
431
- this.ctx.autoCompactionLoader.stop();
432
- this.ctx.autoCompactionLoader = undefined;
433
- }
434
411
  if (this.ctx.retryLoader) {
435
412
  this.ctx.retryLoader.stop();
436
413
  this.ctx.retryLoader = undefined;
@@ -179,10 +179,6 @@ export class SelectorController {
179
179
 
180
180
  switch (id) {
181
181
  // Session-managed settings (not in SettingsManager)
182
- case "autoCompact":
183
- this.ctx.session.setAutoCompactionEnabled(value as boolean);
184
- this.ctx.statusLine.setAutoCompactEnabled(value as boolean);
185
- break;
186
182
  case "steeringMode":
187
183
  this.ctx.session.setSteeringMode(value as "all" | "one-at-a-time");
188
184
  break;
@@ -536,7 +532,6 @@ export class SelectorController {
536
532
 
537
533
  // Clear UI state
538
534
  this.ctx.pendingMessagesContainer.clear();
539
- this.ctx.compactionQueuedMessages = [];
540
535
  this.ctx.streamingComponent = undefined;
541
536
  this.ctx.streamingMessage = undefined;
542
537
  this.ctx.pendingTools.clear();