@lotagate/cli 0.1.25 → 0.1.27

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 (256) hide show
  1. package/README.md +5 -4
  2. package/bin/lotagate.mjs +50 -8
  3. package/dist/application/agent/agent-constants.d.ts +6 -0
  4. package/dist/application/agent/agent-constants.js +1 -0
  5. package/dist/application/agent/agent-session-store-registry.d.ts +16 -0
  6. package/dist/application/agent/agent-session-store-registry.js +1 -0
  7. package/dist/application/agent/agent-session-store.d.ts +4 -0
  8. package/dist/application/agent/agent-session-store.js +5 -5
  9. package/dist/application/agent/bounded-text-accumulator.d.ts +15 -0
  10. package/dist/application/agent/bounded-text-accumulator.js +1 -0
  11. package/dist/application/agent/capability-profile.d.ts +0 -38
  12. package/dist/application/agent/capability-profile.js +0 -1
  13. package/dist/application/agent/cli-agent-execution-service.d.ts +23 -13
  14. package/dist/application/agent/cli-agent-execution-service.js +1 -1
  15. package/dist/application/agent/cli-agent-preparation-cache.d.ts +39 -0
  16. package/dist/application/agent/cli-agent-preparation-cache.js +1 -0
  17. package/dist/application/agent/context-compaction.d.ts +1 -0
  18. package/dist/application/agent/context-compaction.js +7 -6
  19. package/dist/application/agent/context-token-cache.d.ts +21 -0
  20. package/dist/application/agent/context-token-cache.js +4 -0
  21. package/dist/application/agent/context-usage-service.d.ts +52 -0
  22. package/dist/application/agent/context-usage-service.js +1 -0
  23. package/dist/application/agent/continuation-checkpoint.d.ts +15 -0
  24. package/dist/application/agent/continuation-checkpoint.js +2 -0
  25. package/dist/application/agent/interactive-agent-guidance.d.ts +3 -3
  26. package/dist/application/agent/interactive-agent-guidance.js +2 -2
  27. package/dist/application/chat/pending-attachment-store.d.ts +5 -2
  28. package/dist/application/chat/pending-attachment-store.js +1 -1
  29. package/dist/application/commands/application-command-executor.js +2 -2
  30. package/dist/application/commands/cli-command-services.d.ts +1 -1
  31. package/dist/application/commands/cli-command-services.js +31 -31
  32. package/dist/application/commands/command-catalog.js +1 -1
  33. package/dist/application/commands/goal-command-handlers.js +6 -6
  34. package/dist/application/commands/media-command-handlers.js +7 -6
  35. package/dist/application/commands/memory-command-handler.d.ts +1 -1
  36. package/dist/application/commands/memory-command-handler.js +11 -11
  37. package/dist/application/commands/runtime-command-handlers.js +11 -11
  38. package/dist/application/extensions/plugin-contribution-registry.js +1 -1
  39. package/dist/application/intent/completion-gate.d.ts +2 -5
  40. package/dist/application/intent/completion-gate.js +1 -1
  41. package/dist/application/intent/evidence-ledger.d.ts +2 -1
  42. package/dist/application/intent/evidence-recording-tool-executor.js +1 -1
  43. package/dist/application/intent/intent-compiler.js +2 -2
  44. package/dist/application/lifecycle/operation-registry.d.ts +11 -0
  45. package/dist/application/lifecycle/operation-registry.js +1 -0
  46. package/dist/application/memory/memory-extractor.js +2 -2
  47. package/dist/application/model/cached-model-catalog.d.ts +7 -1
  48. package/dist/application/model/cached-model-catalog.js +1 -1
  49. package/dist/application/model/model-catalog-service.js +1 -1
  50. package/dist/application/model/model-context-window.js +1 -1
  51. package/dist/application/model/model-response-retry.d.ts +7 -1
  52. package/dist/application/model/model-response-retry.js +1 -1
  53. package/dist/application/orchestration/cli-subagent-service.d.ts +4 -0
  54. package/dist/application/orchestration/cli-subagent-service.js +3 -3
  55. package/dist/application/orchestration/cli-turn-event-projector.js +1 -1
  56. package/dist/application/orchestration/cli-turn-events.d.ts +0 -7
  57. package/dist/application/orchestration/goal-input.d.ts +1 -1
  58. package/dist/application/orchestration/goal-input.js +1 -1
  59. package/dist/application/orchestration/headless-agent-turn.d.ts +1 -0
  60. package/dist/application/orchestration/headless-agent-turn.js +3 -3
  61. package/dist/application/orchestration/orchestration-constants.d.ts +3 -0
  62. package/dist/application/orchestration/orchestration-constants.js +1 -0
  63. package/dist/application/orchestration/subagent-handoff.js +3 -3
  64. package/dist/application/project-intelligence/project-intelligence-constants.d.ts +56 -0
  65. package/dist/application/project-intelligence/project-intelligence-constants.js +1 -0
  66. package/dist/application/project-intelligence/project-intelligence-service.js +1 -1
  67. package/dist/application/protocol/browser-host-tool-executor.d.ts +13 -3
  68. package/dist/application/protocol/browser-host-tool-executor.js +2 -2
  69. package/dist/application/protocol/computer-host-tool-executor.d.ts +3 -0
  70. package/dist/application/protocol/computer-host-tool-executor.js +2 -2
  71. package/dist/application/protocol/desktop-agent-command.d.ts +2 -2
  72. package/dist/application/protocol/desktop-agent-command.js +1 -3
  73. package/dist/application/protocol/desktop-agent-contracts.d.ts +34 -0
  74. package/dist/application/protocol/desktop-agent-contracts.js +1 -0
  75. package/dist/application/protocol/desktop-agent-helpers.d.ts +5 -0
  76. package/dist/application/protocol/desktop-agent-helpers.js +1 -0
  77. package/dist/application/protocol/desktop-agent-request-parser.d.ts +31 -6
  78. package/dist/application/protocol/desktop-agent-request-parser.js +1 -1
  79. package/dist/application/protocol/desktop-approval-broker.d.ts +14 -4
  80. package/dist/application/protocol/desktop-approval-broker.js +1 -1
  81. package/dist/application/protocol/desktop-attachment-store.d.ts +19 -2
  82. package/dist/application/protocol/desktop-attachment-store.js +1 -1
  83. package/dist/application/protocol/desktop-execution-policy.d.ts +2 -0
  84. package/dist/application/protocol/desktop-execution-policy.js +1 -1
  85. package/dist/application/protocol/desktop-host-bridge.d.ts +33 -0
  86. package/dist/application/protocol/desktop-host-bridge.js +1 -0
  87. package/dist/application/protocol/desktop-host-capabilities.d.ts +12 -0
  88. package/dist/application/protocol/desktop-host-capabilities.js +1 -0
  89. package/dist/application/protocol/desktop-host-tool-executor.d.ts +15 -2
  90. package/dist/application/protocol/desktop-host-tool-executor.js +2 -2
  91. package/dist/application/protocol/desktop-intent-event-writer.js +1 -1
  92. package/dist/application/protocol/desktop-protocol-helpers.js +1 -1
  93. package/dist/application/protocol/desktop-title-generator.d.ts +5 -0
  94. package/dist/application/protocol/desktop-title-generator.js +3 -0
  95. package/dist/application/protocol/json-line-writer.d.ts +24 -2
  96. package/dist/application/protocol/json-line-writer.js +2 -2
  97. package/dist/application/protocol/jsonl-agent-command.d.ts +1 -1
  98. package/dist/application/protocol/jsonl-agent-command.js +2 -2
  99. package/dist/application/protocol/jsonl-protocol.d.ts +1 -1
  100. package/dist/application/protocol/jsonl-protocol.js +2 -2
  101. package/dist/application/security/desktop-tool-scope-policy.js +1 -1
  102. package/dist/application/security/tool-action-risk-analyzer.js +1 -1
  103. package/dist/application/security/tool-approval-service.d.ts +9 -3
  104. package/dist/application/security/tool-approval-service.js +1 -1
  105. package/dist/application/security/tool-policy-registry.d.ts +20 -0
  106. package/dist/application/security/tool-policy-registry.js +1 -0
  107. package/dist/application/security/tool-risk-classifier.d.ts +2 -1
  108. package/dist/application/security/tool-risk-classifier.js +1 -1
  109. package/dist/application/security/workspace-permission-policy.js +1 -1
  110. package/dist/application/workspace/session-execution-workspace.d.ts +2 -2
  111. package/dist/application/workspace/session-execution-workspace.js +3 -3
  112. package/dist/application/workspace/workspace-constants.d.ts +17 -0
  113. package/dist/application/workspace/workspace-constants.js +1 -0
  114. package/dist/application/workspace/workspace-file-index.d.ts +2 -3
  115. package/dist/application/workspace/workspace-file-index.js +1 -1
  116. package/dist/application/workspace/workspace-instruction-loader.js +1 -1
  117. package/dist/bootstrap/composition-root.d.ts +1 -0
  118. package/dist/bootstrap/runtime-factory.d.ts +5 -0
  119. package/dist/bootstrap/runtime-factory.js +1 -1
  120. package/dist/domain/auth/auth-profile.d.ts +1 -0
  121. package/dist/domain/auth/auth-profile.js +1 -1
  122. package/dist/domain/errors/cli-error.js +1 -1
  123. package/dist/domain/extensions/extension-constants.d.ts +1 -0
  124. package/dist/domain/extensions/extension-constants.js +1 -0
  125. package/dist/domain/extensions/host-tool-plugin-ids.d.ts +0 -4
  126. package/dist/domain/extensions/host-tool-plugin-ids.js +1 -1
  127. package/dist/domain/extensions/plugin-manifest.js +1 -1
  128. package/dist/domain/intent/intent-contract.d.ts +0 -8
  129. package/dist/domain/intent/intent-contract.js +1 -1
  130. package/dist/domain/media/gateway-media-contract.js +1 -1
  131. package/dist/domain/media/media-constants.d.ts +3 -0
  132. package/dist/domain/media/media-constants.js +1 -0
  133. package/dist/domain/media/media-execution-policy.js +1 -1
  134. package/dist/domain/memory/memory-constants.d.ts +3 -0
  135. package/dist/domain/memory/memory-constants.js +1 -0
  136. package/dist/domain/memory/memory-search.js +2 -2
  137. package/dist/domain/orchestration/goal.d.ts +0 -1
  138. package/dist/domain/orchestration/goal.js +1 -1
  139. package/dist/domain/orchestration/work-plan.d.ts +0 -62
  140. package/dist/domain/orchestration/work-plan.js +0 -1
  141. package/dist/domain/runtime/assistant-stream-text.d.ts +11 -0
  142. package/dist/domain/runtime/assistant-stream-text.js +1 -0
  143. package/dist/domain/runtime/gateway-request-budget.d.ts +19 -0
  144. package/dist/domain/runtime/gateway-request-budget.js +1 -0
  145. package/dist/domain/runtime/resource-limits.d.ts +26 -0
  146. package/dist/domain/runtime/resource-limits.js +1 -1
  147. package/dist/domain/session/attachment.d.ts +2 -0
  148. package/dist/domain/workspace/workspace-settings.d.ts +2 -0
  149. package/dist/domain/workspace/workspace-settings.js +1 -1
  150. package/dist/infrastructure/agent-sdk/model-response-metrics.d.ts +7 -0
  151. package/dist/infrastructure/agent-sdk/model-response-metrics.js +1 -0
  152. package/dist/infrastructure/agent-sdk/model-tool-name-mapper.js +1 -1
  153. package/dist/infrastructure/agent-sdk/sdk-constants.d.ts +2 -0
  154. package/dist/infrastructure/agent-sdk/sdk-constants.js +1 -0
  155. package/dist/infrastructure/agent-sdk/tool-calling-model-client.js +1 -1
  156. package/dist/infrastructure/cache/cache-policy.d.ts +2 -0
  157. package/dist/infrastructure/cache/cache-policy.js +1 -1
  158. package/dist/infrastructure/cache/file-cache-store.d.ts +13 -0
  159. package/dist/infrastructure/cache/file-cache-store.js +2 -2
  160. package/dist/infrastructure/clipboard/clipboard-adapter-factory.js +1 -1
  161. package/dist/infrastructure/clipboard/clipboard-constants.d.ts +1 -0
  162. package/dist/infrastructure/clipboard/clipboard-constants.js +1 -0
  163. package/dist/infrastructure/clipboard/clipboard-process.d.ts +20 -0
  164. package/dist/infrastructure/clipboard/clipboard-process.js +1 -0
  165. package/dist/infrastructure/clipboard/clipboard-text-adapter-factory.js +1 -1
  166. package/dist/infrastructure/clipboard/image-normalizer.js +1 -1
  167. package/dist/infrastructure/clipboard/windows-clipboard-adapter.js +1 -1
  168. package/dist/infrastructure/clipboard/windows-clipboard-text-adapter.js +1 -1
  169. package/dist/infrastructure/credentials/encrypted-file-credential-store.js +2 -2
  170. package/dist/infrastructure/credentials/secret-input.d.ts +1 -1
  171. package/dist/infrastructure/credentials/secret-input.js +3 -3
  172. package/dist/infrastructure/extensions/extensions-constants.d.ts +6 -0
  173. package/dist/infrastructure/extensions/extensions-constants.js +1 -0
  174. package/dist/infrastructure/extensions/mcp-runtime.d.ts +9 -0
  175. package/dist/infrastructure/extensions/mcp-runtime.js +1 -1
  176. package/dist/infrastructure/extensions/plugin-agent-discovery.d.ts +3 -1
  177. package/dist/infrastructure/extensions/plugin-agent-discovery.js +1 -1
  178. package/dist/infrastructure/extensions/plugin-manager.js +2 -2
  179. package/dist/infrastructure/extensions/skill-manager.js +2 -2
  180. package/dist/infrastructure/extensions/skill-tool-executor.d.ts +3 -1
  181. package/dist/infrastructure/extensions/skill-tool-executor.js +2 -2
  182. package/dist/infrastructure/filesystem/atomic-file-store.d.ts +11 -0
  183. package/dist/infrastructure/filesystem/atomic-file-store.js +1 -1
  184. package/dist/infrastructure/filesystem/filesystem-constants.d.ts +8 -0
  185. package/dist/infrastructure/filesystem/filesystem-constants.js +1 -0
  186. package/dist/infrastructure/filesystem/local-filesystem-tool-executor.d.ts +3 -0
  187. package/dist/infrastructure/filesystem/local-filesystem-tool-executor.js +3 -3
  188. package/dist/infrastructure/logging/daily-rotating-file-writer.d.ts +1 -1
  189. package/dist/infrastructure/logging/daily-rotating-file-writer.js +2 -2
  190. package/dist/infrastructure/logging/log-redactor.js +1 -1
  191. package/dist/infrastructure/logging/logging-constants.d.ts +3 -0
  192. package/dist/infrastructure/logging/logging-constants.js +1 -0
  193. package/dist/infrastructure/logging/structured-logger.d.ts +1 -1
  194. package/dist/infrastructure/logging/structured-logger.js +2 -2
  195. package/dist/infrastructure/observability/tool-execution-logger.d.ts +11 -0
  196. package/dist/infrastructure/observability/tool-execution-logger.js +1 -0
  197. package/dist/infrastructure/platform/host-platform.d.ts +2 -0
  198. package/dist/infrastructure/platform/host-platform.js +1 -1
  199. package/dist/infrastructure/platform/host-process.d.ts +3 -1
  200. package/dist/infrastructure/platform/host-process.js +1 -1
  201. package/dist/infrastructure/platform/platform-constants.d.ts +4 -0
  202. package/dist/infrastructure/platform/platform-constants.js +1 -0
  203. package/dist/infrastructure/platform/process-identity.d.ts +8 -0
  204. package/dist/infrastructure/platform/process-identity.js +1 -0
  205. package/dist/infrastructure/platform/read-only-executable.d.ts +2 -1
  206. package/dist/infrastructure/platform/read-only-executable.js +1 -1
  207. package/dist/infrastructure/sdk/lotagate-client-factory.js +1 -1
  208. package/dist/infrastructure/sdk/sdk-media-gateway-client.d.ts +4 -0
  209. package/dist/infrastructure/sdk/sdk-media-gateway-client.js +1 -1
  210. package/dist/infrastructure/sessions/file-session-store.d.ts +11 -0
  211. package/dist/infrastructure/sessions/file-session-store.js +4 -4
  212. package/dist/infrastructure/sessions/session-constants.d.ts +3 -0
  213. package/dist/infrastructure/sessions/session-constants.js +1 -0
  214. package/dist/infrastructure/sessions/session-index.js +3 -3
  215. package/dist/infrastructure/sessions/session-journal-health.d.ts +7 -0
  216. package/dist/infrastructure/sessions/session-journal-health.js +1 -0
  217. package/dist/infrastructure/shell/shell-tool-executor.d.ts +5 -1
  218. package/dist/infrastructure/shell/shell-tool-executor.js +2 -2
  219. package/dist/infrastructure/tokens/tiktoken-token-estimator.js +1 -1
  220. package/dist/infrastructure/tokens/token-constants.d.ts +1 -0
  221. package/dist/infrastructure/tokens/token-constants.js +1 -0
  222. package/dist/infrastructure/workspace/workspace-settings-store.d.ts +1 -0
  223. package/dist/infrastructure/workspace/workspace-settings-store.js +4 -4
  224. package/dist/main.js +3 -3
  225. package/dist/ports/media-gateway-client.d.ts +6 -0
  226. package/dist/ports/session-store.d.ts +1 -0
  227. package/dist/presentation/tui/ink/components/composer.js +4 -4
  228. package/dist/presentation/tui/ink/components/transcript.d.ts +1 -0
  229. package/dist/presentation/tui/ink/components/transcript.js +5 -5
  230. package/dist/presentation/tui/ink/tui-bridge.d.ts +2 -2
  231. package/dist/presentation/tui/ink/tui-bridge.js +1 -1
  232. package/dist/presentation/tui/tui-agent-turn-controller.d.ts +45 -0
  233. package/dist/presentation/tui/tui-agent-turn-controller.js +1 -0
  234. package/dist/presentation/tui/tui-application-contract.d.ts +1 -0
  235. package/dist/presentation/tui/tui-application.d.ts +3 -4
  236. package/dist/presentation/tui/tui-application.js +3 -3
  237. package/dist/presentation/tui/tui-clipboard-paste-handlers.d.ts +2 -2
  238. package/dist/presentation/tui/tui-clipboard-paste-handlers.js +1 -1
  239. package/dist/presentation/tui/tui-command-executor.js +3 -3
  240. package/dist/presentation/tui/tui-context-compaction.d.ts +4 -1
  241. package/dist/presentation/tui/tui-context-compaction.js +1 -1
  242. package/dist/presentation/tui/tui-context-service.d.ts +2 -34
  243. package/dist/presentation/tui/tui-context-service.js +1 -2
  244. package/dist/presentation/tui/tui-initial-model.js +1 -1
  245. package/dist/presentation/tui/tui-tool-approval.d.ts +1 -1
  246. package/dist/presentation/tui/tui-tool-approval.js +1 -1
  247. package/dist/version.d.ts +1 -1
  248. package/dist/version.js +1 -1
  249. package/native-targets.mjs +1 -1
  250. package/package.json +9 -10
  251. package/scripts/install-native.mjs +5 -13
  252. package/bin/lotagate.exe +0 -1
  253. package/dist/application/protocol/document-host-tool-definitions.d.ts +0 -4
  254. package/dist/application/protocol/document-host-tool-definitions.js +0 -1
  255. package/dist/application/protocol/document-host-tool-executor.d.ts +0 -49
  256. package/dist/application/protocol/document-host-tool-executor.js +0 -2
@@ -1 +1 @@
1
- import{RESOURCE_LIMITS as c}from"../../../domain/runtime/resource-limits.js";class A{listeners=new Set;initializationNotices=new Map;state={ready:!1,runActive:!1,messages:[],subagents:[],pendingAttachments:[],fileSuggestions:[],actionDetails:!1};resolveModal;exitResolvers=new Set;submitHandler;imagePasteHandler;textPasteHandler;clearAttachmentsHandler;interruptHandler;cancelHandler;sequence=0;noticeTimer;assistantRevealTimer;pendingAssistant;assistantSegmentPending=!1;pendingActivityTimers=new Map;snapshot(){return this.state}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}setSubmitHandler(t){this.submitHandler=t}setImagePasteHandler(t){this.imagePasteHandler=t}setTextPasteHandler(t){this.textPasteHandler=t}setClearAttachmentsHandler(t){this.clearAttachmentsHandler=t}setInterruptHandler(t){this.interruptHandler=t}setCancelHandler(t){this.cancelHandler=t}async submit(t){await this.submitHandler?.(t)}async pasteImage(){await this.imagePasteHandler?.()}async pasteText(){return this.textPasteHandler?.()}interrupt(){this.interruptHandler?.()}cancel(){this.cancelHandler?.(),this.resolveActiveModal(void 0),this.update({clearBlockedUntil:Date.now()+1500})}clearAttachments(){this.clearAttachmentsHandler?.()}setReady(){this.update({ready:!0})}setRunActive(t){this.update({runActive:t})}setWelcome(t){this.update({welcome:t})}setPendingAttachments(t){this.update({pendingAttachments:t})}setContextUsage(t){this.update({contextUsage:t})}setFileSuggestions(t){this.update({fileSuggestions:t})}toggleActionDetails(){const t=!this.state.actionDetails;return this.update({actionDetails:t}),t}clearTranscript(){this.initializationNotices.clear(),this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0,this.pendingAssistant=void 0,this.update({messages:[],subagents:[]})}exitCode;requestExit(t=0){this.exitCode??=t;for(const e of this.exitResolvers)e(this.exitCode);this.exitResolvers.clear()}waitForExit(){return this.exitCode===void 0?new Promise(t=>{this.exitResolvers.add(t)}):Promise.resolve(this.exitCode)}userPrompt(t,e=[]){this.append("user",t,e)}command(t){this.append("command",t)}commandOutput(t){this.append("notice",t)}transcriptNotice(t,e=!0){this.append("notice",t,void 0,void 0,void 0,void 0,e)}initializationNotice(t,e){this.initializationNotices.get(t)!==e&&(this.initializationNotices.set(t,e),this.transcriptNotice(e))}fileChange(t){this.append("diff",t.path,void 0,t)}notice(t){this.noticeTimer!==void 0&&clearTimeout(this.noticeTimer),this.update({footerNotice:t}),this.noticeTimer=setTimeout(()=>{this.noticeTimer=void 0,this.update({footerNotice:void 0})},4e3)}dispose(){this.noticeTimer!==void 0&&clearTimeout(this.noticeTimer),this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer);for(const t of this.pendingActivityTimers.values())clearImmediate(t);this.pendingActivityTimers.clear(),this.noticeTimer=void 0,this.assistantRevealTimer=void 0,this.resolveActiveModal(void 0),this.initializationNotices.clear(),this.listeners.clear()}error(t){this.append("error",t)}subagentLifecycle(t){const e=this.state.modal?.kind==="subagent",i=this.state.subagents.find(n=>n.id===t.id),s={id:t.id,displayName:t.displayName,task:t.task,mode:t.mode,model:t.model,status:t.status,background:t.background,createdAt:i?.createdAt??t.timestamp,updatedAt:t.timestamp,...t.durationMs===void 0?{}:{durationMs:t.durationMs},...t.summary===void 0?{}:{summary:t.summary},...t.lastAction===void 0?i?.lastAction===void 0?{}:{lastAction:i.lastAction}:{lastAction:t.lastAction},...t.handoff===void 0?i?.handoff===void 0?{}:{handoff:i.handoff}:{handoff:t.handoff}},a=i===void 0?[...this.state.subagents,s]:this.state.subagents.map(n=>n.id===t.id?s:n);this.update({subagents:a},!e),t.type==="created"&&!this.state.messages.some(n=>n.kind==="subagent"&&n.subagent?.id===t.id)&&this.append("subagent",t.id,void 0,void 0,void 0,s,!e),(t.type==="completed"||t.type==="failed"||t.type==="cancelled")&&t.summary!==void 0&&this.transcriptNotice(`Agent ${t.displayName} ${t.status} \xB7 ${t.summary}`,!e)}startToolActivity(t,e,i){const s=this.state.messages.find(n=>n.kind==="activity"&&(n.activity?.state==="pending"||n.activity?.state==="running")&&n.content===t);let a=s?.id;if(s===void 0){const n=this.message("activity",t,void 0,void 0,{label:e,state:"running",startedAt:Date.now(),...i});a=n.id,this.update({messages:[...this.state.messages,n]})}else this.clearPendingActivityTimer(t),this.updateActivity(s.id,e,"running",i);return{complete:n=>this.completeToolActivity(a,n)}}toolActivityStarted(t,e,i){const s=this.state.messages.find(d=>d.kind==="activity"&&d.content===t&&(d.activity?.state==="pending"||d.activity?.state==="running"));if(s!==void 0){this.updateActivity(s.id,e,s.activity?.state==="pending"?"pending":"running",i);return}const a=this.message("activity",t,void 0,void 0,{label:e,state:"pending",startedAt:Date.now(),...i});this.update({messages:[...this.state.messages,a]});const n=setImmediate(()=>{this.pendingActivityTimers.delete(t);const d=this.state.messages.find(u=>u.kind==="activity"&&u.content===t&&u.activity?.state==="pending");d!==void 0&&this.updateActivity(d.id,e,"running",i)});this.pendingActivityTimers.set(t,n)}toolActivityCompleted(t,e){this.clearPendingActivityTimer(t);const i=this.state.messages.find(s=>s.kind==="activity"&&s.content===t&&(s.activity?.state==="pending"||s.activity?.state==="running"));i!==void 0&&this.completeToolActivity(i.id,e)}status(t){this.update({status:t,activityStartedAt:Date.now(),elapsedMs:void 0,usage:void 0})}activity(t,e,i){this.update({status:t,...this.state.activityStartedAt===void 0?{activityStartedAt:Date.now()-e}:{},elapsedMs:e,...i===void 0?{}:{usage:i}})}clearActivity(){this.update({status:void 0,activityStartedAt:void 0,elapsedMs:void 0,usage:void 0})}complete(t,e){this.update({status:"Done",elapsedMs:t,...e===void 0?{}:{usage:e}})}failed(){this.update({status:"Failed",elapsedMs:void 0,usage:void 0})}cancelled(){this.update({status:"Cancelled",elapsedMs:void 0,usage:void 0})}beginAssistant(){this.flushAssistant(),this.assistantSegmentPending=!1,this.appendAssistant("")}assistantActionBoundary(){this.flushAssistant(),this.assistantSegmentPending=!0}assistantDelta(t){if(this.assistantSegmentPending){this.assistantSegmentPending=!1,this.appendAssistant(t);return}const e=this.state.messages.at(-1);if(e?.kind!=="assistant"){this.flushAssistant(),this.appendAssistant(t);return}const i=this.pendingAssistant;this.pendingAssistant={id:e.id,content:`${i?.id===e.id?i.content:e.content}${t}`},this.revealAssistant()}replaceAssistant(t){this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0,this.pendingAssistant=void 0,this.assistantSegmentPending=!1;let e=-1;for(let s=this.state.messages.length-1;s>=0;s-=1)if(this.state.messages[s]?.kind==="user"){e=s;break}const i=this.state.messages.filter((s,a)=>a<=e||s.kind!=="assistant");this.update({messages:o([...i,this.message("assistant",t)])})}finishAssistant(){this.revealAssistant(),this.assistantSegmentPending=!1}confirmTrust(){return this.request({kind:"trust"}).then(t=>t===!0)}confirmTool(t,e){return this.request({kind:"approval",toolName:t,...e===void 0?{}:{detail:e}}).then(i=>i==="allow"||i===!0)}openSubagentDetails(t){if(this.state.modal!==void 0)return;const e=this.state.subagents.find(i=>i.id===t);e!==void 0&&this.update({modal:{kind:"subagent",subagent:e}})}closeSubagentDetails(){this.state.modal?.kind==="subagent"&&this.update({modal:void 0})}selectModel(t,e,i){return this.selectChoice(t,e,i)}selectScope(t){return this.selectChoice(t,[{value:"user",label:"User",description:"Available across your projects"},{value:"project",label:"Project",description:"Stored in the trusted project"}]).then(e=>e==="user"||e==="project"?e:void 0)}requestSecret(t){return this.request({kind:"secret",label:t}).then(e=>typeof e=="string"?e:void 0)}resolveActiveModal(t){const e=this.resolveModal;e!==void 0&&(this.resolveModal=void 0,this.update({modal:void 0}),e?.(t))}request(t){if(this.resolveModal!==void 0)throw new Error("A TUI decision is already active.");return this.update({modal:t}),new Promise(e=>{this.resolveModal=e})}selectChoice(t,e,i){return this.request({kind:"choice",title:t,choices:e,...i===void 0?{}:{currentValue:i}}).then(s=>typeof s=="string"?s:void 0)}append(t,e,i,s,a,n,d=!0){this.update({messages:o([...this.state.messages,this.message(t,e,i,s,a,n)])},d)}appendAssistant(t){const e=this.message("assistant","");this.update({messages:o([...this.state.messages,e])}),this.pendingAssistant={id:e.id,content:t},this.revealAssistant()}message(t,e,i,s,a,n){return{id:`tui-${++this.sequence}`,kind:t,content:e,...i===void 0||i.length===0?{}:{attachments:i},...s===void 0?{}:{fileChange:s},...a===void 0?{}:{activity:a},...n===void 0?{}:{subagent:n}}}updateActivity(t,e,i,s){const a=this.state.messages.map(n=>n.id===t&&n.activity!==void 0?{...n,content:n.content,activity:{...n.activity,label:e,state:i,...s}}:n);this.update({messages:a})}completeToolActivity(t,e){const i=this.state.messages.find(s=>s.id===t&&s.activity!==void 0);i?.activity===void 0||i.activity.state!=="pending"&&i.activity.state!=="running"||this.update({messages:this.state.messages.map(s=>s.id===t&&s.activity!==void 0?{...s,activity:{...s.activity,state:e?"failed":"completed",elapsedMs:Date.now()-s.activity.startedAt}}:s)})}clearPendingActivityTimer(t){const e=this.pendingActivityTimers.get(t);e!==void 0&&(clearImmediate(e),this.pendingActivityTimers.delete(t))}update(t,e=!0){if(this.state={...this.state,...t},!!e)for(const i of this.listeners)i()}flushAssistant(){this.assistantRevealTimer!==void 0&&(clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0);const t=this.pendingAssistant;if(t===void 0)return;this.pendingAssistant=void 0;const e=this.state.messages.findIndex(a=>a.id===t.id);if(e<0)return;const i=[...this.state.messages],s=i[e];s===void 0||s.kind!=="assistant"||(i[e]={...s,content:t.content},this.update({messages:i}))}revealAssistant(){const t=this.pendingAssistant;if(t===void 0)return;const e=this.state.messages.findIndex(l=>l.id===t.id);if(e<0){this.pendingAssistant=void 0;return}const i=this.state.messages[e];if(i===void 0||i.kind!=="assistant"){this.pendingAssistant=void 0;return}const s=Array.from(t.content),a=Array.from(i.content),n=a.length===0,d=Math.min(s.length,a.length+(n?p:m)),u=d>=s.length,h=[...this.state.messages];if(h[e]={...i,content:s.slice(0,d).join("")},this.update({messages:h}),u){this.pendingAssistant=void 0,this.assistantRevealTimer!==void 0&&(clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0);return}this.assistantRevealTimer===void 0&&(this.assistantRevealTimer=setTimeout(()=>{this.assistantRevealTimer=void 0,this.revealAssistant()},f))}}const f=16,p=64,m=8;function o(r){if(r.length<=c.tuiTranscriptMessages)return r;const t=r.filter(s=>s.activity?.state==="pending"||s.activity?.state==="running"||s.subagent?.status==="queued"||s.subagent?.status==="running"),e=r.slice(-c.tuiTranscriptMessages);return[...t,...e.filter(s=>!t.some(a=>a.id===s.id))].slice(-c.tuiTranscriptMessages)}export{A as InkTuiBridge};
1
+ import{RESOURCE_LIMITS as h}from"../../../domain/runtime/resource-limits.js";class y{listeners=new Set;initializationNotices=new Map;state={ready:!1,runActive:!1,messages:[],subagents:[],pendingAttachments:[],fileSuggestions:[],actionDetails:!1};resolveModal;exitResolvers=new Set;submitHandler;imagePasteHandler;textPasteHandler;clearAttachmentsHandler;interruptHandler;cancelHandler;sequence=0;noticeTimer;assistantRevealTimer;pendingAssistant;assistantSegmentPending=!1;pendingActivityTimers=new Map;snapshot(){return this.state}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}setSubmitHandler(t){this.submitHandler=t}setImagePasteHandler(t){this.imagePasteHandler=t}setTextPasteHandler(t){this.textPasteHandler=t}setClearAttachmentsHandler(t){this.clearAttachmentsHandler=t}setInterruptHandler(t){this.interruptHandler=t}setCancelHandler(t){this.cancelHandler=t}async submit(t){await this.submitHandler?.(t)}async pasteImage(t){await this.imagePasteHandler?.(t)}async pasteText(){return this.textPasteHandler?.()}interrupt(){this.interruptHandler?.()}cancel(){this.cancelHandler?.(),this.resolveActiveModal(void 0),this.update({clearBlockedUntil:Date.now()+1500})}clearAttachments(){this.clearAttachmentsHandler?.()}setReady(){this.update({ready:!0})}setRunActive(t){this.update({runActive:t})}setWelcome(t){this.update({welcome:t})}setPendingAttachments(t){this.update({pendingAttachments:t})}setContextUsage(t){this.update({contextUsage:t})}setFileSuggestions(t){this.update({fileSuggestions:t})}toggleActionDetails(){const t=!this.state.actionDetails;return this.update({actionDetails:t}),t}clearTranscript(){this.initializationNotices.clear(),this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0,this.pendingAssistant=void 0,this.update({messages:[],subagents:[]})}exitCode;requestExit(t=0){this.exitCode??=t;for(const e of this.exitResolvers)e(this.exitCode);this.exitResolvers.clear()}waitForExit(){return this.exitCode===void 0?new Promise(t=>{this.exitResolvers.add(t)}):Promise.resolve(this.exitCode)}userPrompt(t,e=[]){this.append("user",t,e)}command(t){this.append("command",t)}commandOutput(t){this.append("notice",t)}transcriptNotice(t,e=!0){this.append("notice",t,void 0,void 0,void 0,void 0,e)}initializationNotice(t,e){this.initializationNotices.get(t)!==e&&(this.initializationNotices.set(t,e),this.transcriptNotice(e))}fileChange(t){this.append("diff",t.path,void 0,t)}notice(t){this.noticeTimer!==void 0&&clearTimeout(this.noticeTimer),this.update({footerNotice:t}),this.noticeTimer=setTimeout(()=>{this.noticeTimer=void 0,this.update({footerNotice:void 0})},4e3)}dispose(){this.noticeTimer!==void 0&&clearTimeout(this.noticeTimer),this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer);for(const t of this.pendingActivityTimers.values())clearImmediate(t);this.pendingActivityTimers.clear(),this.noticeTimer=void 0,this.assistantRevealTimer=void 0,this.resolveActiveModal(void 0),this.initializationNotices.clear(),this.listeners.clear()}error(t){this.append("error",t)}subagentLifecycle(t){const e=this.state.modal?.kind==="subagent",i=this.state.subagents.find(n=>n.id===t.id),s={id:t.id,displayName:t.displayName,task:t.task,mode:t.mode,model:t.model,status:t.status,background:t.background,createdAt:i?.createdAt??t.timestamp,updatedAt:t.timestamp,...t.durationMs===void 0?{}:{durationMs:t.durationMs},...t.summary===void 0?{}:{summary:t.summary},...t.lastAction===void 0?i?.lastAction===void 0?{}:{lastAction:i.lastAction}:{lastAction:t.lastAction},...t.handoff===void 0?i?.handoff===void 0?{}:{handoff:i.handoff}:{handoff:t.handoff}},a=i===void 0?[...this.state.subagents,s]:this.state.subagents.map(n=>n.id===t.id?s:n);this.update({subagents:a},!e),t.type==="created"&&!this.state.messages.some(n=>n.kind==="subagent"&&n.subagent?.id===t.id)&&this.append("subagent",t.id,void 0,void 0,void 0,s,!e),(t.type==="completed"||t.type==="failed"||t.type==="cancelled")&&t.summary!==void 0&&this.transcriptNotice(`Agent ${t.displayName} ${t.status} \xB7 ${t.summary}`,!e)}startToolActivity(t,e,i){const s=this.state.messages.find(n=>n.kind==="activity"&&(n.activity?.state==="pending"||n.activity?.state==="running")&&n.content===t);let a=s?.id;if(s===void 0){const n=this.message("activity",t,void 0,void 0,{label:e,state:"running",startedAt:Date.now(),...i});a=n.id,this.update({messages:[...this.state.messages,n]})}else this.clearPendingActivityTimer(t),this.updateActivity(s.id,e,"running",i);return{complete:n=>this.completeToolActivity(a,n)}}toolActivityStarted(t,e,i){const s=this.state.messages.find(d=>d.kind==="activity"&&d.content===t&&(d.activity?.state==="pending"||d.activity?.state==="running"));if(s!==void 0){this.updateActivity(s.id,e,s.activity?.state==="pending"?"pending":"running",i);return}const a=this.message("activity",t,void 0,void 0,{label:e,state:"pending",startedAt:Date.now(),...i});this.update({messages:[...this.state.messages,a]});const n=setImmediate(()=>{this.pendingActivityTimers.delete(t);const d=this.state.messages.find(c=>c.kind==="activity"&&c.content===t&&c.activity?.state==="pending");d!==void 0&&this.updateActivity(d.id,e,"running",i)});this.pendingActivityTimers.set(t,n)}toolActivityCompleted(t,e){this.clearPendingActivityTimer(t);const i=this.state.messages.find(s=>s.kind==="activity"&&s.content===t&&(s.activity?.state==="pending"||s.activity?.state==="running"));i!==void 0&&this.completeToolActivity(i.id,e)}status(t){this.update({status:t,activityStartedAt:Date.now(),elapsedMs:void 0,usage:void 0})}activity(t,e,i){this.update({status:t,...this.state.activityStartedAt===void 0?{activityStartedAt:Date.now()-e}:{},elapsedMs:e,...i===void 0?{}:{usage:i}})}clearActivity(){this.update({status:void 0,activityStartedAt:void 0,elapsedMs:void 0,usage:void 0})}complete(t,e){this.update({status:"Done",elapsedMs:t,...e===void 0?{}:{usage:e}})}failed(){this.update({status:"Failed",elapsedMs:void 0,usage:void 0})}cancelled(){this.update({status:"Cancelled",elapsedMs:void 0,usage:void 0})}beginAssistant(){this.flushAssistant(),this.assistantSegmentPending=!1,this.appendAssistant("")}assistantActionBoundary(){this.flushAssistant(),this.assistantSegmentPending=!0}assistantDelta(t){if(this.assistantSegmentPending){this.assistantSegmentPending=!1,this.appendAssistant(t);return}const e=this.state.messages.at(-1);if(e?.kind!=="assistant"){this.flushAssistant(),this.appendAssistant(t);return}const i=this.pendingAssistant;this.pendingAssistant={id:e.id,content:`${i?.id===e.id?i.content:e.content}${t}`},this.assistantRevealTimer===void 0&&this.revealAssistant()}replaceAssistant(t){this.assistantRevealTimer!==void 0&&clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0,this.pendingAssistant=void 0,this.assistantSegmentPending=!1;let e=-1;for(let s=this.state.messages.length-1;s>=0;s-=1)if(this.state.messages[s]?.kind==="user"){e=s;break}const i=this.state.messages.filter((s,a)=>a<=e||s.kind!=="assistant");this.update({messages:l([...i,this.message("assistant",t)])})}finishAssistant(){this.revealAssistant(),this.assistantSegmentPending=!1}confirmTrust(){return this.request({kind:"trust"}).then(t=>t===!0)}confirmTool(t,e){return this.request({kind:"approval",toolName:t,...e===void 0?{}:{detail:e}}).then(i=>i==="allow"||i===!0)}openSubagentDetails(t){if(this.state.modal!==void 0)return;const e=this.state.subagents.find(i=>i.id===t);e!==void 0&&this.update({modal:{kind:"subagent",subagent:e}})}closeSubagentDetails(){this.state.modal?.kind==="subagent"&&this.update({modal:void 0})}selectModel(t,e,i){return this.selectChoice(t,e,i)}selectScope(t){return this.selectChoice(t,[{value:"user",label:"User",description:"Available across your projects"},{value:"project",label:"Project",description:"Stored in the trusted project"}]).then(e=>e==="user"||e==="project"?e:void 0)}requestSecret(t){return this.request({kind:"secret",label:t}).then(e=>typeof e=="string"?e:void 0)}resolveActiveModal(t){const e=this.resolveModal;e!==void 0&&(this.resolveModal=void 0,this.update({modal:void 0}),e?.(t))}request(t){if(this.resolveModal!==void 0)throw new Error("A TUI decision is already active.");return this.update({modal:t}),new Promise(e=>{this.resolveModal=e})}selectChoice(t,e,i){return this.request({kind:"choice",title:t,choices:e,...i===void 0?{}:{currentValue:i}}).then(s=>typeof s=="string"?s:void 0)}append(t,e,i,s,a,n,d=!0){this.update({messages:l([...this.state.messages,this.message(t,e,i,s,a,n)])},d)}appendAssistant(t){const e=this.message("assistant","");this.update({messages:l([...this.state.messages,e])}),this.pendingAssistant={id:e.id,content:t},this.revealAssistant()}message(t,e,i,s,a,n){return{id:`tui-${++this.sequence}`,kind:t,content:e,...i===void 0||i.length===0?{}:{attachments:i},...s===void 0?{}:{fileChange:s},...a===void 0?{}:{activity:a},...n===void 0?{}:{subagent:n}}}updateActivity(t,e,i,s){const a=this.state.messages.map(n=>n.id===t&&n.activity!==void 0?{...n,content:n.content,activity:{...n.activity,label:e,state:i,...s}}:n);this.update({messages:a})}completeToolActivity(t,e){const i=this.state.messages.find(s=>s.id===t&&s.activity!==void 0);i?.activity===void 0||i.activity.state!=="pending"&&i.activity.state!=="running"||this.update({messages:this.state.messages.map(s=>s.id===t&&s.activity!==void 0?{...s,activity:{...s.activity,state:e?"failed":"completed",elapsedMs:Date.now()-s.activity.startedAt}}:s)})}clearPendingActivityTimer(t){const e=this.pendingActivityTimers.get(t);e!==void 0&&(clearImmediate(e),this.pendingActivityTimers.delete(t))}update(t,e=!0){if(this.state={...this.state,...t},!!e)for(const i of this.listeners)i()}flushAssistant(){this.assistantRevealTimer!==void 0&&(clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0);const t=this.pendingAssistant;if(t===void 0)return;this.pendingAssistant=void 0;const e=this.state.messages.findIndex(a=>a.id===t.id);if(e<0)return;const i=[...this.state.messages],s=i[e];s===void 0||s.kind!=="assistant"||(i[e]={...s,content:t.content},this.update({messages:i}))}revealAssistant(){const t=this.pendingAssistant;if(t===void 0)return;const e=this.state.messages.findIndex(o=>o.id===t.id);if(e<0){this.pendingAssistant=void 0;return}const i=this.state.messages[e];if(i===void 0||i.kind!=="assistant"){this.pendingAssistant=void 0;return}const s=i.content.length,a=t.content.length,n=a-s;if(n<=0){this.pendingAssistant=void 0,this.assistantRevealTimer!==void 0&&(clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0);return}const m=Math.max(s===0?A:v,Math.ceil(n/4));let u=Math.min(a,s+m);if(u<a){const o=t.content.charCodeAt(u-1);o>=55296&&o<=56319&&(u+=1)}const p=u>=a,f=[...this.state.messages];if(f[e]={...i,content:t.content.slice(0,u)},this.update({messages:f}),p){this.pendingAssistant=void 0,this.assistantRevealTimer!==void 0&&(clearTimeout(this.assistantRevealTimer),this.assistantRevealTimer=void 0);return}this.assistantRevealTimer===void 0&&(this.assistantRevealTimer=setTimeout(()=>{this.assistantRevealTimer=void 0,this.revealAssistant()},g))}}const g=16,A=64,v=8;function l(r){if(r.length<=h.tuiTranscriptMessages)return r;const t=r.filter(s=>s.activity?.state==="pending"||s.activity?.state==="running"||s.subagent?.status==="queued"||s.subagent?.status==="running"),e=r.slice(-h.tuiTranscriptMessages);return[...t,...e.filter(s=>!t.some(a=>a.id===s.id))].slice(-h.tuiTranscriptMessages)}export{y as InkTuiBridge};
@@ -0,0 +1,45 @@
1
+ import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
2
+ import type { CliAgentSessionStore } from '../../application/agent/agent-session-store.js';
3
+ import type { SubagentJobRegistry } from '../../application/orchestration/cli-subagent-service.js';
4
+ import type { SessionExecutionWorkspaceService, SessionExecutionWorkspace } from '../../application/workspace/session-execution-workspace.js';
5
+ import type { SessionMetadata } from '../../domain/session/session.js';
6
+ import type { GoalTurnCallbacks } from '../../application/orchestration/goal-runner.js';
7
+ import type { SkillManifest } from '../../domain/extensions/skill-manifest.js';
8
+ import type { AttachmentPayload } from '../../domain/session/attachment.js';
9
+ import type { HookEvent } from '../../domain/extensions/hook-manifest.js';
10
+ import type { PendingAttachmentStore } from '../../application/chat/pending-attachment-store.js';
11
+ import type { InkTuiBridge } from './ink/tui-bridge.js';
12
+ import type { TuiToolApprovalCoordinator } from './tui-tool-approval.js';
13
+ import type { TuiContextService } from './tui-context-service.js';
14
+ export interface TuiAgentTurnControllerHost {
15
+ readonly runtime: CliRuntime;
16
+ readonly cwd: string;
17
+ readonly renderer: InkTuiBridge;
18
+ readonly pendingAttachments: PendingAttachmentStore;
19
+ readonly approvals: TuiToolApprovalCoordinator;
20
+ readonly contextService: TuiContextService;
21
+ readonly agentSessionStore: CliAgentSessionStore;
22
+ readonly executionWorkspaces: SessionExecutionWorkspaceService;
23
+ getSession(): SessionMetadata | undefined;
24
+ getActiveModel(): string | null;
25
+ getActiveProfile(): string | null;
26
+ getExecutionWorkspace(): SessionExecutionWorkspace;
27
+ setExecutionWorkspace(workspace: SessionExecutionWorkspace): void;
28
+ getSubagentJobs(): SubagentJobRegistry;
29
+ runHookEvent(event: HookEvent, sessionId: string): Promise<void>;
30
+ refreshContextUsage(): Promise<void>;
31
+ }
32
+ /** Owns interactive turn state and keeps prompt execution out of the TUI shell. */
33
+ export declare class TuiAgentTurnController {
34
+ private readonly host;
35
+ private activeAbortController;
36
+ private activePromptRun;
37
+ constructor(host: TuiAgentTurnControllerHost);
38
+ isRunning(): boolean;
39
+ getActiveAbortController(): AbortController | undefined;
40
+ setActiveAbortController(controller: AbortController | undefined): void;
41
+ abortActive(reason?: unknown): void;
42
+ runPrompt(prompt: string, initialSkill?: SkillManifest, goalCallbacks?: GoalTurnCallbacks): Promise<string>;
43
+ sendPrompt(prompt: string, attachments?: readonly AttachmentPayload[], initialSkill?: SkillManifest, goalCallbacks?: GoalTurnCallbacks): Promise<string>;
44
+ private executePrompt;
45
+ }
@@ -0,0 +1 @@
1
+ import{AuthenticationService as j}from"../../application/auth/authentication-service.js";import{loadExecutionConfig as H}from"../../application/config/execution-config.js";import{CliError as B,asCliError as R}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as P}from"../../domain/errors/error-codes.js";import{buildUserMessage as q}from"../../infrastructure/clipboard/image-normalizer.js";import{createLotaGateClient as G}from"../../infrastructure/sdk/lotagate-client-factory.js";import{estimateTurnUsage as $}from"../../infrastructure/tokens/tiktoken-token-estimator.js";import{AgentRunTracker as J}from"../../application/agent/agent-run-tracker.js";import{prepareCliAgent as V}from"../../application/agent/cli-agent-execution-service.js";import{BoundedTextAccumulator as Y}from"../../application/agent/bounded-text-accumulator.js";import{createTurnId as z,recordTurnCompletion as K,recordTurnFailure as Q,recordTurnStart as X}from"../../application/session/session-turn-lifecycle.js";import{createTuiContextManagement as Z,createTuiContinuationContext as ee}from"./tui-context-compaction.js";import{isAbortError as te,throwIfAborted as k}from"./tui-lifecycle-actions.js";import{runTuiAgentEvents as oe}from"./tui-agent-event-runner.js";import{AUTH_LOGIN_HINT as se,MODEL_SELECT_HINT as re,formatCliErrorMessage as M,formatCommandHint as I}from"../../application/commands/command-hints.js";class Ee{host;activeAbortController;activePromptRun;constructor(s){this.host=s}isRunning(){return this.activePromptRun!==void 0}getActiveAbortController(){return this.activeAbortController}setActiveAbortController(s){this.activeAbortController=s}abortActive(s){this.activeAbortController?.abort(s)}async runPrompt(s,n,g){return this.sendPrompt(s,this.host.pendingAttachments.list(),n,g)}async sendPrompt(s,n=[],g,d){if(this.activePromptRun!==void 0)return this.host.renderer.notice("A response is already running. Stop it before sending another prompt."),"";try{this.host.pendingAttachments.assertPromptFits(s,n)}catch(A){const w=R(A);return this.host.renderer.error(M(w,"tui")),""}const u=this.host.getSession(),h=u===void 0?void 0:await this.host.executionWorkspaces.acquireTurn(u.id),m=this.executePrompt(s,n,g,d);this.activePromptRun=m,this.host.renderer.setRunActive(!0);try{return await m}finally{this.activePromptRun===m&&(this.activePromptRun=void 0),this.host.renderer.setRunActive(!1),await h?.()}}async executePrompt(s,n,g,d){const u=await H(this.host.runtime,this.host.cwd),h=this.host.getActiveModel()??u.config.model;if(h===null)return this.host.renderer.error(`No model is selected. ${I(re,"tui")}`),"";const m=this.host.getActiveProfile()??u.config.profile??j.defaultProfileName(),A=await this.host.runtime.credentialStore.get(m);if(A===void 0)return this.host.renderer.error(`No API key is configured. ${I(se,"tui")}`),"";const w=await this.host.runtime.projectTrust.inspect(this.host.cwd),t=this.host.getSession();t!==void 0&&this.host.setExecutionWorkspace(await this.host.executionWorkspaces.prepare({sessionId:t.id,projectRoot:w.canonicalPath})),await this.host.runHookEvent("prompt.before",t?.id??"tui"),this.host.renderer.userPrompt(s,n.map(({attachment:e})=>e));const C=z();t!==void 0&&await X(this.host.runtime.sessionStore,t.id,C,s,n.map(({attachment:e})=>e.id));const x=Date.now();let c,v=!1;this.host.renderer.status("Thinking");const p=new AbortController;this.activeAbortController=p;const T=G(A.profile,A.apiKey),U=await this.host.runtime.projectTrust.isTrusted(w),o=t===void 0?void 0:await this.host.runtime.goalStore.get(t.id),i=new J,L={start:e=>this.host.renderer.startToolActivity(e.key,e.label)},N={onSubagentLifecycle:e=>{e.sessionId===t?.id&&this.host.renderer.subagentLifecycle(e)}},W=await this.host.contextService.getModelContextWindow(h,m),_=e=>{i.observeModel(e),e.usage!==void 0&&(c=e.usage,v=!0,d?.onUsage({usage:e.usage,modelCalls:1})),this.host.runtime.logger.debug("Model turn completed.",{model:e.model,stream:e.stream,contentLength:e.contentLength,toolCallCount:e.toolCallCount,toolNames:e.toolNames,finishReason:e.finishReason})},E=await V({runtime:this.host.runtime,projectRoot:w.canonicalPath,executionCwd:this.host.getExecutionWorkspace().executionCwd,executionWorkspaceId:this.host.getExecutionWorkspace().id,model:h,reasoningEffort:u.config.effort,client:T,profile:U?"interactive-trusted":"interactive-untrusted",approvalMode:u.config.approvalMode,subagentJobs:this.host.getSubagentJobs(),...g===void 0?{}:{initialSkill:g},onWrite:e=>this.host.renderer.fileChange(e),prompt:(e,a)=>this.host.approvals.ask(e,a),rememberApproval:e=>this.host.approvals.remember(w.canonicalPath,e),onApprovalPersistenceFailure:(e,a)=>this.host.approvals.rememberFailure(a),audit:e=>this.host.approvals.audit(e),onModelComplete:_,onSubagentModelComplete:e=>{e.usage!==void 0&&d?.onUsage({usage:e.usage,modelCalls:1})},contextManagement:Z(T,h,W,e=>this.host.runtime.logger.warn("Context summarization failed; using fallback summary.",{reason:e instanceof Error?e.message:String(e)}),()=>ee(i.snapshot(),o)),agentSessionStore:this.host.agentSessionStore,toolActivity:L,onIntentLifecycle:e=>{e.type==="intent.compiled"?this.host.renderer.status("Understanding the task"):e.type==="intent.verification.required"?this.host.renderer.status("Verifying the result"):e.type==="intent.blocked"&&this.host.renderer.status("Verification is incomplete")},subagentLifecycle:N,...o===void 0?{}:{goal:{objective:o.objective,status:o.status,turns:o.turns,evaluatorRuns:o.evaluatorRuns,tokensUsed:o.usage.totalTokens,...o.tokenBudget===void 0?{}:{tokenBudget:o.tokenBudget},...o.maxTurns===void 0?{}:{maxTurns:o.maxTurns},...o.maxDurationMs===void 0?{}:{maxDurationMs:o.maxDurationMs},...o.lastError===void 0?{}:{lastError:o.lastError},...o.lastEvaluation===void 0?{}:{lastEvaluation:o.lastEvaluation.reason}}}}),f=new Y;let S=!1;const D=e=>{k(p.signal),f.append(e),this.host.renderer.assistantDelta(e)},F=e=>{k(p.signal),f.replace(e),this.host.renderer.replaceAssistant(e)};try{k(p.signal);const e=await E.buildInput(s);this.host.pendingAttachments.assertPromptFits(e.input,n);const a=n.length===0?void 0:q(e.input,n),r=a?.content===null?void 0:a?.content;if(await oe({prepared:E,input:e.input,userInput:e.userInput,...e.workspaceContext===void 0?{}:{workspaceContext:e.workspaceContext},...r===void 0?{}:{inputContent:r},model:h,...t===void 0?{}:{sessionId:t.id},turnId:C,signal:p.signal,agentSessionStore:this.host.agentSessionStore,tracker:i,runtime:this.host.runtime,renderer:this.host.renderer,startedAt:x,getUsage:()=>c,appendAssistantDelta:D,replaceAssistantResponse:F,hasResponse:()=>!f.isEmpty}),f.toString().trim().length===0){const l=i.snapshot();l.toolCalls>0&&i.markStuck();const O=l.toolCalls>0?P.MODEL_EMPTY_FINAL:P.MODEL_PROTOCOL_EMPTY_RESPONSE,y=l.toolCalls>0?"The model completed its tool work without a final text response.":"The model returned neither text nor a tool call.";throw new B(O,y,{category:"model",userMessage:`${y} Check the selected model and gateway tool-calling support, then try again.`,retryable:!0,details:{modelTurns:l.modelTurns,toolCalls:l.toolCalls,toolCompletions:l.toolCompletions,toolFailures:l.toolFailures,toolNames:l.toolNames,finishReason:l.lastFinishReason}})}t!==void 0&&(await this.host.executionWorkspaces.apply(t.id),S=!0),d?.onSnapshot(i.snapshot())}catch(e){const a=p.signal.aborted||te(e);if(t!==void 0&&!S)try{const r=await this.host.executionWorkspaces.apply(t.id);S=!0,r.appliedPaths.length>0&&this.host.runtime.logger.info("Applied session workspace changes after turn failure.",{sessionId:t.id,turnId:C,appliedPaths:r.appliedPaths})}catch(r){this.host.runtime.logger.error("Failed to apply session workspace changes after turn failure.",{sessionId:t.id,turnId:C,reason:r instanceof Error?r.message:String(r)})}if(t!==void 0&&this.host.agentSessionStore.delete(t.id),a?i.markCancelled():i.snapshot().state!=="stuck"&&i.markFailed(),t!==void 0&&await Q(this.host.runtime.sessionStore,t.id,C,e,a),this.host.renderer.finishAssistant(),a)this.host.renderer.notice("Interrupted.");else{const r=R(e);this.host.renderer.failed(),this.host.runtime.logger.error("Agent run failed.",{code:r.code,category:r.category,...r.details??{}}),this.host.renderer.error(M(r,"tui"))}return d?.onError(e),d?.onSnapshot(i.snapshot()),""}finally{this.activeAbortController===p&&(this.activeAbortController=void 0);try{await E.close()}catch(e){this.host.runtime.logger.warn("Agent cleanup failed after a completed turn.",{reason:e instanceof Error?e.message:String(e)})}if(t!==void 0)try{await this.host.executionWorkspaces.markReady(t.id)}catch(e){this.host.runtime.logger.warn("Unable to release TUI execution workspace after turn.",{sessionId:t.id,reason:e instanceof Error?e.message:String(e)})}}this.host.renderer.finishAssistant();try{t!==void 0&&await K(this.host.runtime.sessionStore,t.id,C,f.toString())}catch(e){this.host.runtime.logger.warn("Unable to persist the completed turn.",{reason:e instanceof Error?e.message:String(e)}),this.host.renderer.notice("Response completed, but the session state could not be saved.")}try{await this.host.runHookEvent("response.after",t?.id??"tui")}catch(e){this.host.runtime.logger.warn("Response hook failed after a completed turn.",{reason:e instanceof Error?e.message:String(e)}),this.host.renderer.notice("Response completed, but the response hook failed.")}this.host.pendingAttachments.clear(),this.host.renderer.setPendingAttachments([]),!v&&c!==void 0&&d?.onUsage({usage:c,modelCalls:1});const b=c?.totalTokens===void 0?$({model:h,prompt:s,response:f.toString()}):c;return!v&&c===void 0&&b!==void 0&&d?.onUsage({usage:b,modelCalls:1}),this.host.renderer.complete(Date.now()-x,b),await this.host.refreshContextUsage(),f.toString()}}export{Ee as TuiAgentTurnController};
@@ -6,5 +6,6 @@ export interface TuiApplicationOptions {
6
6
  };
7
7
  output?: TerminalOutput;
8
8
  sessionId?: string;
9
+ signal?: AbortSignal;
9
10
  }
10
11
  export declare function formatResumeCommand(sessionId: string): string;
@@ -21,8 +21,6 @@ export declare class TuiApplication {
21
21
  private skillRootScopes;
22
22
  private enabledPluginNames;
23
23
  private pluginMcpConfig;
24
- private activeAbortController;
25
- private activePromptRun;
26
24
  private activeForegroundRun;
27
25
  private exitArmedUntil;
28
26
  private lastInterruptAt;
@@ -32,9 +30,11 @@ export declare class TuiApplication {
32
30
  private readonly approvals;
33
31
  private readonly contextService;
34
32
  private readonly agentSessionStore;
33
+ private readonly backgroundOperations;
35
34
  private subagentJobs;
36
35
  private readonly executionWorkspaces;
37
36
  private executionWorkspace;
37
+ private readonly turnController;
38
38
  constructor(runtime: CliRuntime, cwd: string, options?: TuiApplicationOptions);
39
39
  run(): Promise<number>;
40
40
  private processPrompt;
@@ -42,8 +42,6 @@ export declare class TuiApplication {
42
42
  runPrompt(prompt: string, initialSkill?: SkillManifest, goalCallbacks?: GoalTurnCallbacks): Promise<string>;
43
43
  runGoal(objective: string, context: TuiCommandContext, limits?: Omit<CreateGoalInput, 'objective'>): Promise<void>;
44
44
  resumeGoal(context: TuiCommandContext): Promise<void>;
45
- private sendPrompt;
46
- private executePrompt;
47
45
  private commandContext;
48
46
  getActiveModel(): string | null;
49
47
  getActiveProfile(): string | null;
@@ -59,6 +57,7 @@ export declare class TuiApplication {
59
57
  compactSession(): Promise<void>;
60
58
  resumeSession(sessionId: string): Promise<void>;
61
59
  private handleInterrupt;
60
+ private startBackgroundMcpWarmup;
62
61
  private awaitActiveForegroundRun;
63
62
  private runHookEvent;
64
63
  }
@@ -1,3 +1,3 @@
1
- import{createElement as J}from"react";import{render as z}from"ink";import{AuthenticationService as q}from"../../application/auth/authentication-service.js";import{createLotaGateClient as V}from"../../infrastructure/sdk/lotagate-client-factory.js";import{detectTerminalCapabilities as Y}from"./terminal-capabilities.js";import{enterInteractiveScreen as K,exitInteractiveScreen as Q}from"./terminal-screen.js";import{buildUserMessage as X,createImageAttachment as Z,normalizeImage as ee}from"../../infrastructure/clipboard/image-normalizer.js";import{PendingAttachmentStore as te}from"../../application/chat/pending-attachment-store.js";import{CLI_VERSION as x}from"../../version.js";import{asCliError as ie,CliError as se}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as I}from"../../domain/errors/error-codes.js";import{InkTuiBridge as ne}from"./ink/tui-bridge.js";import{LotaGateTui as re}from"./ink/lotagate-tui.js";import{estimateTurnUsage as oe}from"../../infrastructure/tokens/tiktoken-token-estimator.js";import{WorkspaceFileIndex as ae}from"../../application/workspace/workspace-file-index.js";import{ProjectSessionAccess as de}from"../../application/session/project-session-access.js";import{createTuiCommandHost as ce}from"./tui-command-host-factory.js";import{workspaceFileSuggestions as le}from"./tui-file-suggestions.js";import{AUTH_LOGIN_HINT as ue,MODEL_SELECT_HINT as he,formatCliErrorMessage as me,formatCommandHint as R}from"../../application/commands/command-hints.js";import{AgentRunTracker as pe}from"../../application/agent/agent-run-tracker.js";import{prepareCliAgent as fe,warmMcpRuntime as M}from"../../application/agent/cli-agent-execution-service.js";import{TuiToolApprovalCoordinator as ge}from"./tui-tool-approval.js";import{TuiContextService as we}from"./tui-context-service.js";import{createTuiClipboardPasteHandlers as ve}from"./tui-clipboard-paste-handlers.js";import{dispatchTuiPrompt as Se}from"./tui-prompt-dispatcher.js";import{CliAgentSessionStore as Ce,retainLatestCompaction as U}from"../../application/agent/agent-session-store.js";import{createTuiContextManagement as xe}from"./tui-context-compaction.js";import{compactManualTuiSession as be}from"./tui-manual-compaction.js";import{resolveInitialModel as j}from"./tui-initial-model.js";import{cancelTuiResponse as Ae,handleTuiInterrupt as Pe,isAbortError as W,runTuiHookEvent as ke,throwIfAborted as k}from"./tui-lifecycle-actions.js";import{loadExecutionConfig as F}from"../../application/config/execution-config.js";import{resumeTuiGoal as ye,runTuiGoal as Te}from"./tui-goal-controller.js";import{runTuiSkill as Ee}from"./tui-skill-controller.js";import{SubagentJobRegistry as L}from"../../application/orchestration/cli-subagent-service.js";import{formatResumeCommand as Ie}from"./tui-application-contract.js";import{runTuiAgentEvents as Re}from"./tui-agent-event-runner.js";import{createTurnId as Me,recordTurnCompletion as Ue,recordTurnFailure as je,recordTurnStart as We}from"../../application/session/session-turn-lifecycle.js";import{SessionExecutionWorkspaceService as Fe}from"../../application/workspace/session-execution-workspace.js";import{loadTuiExtensions as Le}from"./tui-extension-loader.js";class At{runtime;cwd;options;input;output;renderer;pendingAttachments=new te;session;hookRuntime;hooks=[];skillRootScopes=[];enabledPluginNames=[];pluginMcpConfig={};activeAbortController;activePromptRun;activeForegroundRun;exitArmedUntil=0;lastInterruptAt=0;printResumeCommandOnExit=!1;activeModel=null;activeProfile=null;approvals;contextService;agentSessionStore=new Ce;subagentJobs=new L;executionWorkspaces;executionWorkspace;constructor(n,t,i={}){this.runtime=n,this.cwd=t,this.options=i,this.input=i.input??process.stdin,this.output=i.output??process.stdout,this.renderer=new ne,this.executionWorkspaces=this.runtime.executionWorkspaces??new Fe(this.runtime.paths.globalConfigDir,this.runtime.platform),this.contextService=new we(this.runtime,this.cwd),this.approvals=new ge({renderer:this.renderer,runtime:this.runtime,getSessionId:()=>this.session?.id,getActiveSignal:()=>this.activeAbortController?.signal}),this.renderer.setInterruptHandler(()=>this.handleInterrupt()),this.renderer.setCancelHandler(()=>Ae(this.activeAbortController,this.renderer));const r=ve({platform:this.runtime.platform,notify:s=>this.renderer.notice(s),attachImage:s=>this.attachClipboardImage(s,!1)});this.renderer.setImagePasteHandler(r.image),this.renderer.setTextPasteHandler(r.text),this.renderer.setClearAttachmentsHandler(()=>{this.pendingAttachments.clear(),this.renderer.setPendingAttachments([])})}async run(){if(!Y(this.input,this.output).isInteractive)return this.output.write('Interactive TUI requires a terminal. Use `lotagate chat "prompt"` for non-interactive streaming.\n'),2;K(this.output);const t=z(J(re,{bridge:this.renderer}),{stdin:this.input,stdout:this.output,exitOnCtrlC:!1}),i=()=>this.handleInterrupt();process.on("SIGINT",i);let r="completed";try{const s=await this.runtime.projectTrust.inspect(this.cwd);let d=await this.runtime.projectTrust.isTrusted(s),o=await this.runtime.configLoader.load(this.cwd,{includeProject:d}),g=await j(this.runtime,o.config),l={...o,config:{...o.config,model:g}};if(this.activeModel=l.config.model,this.activeProfile=l.config.profile,this.renderer.setWelcome({version:x,cwd:s.canonicalPath,model:l.config.model,profile:l.config.profile,trusted:d}),this.renderer.setFileSuggestions([]),d||(d=await this.renderer.confirmTrust(),d?(await this.runtime.projectTrust.grant(s),o=await this.runtime.configLoader.load(this.cwd),g=await j(this.runtime,o.config),l={...o,config:{...o.config,model:g}},this.activeModel=l.config.model,this.activeProfile=l.config.profile,this.renderer.setWelcome({version:x,cwd:s.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:!0}),this.renderer.notice("Project trusted.")):this.renderer.notice("Project remains untrusted; local tools and extensions stay disabled.")),d&&await this.runtime.workspaceSettings.ensureInitialized(s.canonicalPath),await this.reloadExtensions(d,l.config.approvalMode,s.canonicalPath),this.options.sessionId!==void 0){const a=await this.runtime.sessionStore.get(this.options.sessionId);if(a===void 0)throw new Error(`Session not found: ${this.options.sessionId}`);if(a.projectFingerprint!==s.fingerprint)throw new Error("Session belongs to another project.");this.session=a,this.renderer.status(`Resuming session ${a.id}`);for(const w of U(await this.runtime.sessionStore.readTranscript(a.id)))w.type==="user"?this.renderer.userPrompt(w.content):w.type==="assistant"&&(this.renderer.beginAssistant(),this.renderer.assistantDelta(w.content),this.renderer.finishAssistant())}else this.session=await this.runtime.sessionStore.create({projectFingerprint:s.fingerprint,cwd:s.canonicalPath,model:l.config.model,profile:l.config.profile,status:"active"});return this.executionWorkspace=await this.executionWorkspaces.prepare({sessionId:this.session.id,projectRoot:s.canonicalPath}),await this.refreshContextUsage(),await this.runHookEvent("session.start",this.session.id),M(this.runtime,this.cwd).catch(a=>this.runtime.logger.warn("MCP session warm-up failed.",{reason:a instanceof Error?a.message:String(a)})),this.renderer.setSubmitHandler(async a=>{await this.processPrompt(a)&&this.renderer.requestExit()}),this.renderer.clearActivity(),this.renderer.setReady(),new ae(s.canonicalPath).listEntries().then(a=>this.renderer.setFileSuggestions(le(a))).catch(a=>this.runtime.logger.debug("Unable to load workspace file suggestions.",{reason:a instanceof Error?a.message:String(a)})),await this.renderer.waitForExit()}catch(s){throw r=W(s)?"cancelled":"failed",s}finally{this.activeAbortController?.abort(new Error("Interactive session is closing.")),this.renderer.resolveActiveModal(void 0),await this.awaitActiveForegroundRun();try{await this.subagentJobs.close()}catch(s){this.runtime.logger.warn("Unable to close subagent jobs during TUI shutdown.",{reason:s instanceof Error?s.message:String(s)})}if(this.session!==void 0){try{await this.runHookEvent("session.end",this.session.id)}catch(s){this.runtime.logger.warn("Session end hook failed during TUI shutdown.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}try{await this.runtime.sessionStore.updateStatus(this.session.id,r)}catch(s){this.runtime.logger.warn("Unable to update TUI session status during shutdown.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}try{await this.executionWorkspaces.markReady(this.session.id)}catch(s){this.runtime.logger.warn("Unable to release TUI execution workspace.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}}process.off("SIGINT",i),this.renderer.dispose(),t.unmount(),Q(this.output),this.printResumeCommandOnExit&&this.session!==void 0&&this.output.write(`
2
- ${Ie(this.session.id)}
3
- `)}}async processPrompt(n){if(this.activeForegroundRun!==void 0)return this.renderer.notice("An operation is already running. Stop it before starting another one."),!1;const t=Se(n,{renderer:this.renderer,logger:this.runtime.logger,commandHost:ce({runtime:this.runtime,cwd:this.cwd,renderer:this.renderer,pendingAttachments:this.pendingAttachments,getHooks:()=>this.hooks,getSession:()=>this.session,getActiveAbortController:()=>this.activeAbortController,setActiveAbortController:i=>{this.activeAbortController=i},attachClipboardImage:i=>this.attachClipboardImage(i),runPrompt:(i,r)=>this.sendPrompt(i,this.pendingAttachments.list(),r),runGoal:(i,r,s)=>this.runGoal(i,r,s),resumeGoal:i=>this.resumeGoal(i),runSkill:(i,r,s,d,o)=>this.runSkill(i,r,s,d,o),refreshExtensions:()=>this.refreshExtensions(),compactSession:()=>this.compactSession(),refreshWelcome:i=>this.refreshWelcome(i),getContextSnapshot:()=>this.getContextSnapshot(),resumeSession:i=>this.resumeSession(i)}),pendingAttachments:this.pendingAttachments,commandContext:()=>this.commandContext(),sendPrompt:(i,r)=>this.sendPrompt(i,r),resetActiveAbortController:()=>{this.activePromptRun===void 0&&(this.activeAbortController=void 0)}});this.activeForegroundRun=t;try{return await t}finally{this.activeForegroundRun===t&&(this.activeForegroundRun=void 0)}}async attachClipboardImage(n,t=!0){if(n===void 0){t&&this.renderer.notice("Clipboard does not contain an image.");return}const i=ee(n.bytes,n.mimeType);this.pendingAttachments.assertCanAdd(i.bytes.byteLength);const r=this.pendingAttachments.nextId(),s=Z(i,"clipboard",r),d=this.session===void 0?s:await this.runtime.sessionStore.saveAttachment(this.session.id,s,i.bytes);this.pendingAttachments.add({attachment:d,bytes:i.bytes}),this.renderer.setPendingAttachments(this.pendingAttachments.list().map(({attachment:o})=>o)),t&&this.renderer.notice(`Attached ${s.name} \xB7 ${s.mimeType} \xB7 ${s.sizeBytes} bytes`)}async runPrompt(n,t,i){return this.sendPrompt(n,this.pendingAttachments.list(),t,i)}async runGoal(n,t,i={}){if(this.activePromptRun!==void 0){t.write("Stop the active response before starting a goal.");return}await Te({runtime:this.runtime,cwd:this.cwd,sessionId:this.session?.id,model:this.activeModel??this.session?.model??null,profile:this.activeProfile??this.session?.profile??null,runPrompt:(r,s)=>this.runPrompt(r,void 0,s),write:r=>t.write(r)},n,i)}async resumeGoal(n){if(this.activePromptRun!==void 0){n.write("Stop the active response before resuming a goal.");return}await ye({runtime:this.runtime,cwd:this.cwd,sessionId:this.session?.id,model:this.activeModel??this.session?.model??null,profile:this.activeProfile??this.session?.profile??null,runPrompt:(t,i)=>this.runPrompt(t,void 0,i),write:t=>n.write(t)})}async sendPrompt(n,t=[],i,r){if(this.activePromptRun!==void 0)return this.renderer.notice("A response is already running. Stop it before sending another prompt."),"";const s=this.executePrompt(n,t,i,r);this.activePromptRun=s,this.renderer.setRunActive(!0);try{return await s}finally{this.activePromptRun===s&&(this.activePromptRun=void 0),this.renderer.setRunActive(!1)}}async executePrompt(n,t=[],i,r){const s=await F(this.runtime,this.cwd),d=this.activeModel??s.config.model;if(d===null)return this.renderer.error(`No model is selected. ${R(he,"tui")}`),"";const o=this.activeProfile??s.config.profile??q.defaultProfileName(),g=await this.runtime.credentialStore.get(o);if(g===void 0)return this.renderer.error(`No API key is configured. ${R(ue,"tui")}`),"";const l=await this.runtime.projectTrust.inspect(this.cwd);this.session!==void 0&&(this.executionWorkspace=await this.executionWorkspaces.prepare({sessionId:this.session.id,projectRoot:l.canonicalPath})),await this.runHookEvent("prompt.before",this.session?.id??"tui"),this.renderer.userPrompt(n,t.map(({attachment:e})=>e));const a=Me();this.session!==void 0&&await We(this.runtime.sessionStore,this.session.id,a,n,t.map(({attachment:e})=>e.id));const w=Date.now();let S,b=!1;this.renderer.status("Thinking");const v=new AbortController;this.activeAbortController=v;const y=V(g.profile,g.apiKey),H=await this.runtime.projectTrust.isTrusted(l),c=this.session===void 0?void 0:await this.runtime.goalStore.get(this.session.id),h=new pe,N={start:e=>this.renderer.startToolActivity(e.key,e.label)},D={onSubagentLifecycle:e=>{e.sessionId===this.session?.id&&this.renderer.subagentLifecycle(e)}},O=await this.contextService.getModelContextWindow(d,o),G=e=>{h.observeModel(e),e.usage!==void 0&&(b=!0,r?.onUsage({usage:e.usage,modelCalls:1})),this.runtime.logger.debug("Model turn completed.",{model:e.model,stream:e.stream,contentLength:e.contentLength,toolCallCount:e.toolCallCount,toolNames:e.toolNames,finishReason:e.finishReason})},C=await fe({runtime:this.runtime,projectRoot:l.canonicalPath,executionCwd:this.executionWorkspace.executionCwd,model:d,reasoningEffort:s.config.effort,client:y,profile:H?"interactive-trusted":"interactive-untrusted",approvalMode:s.config.approvalMode,subagentJobs:this.subagentJobs,...i===void 0?{}:{initialSkill:i},onWrite:e=>this.renderer.fileChange(e),prompt:e=>this.approvals.ask(e),rememberApproval:e=>this.approvals.remember(l.canonicalPath,e),onApprovalPersistenceFailure:(e,f)=>this.approvals.rememberFailure(f),audit:e=>this.approvals.audit(e),onModelComplete:G,onSubagentModelComplete:e=>{e.usage!==void 0&&r?.onUsage({usage:e.usage,modelCalls:1})},contextManagement:xe(y,d,O,e=>this.runtime.logger.warn("Context summarization failed; using fallback summary.",{reason:e instanceof Error?e.message:String(e)})),agentSessionStore:this.agentSessionStore,toolActivity:N,onIntentLifecycle:e=>{e.type==="intent.compiled"?this.renderer.status("Understanding the task"):e.type==="intent.verification.required"?this.renderer.status("Verifying the result"):e.type==="intent.blocked"&&this.renderer.status("Verification is incomplete")},subagentLifecycle:D,...c===void 0?{}:{goal:{objective:c.objective,status:c.status,turns:c.turns,evaluatorRuns:c.evaluatorRuns,tokensUsed:c.usage.totalTokens,...c.tokenBudget===void 0?{}:{tokenBudget:c.tokenBudget},...c.maxTurns===void 0?{}:{maxTurns:c.maxTurns},...c.maxDurationMs===void 0?{}:{maxDurationMs:c.maxDurationMs},...c.lastError===void 0?{}:{lastError:c.lastError},...c.lastEvaluation===void 0?{}:{lastEvaluation:c.lastEvaluation.reason}}}}),p=[];let A=!1;const _=e=>{k(v.signal),p.push(e),this.renderer.assistantDelta(e)},$=e=>{k(v.signal),p.splice(0,p.length,e),this.renderer.replaceAssistant(e)};try{k(v.signal);const e=await C.buildInput(n),f=e.input,u=t.length===0?void 0:X(f,t),T=u?.content===null?void 0:u?.content;if(await Re({prepared:C,input:f,userInput:e.userInput,...e.workspaceContext===void 0?{}:{workspaceContext:e.workspaceContext},...T===void 0?{}:{inputContent:T},model:d,...this.session===void 0?{}:{sessionId:this.session.id},turnId:a,signal:v.signal,agentSessionStore:this.agentSessionStore,tracker:h,runtime:this.runtime,renderer:this.renderer,startedAt:w,getUsage:()=>S,appendAssistantDelta:_,replaceAssistantResponse:$,hasResponse:()=>p.length>0}),p.join("").trim().length===0){const m=h.snapshot();m.toolCalls>0&&h.markStuck();const B=m.toolCalls>0?I.MODEL_EMPTY_FINAL:I.MODEL_PROTOCOL_EMPTY_RESPONSE,E=m.toolCalls>0?"The model completed its tool work without a final text response.":"The model returned neither text nor a tool call.";throw new se(B,E,{category:"model",userMessage:`${E} Check the selected model and gateway tool-calling support, then try again.`,retryable:!0,details:{modelTurns:m.modelTurns,toolCalls:m.toolCalls,toolCompletions:m.toolCompletions,toolFailures:m.toolFailures,toolNames:m.toolNames,finishReason:m.lastFinishReason}})}this.session!==void 0&&(await this.executionWorkspaces.apply(this.session.id),A=!0),r?.onSnapshot(h.snapshot())}catch(e){const f=v.signal.aborted||W(e);if(this.session!==void 0&&!A)try{const u=await this.executionWorkspaces.apply(this.session.id);A=!0,u.appliedPaths.length>0&&this.runtime.logger.info("Applied session workspace changes after turn failure.",{sessionId:this.session.id,turnId:a,appliedPaths:u.appliedPaths})}catch(u){this.runtime.logger.error("Failed to apply session workspace changes after turn failure.",{sessionId:this.session.id,turnId:a,reason:u instanceof Error?u.message:String(u)})}if(this.session!==void 0&&this.agentSessionStore.delete(this.session.id),f?h.markCancelled():h.snapshot().state!=="stuck"&&h.markFailed(),this.session!==void 0&&await je(this.runtime.sessionStore,this.session.id,a,e,f),this.renderer.finishAssistant(),f)this.renderer.notice("Interrupted.");else{const u=ie(e);this.renderer.failed(),this.runtime.logger.error("Agent run failed.",{code:u.code,category:u.category,...u.details??{}}),this.renderer.error(me(u,"tui"))}return r?.onError(e),r?.onSnapshot(h.snapshot()),""}finally{if(this.activeAbortController===v&&(this.activeAbortController=void 0),C!==void 0)try{await C.close()}catch(e){this.runtime.logger.warn("Agent cleanup failed after a completed turn.",{reason:e instanceof Error?e.message:String(e)})}if(this.session!==void 0)try{await this.executionWorkspaces.markReady(this.session.id)}catch(e){this.runtime.logger.warn("Unable to release TUI execution workspace after turn.",{sessionId:this.session.id,reason:e instanceof Error?e.message:String(e)})}}this.renderer.finishAssistant();try{this.session!==void 0&&await Ue(this.runtime.sessionStore,this.session.id,a,p.join(""))}catch(e){this.runtime.logger.warn("Unable to persist the completed turn.",{reason:e instanceof Error?e.message:String(e)}),this.renderer.notice("Response completed, but the session state could not be saved.")}try{await this.runHookEvent("response.after",this.session?.id??"tui")}catch(e){this.runtime.logger.warn("Response hook failed after a completed turn.",{reason:e instanceof Error?e.message:String(e)}),this.renderer.notice("Response completed, but the response hook failed.")}this.pendingAttachments.clear(),this.renderer.setPendingAttachments([]),!b&&S!==void 0&&r?.onUsage({usage:S,modelCalls:1});const P=S?.totalTokens===void 0?oe({model:d,prompt:n,response:p.join("")}):S;return!b&&S===void 0&&P!==void 0&&r?.onUsage({usage:P,modelCalls:1}),this.renderer.complete(Date.now()-w,P),await this.refreshContextUsage(),p.join("")}commandContext(){return{write:n=>this.renderer.commandOutput(n)}}getActiveModel(){return this.activeModel}getActiveProfile(){return this.activeProfile}async refreshExtensions(){const n=await this.runtime.projectTrust.inspect(this.cwd),t=await this.runtime.projectTrust.isTrusted(n),i=await this.runtime.configLoader.load(this.cwd,{includeProject:t});await this.reloadExtensions(t,i.config.approvalMode,n.canonicalPath),await this.refreshContextUsage()}async refreshWelcome(n={}){const t=await this.runtime.projectTrust.inspect(this.cwd),i=await this.runtime.projectTrust.isTrusted(t),r=await this.runtime.configLoader.load(this.cwd,{includeProject:i});this.activeModel=n.model===void 0?this.activeModel??r.config.model:n.model,this.activeProfile=n.profile===void 0?this.activeProfile??r.config.profile:n.profile,this.renderer.setWelcome({version:x,cwd:t.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:i}),await this.refreshContextUsage()}async getContextSnapshot(){const n=this.activeModel??this.session?.model??null,t=this.session===void 0?void 0:await this.runtime.goalStore.get(this.session.id),i=await this.contextService.buildForProject({...this.session===void 0?{}:{sessionId:this.session.id},model:n,profileName:this.activeProfile??this.session?.profile??null,pluginNames:this.enabledPluginNames,pluginMcpConfig:this.pluginMcpConfig,pendingAttachments:this.pendingAttachments.size,skillRootScopes:this.skillRootScopes,agentSessionStore:this.agentSessionStore,...t===void 0?{}:{goal:{objective:t.objective,status:t.status,turns:t.turns,evaluatorRuns:t.evaluatorRuns,tokensUsed:t.usage.totalTokens,...t.tokenBudget===void 0?{}:{tokenBudget:t.tokenBudget},...t.maxTurns===void 0?{}:{maxTurns:t.maxTurns},...t.maxDurationMs===void 0?{}:{maxDurationMs:t.maxDurationMs},...t.lastError===void 0?{}:{lastError:t.lastError},...t.lastEvaluation===void 0?{}:{lastEvaluation:t.lastEvaluation.reason}}}});return this.renderer.setContextUsage({usedTokens:i.usedTokens,...i.contextWindow===void 0?{}:{contextWindow:i.contextWindow}}),i}async refreshContextUsage(){try{await this.getContextSnapshot()}catch(n){this.runtime.logger.debug("Unable to refresh context usage.",{reason:n instanceof Error?n.message:String(n)})}}async runSkill(n,t,i,r,s){await Ee({globalConfigDir:this.runtime.paths.globalConfigDir,skillRootScopes:this.skillRootScopes,runPrompt:(d,o)=>this.sendPrompt(d,this.pendingAttachments.list(),o)},n,t,i,s,r)}async reloadExtensions(n,t,i){const r=await Le({runtime:this.runtime,cwd:this.cwd,trusted:n,approvalMode:t,workspaceRoot:i,approvals:this.approvals});this.hookRuntime=r.hookRuntime,this.skillRootScopes=r.skillRootScopes,this.enabledPluginNames=r.enabledPluginNames,this.pluginMcpConfig=r.pluginMcpConfig,this.hooks=r.hooks}async compactSession(){await be({runtime:this.runtime,cwd:this.cwd,session:this.session,activeModel:this.activeModel,activeProfile:this.activeProfile,activeResponse:this.activeAbortController!==void 0,renderer:this.renderer,contextService:this.contextService,agentSessionStore:this.agentSessionStore,refreshContextUsage:()=>this.refreshContextUsage()})}async resumeSession(n){if(this.activePromptRun!==void 0)throw new Error("Stop the active response before resuming another session.");const t=await this.runtime.projectTrust.inspect(this.cwd),i=await new de(this.runtime.sessionStore).require(n,t.fingerprint);if(i.id===this.session?.id){this.renderer.notice(`Already using session: ${i.id}`);return}const r=await this.runtime.sessionStore.readTranscript(i.id),s=this.session;s!==void 0&&(await this.subagentJobs.close(),this.subagentJobs=new L,await this.runHookEvent("session.end",s.id),await this.runtime.sessionStore.updateStatus(s.id,"completed")),this.session=await this.runtime.sessionStore.updateStatus(i.id,"active"),this.executionWorkspace=await this.executionWorkspaces.prepare({sessionId:i.id,projectRoot:t.canonicalPath});const d=await F(this.runtime,this.cwd);this.activeModel=i.model??d.config.model,this.activeProfile=i.profile??d.config.profile,this.renderer.setWelcome({version:x,cwd:t.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:await this.runtime.projectTrust.isTrusted(t)}),this.renderer.clearTranscript();for(const o of U(r))o.type==="user"?this.renderer.userPrompt(o.content):o.type==="assistant"&&(this.renderer.beginAssistant(),this.renderer.assistantDelta(o.content),this.renderer.finishAssistant());await this.refreshContextUsage(),await this.runHookEvent("session.start",i.id),M(this.runtime,this.cwd).catch(o=>this.runtime.logger.warn("MCP session warm-up failed.",{reason:o instanceof Error?o.message:String(o)})),this.renderer.notice(`Resumed session: ${i.id}`)}handleInterrupt(){const n=Pe({lastInterruptAt:this.lastInterruptAt,exitArmedUntil:this.exitArmedUntil,printResumeCommandOnExit:this.printResumeCommandOnExit},this.activeAbortController,this.renderer);this.lastInterruptAt=n.lastInterruptAt,this.exitArmedUntil=n.exitArmedUntil,this.printResumeCommandOnExit=n.printResumeCommandOnExit}async awaitActiveForegroundRun(){const n=this.activeForegroundRun;if(n!==void 0)try{await n}catch(t){this.runtime.logger.warn("Foreground TUI operation failed during shutdown.",{reason:t instanceof Error?t.message:String(t)})}}async runHookEvent(n,t){await ke(this.hookRuntime,this.hooks,n,this.executionWorkspace?.executionCwd??this.cwd,t)}}export{At as TuiApplication};
1
+ import{createElement as f}from"react";import{render as w}from"ink";import{detectTerminalCapabilities as v}from"./terminal-capabilities.js";import{enterInteractiveScreen as S,exitInteractiveScreen as b}from"./terminal-screen.js";import{createImageAttachment as x,normalizeImage as C}from"../../infrastructure/clipboard/image-normalizer.js";import{PendingAttachmentStore as A}from"../../application/chat/pending-attachment-store.js";import{CLI_VERSION as u}from"../../version.js";import{InkTuiBridge as k}from"./ink/tui-bridge.js";import{LotaGateTui as P}from"./ink/lotagate-tui.js";import{WorkspaceFileIndex as y}from"../../application/workspace/workspace-file-index.js";import{ProjectSessionAccess as T}from"../../application/session/project-session-access.js";import{createTuiCommandHost as I}from"./tui-command-host-factory.js";import{workspaceFileSuggestions as E}from"./tui-file-suggestions.js";import{warmMcpRuntime as R}from"../../application/agent/cli-agent-execution-service.js";import{TuiToolApprovalCoordinator as M}from"./tui-tool-approval.js";import{TuiContextService as W}from"./tui-context-service.js";import{createTuiClipboardPasteHandlers as U}from"./tui-clipboard-paste-handlers.js";import{dispatchTuiPrompt as j}from"./tui-prompt-dispatcher.js";import{CliAgentSessionStore as H,retainLatestCompaction as m}from"../../application/agent/agent-session-store.js";import{compactManualTuiSession as F}from"./tui-manual-compaction.js";import{resolveInitialModel as p}from"./tui-initial-model.js";import{cancelTuiResponse as O,handleTuiInterrupt as G,isAbortError as L,runTuiHookEvent as N}from"./tui-lifecycle-actions.js";import{loadExecutionConfig as B}from"../../application/config/execution-config.js";import{resumeTuiGoal as D,runTuiGoal as $}from"./tui-goal-controller.js";import{runTuiSkill as J}from"./tui-skill-controller.js";import{SubagentJobRegistry as g}from"../../application/orchestration/cli-subagent-service.js";import{formatResumeCommand as z}from"./tui-application-contract.js";import{SessionExecutionWorkspaceService as q}from"../../application/workspace/session-execution-workspace.js";import{loadTuiExtensions as V}from"./tui-extension-loader.js";import{TuiAgentTurnController as _}from"./tui-agent-turn-controller.js";import{OperationRegistry as K}from"../../application/lifecycle/operation-registry.js";class It{runtime;cwd;options;input;output;renderer;pendingAttachments=new A;session;hookRuntime;hooks=[];skillRootScopes=[];enabledPluginNames=[];pluginMcpConfig={};activeForegroundRun;exitArmedUntil=0;lastInterruptAt=0;printResumeCommandOnExit=!1;activeModel=null;activeProfile=null;approvals;contextService;agentSessionStore=new H;backgroundOperations=new K;subagentJobs=new g;executionWorkspaces;executionWorkspace;turnController;constructor(i,t,e={}){this.runtime=i,this.cwd=t,this.options=e,this.input=e.input??process.stdin,this.output=e.output??process.stdout,this.renderer=new k,this.executionWorkspaces=this.runtime.executionWorkspaces??new q(this.runtime.paths.globalConfigDir,this.runtime.platform),this.contextService=new W(this.runtime,this.cwd),this.approvals=new M({renderer:this.renderer,runtime:this.runtime,getSessionId:()=>this.session?.id,getActiveSignal:()=>this.turnController.getActiveAbortController()?.signal}),this.turnController=new _({runtime:this.runtime,cwd:this.cwd,renderer:this.renderer,pendingAttachments:this.pendingAttachments,approvals:this.approvals,contextService:this.contextService,agentSessionStore:this.agentSessionStore,executionWorkspaces:this.executionWorkspaces,getSession:()=>this.session,getActiveModel:()=>this.activeModel,getActiveProfile:()=>this.activeProfile,getExecutionWorkspace:()=>this.executionWorkspace,setExecutionWorkspace:r=>{this.executionWorkspace=r},getSubagentJobs:()=>this.subagentJobs,runHookEvent:(r,s)=>this.runHookEvent(r,s),refreshContextUsage:()=>this.refreshContextUsage()}),this.renderer.setInterruptHandler(()=>this.handleInterrupt()),this.renderer.setCancelHandler(()=>O(this.turnController.getActiveAbortController(),this.renderer));const n=U({platform:this.runtime.platform,notify:r=>this.renderer.notice(r),attachImage:(r,s)=>this.attachClipboardImage(r,!1,s)});this.renderer.setImagePasteHandler(n.image),this.renderer.setTextPasteHandler(n.text),this.renderer.setClearAttachmentsHandler(()=>{this.pendingAttachments.clear(),this.renderer.setPendingAttachments([])})}async run(){if(!v(this.input,this.output).isInteractive)return this.output.write('Interactive TUI requires a terminal. Use `lotagate chat "prompt"` for non-interactive streaming.\n'),2;S(this.output);const t=w(f(P,{bridge:this.renderer}),{stdin:this.input,stdout:this.output,exitOnCtrlC:!1}),e=()=>this.handleInterrupt(),n=()=>{const s=new Error("Interactive session is shutting down.");this.backgroundOperations.abort(s),this.turnController.abortActive(s),this.renderer.requestExit(143)};process.on("SIGINT",e),this.options.signal?.addEventListener("abort",n,{once:!0});let r="completed";try{const s=await this.runtime.projectTrust.inspect(this.cwd);let o=await this.runtime.projectTrust.isTrusted(s),h=await this.runtime.configLoader.load(this.cwd,{includeProject:o}),l=await p(this.runtime,h.config),c={...h,config:{...h.config,model:l}};if(this.activeModel=c.config.model,this.activeProfile=c.config.profile,this.renderer.setWelcome({version:u,cwd:s.canonicalPath,model:c.config.model,profile:c.config.profile,trusted:o}),this.renderer.setFileSuggestions([]),o||(o=await this.renderer.confirmTrust(),o?(await this.runtime.projectTrust.grant(s),h=await this.runtime.configLoader.load(this.cwd),l=await p(this.runtime,h.config),c={...h,config:{...h.config,model:l}},this.activeModel=c.config.model,this.activeProfile=c.config.profile,this.renderer.setWelcome({version:u,cwd:s.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:!0}),this.renderer.notice("Project trusted.")):this.renderer.notice("Project remains untrusted; local tools and extensions stay disabled.")),o&&await this.runtime.workspaceSettings.ensureInitialized(s.canonicalPath),await this.reloadExtensions(o,c.config.approvalMode,s.canonicalPath),this.options.sessionId!==void 0){const a=await this.runtime.sessionStore.get(this.options.sessionId);if(a===void 0)throw new Error(`Session not found: ${this.options.sessionId}`);if(a.projectFingerprint!==s.fingerprint)throw new Error("Session belongs to another project.");this.session=a,this.renderer.status(`Resuming session ${a.id}`);for(const d of m(await this.runtime.sessionStore.readTranscript(a.id)))d.type==="user"?this.renderer.userPrompt(d.content):d.type==="assistant"&&(this.renderer.beginAssistant(),this.renderer.assistantDelta(d.content),this.renderer.finishAssistant())}else this.session=await this.runtime.sessionStore.create({projectFingerprint:s.fingerprint,cwd:s.canonicalPath,model:c.config.model,profile:c.config.profile,status:"active"});return this.executionWorkspace=await this.executionWorkspaces.prepare({sessionId:this.session.id,projectRoot:s.canonicalPath}),await this.refreshContextUsage(),await this.runHookEvent("session.start",this.session.id),this.startBackgroundMcpWarmup(),this.renderer.setSubmitHandler(async a=>{await this.processPrompt(a)&&this.renderer.requestExit()}),this.renderer.clearActivity(),this.renderer.setReady(),this.backgroundOperations.start(a=>new y(s.canonicalPath).listEntries(a)).then(a=>this.renderer.setFileSuggestions(E(a))).catch(a=>this.runtime.logger.debug("Unable to load workspace file suggestions.",{reason:a instanceof Error?a.message:String(a)})),await this.renderer.waitForExit()}catch(s){throw r=L(s)?"cancelled":"failed",s}finally{this.turnController.abortActive(new Error("Interactive session is closing.")),await this.backgroundOperations.close(),this.renderer.resolveActiveModal(void 0),await this.awaitActiveForegroundRun();try{await this.subagentJobs.close()}catch(s){this.runtime.logger.warn("Unable to close subagent jobs during TUI shutdown.",{reason:s instanceof Error?s.message:String(s)})}if(this.agentSessionStore.clear(),this.session!==void 0){try{await this.runHookEvent("session.end",this.session.id)}catch(s){this.runtime.logger.warn("Session end hook failed during TUI shutdown.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}try{await this.runtime.sessionStore.updateStatus(this.session.id,r)}catch(s){this.runtime.logger.warn("Unable to update TUI session status during shutdown.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}try{await this.executionWorkspaces.markReady(this.session.id)}catch(s){this.runtime.logger.warn("Unable to release TUI execution workspace.",{sessionId:this.session.id,reason:s instanceof Error?s.message:String(s)})}}process.off("SIGINT",e),this.options.signal?.removeEventListener("abort",n),this.renderer.dispose(),t.unmount(),b(this.output),this.printResumeCommandOnExit&&this.session!==void 0&&this.output.write(`
2
+ ${z(this.session.id)}
3
+ `)}}async processPrompt(i){if(this.activeForegroundRun!==void 0)return this.renderer.notice("An operation is already running. Stop it before starting another one."),!1;const t=j(i,{renderer:this.renderer,logger:this.runtime.logger,commandHost:I({runtime:this.runtime,cwd:this.cwd,renderer:this.renderer,pendingAttachments:this.pendingAttachments,getHooks:()=>this.hooks,getSession:()=>this.session,getActiveAbortController:()=>this.turnController.getActiveAbortController(),setActiveAbortController:e=>{this.turnController.setActiveAbortController(e)},attachClipboardImage:e=>this.attachClipboardImage(e),runPrompt:(e,n)=>this.turnController.runPrompt(e,n),runGoal:(e,n,r)=>this.runGoal(e,n,r),resumeGoal:e=>this.resumeGoal(e),runSkill:(e,n,r,s,o)=>this.runSkill(e,n,r,s,o),refreshExtensions:()=>this.refreshExtensions(),compactSession:()=>this.compactSession(),refreshWelcome:e=>this.refreshWelcome(e),getContextSnapshot:()=>this.getContextSnapshot(),resumeSession:e=>this.resumeSession(e)}),pendingAttachments:this.pendingAttachments,commandContext:()=>this.commandContext(),sendPrompt:(e,n)=>this.turnController.sendPrompt(e,n),resetActiveAbortController:()=>{this.turnController.isRunning()||this.turnController.setActiveAbortController(void 0)}});this.activeForegroundRun=t;try{return await t}finally{this.activeForegroundRun===t&&(this.activeForegroundRun=void 0)}}async attachClipboardImage(i,t=!0,e=""){if(i===void 0){t&&this.renderer.notice("Clipboard does not contain an image.");return}const n=C(i.bytes,i.mimeType);this.pendingAttachments.assertCanAdd(n.bytes.byteLength,e,{byteLength:n.bytes.byteLength,mimeType:n.mimeType});const r=this.pendingAttachments.nextId(),s=x(n,"clipboard",r),o=this.session===void 0?s:await this.runtime.sessionStore.saveAttachment(this.session.id,s,n.bytes);this.pendingAttachments.add({attachment:o,bytes:n.bytes},e),this.renderer.setPendingAttachments(this.pendingAttachments.list().map(({attachment:h})=>h)),t&&this.renderer.notice(`Attached ${s.name} \xB7 ${s.mimeType} \xB7 ${s.sizeBytes} bytes`)}async runPrompt(i,t,e){return this.turnController.runPrompt(i,t,e)}async runGoal(i,t,e={}){if(this.turnController.isRunning()){t.write("Stop the active response before starting a goal.");return}await $({runtime:this.runtime,cwd:this.cwd,sessionId:this.session?.id,model:this.activeModel??this.session?.model??null,profile:this.activeProfile??this.session?.profile??null,runPrompt:(n,r)=>this.runPrompt(n,void 0,r),write:n=>t.write(n)},i,e)}async resumeGoal(i){if(this.turnController.isRunning()){i.write("Stop the active response before resuming a goal.");return}await D({runtime:this.runtime,cwd:this.cwd,sessionId:this.session?.id,model:this.activeModel??this.session?.model??null,profile:this.activeProfile??this.session?.profile??null,runPrompt:(t,e)=>this.runPrompt(t,void 0,e),write:t=>i.write(t)})}commandContext(){return{write:i=>this.renderer.commandOutput(i)}}getActiveModel(){return this.activeModel}getActiveProfile(){return this.activeProfile}async refreshExtensions(){const i=await this.runtime.projectTrust.inspect(this.cwd);this.runtime.agentPreparation?.clear(i.canonicalPath);const t=await this.runtime.projectTrust.isTrusted(i),e=await this.runtime.configLoader.load(this.cwd,{includeProject:t});await this.reloadExtensions(t,e.config.approvalMode,i.canonicalPath),await this.refreshContextUsage()}async refreshWelcome(i={}){const t=await this.runtime.projectTrust.inspect(this.cwd);this.runtime.agentPreparation?.clear(t.canonicalPath);const e=await this.runtime.projectTrust.isTrusted(t),n=await this.runtime.configLoader.load(this.cwd,{includeProject:e});this.activeModel=i.model===void 0?this.activeModel??n.config.model:i.model,this.activeProfile=i.profile===void 0?this.activeProfile??n.config.profile:i.profile,this.renderer.setWelcome({version:u,cwd:t.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:e}),await this.refreshContextUsage()}async getContextSnapshot(){const i=this.activeModel??this.session?.model??null,t=this.session===void 0?void 0:await this.runtime.goalStore.get(this.session.id),e=await this.contextService.buildForProject({...this.session===void 0?{}:{sessionId:this.session.id},model:i,profileName:this.activeProfile??this.session?.profile??null,pluginNames:this.enabledPluginNames,pluginMcpConfig:this.pluginMcpConfig,pendingAttachments:this.pendingAttachments.size,skillRootScopes:this.skillRootScopes,agentSessionStore:this.agentSessionStore,...t===void 0?{}:{goal:{objective:t.objective,status:t.status,turns:t.turns,evaluatorRuns:t.evaluatorRuns,tokensUsed:t.usage.totalTokens,...t.tokenBudget===void 0?{}:{tokenBudget:t.tokenBudget},...t.maxTurns===void 0?{}:{maxTurns:t.maxTurns},...t.maxDurationMs===void 0?{}:{maxDurationMs:t.maxDurationMs},...t.lastError===void 0?{}:{lastError:t.lastError},...t.lastEvaluation===void 0?{}:{lastEvaluation:t.lastEvaluation.reason}}}});return this.renderer.setContextUsage({usedTokens:e.usedTokens,...e.contextWindow===void 0?{}:{contextWindow:e.contextWindow}}),e}async refreshContextUsage(){try{await this.getContextSnapshot()}catch(i){this.runtime.logger.debug("Unable to refresh context usage.",{reason:i instanceof Error?i.message:String(i)})}}async runSkill(i,t,e,n,r){await J({globalConfigDir:this.runtime.paths.globalConfigDir,skillRootScopes:this.skillRootScopes,runPrompt:(s,o)=>this.turnController.sendPrompt(s,this.pendingAttachments.list(),o)},i,t,e,r,n)}async reloadExtensions(i,t,e){const n=await V({runtime:this.runtime,cwd:this.cwd,trusted:i,approvalMode:t,workspaceRoot:e,approvals:this.approvals});this.hookRuntime=n.hookRuntime,this.skillRootScopes=n.skillRootScopes,this.enabledPluginNames=n.enabledPluginNames,this.pluginMcpConfig=n.pluginMcpConfig,this.hooks=n.hooks}async compactSession(){await F({runtime:this.runtime,cwd:this.cwd,session:this.session,activeModel:this.activeModel,activeProfile:this.activeProfile,activeResponse:this.turnController.getActiveAbortController()!==void 0,renderer:this.renderer,contextService:this.contextService,agentSessionStore:this.agentSessionStore,refreshContextUsage:()=>this.refreshContextUsage()})}async resumeSession(i){if(this.turnController.isRunning())throw new Error("Stop the active response before resuming another session.");const t=await this.runtime.projectTrust.inspect(this.cwd),e=await new T(this.runtime.sessionStore).require(i,t.fingerprint);if(e.id===this.session?.id){this.renderer.notice(`Already using session: ${e.id}`);return}const n=await this.runtime.sessionStore.readTranscript(e.id),r=this.session;r!==void 0&&(await this.subagentJobs.close(),this.subagentJobs=new g,await this.runHookEvent("session.end",r.id),await this.runtime.sessionStore.updateStatus(r.id,"completed"),this.agentSessionStore.delete(r.id)),this.session=await this.runtime.sessionStore.updateStatus(e.id,"active"),this.executionWorkspace=await this.executionWorkspaces.prepare({sessionId:e.id,projectRoot:t.canonicalPath});const s=await B(this.runtime,this.cwd);this.activeModel=e.model??s.config.model,this.activeProfile=e.profile??s.config.profile,this.renderer.setWelcome({version:u,cwd:t.canonicalPath,model:this.activeModel,profile:this.activeProfile,trusted:await this.runtime.projectTrust.isTrusted(t)}),this.renderer.clearTranscript();for(const o of m(n))o.type==="user"?this.renderer.userPrompt(o.content):o.type==="assistant"&&(this.renderer.beginAssistant(),this.renderer.assistantDelta(o.content),this.renderer.finishAssistant());await this.refreshContextUsage(),await this.runHookEvent("session.start",e.id),this.pendingAttachments.clear(),this.renderer.setPendingAttachments([]),this.startBackgroundMcpWarmup(),this.renderer.notice(`Resumed session: ${e.id}`)}handleInterrupt(){const i=G({lastInterruptAt:this.lastInterruptAt,exitArmedUntil:this.exitArmedUntil,printResumeCommandOnExit:this.printResumeCommandOnExit},this.turnController.getActiveAbortController(),this.renderer);this.lastInterruptAt=i.lastInterruptAt,this.exitArmedUntil=i.exitArmedUntil,this.printResumeCommandOnExit=i.printResumeCommandOnExit}startBackgroundMcpWarmup(){this.backgroundOperations.start(i=>R(this.runtime,this.cwd,i)).catch(i=>this.runtime.logger.warn("MCP session warm-up failed.",{reason:i instanceof Error?i.message:String(i)}))}async awaitActiveForegroundRun(){const i=this.activeForegroundRun;if(i!==void 0)try{await i}catch(t){this.runtime.logger.warn("Foreground TUI operation failed during shutdown.",{reason:t instanceof Error?t.message:String(t)})}}async runHookEvent(i,t){await N(this.hookRuntime,this.hooks,i,this.executionWorkspace?.executionCwd??this.cwd,t)}}export{It as TuiApplication};
@@ -1,11 +1,11 @@
1
1
  import type { ClipboardImage } from '../../ports/clipboard-adapter.js';
2
2
  import type { HostPlatformContext } from '../../infrastructure/platform/host-platform.js';
3
3
  export interface TuiClipboardPasteHandlers {
4
- image: () => Promise<void>;
4
+ image: (prompt: string) => Promise<void>;
5
5
  text: () => Promise<string | undefined>;
6
6
  }
7
7
  export declare function createTuiClipboardPasteHandlers(options: {
8
8
  platform: HostPlatformContext;
9
9
  notify: (message: string) => void;
10
- attachImage: (image: ClipboardImage | undefined) => Promise<void>;
10
+ attachImage: (image: ClipboardImage | undefined, prompt: string) => Promise<void>;
11
11
  }): TuiClipboardPasteHandlers;
@@ -1 +1 @@
1
- import{asCliError as t}from"../../domain/errors/cli-error.js";import{createClipboardAdapter as i}from"../../infrastructure/clipboard/clipboard-adapter-factory.js";import{createClipboardTextAdapter as m}from"../../infrastructure/clipboard/clipboard-text-adapter-factory.js";import{formatCliErrorMessage as e}from"../../application/commands/command-hints.js";function l(r){return{image:async()=>{try{await r.attachImage(await i(r.platform).readImage())}catch(a){r.notify(e(t(a),"tui"))}},text:async()=>{try{return await m(r.platform).readText()}catch(a){r.notify(e(t(a),"tui"));return}}}}export{l as createTuiClipboardPasteHandlers};
1
+ import{asCliError as t}from"../../domain/errors/cli-error.js";import{createClipboardAdapter as m}from"../../infrastructure/clipboard/clipboard-adapter-factory.js";import{createClipboardTextAdapter as o}from"../../infrastructure/clipboard/clipboard-text-adapter-factory.js";import{formatCliErrorMessage as e}from"../../application/commands/command-hints.js";function n(r){return{image:async a=>{try{await r.attachImage(await m(r.platform).readImage(),a)}catch(i){r.notify(e(t(i),"tui"))}},text:async()=>{try{return await o(r.platform).readText()}catch(a){r.notify(e(t(a),"tui"));return}}}}export{n as createTuiClipboardPasteHandlers};
@@ -1,4 +1,4 @@
1
- import{AuthenticationService as u}from"../../application/auth/authentication-service.js";import{executeApplicationCommand as c}from"../../application/commands/application-command-executor.js";import{runEffortCommand as f,runModelCommand as m}from"../../application/commands/cli-command-services.js";import{REASONING_EFFORTS as p}from"../../domain/config/config-schema.js";import{loadModelCatalog as d}from"../../application/model/model-catalog-service.js";import{formatContextSnapshot as w}from"./context-display.js";import{createClipboardAdapter as g}from"../../infrastructure/clipboard/clipboard-adapter-factory.js";import{formatCompactTable as y}from"../../application/formatting/compact-table.js";import{formatGoalStatus as A}from"../../application/orchestration/goal-output.js";import{parseGoalLimits as b}from"../../application/orchestration/goal-input.js";import{prepareTuiMediaInvocation as S}from"./tui-media-model-selection.js";async function K(e,i,a){switch(e.action.executor){case"tui-exit":return!0;case"tui-clear":return i.renderer.clearTranscript(),!1;case"tui-stop":return G(i,a),!1;case"tui-details":return a.write(`Action details: ${i.renderer.toggleActionDetails()?"on":"off"}`),!1;case"tui-context":return await L(i,a),!1;case"tui-auth-login":return await T(i,e,a),!1;case"tui-model-select":return await E(i,a),!1;case"tui-effort-select":return await W(i,a),!1;case"tui-skill-run":return await $(i,e,a),!1;case"tui-session-resume":return await i.resumeSession(l(e,0,"session id")),!1;case"tui-session-compact":return await i.compactSession(),!1;case"tui-session-rename":return await k(i,e,a),!1;case"tui-goal":return await I(i,e,a),!1;case"tui-attachments":return await P(i,e,a),!1;case"tui-prompt":return await i.runPrompt(e.positionals.join(" ")),!1;case"tui-agent-info":return a.write("The JSONL agent protocol owns stdin/stdout and must be run directly: lotagate agent stdio."),!1;default:{const t=await S(e,{loadModels:()=>d(i.runtime,i.cwd),selectModel:(r,n)=>i.renderer.selectModel(r,n)});return t===void 0?(a.write("Model selection cancelled."),!1):(await C(t,i,a),await N(i,t),!1)}}}async function C(e,i,a){const t=new AbortController;i.activeAbortController=t;try{await c(e,M(i,a,t.signal))}finally{i.activeAbortController===t&&(i.activeAbortController=void 0)}}function M(e,i,a){return{runtime:e.runtime,cwd:e.cwd,output:{write:t=>i.write(t.endsWith(`
2
- `)?t.slice(0,-1):t)},selectScope:t=>e.renderer.selectScope(t),activity:{start:(t,r)=>e.renderer.startToolActivity(t,r)},signal:a}}async function N(e,i){i.action.id==="model.use"&&await e.refreshWelcome({model:i.positionals[0]??null}),(i.action.id==="trust.grant"||i.action.id==="trust.revoke")&&(await e.refreshExtensions(),await e.refreshWelcome()),i.action.id.startsWith("plugin.")&&i.action.id!=="plugin.list"&&i.action.id!=="plugin.list.default"&&await e.refreshExtensions()}function G(e,i){e.activeAbortController===void 0?i.write("No response is currently running."):(e.activeAbortController.abort(),i.write("Stopping the active response."))}async function L(e,i){i.write(e.session===void 0?"No active session.":w(await e.getContextSnapshot()))}async function T(e,i,a){const t=await e.runtime.configLoader.load(e.cwd,{includeProject:!1}),r=String(i.options.get("profile")??t.config.profile??u.defaultProfileName()),n=String(i.options.get("base-url")??t.config.baseUrl),o=await e.renderer.requestSecret("LotaGate API key");if(o===void 0){a.write("Login cancelled.");return}const s=await e.runtime.auth.login({profileName:r,baseUrl:n,apiKey:o});await e.runtime.configLoader.setGlobal("profile",s.name),await e.refreshWelcome({profile:s.name}),a.write(`Logged in profile: ${s.name}`)}async function E(e,i){const a=await e.runtime.configLoader.load(e.cwd),t=await d(e.runtime,e.cwd);if(t.data.length===0){i.write("No models are available.");return}const r=await e.renderer.selectModel("Select a model",t.data.map(n=>({value:n.id,label:typeof n.display_name=="string"?n.display_name:n.id})),a.config.model??void 0);if(r===void 0){i.write("Model selection cancelled.");return}await m(["use",r],e.runtime,e.cwd,{write:n=>i.write(n.endsWith(`
1
+ import{AuthenticationService as d}from"../../application/auth/authentication-service.js";import{executeApplicationCommand as c}from"../../application/commands/application-command-executor.js";import{runEffortCommand as f,runModelCommand as m}from"../../application/commands/cli-command-services.js";import{REASONING_EFFORTS as p}from"../../domain/config/config-schema.js";import{loadModelCatalog as u}from"../../application/model/model-catalog-service.js";import{formatContextSnapshot as w}from"./context-display.js";import{createClipboardAdapter as g}from"../../infrastructure/clipboard/clipboard-adapter-factory.js";import{formatCompactTable as y}from"../../application/formatting/compact-table.js";import{formatGoalStatus as A}from"../../application/orchestration/goal-output.js";import{parseGoalLimits as b}from"../../application/orchestration/goal-input.js";import{prepareTuiMediaInvocation as S}from"./tui-media-model-selection.js";import{isCliAgentPreparationMutation as C}from"../../application/agent/cli-agent-preparation-cache.js";async function V(e,i,a){switch(e.action.executor){case"tui-exit":return!0;case"tui-clear":return i.renderer.clearTranscript(),!1;case"tui-stop":return L(i,a),!1;case"tui-details":return a.write(`Action details: ${i.renderer.toggleActionDetails()?"on":"off"}`),!1;case"tui-context":return await T(i,a),!1;case"tui-auth-login":return await E(i,e,a),!1;case"tui-model-select":return await P(i,a),!1;case"tui-effort-select":return await W(i,a),!1;case"tui-skill-run":return await k(i,e,a),!1;case"tui-session-resume":return await i.resumeSession(o(e,0,"session id")),!1;case"tui-session-compact":return await i.compactSession(),!1;case"tui-session-rename":return await $(i,e,a),!1;case"tui-goal":return await I(i,e,a),!1;case"tui-attachments":return await j(i,e,a),!1;case"tui-prompt":return await i.runPrompt(e.positionals.join(" ")),!1;case"tui-agent-info":return a.write("The JSONL agent protocol owns stdin/stdout and must be run directly: lotagate agent stdio."),!1;default:{const t=await S(e,{loadModels:()=>u(i.runtime,i.cwd),selectModel:(r,n)=>i.renderer.selectModel(r,n)});return t===void 0?(a.write("Model selection cancelled."),!1):(await M(t,i,a),C(t.action.id,t.action.desktop?.mutationKey)&&i.runtime.agentPreparation?.clear(),await G(i,t),!1)}}}async function M(e,i,a){const t=new AbortController;i.activeAbortController=t;try{await c(e,N(i,a,t.signal))}finally{i.activeAbortController===t&&(i.activeAbortController=void 0)}}function N(e,i,a){return{runtime:e.runtime,cwd:e.cwd,output:{write:t=>i.write(t.endsWith(`
2
+ `)?t.slice(0,-1):t)},selectScope:t=>e.renderer.selectScope(t),activity:{start:(t,r)=>e.renderer.startToolActivity(t,r)},signal:a}}async function G(e,i){i.action.id==="model.use"&&await e.refreshWelcome({model:i.positionals[0]??null}),(i.action.id==="trust.grant"||i.action.id==="trust.revoke")&&(await e.refreshExtensions(),await e.refreshWelcome()),i.action.id.startsWith("plugin.")&&i.action.id!=="plugin.list"&&i.action.id!=="plugin.list.default"&&await e.refreshExtensions()}function L(e,i){e.activeAbortController===void 0?i.write("No response is currently running."):(e.activeAbortController.abort(),i.write("Stopping the active response."))}async function T(e,i){i.write(e.session===void 0?"No active session.":w(await e.getContextSnapshot()))}async function E(e,i,a){const t=await e.runtime.configLoader.load(e.cwd,{includeProject:!1}),r=String(i.options.get("profile")??t.config.profile??d.defaultProfileName()),n=String(i.options.get("base-url")??t.config.baseUrl),l=await e.renderer.requestSecret("LotaGate API key");if(l===void 0){a.write("Login cancelled.");return}const s=await e.runtime.auth.login({profileName:r,baseUrl:n,apiKey:l});await e.runtime.configLoader.setGlobal("profile",s.name),await e.refreshWelcome({profile:s.name}),a.write(`Logged in profile: ${s.name}`)}async function P(e,i){const a=await e.runtime.configLoader.load(e.cwd),t=await u(e.runtime,e.cwd);if(t.data.length===0){i.write("No models are available.");return}const r=await e.renderer.selectModel("Select a model",t.data.map(n=>({value:n.id,label:typeof n.display_name=="string"?n.display_name:n.id})),a.config.model??void 0);if(r===void 0){i.write("Model selection cancelled.");return}await m(["use",r],e.runtime,e.cwd,{write:n=>i.write(n.endsWith(`
3
3
  `)?n.slice(0,-1):n)}),await e.refreshWelcome({model:r})}async function W(e,i){const a=await e.runtime.configLoader.load(e.cwd),t=await e.renderer.selectModel("Select reasoning effort",p.map(r=>({value:r,label:r})),a.config.effort);if(t===void 0){i.write("Effort selection cancelled.");return}await f(["use",t],e.runtime,e.cwd,{write:r=>i.write(r.endsWith(`
4
- `)?r.slice(0,-1):r)})}async function $(e,i,a){const t=l(i,0,"skill name");await e.runSkill(t,i.positionals.slice(1),a,void 0,j(i))}async function k(e,i,a){if(e.session===void 0){a.write("No active session.");return}const t=i.positionals.join(" ").trim();e.session=await e.runtime.sessionStore.rename(e.session.id,t),a.write(`Renamed session: ${e.session.name}`)}async function I(e,i,a){if(i.action.id==="goal.start.tui"){await e.runGoal(i.positionals.join(" "),a,b(i.options));return}if(e.session===void 0){a.write("No active session.");return}if(i.action.id==="goal.status.tui"){const t=await e.runtime.goalStore.get(e.session.id);a.write(t===void 0?"No active goal.":A(t));return}if(i.action.id==="goal.pause.tui"){e.activeAbortController?.abort();const t=await e.runtime.goalStore.get(e.session.id);t?.status==="active"&&await e.runtime.goalStore.pause(e.session.id),a.write(t?.status==="paused"?"Goal already paused.":"Goal paused.");return}if(i.action.id==="goal.resume.tui"){await e.resumeGoal(a);return}e.activeAbortController?.abort(),await e.runtime.goalStore.clear(e.session.id),a.write("Goal cleared.")}async function P(e,i,a){const t=i.action.id;if(t==="attachments.paste"){const r=await g(e.runtime.platform).readImage();await e.attachClipboardImage(r),a.write(r===void 0?"Clipboard does not contain an image.":"Attachment added from clipboard.");return}if(t==="attachments.remove"){const r=l(i,0,"attachment id");e.pendingAttachments.remove(r)?(e.renderer.setPendingAttachments(e.pendingAttachments.list().map(({attachment:n})=>n)),a.write(`Removed attachment: ${r}`)):a.write(`Attachment not found: ${r}`);return}a.write(y(e.pendingAttachments.list().map(({attachment:r})=>({name:r.name,status:r.mimeType,detail:`${r.sizeBytes} bytes`})),{empty:"No pending attachments."}))}function l(e,i,a){const t=e.positionals[i];if(t===void 0)throw new Error(`Missing ${a}.`);return t}function j(e){const i=e.options.get("scope");return i==="user"||i==="project"?i:void 0}export{K as executeTuiCommand};
4
+ `)?r.slice(0,-1):r)})}async function k(e,i,a){const t=o(i,0,"skill name");await e.runSkill(t,i.positionals.slice(1),a,void 0,R(i))}async function $(e,i,a){if(e.session===void 0){a.write("No active session.");return}const t=i.positionals.join(" ").trim();e.session=await e.runtime.sessionStore.rename(e.session.id,t),a.write(`Renamed session: ${e.session.name}`)}async function I(e,i,a){if(i.action.id==="goal.start.tui"){await e.runGoal(i.positionals.join(" "),a,b(i.options));return}if(e.session===void 0){a.write("No active session.");return}if(i.action.id==="goal.status.tui"){const t=await e.runtime.goalStore.get(e.session.id);a.write(t===void 0?"No active goal.":A(t));return}if(i.action.id==="goal.pause.tui"){e.activeAbortController?.abort();const t=await e.runtime.goalStore.get(e.session.id);t?.status==="active"&&await e.runtime.goalStore.pause(e.session.id),a.write(t?.status==="paused"?"Goal already paused.":"Goal paused.");return}if(i.action.id==="goal.resume.tui"){await e.resumeGoal(a);return}e.activeAbortController?.abort(),await e.runtime.goalStore.clear(e.session.id),a.write("Goal cleared.")}async function j(e,i,a){const t=i.action.id;if(t==="attachments.paste"){const r=await g(e.runtime.platform).readImage();await e.attachClipboardImage(r),a.write(r===void 0?"Clipboard does not contain an image.":"Attachment added from clipboard.");return}if(t==="attachments.remove"){const r=o(i,0,"attachment id");e.pendingAttachments.remove(r)?(e.renderer.setPendingAttachments(e.pendingAttachments.list().map(({attachment:n})=>n)),a.write(`Removed attachment: ${r}`)):a.write(`Attachment not found: ${r}`);return}a.write(y(e.pendingAttachments.list().map(({attachment:r})=>({name:r.name,status:r.mimeType,detail:`${r.sizeBytes} bytes`})),{empty:"No pending attachments."}))}function o(e,i,a){const t=e.positionals[i];if(t===void 0)throw new Error(`Missing ${a}.`);return t}function R(e){const i=e.options.get("scope");return i==="user"||i==="project"?i:void 0}export{V as executeTuiCommand};
@@ -1,5 +1,8 @@
1
1
  import type { SessionStore as AgentSessionStore } from '@lotagate/agent-sdk';
2
2
  import type { LotaGate } from '@lotagate/sdk';
3
3
  import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
4
- export declare function createTuiContextManagement(client: LotaGate, model: string, contextWindow: number | undefined, onSummaryFailure: (error: unknown) => void): import("@lotagate/agent-sdk").ContextManagementOptions;
4
+ import type { AgentRunSnapshot } from '../../application/agent/agent-run-tracker.js';
5
+ import { type ContinuationGoal } from '../../application/agent/continuation-checkpoint.js';
6
+ export declare function createTuiContextManagement(client: LotaGate, model: string, contextWindow: number | undefined, onSummaryFailure: (error: unknown) => void, continuationContext?: () => string | undefined): import("@lotagate/agent-sdk").ContextManagementOptions;
7
+ export declare function createTuiContinuationContext(snapshot: AgentRunSnapshot, goal?: ContinuationGoal): string;
5
8
  export declare function compactTuiSession(runtime: CliRuntime, agentSessions: AgentSessionStore, sessionId: string, client: LotaGate, model: string, contextWindow?: number, onSummaryFailure?: (error: unknown) => void): Promise<boolean>;
@@ -1 +1 @@
1
- import{createContextManagement as u,redactCompactionSummary as p}from"../../application/agent/context-compaction.js";import{retainLatestCompaction as f,toAgentMessage as g}from"../../application/agent/agent-session-store.js";import{buildAgentHistory as d}from"../../application/agent/agent-history.js";import{compactSessionMessages as y}from"../../application/session/session-compaction-service.js";function x(e,a,t,s){return u({client:e,model:a,...t===void 0?{}:{contextWindow:t},onSummaryFailure:s})}async function A(e,a,t,s,n,i,m){const o=await a.get(t),c=o?.messages??await l(e,t),r=await y(c,s,n,i,m);return r.summary===void 0?!1:(o!==void 0&&await a.update(t,{messages:r.messages,status:"completed"}),await e.sessionStore.compact(t,p(r.summary)),!0)}async function l(e,a){const t=await e.sessionStore.readHistory(a);return f(d(t.transcript,t.events)).map(g)}export{A as compactTuiSession,x as createTuiContextManagement};
1
+ import{createContextManagement as c,redactCompactionSummary as f}from"../../application/agent/context-compaction.js";import{retainLatestCompaction as p,toAgentMessage as d}from"../../application/agent/agent-session-store.js";import{buildAgentHistory as g}from"../../application/agent/agent-history.js";import{compactSessionMessages as y}from"../../application/session/session-compaction-service.js";import{formatContinuationCheckpoint as C}from"../../application/agent/continuation-checkpoint.js";function T(a,e,t,r,n){return c({client:a,model:e,...t===void 0?{}:{contextWindow:t},onSummaryFailure:r,...n===void 0?{}:{continuationContext:n}})}function h(a,e){return C({snapshot:a,...e===void 0?{}:{goal:e}})}async function H(a,e,t,r,n,i,m){const s=await e.get(t),u=s?.messages??await w(a,t),o=await y(u,r,n,i,m);return o.summary===void 0?!1:(s!==void 0&&await e.update(t,{messages:o.messages,status:"completed"}),await a.sessionStore.compact(t,f(o.summary)),!0)}async function w(a,e){const t=await a.sessionStore.readHistory(e);return p(g(t.transcript,t.events)).map(d)}export{H as compactTuiSession,T as createTuiContextManagement,h as createTuiContinuationContext};
@@ -1,34 +1,2 @@
1
- import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
2
- import type { SkillManifest } from '../../domain/extensions/skill-manifest.js';
3
- import { type CliMcpConfig } from '../../domain/extensions/mcp-config.js';
4
- import type { SkillRootScope } from '../../infrastructure/extensions/skill-roots.js';
5
- import type { TuiContextSnapshot } from './context-display.js';
6
- import type { SessionStore as AgentSessionStore } from '@lotagate/agent-sdk';
7
- import type { AgentGoalSummary } from '../../application/agent/capability-profile.js';
8
- export interface TuiContextServiceInput {
9
- sessionId?: string;
10
- model: string | null;
11
- profileName?: string | null;
12
- trusted: boolean;
13
- skills: readonly (SkillManifest & {
14
- enabled: boolean;
15
- })[];
16
- pluginNames: readonly string[];
17
- pluginMcpConfig?: CliMcpConfig;
18
- pendingAttachments: number;
19
- skillRootScopes?: readonly SkillRootScope[];
20
- agentSessionStore?: AgentSessionStore;
21
- goal?: AgentGoalSummary;
22
- }
23
- /** Builds the human-readable context model from durable session data and CLI-owned metadata. */
24
- export declare class TuiContextService {
25
- private readonly runtime;
26
- private readonly cwd;
27
- private contextWindow;
28
- private contextWindowModel;
29
- constructor(runtime: CliRuntime, cwd: string);
30
- buildForProject(input: Omit<TuiContextServiceInput, 'trusted' | 'skills'>): Promise<TuiContextSnapshot>;
31
- build(input: TuiContextServiceInput): Promise<TuiContextSnapshot>;
32
- getModelContextWindow(model: string | null, profileName?: string | null): Promise<number | undefined>;
33
- private resolveContextWindow;
34
- }
1
+ export { ContextUsageService as TuiContextService } from '../../application/agent/context-usage-service.js';
2
+ export type { ContextUsageServiceInput as TuiContextServiceInput, ContextUsageSnapshot as TuiContextSnapshot } from '../../application/agent/context-usage-service.js';
@@ -1,2 +1 @@
1
- import C from"node:path";import{resolveModelContextWindow as M}from"../../application/model/model-context-window.js";import{buildToolCatalogFromDefinitions as W}from"../../application/agent/tool-catalog.js";import{filesystemToolDefinitions as k}from"../../infrastructure/filesystem/local-filesystem-tool-executor.js";import{shellToolDefinitions as b}from"../../infrastructure/shell/shell-tool-executor.js";import{skillToolDefinitions as S}from"../../infrastructure/extensions/skill-tool-executor.js";import{subagentToolDefinitions as j}from"../../application/orchestration/subagent-tool-executor.js";import{FileMcpConfigStore as w}from"../../infrastructure/extensions/file-mcp-config-store.js";import{mergeMcpConfigsWithOverride as D}from"../../domain/extensions/mcp-config.js";import{SkillManager as A}from"../../infrastructure/extensions/skill-manager.js";import{estimateTextTokens as x}from"../../infrastructure/tokens/tiktoken-token-estimator.js";import{retainLatestCompaction as P}from"../../application/agent/agent-session-store.js";import{buildAgentHistory as F}from"../../application/agent/agent-history.js";import{createAgentGuidance as I}from"../../application/agent/interactive-agent-guidance.js";class X{runtime;cwd;contextWindow;contextWindowModel;constructor(t,o){this.runtime=t,this.cwd=o}async buildForProject(t){const o=await this.runtime.projectTrust.inspect(this.cwd),n=await this.runtime.projectTrust.isTrusted(o),l=n&&t.skillRootScopes!==void 0?await new A(C.join(this.runtime.paths.globalConfigDir,"skills-state.json")).listScoped(t.skillRootScopes):[];return this.build({...t,trusted:n,skills:l})}async build(t){const o=await this.resolveContextWindow(t.model,t.profileName),[n,l]=await Promise.all([t.sessionId===void 0?Promise.resolve({transcript:[],events:[]}):this.runtime.sessionStore.readHistory(t.sessionId),Promise.all([w.forScope(this.cwd,this.runtime.paths.globalConfigDir,"user").list(),w.forScope(this.cwd,this.runtime.paths.globalConfigDir,"project").list()]).then(([e,v])=>D(e,v,t.pluginMcpConfig??{}))]),i=P(F(n.transcript,n.events)),y=(t.trusted?W([...k(),...b(),...S(),...j()]):void 0)?.names??[],r=t.model??"o200k_base",c=t.sessionId===void 0?void 0:await t.agentSessionStore?.get(t.sessionId),a=c?.messages?.[0]?.role==="system"?c.messages.slice(1):c?.messages,d=a===void 0||a.length===0?i:a.map($),f=m(d.filter(e=>e.type==="user"),r),u=m(d.filter(e=>e.type==="assistant"),r),p=m(d.filter(e=>e.type!=="user"&&e.type!=="assistant"),r),h=f+u+p,T=I(t.trusted?"interactive-trusted":"interactive-untrusted"),g=x({model:r,text:T});return{model:t.model,...o===void 0?{}:{contextWindow:o},usedTokens:h+g,systemPromptTokens:g,conversationTokens:h,inputTokens:f,outputTokens:u,otherTokens:p,transcriptEntries:i.length,userMessages:i.filter(e=>e.type==="user").length,assistantMessages:i.filter(e=>e.type==="assistant").length,toolCalls:n.events.filter(e=>e.type==="tool.called").length,compactions:n.events.filter(e=>e.type==="context.compacted").length,pendingAttachments:t.pendingAttachments,toolNames:y,mcpServers:Object.values(l).filter(e=>e.enabled).length,memoryFiles:0}}async getModelContextWindow(t,o){return this.resolveContextWindow(t,o)}async resolveContextWindow(t,o){if(t===null||t.trim().length===0){this.contextWindow=void 0,this.contextWindowModel=void 0;return}const n=`${o??""}\0${t}`;return this.contextWindowModel===n?this.contextWindow:(this.contextWindowModel=n,this.contextWindow=void 0,this.contextWindow=await M(this.runtime,t,o),this.contextWindow)}}function $(s){return{type:s.role,content:E(s.content)}}function E(s){return typeof s=="string"?s:Array.isArray(s)?s.map(t=>typeof t=="object"&&t!==null&&"text"in t&&typeof t.text=="string"?t.text:"").join(""):""}function m(s,t){return x({model:t,text:s.map(o=>`${o.type}: ${o.content}`).join(`
2
- `)})}export{X as TuiContextService};
1
+ import{ContextUsageService as o}from"../../application/agent/context-usage-service.js";export{o as TuiContextService};
@@ -1 +1 @@
1
- import{AuthenticationService as i}from"../../application/auth/authentication-service.js";import{CachedModelCatalog as n,modelCatalogCacheKey as c}from"../../application/model/cached-model-catalog.js";import{ModelCatalogAdapter as d}from"../../infrastructure/sdk/model-catalog-adapter.js";import{createLotaGateClient as s}from"../../infrastructure/sdk/lotagate-client-factory.js";import{selectInitialModel as m}from"../../application/model/initial-model-selection.js";async function w(l,t){if(t.model!==null&&t.model.trim().length>0)return t.model;const r=t.profile??i.defaultProfileName();let o;try{o=await l.credentialStore.get(r)}catch(e){return l.logger.warn("Unable to load credentials while selecting the initial model.",{reason:e instanceof Error?e.message:String(e)}),null}if(o===void 0)return null;try{const e=new n(new d(s(o.profile,o.apiKey)),l.cache,c(o.profile.name,o.profile.baseUrl),l.cachePolicy.modelCatalogTtlMs);return await m(t.model,{list:()=>e.listModels()},a=>l.configLoader.setGlobal("model",a))}catch(e){return l.logger.warn("Unable to select the first model from the catalog.",{reason:e instanceof Error?e.message:String(e)}),null}}export{w as resolveInitialModel};
1
+ import{AuthenticationService as i}from"../../application/auth/authentication-service.js";import{CachedModelCatalog as n,modelCatalogCacheKey as c}from"../../application/model/cached-model-catalog.js";import{ModelCatalogAdapter as d}from"../../infrastructure/sdk/model-catalog-adapter.js";import{createLotaGateClient as s}from"../../infrastructure/sdk/lotagate-client-factory.js";import{selectInitialModel as m}from"../../application/model/initial-model-selection.js";async function u(l,t){if(t.model!==null&&t.model.trim().length>0)return t.model;const r=t.profile??i.defaultProfileName();let o;try{o=await l.credentialStore.get(r)}catch(e){return l.logger.warn("Unable to load credentials while selecting the initial model.",{reason:e instanceof Error?e.message:String(e)}),null}if(o===void 0)return null;try{const e=new n(new d(s(o.profile,o.apiKey)),l.cache,c(o.profile.name,o.profile.baseUrl),l.cachePolicy.modelCatalogTtlMs,l.modelCatalogInFlight);return await m(t.model,{list:()=>e.listModels()},a=>l.configLoader.setGlobal("model",a))}catch(e){return l.logger.warn("Unable to select the first model from the catalog.",{reason:e instanceof Error?e.message:String(e)}),null}}export{u as resolveInitialModel};
@@ -14,7 +14,7 @@ export interface TuiToolApprovalHost {
14
14
  export declare class TuiToolApprovalCoordinator {
15
15
  private readonly host;
16
16
  constructor(host: TuiToolApprovalHost);
17
- ask(request: ToolApprovalRequest): Promise<boolean>;
17
+ ask(request: ToolApprovalRequest, signal?: AbortSignal): Promise<boolean>;
18
18
  create(mode: CliApprovalMode, trustedProject: boolean, workspaceRoot: string, skillScopes?: SkillScopeStore, workspacePermissions?: WorkspacePermissionPolicy): ToolApprovalService;
19
19
  remember(workspaceRoot: string, request: ToolApprovalRequest): Promise<void>;
20
20
  audit(decision: ToolApprovalDecision): Promise<void>;
@@ -1 +1 @@
1
- import{ToolApprovalService as m}from"../../application/security/tool-approval-service.js";import{permissionRuleForRequest as p}from"../../application/security/workspace-permission-policy.js";import{formatShellCommandForDisplay as u,formatToolActivityName as h}from"../../application/agent/tool-display.js";class N{host;constructor(e){this.host=e}async ask(e){this.host.renderer.status("Waiting for approval");try{return await this.host.renderer.confirmTool(e.toolName,c(e))}finally{const o=this.host.getActiveSignal();o!==void 0&&!o.aborted&&this.host.renderer.status("Thinking")}}create(e,o,a,n,i){return new m({mode:e,trustedProject:o,...n===void 0?{}:{skillScopes:n},...i===void 0?{}:{workspacePermissions:i},prompt:r=>this.ask(r),...o?{rememberApproval:r=>this.remember(a,r)}:{},...o?{onRememberApprovalFailure:(r,l)=>this.rememberFailure(l)}:{},audit:r=>this.audit(r)})}async remember(e,o){await this.host.runtime.workspaceSettings.rememberAllow(e,p(o.toolName,o.input))}async audit(e){this.host.runtime.logger.info("Tool authorization decision.",{toolName:e.toolName,decision:e.decision,reason:e.reason,...e.source===void 0?{}:{source:e.source},...e.skillName===void 0?{}:{skillName:e.skillName}});const o=this.host.getSessionId();o!==void 0&&await this.host.runtime.sessionStore.appendEvent({type:"tool.approval",timestamp:new Date().toISOString(),sessionId:o,data:{toolName:e.toolName,...e.source===void 0?{}:{source:e.source},...e.skillName===void 0?{}:{skillName:e.skillName},decision:e.decision,reason:e.reason}})}rememberFailure(e){this.host.runtime.logger.warn("Unable to persist tool approval.",{reason:e instanceof Error?e.message:String(e)}),this.host.renderer.notice("Approval accepted for this action, but could not be remembered.")}}function c(t){if(t.toolName==="filesystem.write")return`Write workspace file: ${f(t.input.path)}`;if(t.toolName==="shell.exec"){const e=typeof t.input.command=="string"?t.input.command:"",o=Array.isArray(t.input.args)?t.input.args.filter(a=>typeof a=="string"):[];return s(`Run command: ${u(e,o,240)}`)}return`This ${h(t.toolName)} operation may change workspace or external state.`}function f(t){const e=typeof t=="string"?t:String(t??"");return s(e.replace(/Bearer\s+[^\s]+/giu,"Bearer [REDACTED]").replace(/sk-[A-Za-z0-9_-]{8,}/gu,"[REDACTED]"))}function s(t){return t.length<=240?t:`${t.slice(0,237)}...`}export{N as TuiToolApprovalCoordinator};
1
+ import{ToolApprovalService as f}from"../../application/security/tool-approval-service.js";import{permissionRuleForRequest as h}from"../../application/security/workspace-permission-policy.js";import{formatShellCommandForDisplay as c,formatToolActivityName as g}from"../../application/agent/tool-display.js";class k{host;constructor(e){this.host=e}async ask(e,r){this.host.renderer.status("Waiting for approval");try{const o=this.host.renderer.confirmTool(e.toolName,y(e));return r===void 0?await o:r.aborted?(this.host.renderer.resolveActiveModal(void 0),!1):await I(o,r,this.host.renderer)}finally{const o=this.host.getActiveSignal();o!==void 0&&!o.aborted&&this.host.renderer.status("Thinking")}}create(e,r,o,s,a){return new f({mode:e,trustedProject:r,...s===void 0?{}:{skillScopes:s},...a===void 0?{}:{workspacePermissions:a},prompt:n=>this.ask(n),...r?{rememberApproval:n=>this.remember(o,n)}:{},...r?{onRememberApprovalFailure:(n,i)=>this.rememberFailure(i)}:{},audit:n=>this.audit(n)})}async remember(e,r){await this.host.runtime.workspaceSettings.rememberAllow(e,h(r.toolName,r.input))}async audit(e){this.host.runtime.logger.info("Tool authorization decision.",{toolName:e.toolName,stage:e.stage,sessionId:e.sessionId,runId:e.runId,decision:e.decision,reason:e.reason,...e.source===void 0?{}:{source:e.source},...e.executorId===void 0?{}:{executorId:e.executorId},...e.ruleId===void 0?{}:{ruleId:e.ruleId},...e.skillName===void 0?{}:{skillName:e.skillName},...e.riskCategory===void 0?{}:{riskCategory:e.riskCategory}});const r=this.host.getSessionId();r!==void 0&&await this.host.runtime.sessionStore.appendEvent({type:"tool.approval",timestamp:new Date().toISOString(),sessionId:r,data:{toolName:e.toolName,stage:e.stage,sessionId:e.sessionId,runId:e.runId,...e.source===void 0?{}:{source:e.source},...e.executorId===void 0?{}:{executorId:e.executorId},...e.ruleId===void 0?{}:{ruleId:e.ruleId},...e.skillName===void 0?{}:{skillName:e.skillName},...e.riskCategory===void 0?{}:{riskCategory:e.riskCategory},decision:e.decision,reason:e.reason}})}rememberFailure(e){this.host.runtime.logger.warn("Unable to persist tool approval.",{reason:e instanceof Error?e.message:String(e)}),this.host.renderer.notice("Approval accepted for this action, but could not be remembered.")}}function I(t,e,r){return new Promise((o,s)=>{let a=!1;const n=()=>e.removeEventListener("abort",l),i=u=>{a||(a=!0,n(),o(u))},p=u=>{a||(a=!0,n(),s(u))},l=()=>{r.resolveActiveModal(void 0),i(!1)};e.aborted?l():e.addEventListener("abort",l,{once:!0}),t.then(i,p)})}function y(t){if(t.toolName==="filesystem.write")return`Write workspace file: ${m(t.input.path)}`;if(t.toolName==="shell.exec"){const e=typeof t.input.command=="string"?t.input.command:"",r=Array.isArray(t.input.args)?t.input.args.filter(s=>typeof s=="string"):[],o=typeof t.input.script=="string"?m(t.input.script):void 0;return d(`Run command: ${c(e,o===void 0?r:[...r,"-Command",o],240)}`)}return`This ${g(t.toolName)} operation may change workspace or external state.`}function m(t){const e=typeof t=="string"?t:String(t??"");return d(e.replace(/Bearer\s+[^\s]+/giu,"Bearer [REDACTED]").replace(/sk-[A-Za-z0-9_-]{8,}/gu,"[REDACTED]"))}function d(t){return t.length<=240?t:`${t.slice(0,237)}...`}export{k as TuiToolApprovalCoordinator};
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "0.1.25";
1
+ export declare const CLI_VERSION = "0.1.27";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- const o="0.1.25";export{o as CLI_VERSION};
1
+ const o="0.1.27";export{o as CLI_VERSION};
@@ -29,7 +29,7 @@ function target(id, platforms, arch, libc) {
29
29
  platforms: Object.freeze(platforms),
30
30
  arch,
31
31
  packageName: `@lotagate/cli-native-${id}`,
32
- binaryName: 'lotagate.exe',
32
+ binaryName: platforms.includes('win32') || platforms.includes('cygwin') ? 'lotagate.exe' : 'lotagate',
33
33
  libc,
34
34
  });
35
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotagate/cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Enterprise-grade terminal client for LotaGate AI agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,11 +26,10 @@
26
26
  },
27
27
  "packageManager": "npm@11.8.0",
28
28
  "bin": {
29
- "lotagate": "./bin/lotagate.exe"
29
+ "lotagate": "./bin/lotagate.mjs"
30
30
  },
31
31
  "sideEffects": false,
32
32
  "files": [
33
- "bin/lotagate.exe",
34
33
  "bin/lotagate.mjs",
35
34
  "dist",
36
35
  "scripts/install-native.mjs",
@@ -65,19 +64,19 @@
65
64
  "prepack": "npm run build"
66
65
  },
67
66
  "dependencies": {
68
- "@lotagate/agent-sdk": "^0.1.7",
67
+ "@lotagate/agent-sdk": "^0.1.9",
69
68
  "@lotagate/sdk": "^0.1.3",
70
69
  "ink": "^7.1.1",
71
70
  "react": "^19.2.4",
72
71
  "tiktoken": "^1.0.22"
73
72
  },
74
73
  "optionalDependencies": {
75
- "@lotagate/cli-native-linux-arm64-gnu": "0.1.25",
76
- "@lotagate/cli-native-linux-x64-gnu": "0.1.25",
77
- "@lotagate/cli-native-macos-arm64": "0.1.25",
78
- "@lotagate/cli-native-macos-x64": "0.1.25",
79
- "@lotagate/cli-native-windows-arm64": "0.1.25",
80
- "@lotagate/cli-native-windows-x64": "0.1.25"
74
+ "@lotagate/cli-native-linux-arm64-gnu": "0.1.27",
75
+ "@lotagate/cli-native-linux-x64-gnu": "0.1.27",
76
+ "@lotagate/cli-native-macos-arm64": "0.1.27",
77
+ "@lotagate/cli-native-macos-x64": "0.1.27",
78
+ "@lotagate/cli-native-windows-arm64": "0.1.27",
79
+ "@lotagate/cli-native-windows-x64": "0.1.27"
81
80
  },
82
81
  "devDependencies": {
83
82
  "@eslint/js": "9.39.5",
@@ -10,8 +10,11 @@ const target = targetForRuntime(process.platform, process.arch);
10
10
 
11
11
  if (existsSync(resolve(packageRoot, '.git'))) process.exit(0);
12
12
 
13
- if (target === undefined) await installNodeFallback();
14
- else await installNativeTarget(target);
13
+ if (target === undefined) {
14
+ if (process.platform === 'win32' || process.platform === 'cygwin') fail(`No native LotaGate CLI artifact is available for ${process.platform}/${process.arch}.`);
15
+ } else {
16
+ await installNativeTarget(target);
17
+ }
15
18
 
16
19
  function findInstalledNativePackageRoot(packageName) {
17
20
  const segments = packageName.split('/');
@@ -45,17 +48,6 @@ async function installNativeTarget(nativeTarget) {
45
48
  }
46
49
  }
47
50
 
48
- async function installNodeFallback() {
49
- if (process.platform === 'win32' || process.platform === 'cygwin') fail(`No native LotaGate CLI artifact is available for ${process.platform}/${process.arch}.`);
50
- const destination = resolve(packageRoot, 'bin', 'lotagate.exe');
51
- try {
52
- await installExecutable(resolve(packageRoot, 'bin', 'lotagate.mjs'), destination);
53
- } catch (error) {
54
- await rm(destination, { force: true }).catch(() => undefined);
55
- fail(`Node launcher installation failed: ${error instanceof Error ? error.message : String(error)}`);
56
- }
57
- }
58
-
59
51
  async function installExecutable(source, destination) {
60
52
  const temporary = `${destination}.install-${process.pid}-${Date.now()}`;
61
53
  await mkdir(dirname(destination), { recursive: true });
package/bin/lotagate.exe DELETED
@@ -1 +0,0 @@
1
- Native executable installation did not complete. Reinstall @lotagate/cli without --ignore-scripts or --omit=optional.
@@ -1,4 +0,0 @@
1
- import type { ToolDefinition } from '@lotagate/sdk';
2
- export declare const DOCUMENT_FORMATS: readonly ["pdf", "pptx", "excel", "docs"];
3
- export type DocumentFormat = typeof DOCUMENT_FORMATS[number];
4
- export declare const DOCUMENT_TOOL_DEFINITIONS: readonly ToolDefinition[];