@animus-labs/cortex 0.2.0

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 (293) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/budget-guard.d.ts +75 -0
  4. package/dist/budget-guard.d.ts.map +1 -0
  5. package/dist/budget-guard.js +142 -0
  6. package/dist/budget-guard.js.map +1 -0
  7. package/dist/compaction/compaction.d.ts +99 -0
  8. package/dist/compaction/compaction.d.ts.map +1 -0
  9. package/dist/compaction/compaction.js +302 -0
  10. package/dist/compaction/compaction.js.map +1 -0
  11. package/dist/compaction/failsafe.d.ts +57 -0
  12. package/dist/compaction/failsafe.d.ts.map +1 -0
  13. package/dist/compaction/failsafe.js +135 -0
  14. package/dist/compaction/failsafe.js.map +1 -0
  15. package/dist/compaction/index.d.ts +381 -0
  16. package/dist/compaction/index.d.ts.map +1 -0
  17. package/dist/compaction/index.js +979 -0
  18. package/dist/compaction/index.js.map +1 -0
  19. package/dist/compaction/microcompaction.d.ts +219 -0
  20. package/dist/compaction/microcompaction.d.ts.map +1 -0
  21. package/dist/compaction/microcompaction.js +536 -0
  22. package/dist/compaction/microcompaction.js.map +1 -0
  23. package/dist/compaction/observational/buffering.d.ts +225 -0
  24. package/dist/compaction/observational/buffering.d.ts.map +1 -0
  25. package/dist/compaction/observational/buffering.js +354 -0
  26. package/dist/compaction/observational/buffering.js.map +1 -0
  27. package/dist/compaction/observational/constants.d.ts +70 -0
  28. package/dist/compaction/observational/constants.d.ts.map +1 -0
  29. package/dist/compaction/observational/constants.js +507 -0
  30. package/dist/compaction/observational/constants.js.map +1 -0
  31. package/dist/compaction/observational/index.d.ts +219 -0
  32. package/dist/compaction/observational/index.d.ts.map +1 -0
  33. package/dist/compaction/observational/index.js +641 -0
  34. package/dist/compaction/observational/index.js.map +1 -0
  35. package/dist/compaction/observational/observer.d.ts +97 -0
  36. package/dist/compaction/observational/observer.d.ts.map +1 -0
  37. package/dist/compaction/observational/observer.js +424 -0
  38. package/dist/compaction/observational/observer.js.map +1 -0
  39. package/dist/compaction/observational/recall-tool.d.ts +27 -0
  40. package/dist/compaction/observational/recall-tool.d.ts.map +1 -0
  41. package/dist/compaction/observational/recall-tool.js +93 -0
  42. package/dist/compaction/observational/recall-tool.js.map +1 -0
  43. package/dist/compaction/observational/reflector.d.ts +94 -0
  44. package/dist/compaction/observational/reflector.d.ts.map +1 -0
  45. package/dist/compaction/observational/reflector.js +167 -0
  46. package/dist/compaction/observational/reflector.js.map +1 -0
  47. package/dist/compaction/observational/types.d.ts +271 -0
  48. package/dist/compaction/observational/types.d.ts.map +1 -0
  49. package/dist/compaction/observational/types.js +15 -0
  50. package/dist/compaction/observational/types.js.map +1 -0
  51. package/dist/context-manager.d.ts +134 -0
  52. package/dist/context-manager.d.ts.map +1 -0
  53. package/dist/context-manager.js +170 -0
  54. package/dist/context-manager.js.map +1 -0
  55. package/dist/cortex-agent.d.ts +1020 -0
  56. package/dist/cortex-agent.d.ts.map +1 -0
  57. package/dist/cortex-agent.js +3589 -0
  58. package/dist/cortex-agent.js.map +1 -0
  59. package/dist/error-classifier.d.ts +48 -0
  60. package/dist/error-classifier.d.ts.map +1 -0
  61. package/dist/error-classifier.js +152 -0
  62. package/dist/error-classifier.js.map +1 -0
  63. package/dist/event-bridge.d.ts +166 -0
  64. package/dist/event-bridge.d.ts.map +1 -0
  65. package/dist/event-bridge.js +381 -0
  66. package/dist/event-bridge.js.map +1 -0
  67. package/dist/index.d.ts +55 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +57 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/mcp-client.d.ts +119 -0
  72. package/dist/mcp-client.d.ts.map +1 -0
  73. package/dist/mcp-client.js +474 -0
  74. package/dist/mcp-client.js.map +1 -0
  75. package/dist/model-wrapper.d.ts +58 -0
  76. package/dist/model-wrapper.d.ts.map +1 -0
  77. package/dist/model-wrapper.js +86 -0
  78. package/dist/model-wrapper.js.map +1 -0
  79. package/dist/noop-logger.d.ts +4 -0
  80. package/dist/noop-logger.d.ts.map +1 -0
  81. package/dist/noop-logger.js +8 -0
  82. package/dist/noop-logger.js.map +1 -0
  83. package/dist/prompt-diagnostics.d.ts +47 -0
  84. package/dist/prompt-diagnostics.d.ts.map +1 -0
  85. package/dist/prompt-diagnostics.js +230 -0
  86. package/dist/prompt-diagnostics.js.map +1 -0
  87. package/dist/provider-manager.d.ts +224 -0
  88. package/dist/provider-manager.d.ts.map +1 -0
  89. package/dist/provider-manager.js +563 -0
  90. package/dist/provider-manager.js.map +1 -0
  91. package/dist/provider-registry.d.ts +115 -0
  92. package/dist/provider-registry.d.ts.map +1 -0
  93. package/dist/provider-registry.js +305 -0
  94. package/dist/provider-registry.js.map +1 -0
  95. package/dist/schema-converter.d.ts +20 -0
  96. package/dist/schema-converter.d.ts.map +1 -0
  97. package/dist/schema-converter.js +48 -0
  98. package/dist/schema-converter.js.map +1 -0
  99. package/dist/skill-preprocessor.d.ts +46 -0
  100. package/dist/skill-preprocessor.d.ts.map +1 -0
  101. package/dist/skill-preprocessor.js +237 -0
  102. package/dist/skill-preprocessor.js.map +1 -0
  103. package/dist/skill-registry.d.ts +107 -0
  104. package/dist/skill-registry.d.ts.map +1 -0
  105. package/dist/skill-registry.js +330 -0
  106. package/dist/skill-registry.js.map +1 -0
  107. package/dist/skill-tool.d.ts +54 -0
  108. package/dist/skill-tool.d.ts.map +1 -0
  109. package/dist/skill-tool.js +88 -0
  110. package/dist/skill-tool.js.map +1 -0
  111. package/dist/sub-agent-manager.d.ts +90 -0
  112. package/dist/sub-agent-manager.d.ts.map +1 -0
  113. package/dist/sub-agent-manager.js +192 -0
  114. package/dist/sub-agent-manager.js.map +1 -0
  115. package/dist/token-estimator.d.ts +23 -0
  116. package/dist/token-estimator.d.ts.map +1 -0
  117. package/dist/token-estimator.js +27 -0
  118. package/dist/token-estimator.js.map +1 -0
  119. package/dist/tool-contract.d.ts +68 -0
  120. package/dist/tool-contract.d.ts.map +1 -0
  121. package/dist/tool-contract.js +35 -0
  122. package/dist/tool-contract.js.map +1 -0
  123. package/dist/tool-result-persistence.d.ts +89 -0
  124. package/dist/tool-result-persistence.d.ts.map +1 -0
  125. package/dist/tool-result-persistence.js +152 -0
  126. package/dist/tool-result-persistence.js.map +1 -0
  127. package/dist/tools/bash/index.d.ts +71 -0
  128. package/dist/tools/bash/index.d.ts.map +1 -0
  129. package/dist/tools/bash/index.js +485 -0
  130. package/dist/tools/bash/index.js.map +1 -0
  131. package/dist/tools/bash/interactive.d.ts +47 -0
  132. package/dist/tools/bash/interactive.d.ts.map +1 -0
  133. package/dist/tools/bash/interactive.js +262 -0
  134. package/dist/tools/bash/interactive.js.map +1 -0
  135. package/dist/tools/bash/safety.d.ts +149 -0
  136. package/dist/tools/bash/safety.d.ts.map +1 -0
  137. package/dist/tools/bash/safety.js +1116 -0
  138. package/dist/tools/bash/safety.js.map +1 -0
  139. package/dist/tools/edit.d.ts +57 -0
  140. package/dist/tools/edit.d.ts.map +1 -0
  141. package/dist/tools/edit.js +310 -0
  142. package/dist/tools/edit.js.map +1 -0
  143. package/dist/tools/glob.d.ts +34 -0
  144. package/dist/tools/glob.d.ts.map +1 -0
  145. package/dist/tools/glob.js +268 -0
  146. package/dist/tools/glob.js.map +1 -0
  147. package/dist/tools/grep.d.ts +53 -0
  148. package/dist/tools/grep.d.ts.map +1 -0
  149. package/dist/tools/grep.js +673 -0
  150. package/dist/tools/grep.js.map +1 -0
  151. package/dist/tools/index.d.ts +62 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +52 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/read.d.ts +43 -0
  156. package/dist/tools/read.d.ts.map +1 -0
  157. package/dist/tools/read.js +459 -0
  158. package/dist/tools/read.js.map +1 -0
  159. package/dist/tools/runtime.d.ts +62 -0
  160. package/dist/tools/runtime.d.ts.map +1 -0
  161. package/dist/tools/runtime.js +116 -0
  162. package/dist/tools/runtime.js.map +1 -0
  163. package/dist/tools/shared/cwd-tracker.d.ts +32 -0
  164. package/dist/tools/shared/cwd-tracker.d.ts.map +1 -0
  165. package/dist/tools/shared/cwd-tracker.js +44 -0
  166. package/dist/tools/shared/cwd-tracker.js.map +1 -0
  167. package/dist/tools/shared/edit-history.d.ts +55 -0
  168. package/dist/tools/shared/edit-history.d.ts.map +1 -0
  169. package/dist/tools/shared/edit-history.js +72 -0
  170. package/dist/tools/shared/edit-history.js.map +1 -0
  171. package/dist/tools/shared/edit-matcher.d.ts +83 -0
  172. package/dist/tools/shared/edit-matcher.d.ts.map +1 -0
  173. package/dist/tools/shared/edit-matcher.js +359 -0
  174. package/dist/tools/shared/edit-matcher.js.map +1 -0
  175. package/dist/tools/shared/file-mutation-lock.d.ts +22 -0
  176. package/dist/tools/shared/file-mutation-lock.d.ts.map +1 -0
  177. package/dist/tools/shared/file-mutation-lock.js +35 -0
  178. package/dist/tools/shared/file-mutation-lock.js.map +1 -0
  179. package/dist/tools/shared/gitignore.d.ts +17 -0
  180. package/dist/tools/shared/gitignore.d.ts.map +1 -0
  181. package/dist/tools/shared/gitignore.js +59 -0
  182. package/dist/tools/shared/gitignore.js.map +1 -0
  183. package/dist/tools/shared/pdf-extractor.d.ts +96 -0
  184. package/dist/tools/shared/pdf-extractor.d.ts.map +1 -0
  185. package/dist/tools/shared/pdf-extractor.js +196 -0
  186. package/dist/tools/shared/pdf-extractor.js.map +1 -0
  187. package/dist/tools/shared/read-registry.d.ts +66 -0
  188. package/dist/tools/shared/read-registry.d.ts.map +1 -0
  189. package/dist/tools/shared/read-registry.js +65 -0
  190. package/dist/tools/shared/read-registry.js.map +1 -0
  191. package/dist/tools/shared/safe-env.d.ts +18 -0
  192. package/dist/tools/shared/safe-env.d.ts.map +1 -0
  193. package/dist/tools/shared/safe-env.js +70 -0
  194. package/dist/tools/shared/safe-env.js.map +1 -0
  195. package/dist/tools/sub-agent.d.ts +91 -0
  196. package/dist/tools/sub-agent.d.ts.map +1 -0
  197. package/dist/tools/sub-agent.js +89 -0
  198. package/dist/tools/sub-agent.js.map +1 -0
  199. package/dist/tools/task-output.d.ts +38 -0
  200. package/dist/tools/task-output.d.ts.map +1 -0
  201. package/dist/tools/task-output.js +186 -0
  202. package/dist/tools/task-output.js.map +1 -0
  203. package/dist/tools/tool-search/index.d.ts +40 -0
  204. package/dist/tools/tool-search/index.d.ts.map +1 -0
  205. package/dist/tools/tool-search/index.js +110 -0
  206. package/dist/tools/tool-search/index.js.map +1 -0
  207. package/dist/tools/tool-search/registry.d.ts +82 -0
  208. package/dist/tools/tool-search/registry.d.ts.map +1 -0
  209. package/dist/tools/tool-search/registry.js +238 -0
  210. package/dist/tools/tool-search/registry.js.map +1 -0
  211. package/dist/tools/undo-edit.d.ts +51 -0
  212. package/dist/tools/undo-edit.d.ts.map +1 -0
  213. package/dist/tools/undo-edit.js +231 -0
  214. package/dist/tools/undo-edit.js.map +1 -0
  215. package/dist/tools/web-fetch/cache.d.ts +49 -0
  216. package/dist/tools/web-fetch/cache.d.ts.map +1 -0
  217. package/dist/tools/web-fetch/cache.js +89 -0
  218. package/dist/tools/web-fetch/cache.js.map +1 -0
  219. package/dist/tools/web-fetch/index.d.ts +53 -0
  220. package/dist/tools/web-fetch/index.d.ts.map +1 -0
  221. package/dist/tools/web-fetch/index.js +513 -0
  222. package/dist/tools/web-fetch/index.js.map +1 -0
  223. package/dist/tools/write.d.ts +59 -0
  224. package/dist/tools/write.d.ts.map +1 -0
  225. package/dist/tools/write.js +316 -0
  226. package/dist/tools/write.js.map +1 -0
  227. package/dist/types.d.ts +881 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +16 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/working-tags.d.ts +44 -0
  232. package/dist/working-tags.d.ts.map +1 -0
  233. package/dist/working-tags.js +103 -0
  234. package/dist/working-tags.js.map +1 -0
  235. package/package.json +87 -0
  236. package/src/budget-guard.ts +170 -0
  237. package/src/compaction/compaction.ts +386 -0
  238. package/src/compaction/failsafe.ts +185 -0
  239. package/src/compaction/index.ts +1199 -0
  240. package/src/compaction/microcompaction.ts +709 -0
  241. package/src/compaction/observational/buffering.ts +430 -0
  242. package/src/compaction/observational/constants.ts +532 -0
  243. package/src/compaction/observational/index.ts +837 -0
  244. package/src/compaction/observational/observer.ts +510 -0
  245. package/src/compaction/observational/recall-tool.ts +130 -0
  246. package/src/compaction/observational/reflector.ts +221 -0
  247. package/src/compaction/observational/types.ts +343 -0
  248. package/src/context-manager.ts +237 -0
  249. package/src/cortex-agent.ts +4297 -0
  250. package/src/error-classifier.ts +199 -0
  251. package/src/event-bridge.ts +508 -0
  252. package/src/index.ts +292 -0
  253. package/src/mcp-client.ts +582 -0
  254. package/src/model-wrapper.ts +128 -0
  255. package/src/noop-logger.ts +9 -0
  256. package/src/prompt-diagnostics.ts +296 -0
  257. package/src/provider-manager.ts +823 -0
  258. package/src/provider-registry.ts +386 -0
  259. package/src/schema-converter.ts +51 -0
  260. package/src/skill-preprocessor.ts +314 -0
  261. package/src/skill-registry.ts +378 -0
  262. package/src/skill-tool.ts +130 -0
  263. package/src/sub-agent-manager.ts +236 -0
  264. package/src/token-estimator.ts +26 -0
  265. package/src/tool-contract.ts +113 -0
  266. package/src/tool-result-persistence.ts +197 -0
  267. package/src/tools/bash/index.ts +633 -0
  268. package/src/tools/bash/interactive.ts +302 -0
  269. package/src/tools/bash/safety.ts +1297 -0
  270. package/src/tools/edit.ts +422 -0
  271. package/src/tools/glob.ts +330 -0
  272. package/src/tools/grep.ts +819 -0
  273. package/src/tools/index.ts +110 -0
  274. package/src/tools/read.ts +580 -0
  275. package/src/tools/runtime.ts +173 -0
  276. package/src/tools/shared/cwd-tracker.ts +50 -0
  277. package/src/tools/shared/edit-history.ts +96 -0
  278. package/src/tools/shared/edit-matcher.ts +457 -0
  279. package/src/tools/shared/file-mutation-lock.ts +40 -0
  280. package/src/tools/shared/gitignore.ts +61 -0
  281. package/src/tools/shared/pdf-extractor.ts +290 -0
  282. package/src/tools/shared/read-registry.ts +93 -0
  283. package/src/tools/shared/safe-env.ts +82 -0
  284. package/src/tools/sub-agent.ts +171 -0
  285. package/src/tools/task-output.ts +236 -0
  286. package/src/tools/tool-search/index.ts +167 -0
  287. package/src/tools/tool-search/registry.ts +278 -0
  288. package/src/tools/undo-edit.ts +314 -0
  289. package/src/tools/web-fetch/cache.ts +112 -0
  290. package/src/tools/web-fetch/index.ts +604 -0
  291. package/src/tools/write.ts +385 -0
  292. package/src/types.ts +1057 -0
  293. package/src/working-tags.ts +118 -0
@@ -0,0 +1,1020 @@
1
+ /**
2
+ * CortexAgent: production-grade wrapper for pi-agent-core's Agent.
3
+ *
4
+ * Composes ContextManager, EventBridge, BudgetGuard, system prompt assembly,
5
+ * and lifecycle management into a single orchestrator class.
6
+ *
7
+ * This is the primary public API of the @animus-labs/cortex package.
8
+ *
9
+ * Lifecycle: CREATED -> ACTIVE -> DESTROYED
10
+ * - CREATED: After construction. Slots can be set, but no loops have run.
11
+ * - ACTIVE: After first prompt(). The agent is running or idle between prompts.
12
+ * - DESTROYED: After destroy(). All resources released. prompt() throws.
13
+ *
14
+ * References:
15
+ * - cortex-architecture.md
16
+ * - system-prompt.md
17
+ * - model-tiers.md
18
+ * - cross-platform-considerations.md
19
+ */
20
+ import { ContextManager } from './context-manager.js';
21
+ import type { AgentContext, AgentMessage, AgentStateAccessor } from './context-manager.js';
22
+ import { EventBridge } from './event-bridge.js';
23
+ import type { PiEventSource } from './event-bridge.js';
24
+ import { BudgetGuard } from './budget-guard.js';
25
+ import { McpClientManager } from './mcp-client.js';
26
+ import { CompactionManager } from './compaction/index.js';
27
+ import type { ObservationalMemoryState, ObservationEvent, ReflectionEvent } from './compaction/observational/types.js';
28
+ import { SubAgentManager } from './sub-agent-manager.js';
29
+ import { SkillRegistry } from './skill-registry.js';
30
+ import type { CortexModel } from './model-wrapper.js';
31
+ import type { CortexTool } from './tool-contract.js';
32
+ import type { CortexAgentConfig, CortexLifecycleState, CortexUsage, SessionUsage, ClassifiedError, AgentTextOutput, CompactionResult, CompactionTarget, CompactionDegradedInfo, CompactionExhaustedInfo, McpTransportConfig, LoadedSkill, SubAgentSpawnConfig, ThinkingLevel, ModelThinkingCapabilities } from './types.js';
33
+ /**
34
+ * Minimal Agent interface matching pi-agent-core's Agent class.
35
+ * Defined here to avoid a hard runtime dependency; the real Agent is
36
+ * passed at construction time.
37
+ */
38
+ export interface PiAgent extends AgentStateAccessor, PiEventSource {
39
+ prompt(input: string, options?: {
40
+ update?: (event: unknown) => void;
41
+ signal?: AbortSignal;
42
+ }): Promise<unknown>;
43
+ abort(): void;
44
+ waitForIdle(): Promise<void>;
45
+ reset(): void;
46
+ /**
47
+ * Inject a steering message into the running agentic loop.
48
+ * Pi applies steering after the current assistant turn and tool batch finish.
49
+ * Only effective while a prompt() call is in progress.
50
+ */
51
+ steer(message: {
52
+ role: string;
53
+ content: string;
54
+ }): void;
55
+ /**
56
+ * Context transformation hook installed by Cortex.
57
+ */
58
+ transformContext?: (messages: unknown[]) => Promise<unknown[]>;
59
+ }
60
+ /**
61
+ * Minimal Model interface matching pi-ai's Model type.
62
+ * Only the fields we need for provider validation and utility model resolution.
63
+ */
64
+ export interface PiModel {
65
+ provider: string;
66
+ name: string;
67
+ contextWindow?: number;
68
+ [key: string]: unknown;
69
+ }
70
+ /**
71
+ * Minimum context window floor in tokens.
72
+ * Below this, the system prompt alone may not fit, breaking the agent.
73
+ */
74
+ export declare const MINIMUM_CONTEXT_WINDOW = 16384;
75
+ /**
76
+ * Operational reminder appended to tool results when working tags are enabled.
77
+ * Exported so consumers (e.g., cortex-code TUI) can strip it from display text.
78
+ */
79
+ export declare const TOOL_RESULT_WORKING_TAGS_REMINDER = "[Do not narrate. If analyzing these results, use <working> tags. Only text outside <working> tags is shown to the user.]";
80
+ export declare class CortexAgent {
81
+ private static readonly globalTrackedPids;
82
+ private static exitHandlerInstalled;
83
+ private readonly agent;
84
+ private readonly contextManager;
85
+ private readonly eventBridge;
86
+ private readonly budgetGuard;
87
+ private readonly config;
88
+ private readonly logger;
89
+ private readonly promptDiagnostics;
90
+ private workingTagsEnabled;
91
+ private readonly workingDirectory;
92
+ private readonly envOverrides;
93
+ private lifecycleState;
94
+ private currentBasePrompt;
95
+ private currentSystemPrompt;
96
+ private _cacheRetention;
97
+ private _activePromptCacheRetention;
98
+ private primaryModel;
99
+ private primaryPiModel;
100
+ private resolvedUtilityModel;
101
+ private resolvedUtilityPiModel;
102
+ private utilityModelManualOverride;
103
+ private readonly registeredTools;
104
+ private readonly toolRuntime;
105
+ private currentPiTools;
106
+ private readonly _deferredToolsEnabled;
107
+ private readonly _deferMcp;
108
+ private readonly _deferredAlwaysLoad;
109
+ private readonly deferredToolRegistry;
110
+ private readonly persistResult?;
111
+ private readonly toolCategories?;
112
+ private readonly toolResultThresholds?;
113
+ private readonly compactionManager;
114
+ private _contextWindowLimit;
115
+ private loopCompleteHandlers;
116
+ private errorHandlers;
117
+ private beforeCompactionHandlers;
118
+ private compactionErrorHandlers;
119
+ private compactionDegradedHandlers;
120
+ private compactionExhaustedHandlers;
121
+ private turnCompleteHandlers;
122
+ private subAgentSpawnedHandlers;
123
+ private subAgentCompletedHandlers;
124
+ private subAgentFailedHandlers;
125
+ private backgroundResultDeliveryHandlers;
126
+ private pendingBackgroundResults;
127
+ private eventUnsubscribers;
128
+ private abortController;
129
+ private _isPrompting;
130
+ private readonly trackedPids;
131
+ private readonly mcpClientManager;
132
+ private readonly subAgentManager;
133
+ private readonly skillRegistry;
134
+ private loadSkillTool;
135
+ private skillBuffer;
136
+ private _prePromptMessageCount;
137
+ private _cacheBreakpointIndices;
138
+ private _lastDirectUsage;
139
+ private _sessionUsage;
140
+ /**
141
+ * Create a CortexAgent. Prefer CortexAgent.create().
142
+ *
143
+ * @param agent - A pi-agent-core Agent instance
144
+ * @param config - CortexAgent configuration
145
+ * @throws Error if the utility model violates the same-provider constraint
146
+ */
147
+ private constructor();
148
+ /**
149
+ * Send a prompt to the agent and run the agentic loop.
150
+ *
151
+ * Transitions from CREATED to ACTIVE on first call.
152
+ * Catches errors, classifies them, and emits onError.
153
+ *
154
+ * @param input - The prompt text
155
+ * @returns The agent's response (opaque, from pi-agent-core)
156
+ * @throws Error if the agent has been destroyed
157
+ */
158
+ prompt(input: string, options?: {
159
+ cacheRetention?: 'none' | 'short' | 'long';
160
+ }): Promise<unknown>;
161
+ /**
162
+ * Inject a steering message into the running agentic loop.
163
+ * Queues the message for pi-agent-core to inject after the current
164
+ * assistant turn and any current tool batch finish.
165
+ * Only effective while a prompt() call is in progress.
166
+ *
167
+ * No-op if the agent is not currently running a prompt.
168
+ *
169
+ * @param message - The message content to inject
170
+ */
171
+ steer(message: string): void;
172
+ /**
173
+ * Make a direct LLM completion call using the primary model.
174
+ * NOT an agentic tool-use loop. Used for structured output phases
175
+ * like THOUGHT and REFLECT where a single LLM response is needed
176
+ * without tool execution.
177
+ *
178
+ * Dynamically imports pi-ai's complete() function. If pi-ai is not
179
+ * installed, throws a clear error.
180
+ *
181
+ * @param context - System prompt and messages for the completion
182
+ * @returns The response text from the LLM
183
+ * @throws Error if pi-ai is not installed or the call fails
184
+ */
185
+ directComplete(context: {
186
+ systemPrompt: string;
187
+ messages: unknown[];
188
+ }, options?: {
189
+ cacheRetention?: 'none' | 'short' | 'long';
190
+ }): Promise<string>;
191
+ /**
192
+ * Make a structured output LLM call using the tool-call-as-structured-output pattern.
193
+ *
194
+ * Defines a tool whose input_schema matches the desired output structure,
195
+ * passes it via pi-ai's complete() with tools, and extracts the tool call
196
+ * arguments as the structured result. This works across all providers that
197
+ * support tool use (Anthropic, OpenAI, Google, Mistral, etc.) without
198
+ * needing provider-specific structured output parameters.
199
+ *
200
+ * @param context - System prompt and messages (accepts pi-ai native message format)
201
+ * @param schema - Tool schema defining the structured output shape (TypeBox or JSON Schema)
202
+ * @param toolName - Name for the virtual tool (default: 'structured_output')
203
+ * @param toolDescription - Description for the virtual tool
204
+ * @returns The parsed tool call arguments, or null if the model didn't call the tool
205
+ */
206
+ structuredComplete(context: {
207
+ systemPrompt: string;
208
+ messages: unknown[];
209
+ }, schema: unknown, toolName?: string, toolDescription?: string, options?: {
210
+ cacheRetention?: 'none' | 'short' | 'long';
211
+ }): Promise<Record<string, unknown> | null>;
212
+ /**
213
+ * Extract tool call arguments from a pi-ai AssistantMessage response.
214
+ */
215
+ /**
216
+ * Check if a pi-ai result represents a silent error.
217
+ *
218
+ * Pi-ai's stream wrapper catches errors and resolves the promise with an
219
+ * output object that has stopReason 'error' and errorMessage set, instead
220
+ * of throwing. This means callers never see the error unless they check.
221
+ * This method surfaces those silent errors as thrown exceptions so they
222
+ * propagate properly (e.g., to retry logic).
223
+ */
224
+ private checkForSilentError;
225
+ private extractToolCallArgs;
226
+ private static loadAgentClass;
227
+ private static buildPiAgentConfig;
228
+ private static normalizePermissionDecision;
229
+ /**
230
+ * Extract safe, identifying fields from tool args for logging.
231
+ * Returns paths, commands, and patterns without content or results.
232
+ */
233
+ private static summarizeToolArgs;
234
+ private static buildPermissionReason;
235
+ private static wireManagedPiAgent;
236
+ private static createManagedAgent;
237
+ /**
238
+ * Create a CortexAgent with a pi-agent-core Agent constructed internally.
239
+ *
240
+ * This eliminates the consumer's need to import pi-agent-core directly.
241
+ * The factory dynamically imports pi-agent-core and pi-ai, resolves the
242
+ * model, creates the internal Agent, and returns a fully configured
243
+ * CortexAgent.
244
+ *
245
+ * @param config - CortexAgent configuration (model, tools, options)
246
+ * @returns A new CortexAgent wrapping an internally-created pi-agent-core Agent
247
+ * @throws Error if pi-agent-core or pi-ai is not installed
248
+ */
249
+ static create(config: CortexAgentConfig & {
250
+ /**
251
+ * Additional consumer-provided tools to register alongside the built-in tools.
252
+ * Built-in tools (Read, Write, Edit, Glob, Grep, Bash, WebFetch, TaskOutput)
253
+ * are registered automatically. Tools passed here must use Cortex's
254
+ * execute(params, context?) contract. Wrap raw pi-agent-core tools with
255
+ * fromPiAgentTool() before passing them to CortexAgent.create().
256
+ */
257
+ tools?: CortexTool[];
258
+ /** @deprecated Use initialBasePrompt instead. */
259
+ systemPrompt?: string;
260
+ }): Promise<CortexAgent>;
261
+ /**
262
+ * Get the ContextManager for slot and ephemeral context management.
263
+ */
264
+ getContextManager(): ContextManager;
265
+ /**
266
+ * Compose a system prompt from the application/base prompt plus
267
+ * Cortex operational sections.
268
+ *
269
+ * Base prompt content comes FIRST (identity, persona, domain instructions).
270
+ * Cortex appends operational rules AFTER (system rules, tool guidance,
271
+ * safety, environment info).
272
+ *
273
+ * @param basePrompt - The application/base prompt content
274
+ * @returns The assembled system prompt
275
+ */
276
+ composeSystemPrompt(basePrompt: string): string;
277
+ /**
278
+ * @deprecated Use composeSystemPrompt() for pure composition or
279
+ * setBasePrompt() to update the live agent state.
280
+ */
281
+ buildSystemPrompt(basePrompt: string): string;
282
+ /**
283
+ * Set the application/base prompt and update the live agent state.
284
+ *
285
+ * Preserves conversation history. Non-destructive.
286
+ */
287
+ setBasePrompt(basePrompt: string): string;
288
+ /**
289
+ * @deprecated Use setBasePrompt().
290
+ */
291
+ rebuildSystemPrompt(newBasePrompt: string): void;
292
+ /**
293
+ * Get the current application/base prompt.
294
+ */
295
+ getBasePrompt(): string;
296
+ /**
297
+ * Get the current assembled system prompt.
298
+ */
299
+ getCurrentSystemPrompt(): string;
300
+ /**
301
+ * Get the Cortex operational system prompt sections as structured data.
302
+ * Useful for context snapshot / inspector tooling.
303
+ */
304
+ getSystemPromptSections(): Array<{
305
+ name: string;
306
+ content: string;
307
+ }>;
308
+ private applySystemPrompt;
309
+ private refreshPromptState;
310
+ private hasConfiguredSystemPrompt;
311
+ /**
312
+ * Get conversation history, excluding the slot region.
313
+ *
314
+ * Returns messages from position slotCount through the end of the array.
315
+ * The consumer snapshots this to their storage.
316
+ *
317
+ * @returns Conversation history messages (everything after slots)
318
+ */
319
+ getConversationHistory(): AgentMessage[];
320
+ /**
321
+ * Restore conversation history after the slot region.
322
+ *
323
+ * Splices saved messages into the array starting at position slotCount,
324
+ * replacing any existing conversation history.
325
+ *
326
+ * @param messages - Previously saved conversation history
327
+ */
328
+ restoreConversationHistory(messages: AgentMessage[]): void;
329
+ /**
330
+ * Get the primary model.
331
+ */
332
+ getModel(): CortexModel;
333
+ /**
334
+ * Get the resolved utility model.
335
+ */
336
+ getUtilityModel(): CortexModel;
337
+ /**
338
+ * Hot-swap the primary model without restarting the agent.
339
+ * Used when the user changes their provider/model in settings.
340
+ *
341
+ * @param model - The new CortexModel to use
342
+ */
343
+ setModel(model: CortexModel): void;
344
+ /**
345
+ * Explicitly set the utility model, overriding auto-resolution.
346
+ * The utility model must be from the same provider as the primary model.
347
+ * After calling this, setModel() will NOT auto-resolve the utility model.
348
+ * Call resetUtilityModel() to restore auto-resolution.
349
+ *
350
+ * @param model - The CortexModel to use as the utility model
351
+ */
352
+ setUtilityModel(model: CortexModel): void;
353
+ /**
354
+ * Reset the utility model to auto-resolution based on the primary model's provider.
355
+ * Clears any manual override set by setUtilityModel().
356
+ */
357
+ resetUtilityModel(): void;
358
+ /**
359
+ * Whether the utility model has been manually overridden.
360
+ */
361
+ isUtilityModelOverridden(): boolean;
362
+ /**
363
+ * Change the thinking/reasoning effort level.
364
+ * Maps Cortex's "max" to pi-agent-core's "xhigh" internally.
365
+ *
366
+ * @param level - The consumer-facing thinking level
367
+ */
368
+ setThinkingLevel(level: ThinkingLevel): void;
369
+ /**
370
+ * Get the current thinking/reasoning effort level.
371
+ * Maps pi-agent-core's "xhigh" back to Cortex's "max".
372
+ *
373
+ * @returns The current consumer-facing thinking level, or 'medium' if not set
374
+ */
375
+ getThinkingLevel(): ThinkingLevel;
376
+ get isWorkingTagsEnabled(): boolean;
377
+ setWorkingTagsEnabled(enabled: boolean): void;
378
+ /**
379
+ * Get the thinking capabilities of the current primary model.
380
+ * Uses pi-ai model metadata to expose the exact supported thinking levels.
381
+ *
382
+ * @returns Capabilities object describing thinking support
383
+ */
384
+ getModelThinkingCapabilities(): Promise<ModelThinkingCapabilities>;
385
+ /**
386
+ * Clamp a requested thinking level to the current model's supported levels.
387
+ * Pi may clamp upward before clamping downward, so callers should surface
388
+ * clamping to users when latency or cost could change.
389
+ */
390
+ clampThinkingLevel(level: ThinkingLevel): Promise<ThinkingLevel>;
391
+ /**
392
+ * Set the cache retention policy for the agentic loop.
393
+ * Used by the consumer to switch between short/long cache based on
394
+ * tick interval and provider. Managed agents pass this through the pi-ai
395
+ * stream options for each provider request.
396
+ */
397
+ setCacheRetention(value: 'none' | 'short' | 'long'): void;
398
+ /**
399
+ * Get the current cache retention policy.
400
+ * Returns null if not yet resolved (pi-ai will use its own default).
401
+ */
402
+ getCacheRetention(): 'none' | 'short' | 'long' | null;
403
+ /**
404
+ * Process a tool result through the result-persistence interceptor.
405
+ * Delegates to the shared `processToolResult` helper, supplying instance
406
+ * state (persistResult callback, tool categories, threshold overrides).
407
+ */
408
+ private applyToolResultPersistence;
409
+ /**
410
+ * Pi 0.74 snapshots the agent state when prompt() starts. When ToolSearch
411
+ * loads deferred tools mid-run, keep the active loop context in sync so the
412
+ * next automatic provider call sees the newly loaded schemas.
413
+ */
414
+ private syncActiveLoopTools;
415
+ /**
416
+ * Update the agent's tool set by adapting Cortex's canonical in-process
417
+ * tool contract to pi-agent-core's raw execute signature.
418
+ *
419
+ * When deferred tools are enabled, this also partitions the union of
420
+ * registered + MCP tools into a "loaded" set (sent to the API) and a
421
+ * "deferred" set (announced by name in the `_available_tools` slot).
422
+ */
423
+ refreshTools(): void;
424
+ /**
425
+ * Register an additional consumer-provided tool at runtime.
426
+ * Useful for dynamic tool management (e.g., enabling a tool after agent
427
+ * creation based on user permission changes).
428
+ */
429
+ addConsumerTool(tool: CortexTool): void;
430
+ /**
431
+ * Remove a consumer-provided tool by name at runtime.
432
+ * Built-in tools cannot be removed.
433
+ */
434
+ removeConsumerTool(toolName: string): void;
435
+ /**
436
+ * Partition candidate tools into "loaded" (sent on every turn) and
437
+ * "deferred" (announced by name in the `_available_tools` slot).
438
+ *
439
+ * A tool is deferred when:
440
+ * - It is not in the consumer's `alwaysLoad` allowlist, AND
441
+ * - Its `alwaysLoad` field is not true, AND
442
+ * - It has not been discovered via ToolSearch this session, AND
443
+ * - Either `tool.shouldDefer === true` OR
444
+ * (`tool.isMcp === true` AND `_deferMcp` is true)
445
+ */
446
+ private partitionDeferredTools;
447
+ private shouldDeferTool;
448
+ /**
449
+ * Update the `_available_tools` slot if its content has actually changed.
450
+ * Skipping no-op writes preserves the prompt cache: identical bytes mean
451
+ * the cached prefix stays valid for the next API call.
452
+ */
453
+ private updateAvailableToolsSlot;
454
+ /**
455
+ * Make a utility completion call using the utility model.
456
+ * Convenience wrapper for internal operations (WebFetch summarization,
457
+ * safety classification, etc.).
458
+ *
459
+ * Analogous to directComplete() but uses the utility model (smaller, cheaper)
460
+ * instead of the primary model. Dynamically imports pi-ai's complete() function.
461
+ *
462
+ * @param context - System prompt and messages for the completion
463
+ * @returns The response text from the LLM
464
+ * @throws Error if pi-ai is not installed or the call fails
465
+ */
466
+ utilityComplete(context: {
467
+ systemPrompt: string;
468
+ messages: Array<{
469
+ role: string;
470
+ content: string;
471
+ }>;
472
+ }): Promise<string>;
473
+ /**
474
+ * Abort the current agentic loop without destroying the agent.
475
+ * The agent remains usable for subsequent prompts.
476
+ */
477
+ abort(): Promise<void>;
478
+ /**
479
+ * Ordered cleanup of all resources.
480
+ * Called by the consumer when the agent is no longer needed.
481
+ *
482
+ * Steps:
483
+ * 1. Abort any in-progress agentic loop
484
+ * 2. Wait for idle (with timeout)
485
+ * 3. Cancel all sub-agents (stub, wired in Phase 4)
486
+ * 4. Emit onLoopComplete for final checkpoint (best-effort)
487
+ * 5. Close all MCP client connections (kills stdio subprocesses, closes HTTP)
488
+ * 6. Clear skill buffer (stub, wired in Phase 4)
489
+ * 7. Unsubscribe all event listeners
490
+ * 8. Clear agent state
491
+ * 9. Mark as destroyed
492
+ *
493
+ * @param timeoutMs - Maximum time to wait for cleanup (default: 8000ms)
494
+ */
495
+ destroy(timeoutMs?: number): Promise<void>;
496
+ /**
497
+ * Whether the agent is currently running an agentic loop.
498
+ */
499
+ get isRunning(): boolean;
500
+ /**
501
+ * Get the current lifecycle state.
502
+ */
503
+ get state(): CortexLifecycleState;
504
+ /**
505
+ * The number of messages in agent.state.messages before the current
506
+ * prompt() call. Used by the cache breakpoint system to distinguish
507
+ * "old history" (cacheable) from "new tick content" (ephemeral).
508
+ */
509
+ get prePromptMessageCount(): number;
510
+ /**
511
+ * Register a handler for when the full agentic loop completes.
512
+ * Maps to pi-agent-core's agent_end event.
513
+ * The consumer uses this to trigger conversation history checkpoints.
514
+ */
515
+ onLoopComplete(handler: () => void): void;
516
+ /**
517
+ * Register a handler for classified errors during the agentic loop.
518
+ */
519
+ onError(handler: (error: ClassifiedError) => void): void;
520
+ /**
521
+ * Register a handler called before compaction starts.
522
+ * Handler is awaited. The consumer should flush critical state
523
+ * (e.g., observational memory) before history is compacted.
524
+ *
525
+ * NOT called during mid-loop emergency truncation (Layer 3).
526
+ */
527
+ onBeforeCompaction(handler: (target: CompactionTarget) => Promise<void>): void;
528
+ /**
529
+ * Register a handler called after compaction completes.
530
+ * The consumer uses this to re-seed messages from messages.db,
531
+ * update internal state, or perform other post-compaction work.
532
+ */
533
+ onPostCompaction(handler: (result: CompactionResult) => void): void;
534
+ /**
535
+ * Register a handler for compaction errors.
536
+ */
537
+ onCompactionError(handler: (error: Error) => void): void;
538
+ /**
539
+ * Register a handler called when Layer 2 compaction failed and Layer 3
540
+ * (emergency truncation) was used as fallback. The session continues
541
+ * but context quality is degraded.
542
+ */
543
+ onCompactionDegraded(handler: (info: CompactionDegradedInfo) => void): void;
544
+ /**
545
+ * Register a handler called when all compaction layers have failed.
546
+ * The consumer should take recovery action (e.g., pause heartbeat,
547
+ * abort the session, or notify the user).
548
+ */
549
+ onCompactionExhausted(handler: (info: CompactionExhaustedInfo) => void): void;
550
+ /**
551
+ * Register a handler for turn completion with parsed working tag output.
552
+ */
553
+ onTurnComplete(handler: (output: AgentTextOutput) => void): void;
554
+ /**
555
+ * Register a handler for sub-agent spawn events.
556
+ */
557
+ onSubAgentSpawned(handler: (taskId: string, instructions: string, background: boolean) => void): void;
558
+ /**
559
+ * Register a handler for sub-agent completion events.
560
+ */
561
+ onSubAgentCompleted(handler: (taskId: string, result: string, status: string, usage: unknown) => void): void;
562
+ /**
563
+ * Register a handler for sub-agent failure events.
564
+ */
565
+ onSubAgentFailed(handler: (taskId: string, error: string) => void): void;
566
+ /**
567
+ * Register a handler that fires when background sub-agent results are about
568
+ * to be delivered to the parent agent, restarting its agentic loop.
569
+ * Consumers can use this to update UI state (show spinners, etc.).
570
+ */
571
+ onBackgroundResultDelivery(handler: (taskIds: string[]) => void): void;
572
+ /**
573
+ * Get the EventBridge for direct event access.
574
+ * Consumers that need raw event data (for logging) can subscribe directly.
575
+ */
576
+ getEventBridge(): EventBridge;
577
+ /**
578
+ * Get the BudgetGuard for inspecting turn/cost state.
579
+ */
580
+ getBudgetGuard(): BudgetGuard;
581
+ /**
582
+ * Get the usage data from the most recent directComplete() or
583
+ * structuredComplete() call. Returns null if no usage was available
584
+ * or no call has been made yet.
585
+ *
586
+ * This is the primary mechanism for consumers (like the backend pipeline)
587
+ * to capture per-phase usage for persistence. The value is reset to null
588
+ * at the start of each directComplete/structuredComplete call.
589
+ */
590
+ getLastDirectUsage(): CortexUsage | null;
591
+ /**
592
+ * Get accumulated session usage (cost, turns, token breakdown).
593
+ *
594
+ * Unlike BudgetGuard (which resets per agentic loop), this accumulates
595
+ * across the entire session lifetime. Consumers can persist this value
596
+ * and restore it via restoreSessionUsage() after loading a saved session.
597
+ */
598
+ getSessionUsage(): SessionUsage;
599
+ /**
600
+ * Restore session usage from consumer-provided data.
601
+ *
602
+ * Call this after restoreConversationHistory() when resuming a saved session.
603
+ * Values are added to any usage already accumulated (in case turns ran
604
+ * before the restore call).
605
+ */
606
+ restoreSessionUsage(usage: SessionUsage): void;
607
+ /**
608
+ * Update the post-hoc current-context token count from LLM usage data.
609
+ * Called by the consumer after each LLM call with the input_tokens
610
+ * from AssistantMessage.usage.
611
+ */
612
+ updateCurrentContextTokenCount(inputTokens: number): void;
613
+ /**
614
+ * Get the post-hoc current-context token count from the most recent parent turn.
615
+ */
616
+ get currentContextTokenCount(): number;
617
+ /**
618
+ * Estimate the current context tokens Cortex would send on the next parent LLM call.
619
+ *
620
+ * This is a heuristic estimate of the transformed context snapshot built from:
621
+ * - the current system prompt
622
+ * - slots and conversation history
623
+ * - ephemeral context
624
+ * - background task state
625
+ * - loaded skills
626
+ *
627
+ * The estimate is compared against the most recent post-hoc parent turn usage
628
+ * and the larger value is returned. This matches the compaction manager's
629
+ * internal decision logic.
630
+ */
631
+ estimateCurrentContextTokens(): number;
632
+ /**
633
+ * Set the context window size (from model metadata).
634
+ * If a contextWindowLimit is set, the effective value will be
635
+ * min(limit, contextWindow) with a floor of MINIMUM_CONTEXT_WINDOW.
636
+ */
637
+ setContextWindow(contextWindow: number): void;
638
+ /**
639
+ * Set a user-configured limit on the context window.
640
+ * The effective context window becomes min(limit, model.contextWindow)
641
+ * with a floor of MINIMUM_CONTEXT_WINDOW (16K tokens).
642
+ * Pass null to remove the limit and use the model's full context window.
643
+ */
644
+ setContextWindowLimit(limit: number | null): void;
645
+ /**
646
+ * Get the raw user-configured context window limit (null = no limit).
647
+ */
648
+ get contextWindowLimit(): number | null;
649
+ /**
650
+ * Get the effective context window after applying the limit and floor.
651
+ */
652
+ get effectiveContextWindow(): number;
653
+ /**
654
+ * Get the model's actual context window (unaffected by consumer limits).
655
+ */
656
+ get modelContextWindow(): number;
657
+ /**
658
+ * Recompute and apply the effective context window from the model
659
+ * and the user-configured limit.
660
+ */
661
+ private _updateEffectiveContextWindow;
662
+ /**
663
+ * Signal how recently the user last interacted.
664
+ * Used by the compaction system to adjust thresholds:
665
+ * - Recent interaction: use normal thresholds
666
+ * - No interaction for a while: compact more aggressively
667
+ *
668
+ * The backend calls this during GATHER when a message-triggered tick fires
669
+ * (set to Date.now()). For interval ticks, it is not called, so the
670
+ * timestamp ages naturally.
671
+ */
672
+ setLastInteractionTime(timestamp: number): void;
673
+ /**
674
+ * Cap a tool result at insertion time. If the result exceeds
675
+ * maxResultTokens, truncates to head+tail bookend format.
676
+ * Call this when tool results enter conversation history.
677
+ */
678
+ capToolResult(content: string): string;
679
+ /**
680
+ * Get the observational memory state for session persistence.
681
+ * Returns null if not using the observational strategy.
682
+ */
683
+ getObservationalMemoryState(): ObservationalMemoryState | null;
684
+ /**
685
+ * Restore observational memory state from a previous session.
686
+ * Must be called after restoreConversationHistory().
687
+ */
688
+ restoreObservationalMemoryState(state: ObservationalMemoryState): void;
689
+ /**
690
+ * Force a synchronous observation cycle.
691
+ * Useful after critical user corrections.
692
+ */
693
+ triggerObservation(): Promise<void>;
694
+ /**
695
+ * Register a handler for observation events.
696
+ * Fires when messages are compressed into observations.
697
+ */
698
+ onObservation(handler: (event: ObservationEvent) => void): void;
699
+ /**
700
+ * Register a handler for reflection events.
701
+ * Fires when the reflector condenses observations.
702
+ */
703
+ onReflection(handler: (event: ReflectionEvent) => void): void;
704
+ /**
705
+ * Run end-of-tick compaction check. Call after EXECUTE completes,
706
+ * before the next tick starts. Returns the CompactionResult if
707
+ * Layer 2 compaction ran, null otherwise.
708
+ */
709
+ checkAndRunCompaction(): Promise<CompactionResult | null>;
710
+ /**
711
+ * Get the CompactionManager for advanced use.
712
+ */
713
+ getCompactionManager(): CompactionManager;
714
+ /**
715
+ * Get the configured environment variable overrides.
716
+ * Consumers use this when creating built-in tools (e.g., BashToolConfig.envOverrides)
717
+ * to ensure all subprocess environments include these overrides.
718
+ */
719
+ getEnvOverrides(): Record<string, string> | undefined;
720
+ /**
721
+ * Get the McpClientManager for managing MCP server connections.
722
+ * Consumers use this to connect/disconnect plugin tool servers
723
+ * and to retrieve discovered tools.
724
+ */
725
+ getMcpClientManager(): McpClientManager;
726
+ /**
727
+ * Connect to an MCP server and discover its tools.
728
+ * Convenience wrapper around mcpClientManager.connect().
729
+ *
730
+ * @param serverName - Unique name for this server (used for tool namespacing)
731
+ * @param config - Transport configuration (stdio or http)
732
+ */
733
+ connectMcpServer(serverName: string, config: McpTransportConfig): Promise<void>;
734
+ /**
735
+ * Disconnect from an MCP server and remove its tools.
736
+ * Convenience wrapper around mcpClientManager.disconnect().
737
+ *
738
+ * @param serverName - The server name to disconnect
739
+ */
740
+ disconnectMcpServer(serverName: string): Promise<void>;
741
+ /**
742
+ * Get all tools from all sources: built-in tools registered on the
743
+ * pi-agent-core Agent, plus MCP-wrapped tools from connected servers.
744
+ *
745
+ * Returns only the MCP-wrapped tools. Built-in tools are registered
746
+ * directly on the Agent and are not included here.
747
+ */
748
+ getMcpTools(): CortexTool[];
749
+ /**
750
+ * Get the composed transformContext hook for the pi-agent-core Agent.
751
+ *
752
+ * Composes five steps in order:
753
+ * 0. Tier 1 insertion-time cap (mutates source messages)
754
+ * 1. Insert ephemeral + skill buffer at the boundary position
755
+ * (after old history, before new tick content) for cache optimization
756
+ * 2. Message sanitization
757
+ * 3. Compaction (all three layers: microcompaction, summarization, failsafe)
758
+ * 4. Compute API message indices for cache breakpoints BP2 and BP3
759
+ *
760
+ * Cache breakpoint strategy:
761
+ * Anthropic allows 4 cache_control breakpoints. Pi-ai sets up to 3
762
+ * (system prompt, last tool definition, last user message). The
763
+ * onPayload hook strips the tool breakpoint and adds BP2 (after last
764
+ * slot) and BP3 (old history boundary), keeping the total at 4.
765
+ *
766
+ * By inserting ephemeral at the boundary instead of the end, the
767
+ * conversation history prefix becomes stable across ticks, enabling
768
+ * cache reads on ~128K of tokens instead of only ~5.5K.
769
+ *
770
+ * The hook is async because Layer 2 compaction may require an LLM call
771
+ * for summarization. Pi-agent-core's transformContext supports async hooks.
772
+ *
773
+ * @returns An async transformContext function for the Agent constructor
774
+ */
775
+ getTransformContextHook(): (context: AgentContext) => Promise<AgentContext>;
776
+ private buildAgentContextSnapshot;
777
+ private buildInjectedAndSanitizedContextSnapshot;
778
+ /**
779
+ * Compute API message indices for cache breakpoints BP2 and BP3.
780
+ *
781
+ * Walks the transformed message array and counts how messages will appear
782
+ * in the final Anthropic API params after convertMessages processes them.
783
+ * convertMessages skips empty user messages and merges consecutive
784
+ * toolResult messages into single user messages.
785
+ *
786
+ * BP2: placed after the last slot message. Slots are stable across the
787
+ * entire session lifetime, so everything up to BP2 is always cached.
788
+ * BP3: placed at the old history boundary (before injected ephemeral/skills).
789
+ * Old history is stable across ticks within the same session, so this
790
+ * is a "ratcheting" breakpoint that advances as history grows.
791
+ *
792
+ * @param messages - The transformed message array (after injection + sanitization)
793
+ * @param slotCount - Number of slot messages at the start of the array
794
+ * @returns API indices for BP2 and BP3, or -1 if not applicable
795
+ */
796
+ private computeCacheBreakpointIndices;
797
+ /**
798
+ * Create built-in tool instances, excluding any in the disabled set.
799
+ */
800
+ private createBuiltinTools;
801
+ /**
802
+ * Normalize registered tools so this agent owns fresh mutable state and
803
+ * everything stored internally uses Cortex's canonical tool contract.
804
+ */
805
+ private normalizeRegisteredTools;
806
+ private resolveModels;
807
+ /**
808
+ * Resolve the utility model from the public CortexModel boundary.
809
+ * If 'default' or undefined, look up the provider default and preserve
810
+ * the raw provider-specific fields from the primary pi-ai model.
811
+ */
812
+ private resolveUtilityModels;
813
+ /**
814
+ * Build the Environment section of the system prompt.
815
+ * Dynamically generated from the actual runtime environment.
816
+ */
817
+ private buildEnvironmentSection;
818
+ /**
819
+ * Detect the current shell.
820
+ */
821
+ private detectShell;
822
+ /**
823
+ * Wire internal event handlers to the EventBridge.
824
+ * Maps bridge events to consumer-registered callbacks.
825
+ */
826
+ private wireInternalEvents;
827
+ /**
828
+ * Extract text from a turn_end event's raw data.
829
+ */
830
+ private extractTurnTextFromEvent;
831
+ /**
832
+ * Extract input token count from a turn_end event's raw data.
833
+ *
834
+ * Pi-agent-core's turn_end event carries the AssistantMessage which
835
+ * includes usage.input from pi-ai. This is the total input token count
836
+ * for that LLM call (an assignment, not a delta).
837
+ *
838
+ * Follows the same multi-pattern extraction approach as BudgetGuard's
839
+ * extractCost to handle variations in pi-agent-core event structure.
840
+ */
841
+ private extractInputTokens;
842
+ /**
843
+ * Compute total input tokens from a pi-ai Usage object.
844
+ * With prefix caching, tokens shift between input/cacheRead/cacheWrite.
845
+ * The real context size is `input + cacheRead + cacheWrite`.
846
+ * Falls back to `totalTokens - output` if individual fields are missing.
847
+ */
848
+ private computeTotalInput;
849
+ /**
850
+ * Check if the agent was aborted (user or system cancellation).
851
+ * Only returns true for actual abort/cancel signals, not arbitrary errors.
852
+ */
853
+ private isAborted;
854
+ /**
855
+ * Check if the agent is currently idle (not running a loop).
856
+ * Tracked via a boolean flag set at prompt() entry and cleared in its finally block.
857
+ */
858
+ private isIdle;
859
+ /**
860
+ * Extract text content from a pi-ai AssistantMessage response.
861
+ *
862
+ * Pi-ai's complete() returns an AssistantMessage with either:
863
+ * - A string `content` field
864
+ * - A `content` array with typed parts (text, thinking, toolCall)
865
+ */
866
+ private extractTextFromAssistantMessage;
867
+ /**
868
+ * Extract a summary of tool calls from a child agent's conversation history.
869
+ * Scans for toolResult messages and builds a name + duration list.
870
+ */
871
+ private extractToolCallSummary;
872
+ /**
873
+ * Extract usage data from a pi-ai AssistantMessage response.
874
+ *
875
+ * The AssistantMessage.usage field has the structure:
876
+ * { input, output, cacheRead, cacheWrite, totalTokens,
877
+ * cost: { input, output, cacheRead, cacheWrite, total } }
878
+ *
879
+ * Returns null if usage data is not present or not in the expected format.
880
+ */
881
+ private extractUsageFromAssistantMessage;
882
+ /**
883
+ * Perform ordered cleanup.
884
+ */
885
+ private orderedCleanup;
886
+ /**
887
+ * Force-kill all tracked subprocesses.
888
+ * Synchronous, last-resort fallback for unclean exits.
889
+ */
890
+ private forceKillAll;
891
+ /**
892
+ * Set up process exit handler for orphaned subprocess cleanup (Level 3 safety net).
893
+ */
894
+ private setupExitHandler;
895
+ private static handleProcessExit;
896
+ private trackPid;
897
+ private untrackPid;
898
+ /**
899
+ * Get the SkillRegistry for add/remove/query operations.
900
+ */
901
+ getSkillRegistry(): SkillRegistry;
902
+ /**
903
+ * Pre-load a skill into the ephemeral context for the current loop.
904
+ * Same path as the load_skill tool, but triggered by the consumer.
905
+ * No LLM turn is consumed.
906
+ */
907
+ loadSkill(name: string, args?: string): Promise<void>;
908
+ /**
909
+ * Clear the skill buffer. The consumer should call this at the start
910
+ * of each tick (before pre-loading skills for the new loop).
911
+ * Cortex cannot auto-clear because it has no concept of tick boundaries,
912
+ * and clearing at prompt() start would wipe consumer pre-loaded skills.
913
+ */
914
+ clearSkillBuffer(): void;
915
+ /**
916
+ * Get the current skill buffer contents.
917
+ */
918
+ getSkillBuffer(): LoadedSkill[];
919
+ /**
920
+ * Set consumer-provided variables for ${VAR} substitution in skills.
921
+ * Merged with Cortex built-ins (SKILL_DIR, ARGUMENTS).
922
+ * Consumer variables take precedence on collision.
923
+ * Call this each tick during GATHER to update runtime values.
924
+ */
925
+ setPreprocessorVariables(variables: Record<string, string>): void;
926
+ /**
927
+ * Set consumer-provided context that will be passed to skill scripts.
928
+ * Merged with Cortex built-in fields (skillDir, args, scriptArgs).
929
+ * Consumer fields take precedence on collision.
930
+ * Call this each tick during GATHER to update runtime values.
931
+ */
932
+ setScriptContext(context: Record<string, unknown>): void;
933
+ /**
934
+ * Get the SubAgentManager for direct sub-agent tracking.
935
+ */
936
+ getSubAgentManager(): SubAgentManager;
937
+ /**
938
+ * Spawn a background sub-agent and return its task ID immediately.
939
+ * Used by consumers that manage delegated work outside the SubAgent tool.
940
+ */
941
+ spawnBackgroundSubAgent(params: Omit<SubAgentSpawnConfig, 'background'>): Promise<{
942
+ taskId: string;
943
+ }>;
944
+ /**
945
+ * Rebuild the load_skill tool's description with the current available
946
+ * skills summary. Called automatically when skills are added/removed
947
+ * via the registry's onChange callback.
948
+ */
949
+ private rebuildLoadSkillDescription;
950
+ private buildAvailableSkillsSummary;
951
+ /**
952
+ * Push a loaded skill to the buffer with deduplication.
953
+ * If the same skill is loaded twice, the second replaces the first.
954
+ */
955
+ private pushToSkillBuffer;
956
+ /**
957
+ * Skill injection is now handled inline in getTransformContextHook()
958
+ * at the boundary position for cache optimization. This method is
959
+ * retained as a no-op for backward compatibility.
960
+ * @deprecated Skill injection moved to getTransformContextHook() boundary insertion
961
+ */
962
+ private injectSkillBuffer;
963
+ /**
964
+ * Wire the sub-agent manager's lifecycle hooks to CortexAgent event handlers.
965
+ */
966
+ private wireSubAgentHooks;
967
+ /**
968
+ * Build a short summary of tool args for background state display.
969
+ */
970
+ private summarizeToolArgs;
971
+ /**
972
+ * Build a <background-tasks> block describing running sub-agents and
973
+ * background bash processes. Returns null if nothing is running.
974
+ * Called from transformContext before each LLM call.
975
+ */
976
+ private buildBackgroundTaskState;
977
+ /**
978
+ * Spawn a foreground sub-agent and block until completion.
979
+ * Used by the SubAgent tool.
980
+ */
981
+ private spawnForegroundSubAgentInternal;
982
+ /**
983
+ * Spawn a background sub-agent and return the task ID immediately.
984
+ */
985
+ private spawnBackgroundSubAgentInternal;
986
+ /**
987
+ * Handle a background sub-agent completing. If the parent is currently
988
+ * prompting, queue the result for delivery after the current loop. If
989
+ * the parent is idle, deliver immediately by restarting the agentic loop.
990
+ */
991
+ private handleBackgroundCompletion;
992
+ /**
993
+ * Drain all pending background sub-agent results by restarting the
994
+ * agentic loop with a combined message. Called at the end of prompt().
995
+ */
996
+ private drainPendingBackgroundResults;
997
+ private formatBackgroundResult;
998
+ private fireBackgroundResultDeliveryHandlers;
999
+ private createChildAgent;
1000
+ private resolveChildPromptSeed;
1001
+ /**
1002
+ * Run a sub-agent to completion. Handles result delivery to the manager.
1003
+ */
1004
+ private runSubAgent;
1005
+ /**
1006
+ * Build child agent config from parent config and spawn params.
1007
+ * Budget guards can be tightened, not loosened.
1008
+ */
1009
+ private buildChildAgentConfig;
1010
+ /**
1011
+ * Build the tool set for a child agent.
1012
+ * SubAgent and load_skill are always excluded from child agents.
1013
+ */
1014
+ private buildChildToolSet;
1015
+ /**
1016
+ * Generate a unique task ID for sub-agents.
1017
+ */
1018
+ private generateTaskId;
1019
+ }
1020
+ //# sourceMappingURL=cortex-agent.d.ts.map