apex-code 0.0.1-alpha.10 → 0.0.1-alpha.11

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 (130) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +9 -8
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +24 -5
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +26 -0
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +77 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/bash-executor.d.ts.map +1 -1
  11. package/dist/core/bash-executor.js +7 -0
  12. package/dist/core/bash-executor.js.map +1 -1
  13. package/dist/core/checkpoints/git-checkpoints.d.ts +33 -0
  14. package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
  15. package/dist/core/checkpoints/git-checkpoints.js +230 -0
  16. package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
  17. package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
  18. package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
  19. package/dist/core/checkpoints/session-checkpoints.js +29 -0
  20. package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
  21. package/dist/core/exec.d.ts.map +1 -1
  22. package/dist/core/exec.js +5 -2
  23. package/dist/core/exec.js.map +1 -1
  24. package/dist/core/extensions/loader.d.ts.map +1 -1
  25. package/dist/core/extensions/loader.js +7 -1
  26. package/dist/core/extensions/loader.js.map +1 -1
  27. package/dist/core/mcp/config.d.ts +16 -0
  28. package/dist/core/mcp/config.d.ts.map +1 -0
  29. package/dist/core/mcp/config.js +152 -0
  30. package/dist/core/mcp/config.js.map +1 -0
  31. package/dist/core/mcp/connector.d.ts +10 -0
  32. package/dist/core/mcp/connector.d.ts.map +1 -0
  33. package/dist/core/mcp/connector.js +70 -0
  34. package/dist/core/mcp/connector.js.map +1 -0
  35. package/dist/core/mcp/contract.d.ts +19 -0
  36. package/dist/core/mcp/contract.d.ts.map +1 -0
  37. package/dist/core/mcp/contract.js +89 -0
  38. package/dist/core/mcp/contract.js.map +1 -0
  39. package/dist/core/mcp/mcp-tool.d.ts +32 -0
  40. package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
  41. package/dist/core/mcp/mcp-tool.js +165 -0
  42. package/dist/core/mcp/mcp-tool.js.map +1 -0
  43. package/dist/core/mcp/metadata-cache.d.ts +29 -0
  44. package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
  45. package/dist/core/mcp/metadata-cache.js +99 -0
  46. package/dist/core/mcp/metadata-cache.js.map +1 -0
  47. package/dist/core/mcp/runtime.d.ts +18 -0
  48. package/dist/core/mcp/runtime.d.ts.map +1 -0
  49. package/dist/core/mcp/runtime.js +35 -0
  50. package/dist/core/mcp/runtime.js.map +1 -0
  51. package/dist/core/mcp/schema.d.ts +22 -0
  52. package/dist/core/mcp/schema.d.ts.map +1 -0
  53. package/dist/core/mcp/schema.js +20 -0
  54. package/dist/core/mcp/schema.js.map +1 -0
  55. package/dist/core/mcp/server-manager.d.ts +43 -0
  56. package/dist/core/mcp/server-manager.d.ts.map +1 -0
  57. package/dist/core/mcp/server-manager.js +142 -0
  58. package/dist/core/mcp/server-manager.js.map +1 -0
  59. package/dist/core/mcp/types.d.ts +98 -0
  60. package/dist/core/mcp/types.d.ts.map +1 -0
  61. package/dist/core/mcp/types.js +8 -0
  62. package/dist/core/mcp/types.js.map +1 -0
  63. package/dist/core/sdk.d.ts.map +1 -1
  64. package/dist/core/sdk.js +14 -1
  65. package/dist/core/sdk.js.map +1 -1
  66. package/dist/core/session-manager.d.ts +13 -1
  67. package/dist/core/session-manager.d.ts.map +1 -1
  68. package/dist/core/session-manager.js +30 -3
  69. package/dist/core/session-manager.js.map +1 -1
  70. package/dist/core/settings-manager.d.ts +7 -0
  71. package/dist/core/settings-manager.d.ts.map +1 -1
  72. package/dist/core/settings-manager.js +3 -0
  73. package/dist/core/settings-manager.js.map +1 -1
  74. package/dist/core/slash-commands.d.ts.map +1 -1
  75. package/dist/core/slash-commands.js +1 -0
  76. package/dist/core/slash-commands.js.map +1 -1
  77. package/dist/core/tools/contract-snapshot.d.ts +58 -0
  78. package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
  79. package/dist/core/tools/contract-snapshot.js +51 -0
  80. package/dist/core/tools/contract-snapshot.js.map +1 -0
  81. package/dist/core/tools/contract.d.ts +4 -2
  82. package/dist/core/tools/contract.d.ts.map +1 -1
  83. package/dist/core/tools/contract.js +4 -2
  84. package/dist/core/tools/contract.js.map +1 -1
  85. package/dist/core/tools/index.d.ts +9 -0
  86. package/dist/core/tools/index.d.ts.map +1 -1
  87. package/dist/core/tools/index.js +3 -0
  88. package/dist/core/tools/index.js.map +1 -1
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +2 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/main.d.ts.map +1 -1
  94. package/dist/main.js +6 -6
  95. package/dist/main.js.map +1 -1
  96. package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
  97. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  98. package/dist/modes/interactive/components/assistant-message.js +182 -23
  99. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  100. package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
  101. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/bash-execution.js +20 -0
  103. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  104. package/dist/modes/interactive/components/footer.d.ts +8 -0
  105. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  106. package/dist/modes/interactive/components/footer.js +29 -9
  107. package/dist/modes/interactive/components/footer.js.map +1 -1
  108. package/dist/modes/interactive/components/tool-execution.d.ts +12 -0
  109. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  110. package/dist/modes/interactive/components/tool-execution.js +31 -0
  111. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  112. package/dist/modes/interactive/interactive-mode.d.ts +29 -0
  113. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  114. package/dist/modes/interactive/interactive-mode.js +88 -4
  115. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  116. package/dist/package-manager-cli.d.ts.map +1 -1
  117. package/dist/package-manager-cli.js +0 -6
  118. package/dist/package-manager-cli.js.map +1 -1
  119. package/dist/utils/version-check.d.ts.map +1 -1
  120. package/dist/utils/version-check.js +6 -4
  121. package/dist/utils/version-check.js.map +1 -1
  122. package/docs/compaction.md +2 -0
  123. package/docs/environment-variables.md +1 -1
  124. package/examples/extensions/git-checkpoint.ts +24 -36
  125. package/npm-shrinkwrap.json +176 -28
  126. package/package.json +10 -8
  127. package/dist/server/create-harness.d.ts +0 -26
  128. package/dist/server/create-harness.d.ts.map +0 -1
  129. package/dist/server/create-harness.js +0 -107
  130. package/dist/server/create-harness.js.map +0 -1
@@ -22,6 +22,7 @@ import { sleep } from "../utils/sleep.js";
22
22
  import { normalizeToolResultImages } from "../utils/tool-result-images.js";
23
23
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
24
24
  import { executeBashWithOperations } from "./bash-executor.js";
25
+ import { createSessionCheckpoints } from "./checkpoints/session-checkpoints.js";
25
26
  import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
26
27
  import { evictionBudget, installContextPipeline, isDefaultStreamFunction } from "./context/pipeline.js";
27
28
  import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "./defaults.js";
@@ -41,6 +42,7 @@ import { slugifySkillCommandName } from "./skills.js";
41
42
  import { createSyntheticSourceInfo } from "./source-info.js";
42
43
  import { buildSystemPrompt } from "./system-prompt.js";
43
44
  import { createLocalBashOperations } from "./tools/bash.js";
45
+ import { buildToolContractSnapshot, isUnclassifiedTool, } from "./tools/contract-snapshot.js";
44
46
  import { createAllToolDefinitions } from "./tools/index.js";
45
47
  import { createSkillSearchToolDefinition } from "./tools/skill-search.js";
46
48
  import { createTodoWriteToolDefinition } from "./tools/todo-write.js";
@@ -104,6 +106,7 @@ export class AgentSession {
104
106
  _compactionAbortController = undefined;
105
107
  _autoCompactionAbortController = undefined;
106
108
  _overflowRecoveryAttempted = false;
109
+ _midRunCompactionNeeded = false;
107
110
  // Branch summarization state
108
111
  _branchSummaryAbortController = undefined;
109
112
  // Retry state
@@ -129,6 +132,16 @@ export class AgentSession {
129
132
  _evidenceSink;
130
133
  _diagnosticsOperations;
131
134
  _lspOperations;
135
+ _mcpRuntime;
136
+ /** Configured MCP subsystem, or undefined when no server is configured. */
137
+ get mcpRuntime() {
138
+ return this._mcpRuntime;
139
+ }
140
+ _checkpoints;
141
+ /** Worktree checkpoints for this session. Inert unless `checkpoints.enabled` is set. */
142
+ get checkpoints() {
143
+ return this._checkpoints;
144
+ }
132
145
  _webSearchOperations;
133
146
  _extensionUIContext;
134
147
  _extensionMode = "print";
@@ -167,12 +180,19 @@ export class AgentSession {
167
180
  this._evidenceSink = config.evidenceSink ?? new SessionEvidenceSink(this.sessionManager);
168
181
  this._diagnosticsOperations = config.diagnosticsOperations;
169
182
  this._lspOperations = config.lspOperations;
183
+ this._mcpRuntime = config.mcpRuntime;
170
184
  this._webSearchOperations = config.webSearchOperations;
185
+ this._checkpoints = createSessionCheckpoints({
186
+ workspace: this._cwd,
187
+ sessionId: this.sessionManager.getSessionId(),
188
+ settings: config.checkpointSettings,
189
+ });
171
190
  // Always subscribe to agent events for internal handling
172
191
  // (session persistence, extensions, auto-compaction, retry logic)
173
192
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
174
193
  this._installAgentToolHooks();
175
194
  this._installAgentNextTurnRefresh();
195
+ this._installMidRunCompactionHook();
176
196
  this._installContextPipeline();
177
197
  this._buildRuntime({
178
198
  activeToolNames: this._initialActiveToolNames,
@@ -348,6 +368,35 @@ export class AgentSession {
348
368
  };
349
369
  };
350
370
  }
371
+ /** Stop an over-threshold tool loop before it sends another provider request. */
372
+ _installMidRunCompactionHook() {
373
+ const previousShouldStopAfterTurn = this.agent.shouldStopAfterTurn;
374
+ this.agent.shouldStopAfterTurn = async (turn, signal) => {
375
+ if (await previousShouldStopAfterTurn?.(turn, signal)) {
376
+ return true;
377
+ }
378
+ return this._shouldStopForMidRunCompaction(turn);
379
+ };
380
+ }
381
+ _shouldStopForMidRunCompaction(turn) {
382
+ if (!turn.hasMoreToolCalls || turn.toolResults.length === 0) {
383
+ return false;
384
+ }
385
+ const settings = this.settingsManager.getCompactionSettings();
386
+ if (!settings.enabled) {
387
+ return false;
388
+ }
389
+ const contextWindow = this.model?.contextWindow ?? 0;
390
+ if (contextWindow <= 0) {
391
+ return false;
392
+ }
393
+ const contextTokens = estimateContextTokens(turn.context.messages).tokens;
394
+ if (!shouldCompact(contextTokens, contextWindow, settings)) {
395
+ return false;
396
+ }
397
+ this._midRunCompactionNeeded = true;
398
+ return true;
399
+ }
351
400
  /**
352
401
  * Installs the context pipeline settled in `docs/architecture/contracts.md` § 2:
353
402
  * deferred-schema resolution → tool-result eviction → compaction. Compaction
@@ -548,6 +597,18 @@ export class AgentSession {
548
597
  await this._extensionRunner.emit({ type: "agent_end", messages: event.messages });
549
598
  }
550
599
  else if (event.type === "turn_start") {
600
+ // Snapshot before the model gets to act, keyed to the entry `/tree` and `/fork`
601
+ // already navigate to, so the two agree about what an entry means.
602
+ //
603
+ // Awaited, despite the turn latency. Detached, the snapshot races the turn it is
604
+ // supposed to precede: a tool call can edit the worktree while `add -A` is still
605
+ // walking it, and the ref then holds mid-turn state that no `/fork` should ever
606
+ // restore. "The state before the model acted" is the whole guarantee, so paying
607
+ // for it here is the point. The engine's own timeout bounds the wait and a failed
608
+ // capture is never fatal.
609
+ const leafEntryId = this.sessionManager.getLeafEntry()?.id;
610
+ if (leafEntryId)
611
+ await this._checkpoints.capture(leafEntryId);
551
612
  const extensionEvent = {
552
613
  type: "turn_start",
553
614
  turnIndex: this._turnIndex,
@@ -669,6 +730,9 @@ export class AgentSession {
669
730
  this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().");
670
731
  this._disconnectFromAgent();
671
732
  this._eventListeners = [];
733
+ // Every connected MCP server is a child process this session started. Without
734
+ // this, one leaks per server per session, because nothing else owns them.
735
+ this._mcpRuntime?.close().catch(() => undefined);
672
736
  cleanupSessionResources(this.sessionId);
673
737
  }
674
738
  // =========================================================================
@@ -712,6 +776,13 @@ export class AgentSession {
712
776
  /**
713
777
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
714
778
  */
779
+ /**
780
+ * The ADR 0010 projection over this session's registry: the one read every surface
781
+ * that *describes* the tool set consumes. Never an authorization input.
782
+ */
783
+ getToolContractSnapshot() {
784
+ return buildToolContractSnapshot(Array.from(this._toolDefinitions.values()).map(({ definition }) => definition));
785
+ }
715
786
  getAllTools() {
716
787
  const schemaToolActive = this.getActiveToolNames().includes("tool_schema");
717
788
  return Array.from(this._toolDefinitions.values())
@@ -722,7 +793,7 @@ export class AgentSession {
722
793
  parameters: definition.parameters,
723
794
  promptGuidelines: definition.promptGuidelines,
724
795
  sourceInfo,
725
- unclassified: !("contract" in definition),
796
+ unclassified: isUnclassifiedTool(definition),
726
797
  }));
727
798
  }
728
799
  getToolDefinition(name) {
@@ -862,6 +933,10 @@ export class AgentSession {
862
933
  }
863
934
  }
864
935
  async _handlePostAgentRun() {
936
+ if (this._midRunCompactionNeeded) {
937
+ this._midRunCompactionNeeded = false;
938
+ return await this._runAutoCompaction("threshold", true);
939
+ }
865
940
  const msg = this._lastAssistantMessage;
866
941
  this._lastAssistantMessage = undefined;
867
942
  if (!msg) {
@@ -2264,6 +2339,7 @@ export class AgentSession {
2264
2339
  edit: { diagnosticsOperations: this._diagnosticsOperations },
2265
2340
  write: { diagnosticsOperations: this._diagnosticsOperations },
2266
2341
  ...(this._lspOperations ? { lsp: { operations: this._lspOperations } } : {}),
2342
+ ...(this._mcpRuntime ? { mcp: this._mcpRuntime } : {}),
2267
2343
  ...(this._webSearchOperations ? { web_search: { operations: this._webSearchOperations } } : {}),
2268
2344
  });
2269
2345
  baseToolDefinitions.tool_schema = createToolSchemaToolDefinition({