@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,2 +1,2 @@
1
- import{once as E}from"node:events";import{RESOURCE_LIMITS as u}from"../../domain/runtime/resource-limits.js";const y=1;class v{executor;options;constructor(e,n={}){this.executor=e,this.options=n}async run(e,n){const r=new Map,o=new Set,l=this.options.maxLineBytes??u.jsonlLineBytes,d=this.options.maxInFlight??u.jsonlMaxInFlight;let s=0;try{for await(const a of R(e,l)){if(Buffer.byteLength(a,"utf8")>l){s+=1,await c(n,p("unknown",m("JSONL_REQUEST_TOO_LARGE","Request line exceeds the maximum size.")));continue}let i;try{i=O(JSON.parse(a))}catch(L){s+=1,await c(n,p("unknown",w(L)));continue}if(i.method==="cancel"){r.get(i.params.requestId)?.abort();continue}if(r.has(i.id)){s+=1,await c(n,p(i.id,m("JSONL_DUPLICATE_REQUEST","Request id is already in flight.")));continue}if(o.size>=d){s+=1,await c(n,p(i.id,m("JSONL_OVERLOADED","Too many in-flight requests.",!0)));continue}const f=new AbortController;r.set(i.id,f);const g=this.executeOne(i,f.signal,n).then(L=>{L||(s+=1)}).finally(()=>{r.delete(i.id),o.delete(g)});o.add(g)}await Promise.allSettled(o)}catch(a){if(!(a instanceof x))throw a;s+=1,await c(n,p("unknown",w(a)))}finally{for(const a of r.values())a.abort();await Promise.allSettled([...o])}return{errorCount:s}}async executeOne(e,n,r){try{await c(r,{version:y,id:e.id,type:"started"});for await(const o of this.executor(e,n))o.type==="event"?await c(r,{version:y,id:e.id,type:"event",event:o.event,...o.data===void 0?{}:{data:o.data}}):await c(r,{version:y,id:e.id,type:o.type,content:o.content});return!0}catch(o){return await c(r,p(e.id,w(o))),!1}}}function O(t){if(typeof t!="object"||t===null)throw h("Request must be an object.");const e=t;if(e.version!==1||typeof e.id!="string"||e.id.length===0||Buffer.byteLength(e.id,"utf8")>u.jsonlIdBytes||typeof e.method!="string"||typeof e.params!="object"||e.params===null)throw h("Invalid JSONL request envelope.");if(e.method==="cancel"){const r=e.params;if(typeof r.requestId!="string"||r.requestId.length===0||Buffer.byteLength(r.requestId,"utf8")>u.jsonlIdBytes)throw h("Invalid cancel request.");return{version:y,id:e.id,method:"cancel",params:{requestId:r.requestId}}}if(e.method!=="exec")throw h("Unsupported JSONL method.");const n=e.params;if(typeof n.prompt!="string"||n.prompt.trim().length===0||Buffer.byteLength(n.prompt,"utf8")>u.jsonlPromptBytes||n.model!==void 0&&(typeof n.model!="string"||Buffer.byteLength(n.model,"utf8")>u.jsonlIdBytes))throw h("Invalid exec params.");return{version:y,id:e.id,method:"exec",params:{prompt:n.prompt,...n.model===void 0?{}:{model:n.model}}}}async function c(t,e){t.write(`${JSON.stringify(e)}
2
- `)||await E(t,"drain")}function p(t,e){return{version:y,id:t,type:"error",error:e}}function h(t){return new b(m("JSONL_INVALID_REQUEST",t))}function m(t,e,n=!1){return{code:t,category:"protocol",message:e,retryable:n}}function w(t){return t instanceof b?t.payload:I(t)?{code:t.code,category:t.category,message:t.userMessage,retryable:t.retryable}:m("CLI_INTERNAL_ERROR","The request could not be completed. Retry the request or inspect CLI diagnostics.",!0)}function I(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.code=="string"&&typeof e.category=="string"&&typeof e.userMessage=="string"&&typeof e.retryable=="boolean"}class b extends Error{payload;constructor(e){super(e.message),this.payload=e}}class x extends b{constructor(e){super(m("JSONL_REQUEST_TOO_LARGE",e))}}async function*R(t,e){let n=[],r=0;for await(const o of t){const l=Buffer.isBuffer(o)?o:Buffer.from(o);let d=0;for(;d<l.byteLength;){const s=l.indexOf(10,d),a=s<0?l.byteLength:s,i=l.subarray(d,a);if(r+i.byteLength>e)throw new x("Request line exceeds the maximum size.");if(i.byteLength>0&&n.push(i),r+=i.byteLength,s<0)break;const f=Buffer.concat(n,r);yield(f[f.byteLength-1]===13?f.subarray(0,f.byteLength-1):f).toString("utf8"),n=[],r=0,d=s+1}}r>0&&(yield Buffer.concat(n,r).toString("utf8"))}export{y as JSONL_PROTOCOL_VERSION,v as JsonlProtocolRunner,R as readLinesBounded};
1
+ import{RESOURCE_LIMITS as y}from"../../domain/runtime/resource-limits.js";import{waitForWritableDrain as I}from"./json-line-writer.js";const m=1;class J{executor;options;constructor(e,n={}){this.executor=e,this.options=n}async run(e,n,r){const o=new Map,i=new Set,l=this.options.maxLineBytes??y.jsonlLineBytes,u=this.options.maxInFlight??y.jsonlMaxInFlight;let c=0;const d=()=>{for(const s of o.values())s.abort(r?.reason);e.destroy()};r?.addEventListener("abort",d,{once:!0});try{for await(const s of v(e,l)){if(Buffer.byteLength(s,"utf8")>l){c+=1,await f(n,p("unknown",h("JSONL_REQUEST_TOO_LARGE","Request line exceeds the maximum size.")));continue}let a;try{a=R(JSON.parse(s))}catch(L){c+=1,await f(n,p("unknown",w(L)));continue}if(a.method==="cancel"){o.get(a.params.requestId)?.abort();continue}if(o.has(a.id)){c+=1,await f(n,p(a.id,h("JSONL_DUPLICATE_REQUEST","Request id is already in flight.")));continue}if(i.size>=u){c+=1,await f(n,p(a.id,h("JSONL_OVERLOADED","Too many in-flight requests.",!0)));continue}const E=new AbortController;o.set(a.id,E);const x=this.executeOne(a,E.signal,n).then(L=>{L||(c+=1)}).finally(()=>{o.delete(a.id),i.delete(x)});i.add(x)}await Promise.allSettled(i)}catch(s){if(!(s instanceof O))throw s;c+=1,await f(n,p("unknown",w(s)))}finally{r?.removeEventListener("abort",d);for(const s of o.values())s.abort();await Promise.allSettled([...i])}return{errorCount:c}}async executeOne(e,n,r){try{await f(r,{version:m,id:e.id,type:"started"});for await(const o of this.executor(e,n))o.type==="event"?await f(r,{version:m,id:e.id,type:"event",event:o.event,...o.data===void 0?{}:{data:o.data}}):await f(r,{version:m,id:e.id,type:o.type,content:o.content});return!0}catch(o){return await f(r,p(e.id,w(o))),!1}}}function R(t){if(typeof t!="object"||t===null)throw g("Request must be an object.");const e=t;if(e.version!==1||typeof e.id!="string"||e.id.length===0||Buffer.byteLength(e.id,"utf8")>y.jsonlIdBytes||typeof e.method!="string"||typeof e.params!="object"||e.params===null)throw g("Invalid JSONL request envelope.");if(e.method==="cancel"){const r=e.params;if(typeof r.requestId!="string"||r.requestId.length===0||Buffer.byteLength(r.requestId,"utf8")>y.jsonlIdBytes)throw g("Invalid cancel request.");return{version:m,id:e.id,method:"cancel",params:{requestId:r.requestId}}}if(e.method!=="exec")throw g("Unsupported JSONL method.");const n=e.params;if(typeof n.prompt!="string"||n.prompt.trim().length===0||Buffer.byteLength(n.prompt,"utf8")>y.jsonlPromptBytes||n.model!==void 0&&(typeof n.model!="string"||Buffer.byteLength(n.model,"utf8")>y.jsonlIdBytes))throw g("Invalid exec params.");return{version:m,id:e.id,method:"exec",params:{prompt:n.prompt,...n.model===void 0?{}:{model:n.model}}}}async function f(t,e){t.write(`${JSON.stringify(e)}
2
+ `)||await I(t)}function p(t,e){return{version:m,id:t,type:"error",error:e}}function g(t){return new b(h("JSONL_INVALID_REQUEST",t))}function h(t,e,n=!1){return{code:t,category:"protocol",message:e,retryable:n}}function w(t){return t instanceof b?t.payload:S(t)?{code:t.code,category:t.category,message:t.userMessage,retryable:t.retryable}:h("CLI_INTERNAL_ERROR","The request could not be completed. Retry the request or inspect CLI diagnostics.",!0)}function S(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.code=="string"&&typeof e.category=="string"&&typeof e.userMessage=="string"&&typeof e.retryable=="boolean"}class b extends Error{payload;constructor(e){super(e.message),this.payload=e}}class O extends b{constructor(e){super(h("JSONL_REQUEST_TOO_LARGE",e))}}async function*v(t,e){let n=[],r=0;for await(const o of t){const i=Buffer.isBuffer(o)?o:Buffer.from(o);let l=0;for(;l<i.byteLength;){const u=i.indexOf(10,l),c=u<0?i.byteLength:u,d=i.subarray(l,c);if(r+d.byteLength>e)throw new O("Request line exceeds the maximum size.");if(d.byteLength>0&&n.push(d),r+=d.byteLength,u<0)break;const s=Buffer.concat(n,r);yield(s[s.byteLength-1]===13?s.subarray(0,s.byteLength-1):s).toString("utf8"),n=[],r=0,l=u+1}}r>0&&(yield Buffer.concat(n,r).toString("utf8"))}export{m as JSONL_PROTOCOL_VERSION,J as JsonlProtocolRunner,v as readLinesBounded};
@@ -1 +1 @@
1
- import{isReadOnlyShellRequest as o}from"./tool-risk-classifier.js";async function x(e,r,n){for(const t of r)if(await u(t,e,n))return!0;return!1}async function u(e,r,n){const t=r.toolName;if(e===t)return!0;if(e==="filesystem.read")return t==="filesystem.read"||t==="filesystem.list"||t==="filesystem.exists";if(e==="filesystem.write")return t==="filesystem.write";if(t!=="shell.exec")return d(e,t)||m(e,t)||f(e,t);const a=l(r.input),i=w(r.input);if(a===void 0||i===void 0)return!1;if(e==="terminal.read")return await o(a,i,r.context,n,r.input.cwd);if(e==="terminal.execute")return!0;if(!p(a,i))return!1;const s=c(i);return e==="git.read"?s!==void 0&&b.has(s)&&await o(a,i,r.context,n,r.input.cwd):e==="git.stage"?s==="add":e==="git.commit"?s==="commit":e==="git.push"?s==="push":!1}function d(e,r){return r.startsWith("browser.")?e==="browser.navigate"?["browser.navigate","browser.back","browser.forward","browser.reload"].includes(r):e==="browser.inspect"?["browser.inspect","browser.inspectElement","browser.extractTable","browser.listFrames","browser.console","browser.network","browser.accessibility","browser.setViewport","browser.resetViewport","browser.screenshot","browser.tabs","browser.readField"].includes(r):e==="browser.interact"?!["browser.navigate","browser.inspect","browser.inspectElement","browser.extractTable","browser.listFrames","browser.console","browser.network","browser.accessibility","browser.setViewport","browser.resetViewport","browser.screenshot","browser.tabs","browser.readField"].includes(r):!1:!1}function m(e,r){return r.startsWith("computer.")?e==="computer.read"?["computer.listWindows","computer.inspect","computer.screenshot","computer.readText","computer.readSelection","computer.readGrid","computer.recognizeText","computer.listDisplays","computer.wait","computer.readClipboard","computer.waitForState"].includes(r):e==="computer.interact"?!["computer.listWindows","computer.inspect","computer.screenshot","computer.readText","computer.readSelection","computer.readGrid","computer.recognizeText","computer.listDisplays","computer.wait","computer.readClipboard","computer.waitForState","computer.launch"].includes(r):e==="computer.launch"?r==="computer.launch":!1:!1}function f(e,r){return/^(?:pdf|pptx|excel|docs)\./u.test(r)?e==="document.read"?/\.(?:open|inspect|validate|readText|readSlide|readRange|readContent|extractTables|recognizeText|search|extractImages|extractLinks|extractAnnotations|readForm|find|readFormulas|inspectStructure|manageRevisions)$/u.test(r):e==="document.write"?!/\.(?:open|inspect|validate|readText|readSlide|readRange|readContent|extractTables|recognizeText|search|extractImages|extractLinks|extractAnnotations|readForm|find|readFormulas|inspectStructure|manageRevisions)$/u.test(r):e===r:!1}function l(e){return typeof e.command=="string"?e.command.trim():void 0}function w(e){const r=e.args;return Array.isArray(r)&&r.every(n=>typeof n=="string")?r:void 0}function p(e,r){return(e.split(/[\\/]/u).at(-1)??"").replace(/\.(?:exe|cmd|bat)$/iu,"").toLowerCase()==="git"&&c(r)!==void 0}function c(e){return e.find(r=>!r.startsWith("-"))?.toLowerCase()}const b=new Set(["status","diff","log","show","branch","tag","remote","rev-parse","ls-files"]);export{x as matchesDesktopToolScope};
1
+ import{isReadOnlyShellRequest as u}from"./tool-risk-classifier.js";import{BROWSER_INSPECTION_TOOLS as f,BROWSER_NAVIGATION_TOOLS as m,COMPUTER_LAUNCH_TOOLS as c,READ_ONLY_COMPUTER_TOOLS as d,READ_ONLY_GIT_COMMANDS as h}from"./tool-policy-registry.js";async function C(t,r,n){for(const e of r)if(await l(e,t,n))return!0;return!1}async function l(t,r,n){const e=r.toolName;if(t===e)return!0;if(t==="filesystem.read")return e==="filesystem.read"||e==="filesystem.list"||e==="filesystem.exists";if(t==="filesystem.write")return e==="filesystem.write";if(e!=="shell.exec")return O(t,e)||w(t,e);const s=y(r.input),i=S(r.input);if(s===void 0||i===void 0)return!1;if(t==="terminal.read")return await u(s,i,r.context,n,r.input.cwd);if(t==="terminal.execute")return!0;if(!g(s,i))return!1;const a=o(i);return t==="git.read"?a!==void 0&&h.has(a)&&await u(s,i,r.context,n,r.input.cwd):t==="git.stage"?a==="add":t==="git.commit"?a==="commit":t==="git.push"?a==="push":!1}function O(t,r){return r.startsWith("browser.")?t==="browser.navigate"?m.has(r):t==="browser.inspect"?f.has(r):t==="browser.interact"?!m.has(r)&&!f.has(r):!1:!1}function w(t,r){return r.startsWith("computer.")?t==="computer.read"?d.has(r):t==="computer.interact"?!d.has(r)&&!c.has(r):t==="computer.launch"?c.has(r):!1:!1}function y(t){return typeof t.command=="string"?t.command.trim():void 0}function S(t){const r=t.args;return Array.isArray(r)&&r.every(n=>typeof n=="string")?r:void 0}function g(t,r){return(t.split(/[\\/]/u).at(-1)??"").replace(/\.(?:exe|cmd|bat)$/iu,"").toLowerCase()==="git"&&o(r)!==void 0}function o(t){return t.find(r=>!r.startsWith("-"))?.toLowerCase()}export{C as matchesDesktopToolScope};
@@ -1 +1 @@
1
- function f(e){const n=typeof e.input.path=="string"?e.input.path.trim():void 0;if(n!==void 0&&s(n))return{risk:"review",category:"sensitive-target",reason:"sensitive-target-review"};const t=o(e);if(t!==void 0){if(d.test(t))return{risk:"review",category:"download-and-execute",reason:"download-and-execute-review"};if(c.test(t))return{risk:"deny",category:"credential-exfiltration",reason:"credential-exfiltration-deny"}}if(a(e))return{risk:"review",category:"hidden-control-data",reason:"hidden-control-data-review"}}function o(e){if(e.toolName!=="shell.exec")return;const n=e.input.command,t=e.input.args;if(!(typeof n!="string"||!Array.isArray(t)||t.some(r=>typeof r!="string")))return[n,...t].join(" ")}function s(e){const n=e.replace(/\\/gu,"/").toLowerCase();return n===".env"||n.endsWith("/.env")||n.includes("/.git/config")||n.includes("/.git/credentials")||n.includes("/.lotagate/auth")||n.includes("/.lotagate/credentials")||n.includes("/.codex/auth")||n.includes("/.ssh/")||n.endsWith("/id_rsa")||n.endsWith("/id_ed25519")}function a(e){return i(e.input).some(n=>[...n].some(t=>u.has(t.codePointAt(0)??0)))}function i(e){return typeof e=="string"?[e]:Array.isArray(e)?e.flatMap(i):e!==null&&typeof e=="object"?Object.values(e).flatMap(i):[]}const d=/(?:curl|wget|invoke-webrequest|irm)\b[^\n|]*\|\s*(?:sh|bash|zsh|pwsh|powershell|cmd)\b|(?:powershell|pwsh)\b[^\n]*-(?:enc|encodedcommand)\b|\b(?:invoke-expression|iex)\b/iu,c=/(?:curl|wget|invoke-webrequest|irm)\b[^\n]*(?:api[_-]?key|token|secret|password|credential|\.env|process\.env|\$env:)/iu,u=new Set([1564,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8288,8289,8290,8291,8292,8294,8295,8297,8298,8299,8300,8301,8302,8303,65279]);export{f as assessToolAction};
1
+ function x(e){const n=typeof e.input.path=="string"?e.input.path.trim():void 0;if(n!==void 0&&a(n))return{risk:"review",category:"sensitive-target",reason:"sensitive-target-review"};const t=d(e);if(t!==void 0){if(f.test(t))return{risk:"review",category:"download-and-execute",reason:"download-and-execute-review"};if(u.test(t))return{risk:"deny",category:"credential-exfiltration",reason:"credential-exfiltration-deny"}}if(c(e))return{risk:"review",category:"hidden-control-data",reason:"hidden-control-data-review"}}function d(e){if(e.toolName!=="shell.exec")return;const n=e.input.command,t=e.input.args,i=e.input.script;if(typeof n!="string"||i!==void 0&&typeof i!="string")return;const r=t===void 0?[]:t;if(!(!Array.isArray(r)||r.some(s=>typeof s!="string")))return typeof i=="string"?[n,...r,"-Command",i].join(" "):[n,...r].join(" ")}function a(e){const n=e.replace(/\\/gu,"/").toLowerCase();return n===".env"||n.endsWith("/.env")||n.includes("/.git/config")||n.includes("/.git/credentials")||n.includes("/.lotagate/auth")||n.includes("/.lotagate/credentials")||n.includes("/.codex/auth")||n.includes("/.ssh/")||n.endsWith("/id_rsa")||n.endsWith("/id_ed25519")}function c(e){return o(e.input).some(n=>[...n].some(t=>l.has(t.codePointAt(0)??0)))}function o(e){return typeof e=="string"?[e]:Array.isArray(e)?e.flatMap(o):e!==null&&typeof e=="object"?Object.values(e).flatMap(o):[]}const f=/(?:curl|wget|invoke-webrequest|irm)\b[^\n|]*\|\s*(?:sh|bash|zsh|pwsh|powershell|cmd)\b|(?:powershell|pwsh)\b[^\n]*-(?:enc|encodedcommand)\b|\b(?:invoke-expression|iex)\b/iu,u=/(?:curl|wget|invoke-webrequest|irm)\b[^\n]*(?:api[_-]?key|token|secret|password|credential|\.env|process\.env|\$env:)/iu,l=new Set([1564,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8288,8289,8290,8291,8292,8294,8295,8297,8298,8299,8300,8301,8302,8303,65279]);export{x as assessToolAction};
@@ -1,4 +1,4 @@
1
- import type { ToolApprovalRequest, ToolPolicyOptions } from '@lotagate/agent-sdk';
1
+ import type { ToolApprovalRequest, ToolAuthorizationDecision, ToolAuthorizationEvent, ToolPolicyOptions } from '@lotagate/agent-sdk';
2
2
  import type { SkillScopeStore } from '../extensions/skill-scope-store.js';
3
3
  import type { WorkspacePermissionPolicy } from '../../domain/workspace/workspace-settings.js';
4
4
  import type { WorkspaceTargetResolver } from './tool-risk-classifier.js';
@@ -6,7 +6,7 @@ export type CliApprovalMode = 'ask' | 'auto' | 'deny' | 'review' | 'autonomous';
6
6
  export interface ToolApprovalServiceOptions {
7
7
  mode: CliApprovalMode;
8
8
  trustedProject: boolean;
9
- prompt?: (request: ToolApprovalRequest) => boolean | Promise<boolean>;
9
+ prompt?: (request: ToolApprovalRequest) => boolean | ToolAuthorizationDecision | Promise<boolean | ToolAuthorizationDecision>;
10
10
  rememberApproval?: (request: ToolApprovalRequest) => void | Promise<void>;
11
11
  onRememberApprovalFailure?: (request: ToolApprovalRequest, error: unknown) => void | Promise<void>;
12
12
  audit?: (decision: ToolApprovalDecision) => void | Promise<void>;
@@ -17,9 +17,14 @@ export interface ToolApprovalServiceOptions {
17
17
  }
18
18
  export interface ToolApprovalDecision {
19
19
  toolName: string;
20
+ stage: ToolAuthorizationEvent['stage'];
21
+ sessionId: string;
22
+ runId: string;
20
23
  source?: string;
21
- decision: 'allow' | 'deny';
24
+ executorId?: string;
25
+ decision: 'allow' | 'deny' | 'redirect';
22
26
  reason: string;
27
+ ruleId?: string;
23
28
  skillName?: string;
24
29
  riskCategory?: string;
25
30
  }
@@ -32,6 +37,7 @@ export declare class ToolApprovalService {
32
37
  private authorizeActionRisk;
33
38
  private authorizeSkill;
34
39
  private requestApproval;
40
+ private resolvePrompt;
35
41
  private rememberApproval;
36
42
  private observe;
37
43
  }
@@ -1 +1 @@
1
- import{requiresMutationApproval as t}from"./tool-risk-classifier.js";import{assessToolAction as a}from"./tool-action-risk-analyzer.js";import{workspacePermissionDecision as r}from"./workspace-permission-policy.js";import{matchesDesktopToolScope as n}from"./desktop-tool-scope-policy.js";class m{options;constructor(e){this.options=e}policy(){return{authorizationRules:[...this.options.desktopToolScopes===void 0?[]:[{id:"desktop-tool-scope",authorize:o=>this.authorizeDesktopScope(o)}],...this.options.skillScopes===void 0?[]:[{id:"cli-skill-scope",authorize:o=>this.authorizeSkill(o)}],{id:"cli-action-risk",authorize:o=>this.authorizeActionRisk(o)},{id:"cli-workspace-policy",authorize:o=>this.authorizeWorkspace(o)}],authorizationObserver:o=>this.observe(o),requireApproval:!1}}async authorizeDesktopScope(e){return await n(e,this.options.desktopToolScopes??[],this.options.resolveWorkspaceTarget)?{decision:"allow",reason:"desktop-tool-scope-allow"}:{decision:"deny",reason:"desktop-tool-scope-deny"}}async authorizeWorkspace(e){if(!this.options.trustedProject)return{decision:"deny",reason:"project-untrusted"};if(this.options.mode==="deny")return{decision:"deny",reason:"mode-deny"};const o=this.options.workspacePermissions===void 0?void 0:r(this.options.workspacePermissions,e.toolName,e.input);return o==="deny"?{decision:"deny",reason:"workspace-policy-deny"}:this.options.mode==="review"?this.requestApproval(e,"review-policy"):o==="allow"?{decision:"allow",reason:"workspace-policy-allow"}:o==="ask"?this.requestApproval(e,"workspace-policy-ask"):await t(e,this.options.resolveWorkspaceTarget)&&this.options.mode!=="autonomous"?this.requestApproval(e,"mutation-approval"):{decision:"allow",reason:this.options.mode==="auto"?"mode-auto":"read-only"}}async authorizeActionRisk(e){const o=a(e);return o===void 0?{decision:"allow",reason:"action-risk-clear"}:o.risk==="deny"?{decision:"deny",reason:o.reason,metadata:{riskCategory:o.category}}:await this.options.prompt?.(e)??!1?{decision:"allow",reason:`${o.reason}-allow`,metadata:{riskCategory:o.category}}:{decision:"deny",reason:`${o.reason}-deny`,metadata:{riskCategory:o.category}}}authorizeSkill(e){const o=this.options.skillScopes?.get(e.context.runId);return o===void 0||l(e.toolName)?{decision:"allow",reason:"skill-policy-not-active"}:o.allowedTools.includes(e.toolName)?{decision:"allow",reason:"skill-policy-allow",metadata:{skillName:o.skillName}}:{decision:"deny",reason:"skill-policy-deny",metadata:{skillName:o.skillName}}}async requestApproval(e,o){const i=await this.options.prompt?.(e)??!1;return i&&await this.rememberApproval(e),i?{decision:"allow",reason:`${o}-allow`}:{decision:"deny",reason:`${o}-deny`}}async rememberApproval(e){try{await this.options.rememberApproval?.(e)}catch(o){try{await this.options.onRememberApprovalFailure?.(e,o)}catch{}}}async observe(e){const o=typeof e.metadata?.skillName=="string"?e.metadata.skillName:void 0,i=typeof e.metadata?.riskCategory=="string"?e.metadata.riskCategory:void 0;await this.options.audit?.({toolName:e.toolName,...e.source===void 0?{}:{source:e.source},decision:e.decision,reason:e.reason,...o===void 0?{}:{skillName:o},...i===void 0?{}:{riskCategory:i}})}}function l(s){return s==="skill.list"||s==="skill.load"}export{m as ToolApprovalService};
1
+ import{requiresMutationApproval as t}from"./tool-risk-classifier.js";import{assessToolAction as r}from"./tool-action-risk-analyzer.js";import{workspacePermissionDecision as a}from"./workspace-permission-policy.js";import{matchesDesktopToolScope as n}from"./desktop-tool-scope-policy.js";class m{options;constructor(o){this.options=o}policy(){return{authorizationRules:[...this.options.desktopToolScopes===void 0?[]:[{id:"desktop-tool-scope",authorize:e=>this.authorizeDesktopScope(e)}],...this.options.skillScopes===void 0?[]:[{id:"cli-skill-scope",authorize:e=>this.authorizeSkill(e)}],{id:"cli-action-risk",authorize:e=>this.authorizeActionRisk(e)},{id:"cli-workspace-policy",authorize:e=>this.authorizeWorkspace(e)}],authorizationObserver:e=>this.observe(e),requireApproval:!1}}async authorizeDesktopScope(o){return await n(o,this.options.desktopToolScopes??[],this.options.resolveWorkspaceTarget)?{decision:"allow",reason:"desktop-tool-scope-allow"}:{decision:"deny",reason:"desktop-tool-scope-deny"}}async authorizeWorkspace(o){if(!this.options.trustedProject)return{decision:"deny",reason:"project-untrusted"};if(this.options.mode==="deny")return{decision:"deny",reason:"mode-deny"};const e=this.options.workspacePermissions===void 0?void 0:a(this.options.workspacePermissions,o.toolName,o.input);return e==="deny"?{decision:"deny",reason:"workspace-policy-deny"}:this.options.mode==="review"?this.requestApproval(o,"review-policy"):e==="allow"?{decision:"allow",reason:"workspace-policy-allow"}:e==="ask"?this.requestApproval(o,"workspace-policy-ask"):await t(o,this.options.resolveWorkspaceTarget)&&this.options.mode!=="autonomous"?this.requestApproval(o,"mutation-approval"):{decision:"allow",reason:this.options.mode==="auto"?"mode-auto":"read-only"}}async authorizeActionRisk(o){const e=r(o);if(e===void 0)return{decision:"allow",reason:"action-risk-clear"};if(e.risk==="deny")return{decision:"deny",reason:e.reason,metadata:{riskCategory:e.category}};const i=await this.resolvePrompt(o);return{...i,...i.reason===void 0?{reason:`${e.reason}-${i.decision}`}:{},metadata:{...i.metadata??{},riskCategory:e.category}}}authorizeSkill(o){const e=this.options.skillScopes?.get(o.context.runId);return e===void 0||l(o.toolName)?{decision:"allow",reason:"skill-policy-not-active"}:e.allowedTools.includes(o.toolName)?{decision:"allow",reason:"skill-policy-allow",metadata:{skillName:e.skillName}}:{decision:"deny",reason:"skill-policy-deny",metadata:{skillName:e.skillName}}}async requestApproval(o,e){const i=await this.resolvePrompt(o);return i.decision==="allow"&&await this.rememberApproval(o),i.reason===void 0?{...i,reason:`${e}-${i.decision}`}:i}async resolvePrompt(o){const e=await this.options.prompt?.(o)??!1;return typeof e=="boolean"?e?{decision:"allow"}:{decision:"deny"}:e}async rememberApproval(o){try{await this.options.rememberApproval?.(o)}catch(e){try{await this.options.onRememberApprovalFailure?.(o,e)}catch{}}}async observe(o){const e=typeof o.metadata?.skillName=="string"?o.metadata.skillName:void 0,i=typeof o.metadata?.riskCategory=="string"?o.metadata.riskCategory:void 0;await this.options.audit?.({toolName:o.toolName,stage:o.stage,sessionId:o.sessionId,runId:o.runId,...o.source===void 0?{}:{source:o.source},...o.executorId===void 0?{}:{executorId:o.executorId},decision:o.decision,reason:o.reason,...o.ruleId===void 0?{}:{ruleId:o.ruleId},...e===void 0?{}:{skillName:e},...i===void 0?{}:{riskCategory:i}})}}function l(s){return s==="skill.list"||s==="skill.load"}export{m as ToolApprovalService};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Concrete tool policy owned by the CLI security boundary.
3
+ *
4
+ * Desktop sends stable scopes; this registry is the single place where those
5
+ * scopes and tool metadata are expanded into concrete CLI capabilities.
6
+ */
7
+ export declare const READ_ONLY_EXECUTABLES: ReadonlySet<string>;
8
+ export declare const READ_ONLY_GIT_COMMANDS: ReadonlySet<string>;
9
+ export declare const READ_ONLY_GIT_FLAGS: ReadonlySet<string>;
10
+ export declare const MUTATING_GIT_FLAGS: ReadonlySet<string>;
11
+ export declare const MUTATING_GIT_SUBCOMMANDS: ReadonlySet<string>;
12
+ export declare const GIT_GLOBAL_EXECUTION_FLAGS: ReadonlySet<string>;
13
+ export declare const GIT_UNSAFE_READ_FLAGS: ReadonlySet<string>;
14
+ export declare const READ_ONLY_EXECUTABLE_FLAGS: Readonly<Record<string, readonly string[]>>;
15
+ export declare const READ_ONLY_TOOL_NAMES: ReadonlySet<string>;
16
+ export declare const BROWSER_NAVIGATION_TOOLS: ReadonlySet<string>;
17
+ export declare const BROWSER_INSPECTION_TOOLS: ReadonlySet<string>;
18
+ export declare const READ_ONLY_BROWSER_TOOLS: ReadonlySet<string>;
19
+ export declare const READ_ONLY_COMPUTER_TOOLS: ReadonlySet<string>;
20
+ export declare const COMPUTER_LAUNCH_TOOLS: ReadonlySet<string>;
@@ -0,0 +1 @@
1
+ const t=new Set(["read-file","read_file","get-content","cat","type","more","head","tail","sed","rg","grep","ls","dir","pwd","where","which","stat","wc","uniq","file"]),r=new Set(["status","diff","log","show","branch","tag","remote","rev-parse","ls-files"]),o=new Set(["--","--short","--porcelain","--branch","--stat","--name-only","--name-status","--oneline","--all","--show-toplevel","--abbrev-ref","--verify","--cached","--staged","-l","-n"]),s=new Set(["-d","-D","-m","-M","-c","-C","--delete","--move","--force","--unset-upstream"]),n=new Set(["add","remove","rename","set-url","set-head","delete","-d"]),c=new Set(["-c","--config-env","--exec-path"]),a=new Set(["-o","--output","--ext-diff","--textconv"]),i={cat:["-n","-b","-s"],head:["-n","-c"],tail:["-n","-c"],rg:["--files","-n","-i","-l","-g","--glob","--hidden","--no-ignore","--fixed-strings","-f"],grep:["-n","-i","-l","-r","-e","-f"],ls:["-l","-a","-la","-al","-h"],pwd:[],stat:[],wc:["-l","-w","-c"],uniq:["-c","-d","-u"],file:["-b","--mime-type"]},l=new Set(["filesystem.read","filesystem.list","filesystem.exists","skill.list","skill.load","agent.wait"]),w=new Set(["browser.navigate","browser.back","browser.forward","browser.reload"]),e=new Set(["browser.inspect","browser.inspectElement","browser.extractTable","browser.listFrames","browser.console","browser.network","browser.accessibility","browser.setViewport","browser.resetViewport","browser.screenshot","browser.tabs","browser.readField"]),p=new Set([...e,"browser.scroll","browser.focus","browser.hover","browser.waitFor"]),_=new Set(["computer.listWindows","computer.inspect","computer.screenshot","computer.readText","computer.readSelection","computer.readGrid","computer.recognizeText","computer.listDisplays","computer.wait","computer.readClipboard","computer.waitForState"]),d=new Set(["computer.launch"]);export{e as BROWSER_INSPECTION_TOOLS,w as BROWSER_NAVIGATION_TOOLS,d as COMPUTER_LAUNCH_TOOLS,c as GIT_GLOBAL_EXECUTION_FLAGS,a as GIT_UNSAFE_READ_FLAGS,s as MUTATING_GIT_FLAGS,n as MUTATING_GIT_SUBCOMMANDS,p as READ_ONLY_BROWSER_TOOLS,_ as READ_ONLY_COMPUTER_TOOLS,t as READ_ONLY_EXECUTABLES,i as READ_ONLY_EXECUTABLE_FLAGS,r as READ_ONLY_GIT_COMMANDS,o as READ_ONLY_GIT_FLAGS,l as READ_ONLY_TOOL_NAMES};
@@ -1,4 +1,5 @@
1
1
  import type { ToolApprovalRequest } from '@lotagate/agent-sdk';
2
+ import { type HostPlatformContext } from '../../infrastructure/platform/host-platform.js';
2
3
  export type WorkspaceTargetResolver = (input: unknown, context: Readonly<{
3
4
  cwd?: string;
4
5
  workspaceRoot?: string;
@@ -15,4 +16,4 @@ export declare function requiresMutationApproval(request: ToolApprovalRequest, r
15
16
  export declare function isReadOnlyShellRequest(commandValue: unknown, inputArgs: unknown, context?: Readonly<{
16
17
  cwd?: string;
17
18
  workspaceRoot?: string;
18
- }>, resolveTarget?: WorkspaceTargetResolver, workingDirectory?: unknown): Promise<boolean>;
19
+ }>, resolveTarget?: WorkspaceTargetResolver, workingDirectory?: unknown, platform?: HostPlatformContext): Promise<boolean>;
@@ -1 +1 @@
1
- import{resolveReadOnlyExecutable as u}from"../../infrastructure/platform/read-only-executable.js";async function m(t,s){const e=t.toolInfo?.metadata?.risk;return(t.toolInfo?.source==="filesystem"||t.toolInfo?.executorId==="desktop-browser-host"||t.toolInfo?.executorId==="desktop-computer-host")&&(e==="read"||e==="write"||e==="unknown")?e:t.toolName==="filesystem.read"||t.toolName==="filesystem.list"||t.toolName==="filesystem.exists"||t.toolName==="skill.list"||t.toolName==="skill.load"||t.toolName==="agent.wait"?"read":t.toolName==="agent.spawn"?t.input.mode==="worker"?"unknown":"read":t.toolName==="filesystem.write"||/(?:^|[._-])(delete|remove|move|copy|rename)(?:$|[._-])/iu.test(t.toolName)?"write":t.toolName==="shell.exec"&&await h(t.input.command,t.input.args,t.context,s,t.input.cwd)?"read":"unknown"}async function O(t,s){return await m(t,s)!=="read"}async function h(t,s,e,o,a){if(typeof t!="string"||!Array.isArray(s)||s.some(r=>typeof r!="string"))return!1;const n=t.trim();if(/[\\/:]/u.test(n)||/\.(?:cmd|bat|ps1)$/iu.test(n))return!1;const f=s,i=n.split(/[\\/]/u).at(-1)?.toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u,"")??"",l=f.map(r=>r.toLowerCase()),c=g.has(i)?!b(i,l):i==="git"&&y(l);if(!c||e===void 0||e.cwd===void 0&&e.workspaceRoot===void 0)return c;if(o===void 0||await u(n,e.workspaceRoot??e.cwd)===void 0)return!1;const d=typeof a=="string"?{...e,cwd:await o(a,e).catch(()=>"")}:e;return d.cwd===""?!1:await w(f,d,o)}async function w(t,s,e){const o=t.flatMap(p);for(const a of o)try{await e(a,s,!0)}catch{return!1}return!0}function p(t){const s=[];for(const e of[t,...t.includes("=")?[t.slice(t.indexOf("=")+1)]:[]]){const o=e.trim().replace(/^['"]|['"]$/gu,"");o.length!==0&&(o.startsWith("-")||s.push(o))}return s}function y(t){const s=new Set(["--","--short","--porcelain","--branch","--stat","--name-only","--name-status","--oneline","--all","--show-toplevel","--abbrev-ref","--verify","--cached","--staged","-l","-n"]);if(t.some(n=>n.startsWith("-")&&!s.has(n)&&!/^-(?:\d+)$|^--max-count=\d+$/u.test(n))||t.some(n=>_.has(n)||n.startsWith("--config-env=")||n.startsWith("-c")))return!1;const e=t.find(n=>!n.startsWith("-"));if(e===void 0||!N.has(e)||t.some(n=>I.has(n))||(e==="remote"||e==="tag")&&t.some(n=>S.has(n)))return!1;const o=t.indexOf(e),a=t.slice(o+1).filter(n=>!n.startsWith("-"));return!((e==="branch"||e==="tag"||e==="remote")&&a.length>0||t.some(n=>A.has(n)||n.startsWith("--output=")))}const g=new Set(["cat","type","more","head","tail","rg","grep","ls","dir","pwd","where","which","stat","wc","uniq","file"]),N=new Set(["status","diff","log","show","branch","tag","remote","rev-parse","ls-files"]),I=new Set(["-d","-D","-m","-M","-c","-C","--delete","--move","--force","--unset-upstream"]),S=new Set(["add","remove","rename","set-url","set-head","delete","-d"]),_=new Set(["-c","--config-env","--exec-path"]),A=new Set(["-o","--output","--ext-diff","--textconv"]);function b(t,s){const o={cat:["-n","-b","-s"],head:["-n","-c"],tail:["-n","-c"],rg:["--files","-n","-i","-l","-g","--glob","--hidden","--no-ignore","--fixed-strings","-f"],grep:["-n","-i","-l","-r","-e","-f"],ls:["-l","-a","-la","-al","-h"],pwd:[],stat:[],wc:["-l","-w","-c"],uniq:["-c","-d","-u"],file:["-b","--mime-type"]}[t];return o===void 0||s.some(a=>a.startsWith("-")&&a!=="--"&&!o.includes(a))?!0:t==="uniq"&&s.filter(a=>!a.startsWith("-")).length>1}export{m as classifyToolRisk,h as isReadOnlyShellRequest,O as requiresMutationApproval};
1
+ import{resolveReadOnlyExecutable as m}from"../../infrastructure/platform/read-only-executable.js";import{GIT_GLOBAL_EXECUTION_FLAGS as p,GIT_UNSAFE_READ_FLAGS as h,MUTATING_GIT_FLAGS as _,MUTATING_GIT_SUBCOMMANDS as w,READ_ONLY_EXECUTABLE_FLAGS as A,READ_ONLY_EXECUTABLES as I,READ_ONLY_GIT_COMMANDS as y,READ_ONLY_GIT_FLAGS as O,READ_ONLY_TOOL_NAMES as E}from"./tool-policy-registry.js";import{createIsolatedGuestPlatform as L}from"../../infrastructure/platform/host-platform.js";async function N(t,e){const o=t.toolInfo?.metadata?.risk;if((t.toolInfo?.source==="filesystem"||t.toolInfo?.executorId==="desktop-artifact-publisher"||t.toolInfo?.executorId==="desktop-browser-host"||t.toolInfo?.executorId==="desktop-computer-host")&&(o==="read"||o==="write"||o==="unknown"))return o;if(E.has(t.toolName))return"read";if(t.toolName==="agent.spawn")return t.input.mode==="worker"?"unknown":"read";if(t.toolName==="filesystem.write"||/(?:^|[._-])(delete|remove|move|copy|rename)(?:$|[._-])/iu.test(t.toolName))return"write";if(t.toolName==="shell.exec"){const r=t.toolInfo?.metadata?.boundary==="sandbox"?L():void 0;return await G(t.input.command,t.input.args,t.context,e,t.input.cwd,r)?"read":"unknown"}return"unknown"}async function C(t,e){return await N(t,e)!=="read"}async function G(t,e,o,r,n,l){if(typeof t!="string"||!Array.isArray(e)||e.some(s=>typeof s!="string"))return!1;const a=t.trim();if(/[\\/:]/u.test(a)||/\.(?:cmd|bat|ps1)$/iu.test(a))return!1;const f=e,i=a.split(/[\\/]/u).at(-1)?.toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u,"")??"",d=f.map(s=>s.toLowerCase()),c=I.has(i)?!S(i,d):i==="git"&&k(d);if(!c||o===void 0||o.cwd===void 0&&o.workspaceRoot===void 0)return c;if(r===void 0||await m(a,o.workspaceRoot??o.cwd,l)===void 0)return!1;const u=typeof n=="string"?{...o,cwd:await r(n,o).catch(()=>"")}:o;return u.cwd===""?!1:await R(f,u,r)}async function R(t,e,o){const r=t.flatMap(T);for(const n of r)try{await o(n,e,!0)}catch{return!1}return!0}function T(t){const e=[];for(const o of[t,...t.includes("=")?[t.slice(t.indexOf("=")+1)]:[]]){const r=o.trim().replace(/^['"]|['"]$/gu,"");r.length!==0&&(r.startsWith("-")||e.push(r))}return e}function k(t){if(t.some(n=>n.startsWith("-")&&!O.has(n)&&!/^-(?:\d+)$|^--max-count=\d+$/u.test(n))||t.some(n=>p.has(n)||n.startsWith("--config-env=")||n.startsWith("-c")))return!1;const e=t.find(n=>!n.startsWith("-"));if(e===void 0||!y.has(e)||t.some(n=>_.has(n))||(e==="remote"||e==="tag")&&t.some(n=>w.has(n)))return!1;const o=t.indexOf(e),r=t.slice(o+1).filter(n=>!n.startsWith("-"));return!((e==="branch"||e==="tag"||e==="remote")&&r.length>0||t.some(n=>h.has(n)||n.startsWith("--output=")))}function S(t,e){const o=A[t];return o===void 0||e.some(r=>r.startsWith("-")&&r!=="--"&&!o.includes(r))?!0:t==="uniq"&&e.filter(r=>!r.startsWith("-")).length>1}export{N as classifyToolRisk,G as isReadOnlyShellRequest,C as requiresMutationApproval};
@@ -1 +1 @@
1
- function m(s,r,t){const a=o(r,t);if(s.deny.some(n=>a.some(e=>i(n,e))))return"deny";if(s.ask.some(n=>a.some(e=>i(n,e))))return"ask";if(s.allow.some(n=>a.some(e=>i(n,e))))return"allow"}function f(s,r){if(typeof r.path=="string"&&r.path.trim().length>0)return`${s}:${r.path.trim()}`;if(typeof r.command=="string"&&r.command.trim().length>0){const t=r.command.trim(),n=(Array.isArray(r.args)?r.args.filter(e=>typeof e=="string"&&e.trim().length>0):[]).find(e=>!e.startsWith("-"))?.trim();return`${s}:${t}${n===void 0?"":` ${n}`}`}return s}function o(s,r){const t=[s];if(typeof r.command=="string"){const a=Array.isArray(r.args)?r.args.filter(e=>typeof e=="string"):[];t.push(`${s}:${r.command}${a.length===0?"":` ${a.join(" ")}`}`);const n=a.find(e=>!e.startsWith("-"));n!==void 0&&t.push(`${s}:${r.command} ${n}`)}return typeof r.path=="string"&&t.push(`${s}:${r.path}`),t}function i(s,r){if(s===r)return!0;if(!s.includes("*"))return!1;const t=s.replace(/[.+?^${}()|[\]\\]/gu,"\\$&").replaceAll("*",".*");return new RegExp(`^${t}$`,"u").test(r)}export{f as permissionRuleForRequest,m as workspacePermissionDecision};
1
+ import d from"node:crypto";import h from"node:path";function l(s,r,t){const i=$(r,t);if(s.deny.some(e=>i.some(n=>a(e,n))))return"deny";if(s.ask.some(e=>i.some(n=>a(e,n))))return"ask";if(s.allow.some(e=>i.some(n=>a(e,n))))return"allow"}function u(s,r){if(typeof r.path=="string"&&r.path.trim().length>0)return`${s}:${c(r.path)}`;if(typeof r.command=="string"&&r.command.trim().length>0){const t=r.command.trim(),e=(Array.isArray(r.args)?r.args.filter(o=>typeof o=="string"&&o.trim().length>0):[]).find(o=>!o.startsWith("-"))?.trim(),n=`${s}:${t}${e===void 0?"":` ${e}`}`;return typeof r.script=="string"?`${n} script-sha256:${f(r.script)}`:n}return s}function $(s,r){const t=[s];if(typeof r.command=="string"){const i=Array.isArray(r.args)?r.args.filter(n=>typeof n=="string"):[];t.push(`${s}:${r.command}${i.length===0?"":` ${i.join(" ")}`}`);const e=i.find(n=>!n.startsWith("-"));e!==void 0&&t.push(`${s}:${r.command} ${e}`),typeof r.script=="string"&&t.push(`${s}:${r.command} script-sha256:${f(r.script)}`)}return typeof r.path=="string"&&t.push(`${s}:${c(r.path)}`),t}function a(s,r){const t=m(s),i=m(r);if(t===i)return!0;if(!t.includes("*"))return!1;const e=t.replace(/[.+?^${}()|[\]\\]/gu,"\\$&").replaceAll("*",".*");return new RegExp(`^${e}$`,"u").test(i)}function c(s){const r=s.trim().replaceAll("\\","/"),t=h.posix.normalize(r);return t==="."?"":t.startsWith("./")?t.slice(2):t}function m(s){const r=s.indexOf(":");return r<0||!s.slice(0,r).startsWith("filesystem.")?s:`${s.slice(0,r)}:${c(s.slice(r+1))}`}function f(s){return d.createHash("sha256").update(s,"utf8").digest("hex")}export{u as permissionRuleForRequest,l as workspacePermissionDecision};
@@ -17,8 +17,6 @@ export interface PrepareInput {
17
17
  sessionId: string;
18
18
  projectRoot: string;
19
19
  }
20
- export declare const SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS: number;
21
- export declare const SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS: number;
22
20
  /** Owns durable, session-scoped execution directories for all CLI surfaces. */
23
21
  export declare class SessionExecutionWorkspaceService {
24
22
  private readonly platform;
@@ -29,6 +27,8 @@ export declare class SessionExecutionWorkspaceService {
29
27
  constructor(globalConfigDir: string, platform: HostPlatformContext, now?: () => number);
30
28
  prepare(input: PrepareInput): Promise<SessionExecutionWorkspace>;
31
29
  get(sessionId: string): Promise<SessionExecutionWorkspace | undefined>;
30
+ /** Holds one durable session turn lease across CLI processes. */
31
+ acquireTurn(sessionId: string): Promise<() => Promise<void>>;
32
32
  markReady(sessionId: string): Promise<void>;
33
33
  remove(sessionId: string): Promise<void>;
34
34
  apply(sessionId: string): Promise<{
@@ -1,3 +1,3 @@
1
- import p from"node:crypto";import{createReadStream as W}from"node:fs";import h from"node:fs/promises";import a from"node:path";import{atomicWriteFile as I,withFileLock as F}from"../../infrastructure/filesystem/atomic-file-store.js";import{readJsonFileBounded as S}from"../../infrastructure/filesystem/bounded-json-reader.js";import{isFileNotFound as y}from"../../infrastructure/filesystem/fs-errors.js";import{execPlatformCommand as M}from"../../infrastructure/platform/host-process.js";import{RESOURCE_LIMITS as b}from"../../domain/runtime/resource-limits.js";const U="session-execution-workspaces.json",$="session-execution-workspaces",z="session-execution-workspace-baselines",N=2*1024*1024,K=8*1024*1024,V=720*60*60*1e3,X=60*1e3,C=new Set([".git","node_modules"]),Y={timeoutMs:X,userMessage:"Another session is updating workspace state. Try again shortly."};class de{platform;now;indexFile;rootDirectory;baselineDirectory;constructor(e,t,i=Date.now){this.platform=t,this.now=i,this.indexFile=a.join(e,U),this.rootDirectory=a.join(e,$),this.baselineDirectory=a.join(e,z)}async prepare(e){const t=await h.realpath(a.resolve(e.projectRoot));return this.withWorkspaceLock(async()=>{await this.gcLocked(V);const i=await this.readIndex(),n=i.entries.find(o=>o.sessionId===e.sessionId&&o.projectRoot===t);if(n!==void 0){const o=await this.normalizeExecutionRoot(n);if(o.executionCwd!==n.executionCwd&&!await L(o.executionCwd)&&(await h.mkdir(o.executionCwd,{recursive:!0}),await k(t,o.executionCwd)),await L(o.executionCwd)){await this.synchronizeFromProjectRoot(o);const c={...o,state:"active",lastUsedAt:new Date(this.now()).toISOString()};return await this.writeIndex(i.entries.map(u=>u.id===n.id?c:u)),c}}const r=await this.create(e.sessionId,t);return await this.writeIndex([...i.entries.filter(o=>o.sessionId!==e.sessionId),r]),r})}async get(e){return(await this.readIndex()).entries.find(t=>t.sessionId===e)}async markReady(e){const t=await this.get(e);t!==void 0&&await this.updateEntry(t.id,i=>({...i,state:"ready",lastUsedAt:new Date(this.now()).toISOString()}))}async remove(e){await this.removeEntry(e)}async apply(e){return this.withWorkspaceLock(async()=>{const t=await this.readIndex(),i=t.entries.find(w=>w.sessionId===e);if(i===void 0)throw new Error("The session execution workspace was not found.");const n=await this.normalizeExecutionRoot(i);n.executionCwd!==i.executionCwd&&await this.writeIndex(t.entries.map(w=>w.id===n.id?n:w));const r=await this.readBaseline(n.id),[o,c]=await Promise.all([l(n.projectRoot),l(n.executionCwd)]),d=[...new Set([...Object.keys(r.entries),...o.keys(),...c.keys()])].filter(w=>!f(c.get(w),r.entries[w])).sort(),x=d.filter(w=>{const _=!f(o.get(w),r.entries[w]),B=!f(c.get(w),r.entries[w]);return _&&B&&!f(o.get(w),c.get(w))});if(x.length>0)throw new Error(`Cannot apply session changes because the project changed concurrently: ${x.join(", ")}.`);const P=await j(n.projectRoot,d,o);try{for(const w of d)await g(n.projectRoot,w,c.get(w),n.executionCwd)}catch(w){throw await A(n.projectRoot,P,d).catch(()=>{}),w}await this.writeBaseline(n.id,c);const T=await this.readIndex();return await this.writeIndex(T.entries.map(w=>w.id===n.id?{...w,lastUsedAt:new Date(this.now()).toISOString()}:w)),{appliedPaths:d}})}async removeEntry(e,t){await this.withWorkspaceLock(()=>this.removeEntryLocked(e,t))}async removeEntryLocked(e,t){const i=(await this.readIndex()).entries.find(r=>r.sessionId===e&&(t===void 0||r.id===t));if(i===void 0){const r=await this.readIndex();await this.writeIndex(r.entries.filter(o=>o.sessionId!==e));return}i.worktreePath!==void 0?(await m(["worktree","remove","--force",i.worktreePath],i.projectRoot,this.platform),i.branch!==void 0&&await q(i.branch,i.projectRoot,this.platform)):await h.rm(i.executionCwd,{recursive:!0,force:!0}),await h.rm(this.baselinePath(i.id),{force:!0});const n=await this.readIndex();await this.writeIndex(n.entries.filter(r=>r.id!==i.id))}async gc(e){return this.withWorkspaceLock(()=>this.gcLocked(e))}async gcLocked(e){const t=this.now()-e,n=(await this.readIndex()).entries.filter(r=>Date.parse(r.lastUsedAt)<t);for(const r of n)await this.removeEntryLocked(r.sessionId,r.id);return n.length}async create(e,t){const i=p.randomUUID(),n=new Date(this.now()).toISOString();await h.mkdir(this.rootDirectory,{recursive:!0});const r=a.join(this.rootDirectory,i),o=await l(t),c=await D(t,this.platform);if(c!==void 0){const u=`lotagate/session-${i}`;await m(["worktree","add","-b",u,r,"HEAD"],c,this.platform);const d=v(c,t,r);return await h.mkdir(d,{recursive:!0}),await k(t,d),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:d,isolationMode:"worktree-per-session",state:"active",branch:u,worktreePath:r,createdAt:n,lastUsedAt:n}}return await k(t,r),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:r,isolationMode:"worktree-per-session",state:"active",createdAt:n,lastUsedAt:n}}async synchronizeFromProjectRoot(e){const t=await this.readBaseline(e.id),i=await l(e.projectRoot),r=[...new Set([...Object.keys(t.entries),...i.keys()])].filter(d=>!f(i.get(d),t.entries[d])).sort();if(r.length===0)return;const o=await l(e.executionCwd),c=r.filter(d=>!f(o.get(d),t.entries[d])&&!f(o.get(d),i.get(d)));if(c.length>0)throw new Error(`Cannot synchronize unresolved session changes: ${c.join(", ")}.`);const u=await j(e.executionCwd,r,o);try{for(const d of r)await g(e.executionCwd,d,i.get(d),e.projectRoot)}catch(d){throw await A(e.executionCwd,u,r).catch(()=>{}),d}await this.writeBaseline(e.id,i)}async normalizeExecutionRoot(e){if(e.worktreePath===void 0)return e;const t=await D(e.projectRoot,this.platform);return t===void 0?e:{...e,executionCwd:v(t,e.projectRoot,e.worktreePath)}}baselinePath(e){return a.join(this.baselineDirectory,`${e}.json`)}async readBaseline(e){const t=await S(this.baselinePath(e),K);if(t.schemaVersion!==1||typeof t.entries!="object"||t.entries===null||Array.isArray(t.entries))throw new Error("The session execution workspace baseline is missing or invalid.");return{schemaVersion:1,entries:Object.fromEntries(Object.entries(t.entries).filter(([i,n])=>O(i)&&H(n)))}}async writeBaseline(e,t){const i={};for(const[n,r]of t)i[n]={kind:r.kind,hash:r.hash,size:r.size,...r.target===void 0?{}:{target:r.target}};await h.mkdir(this.baselineDirectory,{recursive:!0}),await I(this.baselinePath(e),`${JSON.stringify({schemaVersion:1,entries:i})}
2
- `)}async readIndex(){try{const e=await S(this.indexFile,N);return e.schemaVersion!==2||!Array.isArray(e.entries)?{schemaVersion:2,entries:[]}:{schemaVersion:2,entries:e.entries.filter(Z)}}catch(e){if(y(e))return{schemaVersion:2,entries:[]};throw e}}async writeIndex(e){await I(this.indexFile,`${JSON.stringify({schemaVersion:2,entries:e})}
3
- `)}async writeEntries(e){await this.withWorkspaceLock(async()=>{const t=await this.readIndex();await this.writeIndex(e(t.entries))})}async withWorkspaceLock(e){return F(this.indexFile,e,Y)}async updateEntry(e,t){await this.writeEntries(i=>i.map(n=>n.id===e?t(n):n))}}async function k(s,e){await h.cp(s,e,{recursive:!0,force:!0,filter:t=>{const i=a.relative(s,t);return i.length===0||!i.split(a.sep).some(n=>C.has(n))}})}async function l(s){const e=new Map;return await t(s,""),e;async function t(i,n){for(const r of await h.readdir(i,{withFileTypes:!0})){if(C.has(r.name))continue;const o=n.length===0?r.name:a.join(n,r.name),c=a.join(s,o),u=await h.lstat(c);if(u.isDirectory()){await t(c,o);continue}if(u.isSymbolicLink()){const d=await h.readlink(c);e.set(o,{kind:"symlink",hash:p.createHash("sha256").update(`symlink\0${d}`).digest("hex"),size:Buffer.byteLength(d),bytes:Buffer.alloc(0),target:d});continue}u.isFile()&&e.set(o,{kind:"file",hash:await J(c),size:u.size})}}}async function j(s,e,t){const i=new Map;for(const n of e){const r=t.get(n);r!==void 0&&(r.kind==="symlink"?i.set(n,r):i.set(n,{...r,bytes:await h.readFile(E(s,n))}))}return i}async function J(s){const e=p.createHash("sha256");for await(const t of W(s))e.update(t);return e.digest("hex")}function v(s,e,t){const i=a.relative(a.resolve(s),a.resolve(e));if(i===""||i===".")return a.resolve(t);if(i===".."||i.startsWith(`..${a.sep}`)||a.isAbsolute(i))throw new Error("The project root is outside the Git worktree root.");return a.resolve(t,i)}function f(s,e){return s===void 0||e===void 0?s===e:s.kind===e.kind&&s.hash===e.hash&&(s.kind!=="symlink"||s.target===e.target)}async function g(s,e,t,i=s){const n=E(s,e);if(await R(s,n),t===void 0){await h.unlink(n).catch(u=>{if(!y(u))throw u});return}const r=a.dirname(n);if(await h.mkdir(r,{recursive:!0}),await R(s,n),(await h.lstat(n).catch(u=>{if(!y(u))throw u}))?.isDirectory())throw new Error(`Cannot apply ${e}: the project root contains a directory at that path.`);const c=`${n}.${p.randomUUID()}.tmp`;try{t.kind==="symlink"?await h.symlink(t.target??"",c):await h.writeFile(c,t.bytes??await h.readFile(E(i,e))),await h.rename(c,n)}finally{await h.rm(c,{force:!0})}}async function R(s,e){const t=a.resolve(s),i=await h.realpath(t);let n=a.dirname(e);for(;;){const r=a.resolve(n),o=a.relative(t,r);if(o===".."||o.startsWith(`..${a.sep}`)||a.isAbsolute(o))throw new Error("The workspace path escapes the project root.");const c=await h.lstat(r).catch(u=>{if(!y(u))throw u});if(c?.isSymbolicLink())throw new Error("The workspace path contains a symbolic-link parent.");if(c!==void 0&&!G(i,await h.realpath(r)))throw new Error("The workspace path escapes the project root.");if(r===t)return;n=a.dirname(r)}}function G(s,e){const t=a.relative(s,e);return t===""||t!==".."&&!t.startsWith(`..${a.sep}`)&&!a.isAbsolute(t)}async function A(s,e,t){for(const i of[...t].reverse())await g(s,i,e.get(i))}function E(s,e){if(!O(e))throw new Error("The workspace path is invalid.");const t=a.resolve(s),i=a.resolve(t,e),n=a.relative(t,i);if(n===".."||n.startsWith(`..${a.sep}`)||a.isAbsolute(n))throw new Error("The workspace path escapes the project root.");return i}function O(s){return s.length>0&&!a.isAbsolute(s)&&s!=="."&&s!==".."&&!s.startsWith(`..${a.sep}`)&&!s.includes("\0")}function H(s){if(typeof s!="object"||s===null)return!1;const e=s;return(e.kind==="file"||e.kind==="symlink")&&typeof e.hash=="string"&&typeof e.size=="number"&&(e.target===void 0||typeof e.target=="string")}async function D(s,e){try{return(await m(["rev-parse","--show-toplevel"],s,e)).trim()||void 0}catch{return}}async function q(s,e,t){if(!/^lotagate\/session-[a-z0-9-]+$/iu.test(s))throw new Error("The session workspace branch name is invalid.");try{await m(["branch","--delete","--force","--",s],e,t)}catch(i){const n=i instanceof Error?i.message:String(i);if(!/not found|not a valid branch|unknown revision/iu.test(n))throw i}}async function m(s,e,t){return Q("git",s,e,t)}function Q(s,e,t,i){return M(s,e,i,{cwd:t,maxBufferBytes:b.internalProcessOutputBytes,timeoutMs:b.internalProcessTimeoutMs}).then(n=>n.stdout)}async function L(s){try{return(await h.stat(s)).isDirectory()}catch{return!1}}function Z(s){if(typeof s!="object"||s===null)return!1;const e=s;return typeof e.id=="string"&&typeof e.sessionId=="string"&&typeof e.projectRoot=="string"&&typeof e.executionCwd=="string"&&e.isolationMode==="worktree-per-session"&&(e.state==="ready"||e.state==="active"||e.state==="orphaned")&&typeof e.createdAt=="string"&&typeof e.lastUsedAt=="string"}export{X as SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS,V as SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS,de as SessionExecutionWorkspaceService};
1
+ import p from"node:crypto";import{createReadStream as _}from"node:fs";import h from"node:fs/promises";import a from"node:path";import{acquireFileLock as $,atomicWriteFile as S,withFileLock as U}from"../../infrastructure/filesystem/atomic-file-store.js";import{readJsonFileBounded as j}from"../../infrastructure/filesystem/bounded-json-reader.js";import{isFileNotFound as k}from"../../infrastructure/filesystem/fs-errors.js";import{execPlatformCommand as N}from"../../infrastructure/platform/host-process.js";import{RESOURCE_LIMITS as v}from"../../domain/runtime/resource-limits.js";import{COPY_EXCLUDED as x,MAX_BASELINE_BYTES as V,MAX_INDEX_BYTES as X,SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS as K,WORKSPACE_BASELINE_DIRECTORY as Y,WORKSPACE_DIRECTORY as q,WORKSPACE_INDEX_FILE as H,WORKSPACE_LOCK_OPTIONS as C}from"./workspace-constants.js";class we{platform;now;indexFile;rootDirectory;baselineDirectory;constructor(e,t,i=Date.now){this.platform=t,this.now=i,this.indexFile=a.join(e,H),this.rootDirectory=a.join(e,q),this.baselineDirectory=a.join(e,Y)}async prepare(e){const t=await h.realpath(a.resolve(e.projectRoot));return this.withWorkspaceLock(async()=>{await this.gcLocked(K);const i=await this.readIndex(),r=i.entries.find(o=>o.sessionId===e.sessionId&&o.projectRoot===t);if(r!==void 0){const o=await this.normalizeExecutionRoot(r);if(o.executionCwd!==r.executionCwd&&!await B(o.executionCwd)&&(await h.mkdir(o.executionCwd,{recursive:!0}),await I(t,o.executionCwd)),await B(o.executionCwd)){await this.synchronizeFromProjectRoot(o);const c={...o,state:"active",lastUsedAt:new Date(this.now()).toISOString()};return await this.writeIndex(i.entries.map(w=>w.id===r.id?c:w)),c}}const n=await this.create(e.sessionId,t);return await this.writeIndex([...i.entries.filter(o=>o.sessionId!==e.sessionId),n]),n})}async get(e){return(await this.readIndex()).entries.find(t=>t.sessionId===e)}async acquireTurn(e){const t=p.createHash("sha256").update(e,"utf8").digest("hex");return $(a.join(this.rootDirectory,"turn-locks",t),C)}async markReady(e){const t=await this.get(e);t!==void 0&&await this.updateEntry(t.id,i=>({...i,state:"ready",lastUsedAt:new Date(this.now()).toISOString()}))}async remove(e){await this.removeEntry(e)}async apply(e){return this.withWorkspaceLock(async()=>{const t=await this.readIndex(),i=t.entries.find(u=>u.sessionId===e);if(i===void 0)throw new Error("The session execution workspace was not found.");const r=await this.normalizeExecutionRoot(i);r.executionCwd!==i.executionCwd&&await this.writeIndex(t.entries.map(u=>u.id===r.id?r:u));const n=await this.readBaseline(r.id),[o,c]=await Promise.all([y(r.projectRoot,n.entries),y(r.executionCwd,n.entries)]),d=[...new Set([...Object.keys(n.entries),...o.keys(),...c.keys()])].filter(u=>!l(c.get(u),n.entries[u])).sort(),f=d.filter(u=>{const F=!l(o.get(u),n.entries[u]),z=!l(c.get(u),n.entries[u]);return F&&z&&!l(o.get(u),c.get(u))});if(f.length>0)throw new Error(`Cannot apply session changes because the project changed concurrently: ${f.join(", ")}.`);const m=await A(r.projectRoot,d,o);try{for(const u of d)await b(r.projectRoot,u,c.get(u),r.executionCwd)}catch(u){throw await O(r.projectRoot,m,d).catch(()=>{}),u}await this.writeBaseline(r.id,c);const W=await this.readIndex();return await this.writeIndex(W.entries.map(u=>u.id===r.id?{...u,lastUsedAt:new Date(this.now()).toISOString()}:u)),{appliedPaths:d}})}async removeEntry(e,t){await this.withWorkspaceLock(()=>this.removeEntryLocked(e,t))}async removeEntryLocked(e,t){const i=(await this.readIndex()).entries.find(n=>n.sessionId===e&&(t===void 0||n.id===t));if(i===void 0){const n=await this.readIndex();await this.writeIndex(n.entries.filter(o=>o.sessionId!==e));return}if(i.worktreePath!==void 0){let n=!1;for(let o=0;o<3;o+=1)try{await E(["worktree","remove","--force",i.worktreePath],i.projectRoot,this.platform),n=!0;break}catch{o<2&&await new Promise(c=>setTimeout(c,100))}if(!n){const o=await this.readIndex();await this.writeIndex(o.entries.map(c=>c.id===i.id?{...c,state:"orphaned"}:c));return}i.branch!==void 0&&await Z(i.branch,i.projectRoot,this.platform)}else await h.rm(i.executionCwd,{recursive:!0,force:!0});await h.rm(this.baselinePath(i.id),{force:!0});const r=await this.readIndex();await this.writeIndex(r.entries.filter(n=>n.id!==i.id))}async gc(e){return this.withWorkspaceLock(()=>this.gcLocked(e))}async gcLocked(e){const t=this.now()-e,r=(await this.readIndex()).entries.filter(n=>n.state==="orphaned"||Date.parse(n.lastUsedAt)<t);for(const n of r)await this.removeEntryLocked(n.sessionId,n.id);return r.length}async create(e,t){const i=p.randomUUID(),r=new Date(this.now()).toISOString();await h.mkdir(this.rootDirectory,{recursive:!0});const n=a.join(this.rootDirectory,i),o=await y(t),c=await T(t,this.platform);if(c!==void 0){const w=`lotagate/session-${i}`;await E(["worktree","add","-b",w,n,"HEAD"],c,this.platform);const d=M(c,t,n);return await h.mkdir(d,{recursive:!0}),await I(t,d),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:d,isolationMode:"worktree-per-session",state:"active",branch:w,worktreePath:n,createdAt:r,lastUsedAt:r}}return await I(t,n),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:n,isolationMode:"worktree-per-session",state:"active",createdAt:r,lastUsedAt:r}}async synchronizeFromProjectRoot(e){const t=await this.readBaseline(e.id),i=await y(e.projectRoot,t.entries),n=[...new Set([...Object.keys(t.entries),...i.keys()])].filter(d=>!l(i.get(d),t.entries[d])).sort();if(n.length===0)return;const o=await y(e.executionCwd,t.entries),c=n.filter(d=>!l(o.get(d),t.entries[d])&&!l(o.get(d),i.get(d)));if(c.length>0)throw new Error(`Cannot synchronize unresolved session changes: ${c.join(", ")}.`);const w=await A(e.executionCwd,n,o);try{for(const d of n)await b(e.executionCwd,d,i.get(d),e.projectRoot)}catch(d){throw await O(e.executionCwd,w,n).catch(()=>{}),d}await this.writeBaseline(e.id,i)}async normalizeExecutionRoot(e){if(e.worktreePath===void 0)return e;const t=await T(e.projectRoot,this.platform);return t===void 0?e:{...e,executionCwd:M(t,e.projectRoot,e.worktreePath)}}baselinePath(e){return a.join(this.baselineDirectory,`${e}.json`)}async readBaseline(e){const t=await j(this.baselinePath(e),V);if(t.schemaVersion!==1||typeof t.entries!="object"||t.entries===null||Array.isArray(t.entries))throw new Error("The session execution workspace baseline is missing or invalid.");return{schemaVersion:1,entries:Object.fromEntries(Object.entries(t.entries).filter(([i,r])=>L(i)&&Q(r)))}}async writeBaseline(e,t){const i={};for(const[r,n]of t)i[r]={kind:n.kind,hash:n.hash,size:n.size,...n.mode===void 0?{}:{mode:n.mode},...n.mtimeMs===void 0?{}:{mtimeMs:n.mtimeMs},...n.target===void 0?{}:{target:n.target}};await h.mkdir(this.baselineDirectory,{recursive:!0}),await S(this.baselinePath(e),`${JSON.stringify({schemaVersion:1,entries:i})}
2
+ `)}async readIndex(){try{const e=await j(this.indexFile,X);return e.schemaVersion!==2||!Array.isArray(e.entries)?{schemaVersion:2,entries:[]}:{schemaVersion:2,entries:e.entries.filter(te)}}catch(e){if(k(e))return{schemaVersion:2,entries:[]};throw e}}async writeIndex(e){await S(this.indexFile,`${JSON.stringify({schemaVersion:2,entries:e})}
3
+ `)}async writeEntries(e){await this.withWorkspaceLock(async()=>{const t=await this.readIndex();await this.writeIndex(e(t.entries))})}async withWorkspaceLock(e){return U(this.indexFile,e,C)}async updateEntry(e,t){await this.writeEntries(i=>i.map(r=>r.id===e?t(r):r))}}async function I(s,e){await h.cp(s,e,{recursive:!0,force:!0,filter:r=>{const n=a.relative(s,r);return n.length===0||!n.split(a.sep).some(o=>x.has(o))}});const[t,i]=await Promise.all([R(s),R(e)]);for(const r of[...i].filter(n=>!t.has(n)).sort((n,o)=>o.split(a.sep).length-n.split(a.sep).length))await h.rm(g(e,r),{recursive:!0,force:!0})}async function R(s){const e=new Set;return await t(s,""),e;async function t(i,r){for(const n of await h.readdir(i,{withFileTypes:!0})){if(x.has(n.name))continue;const o=r.length===0?n.name:a.join(r,n.name);e.add(o),n.isDirectory()&&await t(a.join(i,n.name),o)}}}async function y(s,e){const t=new Map;return await i(s,""),t;async function i(r,n){for(const o of await h.readdir(r,{withFileTypes:!0})){if(x.has(o.name))continue;const c=n.length===0?o.name:a.join(n,o.name),w=a.join(s,c),d=await h.lstat(w);if(d.isDirectory()){await i(w,c);continue}if(d.isSymbolicLink()){const m=await h.readlink(w);t.set(c,{kind:"symlink",hash:p.createHash("sha256").update(`symlink\0${m}`).digest("hex"),size:Buffer.byteLength(m),bytes:Buffer.alloc(0),target:m});continue}if(!d.isFile())continue;const f=e instanceof Map?e.get(c):e?.[c];if(f!==void 0&&f.kind==="file"&&f.size===d.size&&f.mtimeMs!==void 0&&Math.abs(f.mtimeMs-d.mtimeMs)<1&&P(f.mode,d.mode&4095)){t.set(c,{kind:"file",hash:f.hash,size:d.size,mtimeMs:d.mtimeMs,mode:d.mode&4095});continue}t.set(c,{kind:"file",hash:await J(w),size:d.size,mtimeMs:d.mtimeMs,mode:d.mode&4095})}}}async function A(s,e,t){const i=new Map;for(const r of e){const n=t.get(r);n!==void 0&&(n.kind==="symlink"?i.set(r,n):i.set(r,{...n,bytes:await h.readFile(g(s,r))}))}return i}async function J(s){const e=p.createHash("sha256");for await(const t of _(s))e.update(t);return e.digest("hex")}function M(s,e,t){const i=a.relative(a.resolve(s),a.resolve(e));if(i===""||i===".")return a.resolve(t);if(i===".."||i.startsWith(`..${a.sep}`)||a.isAbsolute(i))throw new Error("The project root is outside the Git worktree root.");return a.resolve(t,i)}function P(s,e){return s===void 0||e===void 0||process.platform==="win32"?!0:(s&73)===(e&73)}function l(s,e){return s===void 0||e===void 0?s===e:s.kind===e.kind&&s.hash===e.hash&&(s.kind!=="file"||P(s.mode,e.mode))&&(s.kind!=="symlink"||s.target===e.target)}async function b(s,e,t,i=s){const r=g(s,e);if(await D(s,r),t===void 0){await h.unlink(r).catch(w=>{if(!k(w))throw w});return}const n=a.dirname(r);if(await h.mkdir(n,{recursive:!0}),await D(s,r),(await h.lstat(r).catch(w=>{if(!k(w))throw w}))?.isDirectory())throw new Error(`Cannot apply ${e}: the project root contains a directory at that path.`);const c=`${r}.${p.randomUUID()}.tmp`;try{t.kind==="symlink"?await h.symlink(t.target??"",c):await h.writeFile(c,t.bytes??await h.readFile(g(i,e)),{mode:t.mode}),t.kind==="file"&&t.mode!==void 0&&await h.chmod(c,t.mode),await h.rename(c,r)}finally{await h.rm(c,{force:!0})}}async function D(s,e){const t=a.resolve(s),i=await h.realpath(t);let r=a.dirname(e);for(;;){const n=a.resolve(r),o=a.relative(t,n);if(o===".."||o.startsWith(`..${a.sep}`)||a.isAbsolute(o))throw new Error("The workspace path escapes the project root.");const c=await h.lstat(n).catch(w=>{if(!k(w))throw w});if(c?.isSymbolicLink())throw new Error("The workspace path contains a symbolic-link parent.");if(c!==void 0&&!G(i,await h.realpath(n)))throw new Error("The workspace path escapes the project root.");if(n===t)return;r=a.dirname(n)}}function G(s,e){const t=a.relative(s,e);return t===""||t!==".."&&!t.startsWith(`..${a.sep}`)&&!a.isAbsolute(t)}async function O(s,e,t){for(const i of[...t].reverse())await b(s,i,e.get(i))}function g(s,e){if(!L(e))throw new Error("The workspace path is invalid.");const t=a.resolve(s),i=a.resolve(t,e),r=a.relative(t,i);if(r===".."||r.startsWith(`..${a.sep}`)||a.isAbsolute(r))throw new Error("The workspace path escapes the project root.");return i}function L(s){return s.length>0&&!a.isAbsolute(s)&&s!=="."&&s!==".."&&!s.startsWith(`..${a.sep}`)&&!s.includes("\0")}function Q(s){if(typeof s!="object"||s===null)return!1;const e=s;return(e.kind==="file"||e.kind==="symlink")&&typeof e.hash=="string"&&typeof e.size=="number"&&(e.mode===void 0||typeof e.mode=="number"&&Number.isInteger(e.mode)&&e.mode>=0&&e.mode<=4095)&&(e.mtimeMs===void 0||typeof e.mtimeMs=="number")&&(e.target===void 0||typeof e.target=="string")}async function T(s,e){try{return(await E(["rev-parse","--show-toplevel"],s,e)).trim()||void 0}catch{return}}async function Z(s,e,t){if(!/^lotagate\/session-[a-z0-9-]+$/iu.test(s))throw new Error("The session workspace branch name is invalid.");try{await E(["branch","--delete","--force","--",s],e,t)}catch(i){const r=i instanceof Error?i.message:String(i);if(!/not found|not a valid branch|unknown revision/iu.test(r))throw i}}async function E(s,e,t){return ee("git",s,e,t)}function ee(s,e,t,i){return N(s,e,i,{cwd:t,maxBufferBytes:v.internalProcessOutputBytes,timeoutMs:v.internalProcessTimeoutMs}).then(r=>r.stdout)}async function B(s){try{return(await h.stat(s)).isDirectory()}catch{return!1}}function te(s){if(typeof s!="object"||s===null)return!1;const e=s;return typeof e.id=="string"&&typeof e.sessionId=="string"&&typeof e.projectRoot=="string"&&typeof e.executionCwd=="string"&&e.isolationMode==="worktree-per-session"&&(e.state==="ready"||e.state==="active"||e.state==="orphaned")&&typeof e.createdAt=="string"&&typeof e.lastUsedAt=="string"}export{we as SessionExecutionWorkspaceService};
@@ -0,0 +1,17 @@
1
+ export declare const DEFAULT_IGNORED_WORKSPACE_DIRECTORIES: Set<string>;
2
+ export declare const MAX_INDEXED_ENTRIES = 2000;
3
+ export declare const INSTRUCTION_PATHS: readonly ["AGENTS.md", "CLAUDE.md", "CLAUDE.local.md", "QWEN.md", "QWEN.local.md", "GEMINI.md", "CONTEXT.md", "CONVENTIONS.md", ".claude/CLAUDE.md", ".qwen/QWEN.md", ".qwen/QWEN.local.md", ".github/copilot-instructions.md", ".cursorrules", ".windsurfrules"];
4
+ export declare const RULE_DIRECTORIES: readonly [".claude/rules", ".cursor/rules", ".windsurf/rules", ".devin/rules", ".clinerules"];
5
+ export declare const RULE_EXTENSIONS: Set<string>;
6
+ export declare const WORKSPACE_INDEX_FILE = "session-execution-workspaces.json";
7
+ export declare const WORKSPACE_DIRECTORY = "session-execution-workspaces";
8
+ export declare const WORKSPACE_BASELINE_DIRECTORY = "session-execution-workspace-baselines";
9
+ export declare const MAX_INDEX_BYTES: number;
10
+ export declare const MAX_BASELINE_BYTES: number;
11
+ export declare const SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS: number;
12
+ export declare const SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS: number;
13
+ export declare const COPY_EXCLUDED: Set<string>;
14
+ export declare const WORKSPACE_LOCK_OPTIONS: {
15
+ readonly timeoutMs: number;
16
+ readonly userMessage: "Another session is updating workspace state. Try again shortly.";
17
+ };
@@ -0,0 +1 @@
1
+ const o=new Set([".git",".lotagate","node_modules","dist","build","coverage",".next",".nuxt",".cache",".turbo","vendor"]),s=2e3,t=["AGENTS.md","CLAUDE.md","CLAUDE.local.md","QWEN.md","QWEN.local.md","GEMINI.md","CONTEXT.md","CONVENTIONS.md",".claude/CLAUDE.md",".qwen/QWEN.md",".qwen/QWEN.local.md",".github/copilot-instructions.md",".cursorrules",".windsurfrules"],E=[".claude/rules",".cursor/rules",".windsurf/rules",".devin/rules",".clinerules"],n=new Set([".md",".mdc"]),r="session-execution-workspaces.json",c="session-execution-workspaces",_="session-execution-workspace-baselines",S=2*1024*1024,d=8*1024*1024,I=720*60*60*1e3,e=60*1e3,O=new Set([".git",".lotagate","node_modules"]),u={timeoutMs:e,userMessage:"Another session is updating workspace state. Try again shortly."};export{O as COPY_EXCLUDED,o as DEFAULT_IGNORED_WORKSPACE_DIRECTORIES,t as INSTRUCTION_PATHS,d as MAX_BASELINE_BYTES,s as MAX_INDEXED_ENTRIES,S as MAX_INDEX_BYTES,E as RULE_DIRECTORIES,n as RULE_EXTENSIONS,e as SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS,I as SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS,_ as WORKSPACE_BASELINE_DIRECTORY,c as WORKSPACE_DIRECTORY,r as WORKSPACE_INDEX_FILE,u as WORKSPACE_LOCK_OPTIONS};
@@ -1,4 +1,3 @@
1
- export declare const DEFAULT_IGNORED_WORKSPACE_DIRECTORIES: Set<string>;
2
1
  export type WorkspaceEntryKind = 'file' | 'directory';
3
2
  export interface WorkspaceEntry {
4
3
  path: string;
@@ -9,7 +8,7 @@ export declare class WorkspaceFileIndex {
9
8
  private readonly root;
10
9
  private readonly ignoredDirectories;
11
10
  constructor(root: string, ignoredDirectories?: ReadonlySet<string>);
12
- list(): Promise<readonly string[]>;
13
- listEntries(): Promise<readonly WorkspaceEntry[]>;
11
+ list(signal?: AbortSignal): Promise<readonly string[]>;
12
+ listEntries(signal?: AbortSignal): Promise<readonly WorkspaceEntry[]>;
14
13
  private visit;
15
14
  }
@@ -1 +1 @@
1
- import a from"node:fs/promises";import o from"node:path";const c=new Set([".git",".lotagate","node_modules","dist","build","coverage",".next",".nuxt",".cache",".turbo","vendor"]),n=2e3;class u{root;ignoredDirectories;constructor(t,i=c){this.root=t,this.ignoredDirectories=i}async list(){return(await this.listEntries()).filter(t=>t.kind==="file").map(t=>t.path)}async listEntries(){const t=[];return await this.visit(this.root,t),t.sort((i,r)=>i.path.localeCompare(r.path))}async visit(t,i){if(i.length>=n)return;let r;try{r=await a.readdir(t,{withFileTypes:!0})}catch{return}for(const e of r){if(i.length>=n)return;const s=o.join(t,e.name);if(!e.isSymbolicLink())if(e.isDirectory()){if(this.ignoredDirectories.has(e.name))continue;i.push({path:o.relative(this.root,s).split(o.sep).join("/"),kind:"directory"}),await this.visit(s,i)}else e.isFile()&&i.push({path:o.relative(this.root,s).split(o.sep).join("/"),kind:"file"})}}}export{c as DEFAULT_IGNORED_WORKSPACE_DIRECTORIES,u as WorkspaceFileIndex};
1
+ import h from"node:fs/promises";import e from"node:path";import{DEFAULT_IGNORED_WORKSPACE_DIRECTORIES as c,MAX_INDEXED_ENTRIES as n}from"./workspace-constants.js";class u{root;ignoredDirectories;constructor(i,t=c){this.root=i,this.ignoredDirectories=t}async list(i){return(await this.listEntries(i)).filter(t=>t.kind==="file").map(t=>t.path)}async listEntries(i){const t=[];return await this.visit(this.root,t,i),t.sort((o,s)=>o.path.localeCompare(s.path))}async visit(i,t,o){if(o?.throwIfAborted(),t.length>=n)return;let s;try{s=await h.readdir(i,{withFileTypes:!0})}catch(r){if(o?.aborted===!0)throw r;return}for(const r of s){if(o?.throwIfAborted(),t.length>=n)return;const a=e.join(i,r.name);if(!r.isSymbolicLink())if(r.isDirectory()){if(this.ignoredDirectories.has(r.name))continue;t.push({path:e.relative(this.root,a).split(e.sep).join("/"),kind:"directory"}),await this.visit(a,t,o)}else r.isFile()&&t.push({path:e.relative(this.root,a).split(e.sep).join("/"),kind:"file"})}}}export{u as WorkspaceFileIndex};
@@ -1 +1 @@
1
- import d from"node:fs/promises";import o from"node:path";import{readFileBounded as N}from"../../infrastructure/filesystem/bounded-file-reader.js";import{isFileNotFound as w}from"../../infrastructure/filesystem/fs-errors.js";import{RESOURCE_LIMITS as m}from"../../domain/runtime/resource-limits.js";const S=["AGENTS.md","CLAUDE.md","CLAUDE.local.md","QWEN.md","QWEN.local.md","GEMINI.md","CONTEXT.md","CONVENTIONS.md",".claude/CLAUDE.md",".qwen/QWEN.md",".qwen/QWEN.local.md",".github/copilot-instructions.md",".cursorrules",".windsurfrules"],T=[".claude/rules",".cursor/rules",".windsurf/rules",".devin/rules",".clinerules"],C=new Set([".md",".mdc"]);class U{async load(r,i=r){const t=await d.realpath(r),n=await d.realpath(i);if(n!==t&&!n.startsWith(`${t}${o.sep}`))return[];const u=g(t,n),e=[];let a=0;for(const l of u){for(const c of S)if(e.length>=m.instructionFiles||await h(o.join(l,c),t,e,()=>a,p=>{a=p})==="limit")return e;for(const c of T){const f=await I(o.join(l,c));for(const p of f)if(e.length>=m.instructionFiles||await h(p,t,e,()=>a,y=>{a=y},y=>L(y))==="limit")return e}}return e}}async function h(s,r,i,t,n,u){try{const e=await d.lstat(s);if(!e.isFile()||e.isSymbolicLink())return"skipped";const a=await N(s,m.instructionFileBytes);if(a.truncated)return"skipped";const l=a.bytes.toString("utf8");if(u!==void 0&&!u(l))return"skipped";const c=t()+a.bytes.byteLength;if(c>m.instructionTotalBytes)return"limit";n(c);const f=o.relative(r,s)||o.basename(s);return i.push({path:f.split(o.sep).join("/"),content:l}),"added"}catch(e){if(!w(e))throw e;return"skipped"}}async function I(s){const r=[];return await E(s,r),r.sort((i,t)=>i.localeCompare(t))}async function E(s,r){try{const i=await d.readdir(s,{withFileTypes:!0});for(const t of i.sort((n,u)=>n.name.localeCompare(u.name))){const n=o.join(s,t.name);t.isSymbolicLink()||(t.isDirectory()?await E(n,r):t.isFile()&&C.has(o.extname(t.name).toLowerCase())&&r.push(n))}}catch(i){if(w(i))return;throw i}}function L(s){const r=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(s)?.[1];return r===void 0||/^\s*(?:alwaysApply|always_apply)\s*:\s*true\s*$/imu.test(r)||/^\s*trigger\s*:\s*(?:always|always_on)\s*$/imu.test(r)?!0:!/^\s*(?:alwaysApply|always_apply|globs|paths|trigger)\s*:/imu.test(r)}function g(s,r){const i=[];let t=r;for(;;){if(i.unshift(t),t===s)return i;const n=o.dirname(t);if(n===t)return[];t=n}}export{U as WorkspaceInstructionLoader};
1
+ import p from"node:fs/promises";import o from"node:path";import{readFileBounded as F}from"../../infrastructure/filesystem/bounded-file-reader.js";import{isFileNotFound as h}from"../../infrastructure/filesystem/fs-errors.js";import{RESOURCE_LIMITS as y}from"../../domain/runtime/resource-limits.js";import{INSTRUCTION_PATHS as g,RULE_DIRECTORIES as I,RULE_EXTENSIONS as L}from"./workspace-constants.js";class ${async load(r,n=r){const t=await p.realpath(r),s=await p.realpath(n);if(s!==t&&!s.startsWith(`${t}${o.sep}`))return[];const u=E(t,s),e=[];let a=0;for(const l of u){for(const c of g)if(e.length>=y.instructionFiles||await w(o.join(l,c),t,e,()=>a,m=>{a=m})==="limit")return e;for(const c of I){const f=await R(o.join(l,c));for(const m of f)if(e.length>=y.instructionFiles||await w(m,t,e,()=>a,d=>{a=d},d=>T(d))==="limit")return e}}return e}}async function w(i,r,n,t,s,u){try{const e=await p.lstat(i);if(!e.isFile()||e.isSymbolicLink())return"skipped";const a=await F(i,y.instructionFileBytes);if(a.truncated)return"skipped";const l=a.bytes.toString("utf8");if(u!==void 0&&!u(l))return"skipped";const c=t()+a.bytes.byteLength;if(c>y.instructionTotalBytes)return"limit";s(c);const f=o.relative(r,i)||o.basename(i);return n.push({path:f.split(o.sep).join("/"),content:l}),"added"}catch(e){if(!h(e))throw e;return"skipped"}}async function R(i){const r=[];return await S(i,r),r.sort((n,t)=>n.localeCompare(t))}async function S(i,r){try{const n=await p.readdir(i,{withFileTypes:!0});for(const t of n.sort((s,u)=>s.name.localeCompare(u.name))){const s=o.join(i,t.name);t.isSymbolicLink()||(t.isDirectory()?await S(s,r):t.isFile()&&L.has(o.extname(t.name).toLowerCase())&&r.push(s))}}catch(n){if(h(n))return;throw n}}function T(i){const r=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(i)?.[1];return r===void 0||/^\s*(?:alwaysApply|always_apply)\s*:\s*true\s*$/imu.test(r)||/^\s*trigger\s*:\s*(?:always|always_on)\s*$/imu.test(r)?!0:!/^\s*(?:alwaysApply|always_apply|globs|paths|trigger)\s*:/imu.test(r)}function E(i,r){const n=[];let t=r;for(;;){if(n.unshift(t),t===i)return n;const s=o.dirname(t);if(s===t)return[];t=s}}export{$ as WorkspaceInstructionLoader};
@@ -2,5 +2,6 @@ import type { Writable } from 'node:stream';
2
2
  import { type CliRuntime } from './runtime-factory.js';
3
3
  export interface CompositionRootOptions {
4
4
  stderr?: Writable;
5
+ interactive?: boolean;
5
6
  }
6
7
  export declare function createCompositionRoot(options?: CompositionRootOptions): CliRuntime;
@@ -16,6 +16,8 @@ import { type HostPlatformContext } from '../infrastructure/platform/host-platfo
16
16
  import { McpRuntime } from '../infrastructure/extensions/mcp-runtime.js';
17
17
  import { MemoryService } from '../application/memory/memory-service.js';
18
18
  import { SessionExecutionWorkspaceService } from '../application/workspace/session-execution-workspace.js';
19
+ import { ModelCatalogInFlightRegistry } from '../application/model/cached-model-catalog.js';
20
+ import { CliAgentPreparationCache } from '../application/agent/cli-agent-preparation-cache.js';
19
21
  export interface CliRuntime {
20
22
  readonly platform: HostPlatformContext;
21
23
  readonly paths: PlatformPaths;
@@ -33,9 +35,12 @@ export interface CliRuntime {
33
35
  readonly mcpRuntime: McpRuntime;
34
36
  readonly memory: MemoryService;
35
37
  readonly executionWorkspaces: SessionExecutionWorkspaceService;
38
+ readonly modelCatalogInFlight: ModelCatalogInFlightRegistry;
39
+ readonly agentPreparation?: CliAgentPreparationCache;
36
40
  readonly shutdown: ShutdownManager;
37
41
  }
38
42
  export interface RuntimeFactoryOptions {
39
43
  stderr?: Writable;
44
+ interactive?: boolean;
40
45
  }
41
46
  export declare function createCliRuntime(options?: RuntimeFactoryOptions): CliRuntime;
@@ -1 +1 @@
1
- import{ConfigLoader as C}from"../infrastructure/config/config-loader.js";import{StructuredLogger as P}from"../infrastructure/logging/structured-logger.js";import{resolvePlatformPaths as F}from"../infrastructure/platform/platform-paths.js";import{AuthenticationService as D}from"../application/auth/authentication-service.js";import{CompositeCredentialStore as L}from"../infrastructure/credentials/composite-credential-store.js";import{EncryptedFileCredentialStore as M}from"../infrastructure/credentials/encrypted-file-credential-store.js";import{EnvironmentCredentialStore as R}from"../infrastructure/credentials/environment-credential-store.js";import{FileProjectTrustStore as j}from"../infrastructure/project/file-project-trust-store.js";import{ProjectTrustService as k}from"../application/project/project-trust-service.js";import{DefaultShutdownManager as T}from"./shutdown-manager.js";import{FileSessionStore as W}from"../infrastructure/sessions/file-session-store.js";import{WorkspaceSettingsStore as x}from"../infrastructure/workspace/workspace-settings-store.js";import{FileCacheStore as E}from"../infrastructure/cache/file-cache-store.js";import{resolveCachePolicy as b}from"../infrastructure/cache/cache-policy.js";import{DailyRotatingFileWriter as A}from"../infrastructure/logging/daily-rotating-file-writer.js";import{resolveLoggingPolicy as G}from"../infrastructure/logging/logging-policy.js";import{FileGoalStore as H}from"../infrastructure/sessions/file-goal-store.js";import{detectHostPlatform as q}from"../infrastructure/platform/host-platform.js";import{McpRuntime as z,resolveMcpRuntimePolicy as B}from"../infrastructure/extensions/mcp-runtime.js";import{FileMemoryStore as I}from"../infrastructure/memory/file-memory-store.js";import{MemoryService as J}from"../application/memory/memory-service.js";import{SessionExecutionWorkspaceService as K}from"../application/workspace/session-execution-workspace.js";function ae(a={}){const t=q(),e=F(process.env,t),n=new T,i=b(),u=new E(e.cacheDir,i),c=G();let o;try{o=new A(e.logsDir,c)}catch{}const r=new P({output:a.stderr??process.stderr,level:c.level,consoleLevel:"warn",...o===void 0?{}:{file:o}}),m=new z(void 0,B(),r);o!==void 0&&n.register(()=>o?.close()),n.register(()=>m.close());const S=new C(r,e),s=new M(e),l=new L([new R,s],s),d=new D(l),p=new j(e),g=new k(p),f=new W(e),w=new H(f),v=new x,h=new J(new I(e,r),void 0,r),y=new K(e.globalConfigDir,t);return{platform:t,paths:e,logger:r,configLoader:S,credentialStore:l,auth:d,projectTrustStore:p,projectTrust:g,sessionStore:f,goalStore:w,workspaceSettings:v,cache:u,cachePolicy:i,mcpRuntime:m,memory:h,executionWorkspaces:y,shutdown:n}}export{ae as createCliRuntime};
1
+ import{ConfigLoader as M}from"../infrastructure/config/config-loader.js";import{StructuredLogger as R}from"../infrastructure/logging/structured-logger.js";import{resolvePlatformPaths as D}from"../infrastructure/platform/platform-paths.js";import{AuthenticationService as L}from"../application/auth/authentication-service.js";import{CompositeCredentialStore as j}from"../infrastructure/credentials/composite-credential-store.js";import{EncryptedFileCredentialStore as k}from"../infrastructure/credentials/encrypted-file-credential-store.js";import{EnvironmentCredentialStore as T}from"../infrastructure/credentials/environment-credential-store.js";import{FileProjectTrustStore as W}from"../infrastructure/project/file-project-trust-store.js";import{ProjectTrustService as x}from"../application/project/project-trust-service.js";import{DefaultShutdownManager as E}from"./shutdown-manager.js";import{FileSessionStore as A}from"../infrastructure/sessions/file-session-store.js";import{WorkspaceSettingsStore as I}from"../infrastructure/workspace/workspace-settings-store.js";import{FileCacheStore as b}from"../infrastructure/cache/file-cache-store.js";import{resolveCachePolicy as G}from"../infrastructure/cache/cache-policy.js";import{DailyRotatingFileWriter as H}from"../infrastructure/logging/daily-rotating-file-writer.js";import{resolveLoggingPolicy as q}from"../infrastructure/logging/logging-policy.js";import{FileGoalStore as z}from"../infrastructure/sessions/file-goal-store.js";import{detectHostPlatform as B}from"../infrastructure/platform/host-platform.js";import{McpRuntime as J,resolveMcpRuntimePolicy as K}from"../infrastructure/extensions/mcp-runtime.js";import{FileMemoryStore as N}from"../infrastructure/memory/file-memory-store.js";import{MemoryService as O}from"../application/memory/memory-service.js";import{SessionExecutionWorkspaceService as Q}from"../application/workspace/session-execution-workspace.js";import{ModelCatalogInFlightRegistry as U}from"../application/model/cached-model-catalog.js";import{CliAgentPreparationCache as V}from"../application/agent/cli-agent-preparation-cache.js";function ve(i={}){const t=B(),e=D(process.env,t),n=new E,c=G(),g=new b(e.cacheDir,c),m=q();let o;try{o=new H(e.logsDir,m)}catch{}const d=i.interactive?o===void 0?"warn":"none":"warn",r=new R({output:i.stderr??process.stderr,level:m.level,consoleLevel:d,...o===void 0?{}:{file:o}}),s=new J(void 0,K(),r);o!==void 0&&n.register(()=>o?.close()),n.register(()=>s.close());const u=new M(r,e),l=new k(e),a=new j([new T,l],l),w=new L(a),p=new W(e),S=new x(p),f=new A(e),h=new z(f),v=new I,C=new O(new N(e,r),void 0,r),y=new Q(e.globalConfigDir,t),P=new U,F=new V;return{platform:t,paths:e,logger:r,configLoader:u,credentialStore:a,auth:w,projectTrustStore:p,projectTrust:S,sessionStore:f,goalStore:h,workspaceSettings:v,cache:g,cachePolicy:c,mcpRuntime:s,memory:C,executionWorkspaces:y,modelCatalogInFlight:P,agentPreparation:F,shutdown:n}}export{ve as createCliRuntime};
@@ -9,6 +9,7 @@ export interface StoredCredential {
9
9
  profile: AuthProfile;
10
10
  apiKey: string;
11
11
  }
12
+ export declare const AUTH_API_KEY_MAX_BYTES = 4096;
12
13
  export declare function validateProfileName(name: string): string;
13
14
  export declare function validateBaseUrl(value: string): string;
14
15
  export declare function validateApiKey(apiKey: string): string;
@@ -1 +1 @@
1
- import{CliError as t}from"../errors/cli-error.js";import{CLI_ERROR_CODES as a}from"../errors/error-codes.js";const s=/^[a-z][a-z0-9_-]{0,31}$/;function l(r){const e=r.trim().toLowerCase();if(!s.test(e))throw new t(a.AUTH_PROFILE_NOT_FOUND,`Invalid profile name: ${r}`,{category:"auth",userMessage:"Profile names may contain lowercase letters, digits, hyphens, or underscores; maximum 32 characters."});return e}function c(r){let e;try{e=new URL(r)}catch(o){throw new t(a.AUTH_BASE_URL_INVALID,"Base URL is invalid.",{category:"auth",userMessage:"Invalid base URL.",cause:o})}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new t(a.AUTH_BASE_URL_INVALID,"Base URL must use HTTP or HTTPS.",{category:"auth",userMessage:"Base URL must use HTTP or HTTPS."});return r.replace(/\/+$/,"")}function u(r){const e=r.trim();if(e.length<8||e.length>4096||/[\r\n]/.test(e))throw new t(a.AUTH_API_KEY_INVALID,"API key has an invalid shape.",{category:"auth",userMessage:"API key is invalid or contains a newline."});return e}export{u as validateApiKey,c as validateBaseUrl,l as validateProfileName};
1
+ import{CliError as r}from"../errors/cli-error.js";import{CLI_ERROR_CODES as a}from"../errors/error-codes.js";const s=/^[a-z][a-z0-9_-]{0,31}$/,n=4096;function l(t){const e=t.trim().toLowerCase();if(!s.test(e))throw new r(a.AUTH_PROFILE_NOT_FOUND,`Invalid profile name: ${t}`,{category:"auth",userMessage:"Profile names may contain lowercase letters, digits, hyphens, or underscores; maximum 32 characters."});return e}function u(t){let e;try{e=new URL(t)}catch(o){throw new r(a.AUTH_BASE_URL_INVALID,"Base URL is invalid.",{category:"auth",userMessage:"Invalid base URL.",cause:o})}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new r(a.AUTH_BASE_URL_INVALID,"Base URL must use HTTP or HTTPS.",{category:"auth",userMessage:"Base URL must use HTTP or HTTPS."});return t.replace(/\/+$/,"")}function _(t){const e=t.trim();if(e.length<8||Buffer.byteLength(e,"utf8")>n||/[\r\n]/.test(e))throw new r(a.AUTH_API_KEY_INVALID,"API key has an invalid shape.",{category:"auth",userMessage:"API key is invalid or contains a newline."});return e}export{n as AUTH_API_KEY_MAX_BYTES,_ as validateApiKey,u as validateBaseUrl,l as validateProfileName};
@@ -1 +1 @@
1
- import{CLI_ERROR_CODES as i}from"./error-codes.js";class r extends Error{code;category;userMessage;retryable;exitCode;correlationId;details;hint;constructor(t,a,s){super(a,{cause:s.cause}),this.name="CliError",this.code=t,this.category=s.category,this.userMessage=s.userMessage??a,this.retryable=s.retryable??!1,this.exitCode=s.exitCode??1,this.correlationId=s.correlationId,this.details=s.details,this.hint=s.hint}toJSON(){return{code:this.code,category:this.category,message:this.message,userMessage:this.userMessage,retryable:this.retryable,exitCode:this.exitCode,...this.correlationId!==void 0?{correlationId:this.correlationId}:{},...this.details!==void 0?{details:this.details}:{}}}}function f(e){if(e instanceof r)return e;const t=o(e),a=l(e);return t==="REQUEST_ABORTED"||c(e)?new r(i.INTERRUPTED,n(e),{category:"agent",userMessage:"The request was interrupted.",retryable:!0,...a,cause:e}):t==="REQUEST_TIMEOUT"||t==="NETWORK_ERROR"?new r(i.MEDIA_REQUEST_FAILED,n(e),{category:"media",userMessage:"The media request could not be completed. Retry the request; if it persists, check the selected model, credentials, and network connection.",retryable:!0,...a,cause:e}):t==="REQUEST_VALIDATION_ERROR"||t==="REQUEST_PAYLOAD_TOO_LARGE"?new r(i.INVALID_ARGUMENT,n(e),{category:"media",userMessage:"The media request does not satisfy a gateway validation limit. Review the command options and input file size.",...a,cause:e}):t==="RESPONSE_TOO_LARGE"?new r(i.MEDIA_RESPONSE_TOO_LARGE,n(e),{category:"media",userMessage:"The generated media exceeds the supported download size.",retryable:!1,...a,cause:e}):t==="TOOL_ARGUMENTS_INVALID"?new r(i.TOOL_ARGUMENT_INVALID,n(e),{category:"tool",userMessage:"The selected model returned malformed tool arguments. Retry the request or choose a model with reliable tool-calling support.",retryable:!0,cause:e}):t==="TOOL_DENIED"||t==="TOOL_APPROVAL_REQUIRED"?new r(i.TOOL_DENIED,n(e),{category:"tool",userMessage:"The tool action was denied by the active workspace policy. Use interactive approval or configure an explicit workspace permission.",retryable:!1,...a,cause:e}):t==="TOOL_EXECUTION_FAILED"||t==="MCP_OPERATION_FAILED"||t==="MCP_DISCONNECTED"?new r(i.TOOL_EXECUTION_FAILED,n(e),{category:"tool",userMessage:"The selected tool could not complete. Retry the request; if it persists, check the tool or MCP server connection.",retryable:!0,...a,cause:e}):t==="TOOL_NOT_FOUND"?new r(i.MODEL_STREAM_FAILED,n(e),{category:"model",userMessage:"The selected model requested a tool that is unavailable in this CLI session. Retry the request or choose another model.",retryable:!0,cause:e}):t==="AGENT_LIMIT_EXCEEDED"?new r(i.AGENT_STUCK,n(e),{category:"agent",userMessage:"The agent reached a safety limit before completing. Narrow the task and try again.",retryable:!0,cause:e}):t==="MODEL_RESPONSE_INVALID"||t==="RESPONSE_PARSE_ERROR"||d(e)?new r(i.MODEL_STREAM_FAILED,n(e),{category:"model",userMessage:"The model provider could not complete the request. Retry; if it persists, check the selected model, credentials, and base URL.",retryable:!0,cause:e}):new r(i.INTERNAL_ERROR,e instanceof Error?e.message:String(e),{category:"general",userMessage:"An internal error occurred.",hint:{actionId:"doctor"},cause:e})}function o(e){if(typeof e!="object"||e===null)return;const t=e;return typeof t.code=="string"?t.code:typeof t.errorCode=="string"?t.errorCode:void 0}function c(e){let t=e;for(let a=0;a<5&&t!==void 0&&t!==null;a+=1){if(typeof t!="object")return!1;const s=t;if(s.name==="AbortError"||s.code==="ABORT_ERR"||typeof s.message=="string"&&/\b(aborted|cancelled|canceled)\b/iu.test(s.message))return!0;t=s.cause}return!1}function l(e){if(typeof e!="object"||e===null)return{};const t=e;return{...typeof t.correlationId=="string"?{correlationId:t.correlationId}:{},...u(t.details)?{details:t.details}:{}}}function u(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function d(e){return n(e)==="Upstream AI provider request failed."}function n(e){return e instanceof Error?e.message:String(e)}export{r as CliError,f as asCliError};
1
+ import{CLI_ERROR_CODES as r}from"./error-codes.js";class i extends Error{code;category;userMessage;retryable;exitCode;correlationId;details;hint;constructor(t,a,s){super(a,{cause:s.cause}),this.name="CliError",this.code=t,this.category=s.category,this.userMessage=s.userMessage??a,this.retryable=s.retryable??!1,this.exitCode=s.exitCode??1,this.correlationId=s.correlationId,this.details=s.details,this.hint=s.hint}toJSON(){return{code:this.code,category:this.category,message:this.message,userMessage:this.userMessage,retryable:this.retryable,exitCode:this.exitCode,...this.correlationId!==void 0?{correlationId:this.correlationId}:{},...this.details!==void 0?{details:this.details}:{}}}}function h(e){if(e instanceof i)return e;const t=c(e),a=u(e);if(t==="REQUEST_ABORTED"||d(e))return new i(r.INTERRUPTED,n(e),{category:"agent",userMessage:"The request was interrupted.",retryable:!0,...a,cause:e});if(t==="REQUEST_TIMEOUT"||t==="NETWORK_ERROR")return new i(r.MEDIA_REQUEST_FAILED,n(e),{category:"media",userMessage:"The media request could not be completed. Retry the request; if it persists, check the selected model, credentials, and network connection.",retryable:!0,...a,cause:e});if(t==="REQUEST_PAYLOAD_TOO_LARGE"){const s=a.details?.kind==="json-body",o=E(a.details?.maxBytes);return new i(r.INVALID_ARGUMENT,n(e),{category:"media",userMessage:s?`The serialized Gateway request exceeds ${o}. Remove some attachments or reduce the prompt/context.`:"The media request exceeds a Gateway file or aggregate size limit. Review the command options and input file size.",...a,cause:e})}return t==="REQUEST_VALIDATION_ERROR"?new i(r.INVALID_ARGUMENT,n(e),{category:"media",userMessage:"The media request does not satisfy a gateway validation limit. Review the command options and input file size.",...a,cause:e}):t==="RESPONSE_TOO_LARGE"?new i(r.MEDIA_RESPONSE_TOO_LARGE,n(e),{category:"media",userMessage:"The generated media exceeds the supported download size.",retryable:!1,...a,cause:e}):t==="TOOL_ARGUMENTS_INVALID"?new i(r.TOOL_ARGUMENT_INVALID,n(e),{category:"tool",userMessage:"The selected model returned malformed tool arguments. Retry the request or choose a model with reliable tool-calling support.",retryable:!0,cause:e}):t==="TOOL_DENIED"||t==="TOOL_APPROVAL_REQUIRED"?new i(r.TOOL_DENIED,n(e),{category:"tool",userMessage:"The tool action was denied by the active workspace policy. Use interactive approval or configure an explicit workspace permission.",retryable:!1,...a,cause:e}):t==="TOOL_EXECUTION_FAILED"||t==="MCP_OPERATION_FAILED"||t==="MCP_DISCONNECTED"?new i(r.TOOL_EXECUTION_FAILED,n(e),{category:"tool",userMessage:"The selected tool could not complete. Retry the request; if it persists, check the tool or MCP server connection.",retryable:!0,...a,cause:e}):t==="TOOL_NOT_FOUND"?new i(r.MODEL_STREAM_FAILED,n(e),{category:"model",userMessage:"The selected model requested a tool that is unavailable in this CLI session. Retry the request or choose another model.",retryable:!0,cause:e}):t==="AGENT_LIMIT_EXCEEDED"?new i(r.AGENT_STUCK,n(e),{category:"agent",userMessage:"The agent reached a safety limit before completing. Narrow the task and try again.",retryable:!0,cause:e}):t==="MODEL_RESPONSE_INVALID"||t==="RESPONSE_PARSE_ERROR"||f(e)?new i(r.MODEL_STREAM_FAILED,n(e),{category:"model",userMessage:"The model provider could not complete the request. Retry; if it persists, check the selected model, credentials, and base URL.",retryable:!0,cause:e}):new i(r.INTERNAL_ERROR,e instanceof Error?e.message:String(e),{category:"general",userMessage:"An internal error occurred.",hint:{actionId:"doctor"},cause:e})}function c(e){if(typeof e!="object"||e===null)return;const t=e;return typeof t.code=="string"?t.code:typeof t.errorCode=="string"?t.errorCode:void 0}function d(e){let t=e;for(let a=0;a<5&&t!==void 0&&t!==null;a+=1){if(typeof t!="object")return!1;const s=t;if(s.name==="AbortError"||s.code==="ABORT_ERR"||typeof s.message=="string"&&/\b(aborted|cancelled|canceled)\b/iu.test(s.message))return!0;t=s.cause}return!1}function u(e){if(typeof e!="object"||e===null)return{};const t=e;return{...typeof t.correlationId=="string"?{correlationId:t.correlationId}:{},...l(t.details)?{details:t.details}:{}}}function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function E(e){if(typeof e!="number"||!Number.isFinite(e)||e<=0)return"the configured size limit";const t=e/1e6;return Number.isInteger(t)?`${t} MB`:`${e} bytes`}function f(e){return n(e)==="Upstream AI provider request failed."}function n(e){return e instanceof Error?e.message:String(e)}export{i as CliError,h as asCliError};
@@ -0,0 +1 @@
1
+ export declare const MAX_PLUGIN_DISPLAY_NAME_LENGTH = 128;
@@ -0,0 +1 @@
1
+ const _=128;export{_ as MAX_PLUGIN_DISPLAY_NAME_LENGTH};
@@ -2,8 +2,4 @@
2
2
  export declare const HOST_TOOL_PLUGIN_IDS: {
3
3
  readonly browser: "browser-use";
4
4
  readonly computer: "computer-use";
5
- readonly pdf: "pdf";
6
- readonly pptx: "pptx";
7
- readonly excel: "excel";
8
- readonly docs: "docs";
9
5
  };
@@ -1 +1 @@
1
- const e={browser:"browser-use",computer:"computer-use",pdf:"pdf",pptx:"pptx",excel:"excel",docs:"docs"};export{e as HOST_TOOL_PLUGIN_IDS};
1
+ const e={browser:"browser-use",computer:"computer-use"};export{e as HOST_TOOL_PLUGIN_IDS};
@@ -1 +1 @@
1
- import{CliError as g}from"../errors/cli-error.js";import{CLI_ERROR_CODES as h}from"../errors/error-codes.js";import{findUnexpectedRecordKey as N,isRecord as w}from"../validation/record-schema.js";const y=128,b={markerDirectory:".lotagate-plugin",manifestFile:"plugin.json",skillsDirectory:"skills",agentsDirectory:"agents",hooksDirectory:"hooks",mcpDirectory:"mcp",readmeFile:"README.md",licenseFile:"LICENSE"};function v(n,t){if(!w(n))throw i("Manifest must be a JSON object.");const e=n,r=N(e,["name","displayName","version","description","author","license","homepage","repository","keywords"]);if(r!==void 0)throw i(`Unsupported manifest field: \`${r}\`.`);const s=e.name,d=A(e),a=e.version,f=o(e,"description"),c=o(e,"author"),u=o(e,"license"),l=o(e,"homepage"),m=o(e,"repository"),p=k(e,"keywords");if(typeof s!="string"||!/^[a-z0-9][a-z0-9-]{0,63}$/.test(s))throw i("Plugin name must use lowercase kebab-case.");if(typeof a!="string"||!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(a))throw i("Plugin version must be semver-like.");return{name:s,...d===void 0?{}:{displayName:d},version:a,...f===void 0?{}:{description:f},...c===void 0?{}:{author:c},...u===void 0?{}:{license:u},...l===void 0?{}:{homepage:l},...m===void 0?{}:{repository:m},...p===void 0?{}:{keywords:p},directory:t}}function A(n){const t=n.displayName;if(t===void 0)return;if(typeof t!="string")throw i("Manifest field `displayName` must be a string.");const e=t.trim();if(e.length===0||e.length>y||M(e))throw i(`Manifest field \`displayName\` must be a non-empty string of at most ${y} characters.`);return e}function M(n){return[...n].some(t=>{const e=t.codePointAt(0)??0;return e<32||e===127})}function o(n,t){const e=n[t];if(e!==void 0){if(typeof e!="string")throw i(`Manifest field \`${t}\` must be a string.`);return e}}function k(n,t){const e=n[t];if(e!==void 0){if(!Array.isArray(e)||e.some(r=>typeof r!="string"||r.trim().length===0))throw i(`Manifest field \`${t}\` must be an array of non-empty strings.`);return e.map(r=>r.trim())}}function i(n){return new g(h.PLUGIN_MANIFEST_INVALID,n,{category:"extension",userMessage:`Invalid plugin: ${n}`})}export{b as PLUGIN_LAYOUT,v as parsePluginManifest};
1
+ import{CliError as g}from"../errors/cli-error.js";import{CLI_ERROR_CODES as h}from"../errors/error-codes.js";import{findUnexpectedRecordKey as N,isRecord as w}from"../validation/record-schema.js";import{MAX_PLUGIN_DISPLAY_NAME_LENGTH as y}from"./extension-constants.js";const v={markerDirectory:".lotagate-plugin",manifestFile:"plugin.json",skillsDirectory:"skills",agentsDirectory:"agents",hooksDirectory:"hooks",mcpDirectory:"mcp",readmeFile:"README.md",licenseFile:"LICENSE"};function L(n,t){if(!w(n))throw i("Manifest must be a JSON object.");const e=n,r=N(e,["name","displayName","version","description","author","license","homepage","repository","keywords"]);if(r!==void 0)throw i(`Unsupported manifest field: \`${r}\`.`);const s=e.name,d=A(e),a=e.version,f=o(e,"description"),u=o(e,"author"),c=o(e,"license"),m=o(e,"homepage"),l=o(e,"repository"),p=k(e,"keywords");if(typeof s!="string"||!/^[a-z0-9][a-z0-9-]{0,63}$/.test(s))throw i("Plugin name must use lowercase kebab-case.");if(typeof a!="string"||!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(a))throw i("Plugin version must be semver-like.");return{name:s,...d===void 0?{}:{displayName:d},version:a,...f===void 0?{}:{description:f},...u===void 0?{}:{author:u},...c===void 0?{}:{license:c},...m===void 0?{}:{homepage:m},...l===void 0?{}:{repository:l},...p===void 0?{}:{keywords:p},directory:t}}function A(n){const t=n.displayName;if(t===void 0)return;if(typeof t!="string")throw i("Manifest field `displayName` must be a string.");const e=t.trim();if(e.length===0||e.length>y||M(e))throw i(`Manifest field \`displayName\` must be a non-empty string of at most ${y} characters.`);return e}function M(n){return[...n].some(t=>{const e=t.codePointAt(0)??0;return e<32||e===127})}function o(n,t){const e=n[t];if(e!==void 0){if(typeof e!="string")throw i(`Manifest field \`${t}\` must be a string.`);return e}}function k(n,t){const e=n[t];if(e!==void 0){if(!Array.isArray(e)||e.some(r=>typeof r!="string"||r.trim().length===0))throw i(`Manifest field \`${t}\` must be an array of non-empty strings.`);return e.map(r=>r.trim())}}function i(n){return new g(h.PLUGIN_MANIFEST_INVALID,n,{category:"extension",userMessage:`Invalid plugin: ${n}`})}export{v as PLUGIN_LAYOUT,L as parsePluginManifest};
@@ -18,14 +18,6 @@ export interface IntentCompilationInput {
18
18
  readonly objective: string;
19
19
  readonly steps: readonly Omit<IntentStep, 'id'>[];
20
20
  }
21
- /**
22
- * Applies a deterministic safety correction to the model-assisted intent
23
- * classification. Direct information questions are answer work, even when
24
- * the model describes them with a research-like objective such as "find".
25
- * Explicit work requests remain unchanged and continue through host evidence
26
- * and verification gates.
27
- */
28
- export declare function stabilizeIntentCompilation(prompt: string, input: IntentCompilationInput): IntentCompilationInput;
29
21
  export interface CompletionAssessment {
30
22
  readonly decision: 'complete' | 'continue';
31
23
  readonly missing: readonly string[];
@@ -1 +1 @@
1
- import h from"node:crypto";import{CliError as u}from"../errors/cli-error.js";import{CLI_ERROR_CODES as d}from"../errors/error-codes.js";import{findUnexpectedRecordKey as c,isRecord as s}from"../validation/record-schema.js";const f=["answer","research","change","automation"];function j(t,e){return e.kind==="answer"||!b(t)?e:{...e,kind:"answer",steps:e.steps.map(i=>({...i,requiresVerification:!1}))}}function p(t){return t==="change"||t==="automation"}function m(t,e=new Date().toISOString()){const i=l(t),n=p(i.kind);return{id:h.randomUUID(),kind:i.kind,objective:i.objective,steps:i.steps.map((o,a)=>({...o,requiresVerification:n||o.requiresVerification,id:`step-${a+1}`})),createdAt:e}}function l(t){if(!s(t))throw r("Intent compilation must be an object.");const e=c(t,["kind","objective","steps"]);if(e!==void 0)throw r(`Unsupported intent field: ${e}.`);const i=t.kind,n=t.objective,o=t.steps;if(!w(i))throw r("Intent kind is invalid.");if(typeof n!="string"||n.trim().length===0||n.length>16384)throw r("Intent objective is invalid.");if(!Array.isArray(o)||o.length===0||o.length>10)throw r("Intent requires between one and ten steps.");return{kind:i,objective:n.trim(),steps:o.map(y)}}function V(t){const e=t.trim();if(e.length===0)throw r("Intent objective is required.");const i=I(e);return m({kind:i,objective:e,steps:[{title:g(i),acceptanceCriteria:[e],requiresVerification:i==="change"||i==="automation"}]})}function g(t){return t==="change"?"Implement and verify the requested change":"Address the requested outcome"}function w(t){return typeof t=="string"&&f.includes(t)}function y(t){if(!s(t))throw r("Intent step is invalid.");const e=c(t,["title","acceptanceCriteria","requiresVerification"]);if(e!==void 0)throw r(`Unsupported intent step field: ${e}.`);const i=t.title,n=t.acceptanceCriteria,o=t.requiresVerification;if(typeof i!="string"||i.trim().length===0||i.length>2048)throw r("Intent step title is invalid.");if(!Array.isArray(n)||n.length===0||n.length>16||n.some(a=>typeof a!="string"||a.trim().length===0||a.length>2048))throw r("Intent acceptance criteria are invalid.");if(typeof o!="boolean")throw r("Intent verification requirement is invalid.");return{title:i.trim(),acceptanceCriteria:n.map(a=>String(a).trim()),requiresVerification:o}}function I(t){const e=t.toLocaleLowerCase();return/(fix|implement|change|refactor|add|remove|sửa|triển khai|thêm|xóa)/u.test(e)?"change":/(research|investigate|audit|analy[sz]e|nghiên cứu|kiểm tra|đánh giá)/u.test(e)?"research":/(run|execute|deploy|monitor|automation|chạy|triển khai|theo dõi)/u.test(e)?"automation":"answer"}function b(t){const e=t.trim().toLocaleLowerCase();return e.length===0||k(e)?!1:/[?؟]/u.test(e)||/(?:^|\s)(?:what|who|where|when|why|how|which|is|are|can|do|does|là gì|ai|ở đâu|khi nào|tại sao|thế nào|như nào|nào|có phải|có .* không|cho biết|nói cho tôi biết)\b/iu.test(e)||/(?:memory|context|ghi nhớ|đã lưu|remembered|what do you know)/iu.test(e)}function k(t){return/(?:implement|fix|change|edit|write|create|remove|delete|build|run|test|audit|research|investigate|analy[sz]e|check|inspect|review|verify|validate|trace|deploy|monitor|sửa|thay đổi|viết|tạo|xóa|chạy|xem|kiểm tra|rà soát|nghiên cứu|triển khai|theo dõi)\b/iu.test(t)}function r(t){return new u(d.INVALID_ARGUMENT,t,{category:"intent",userMessage:t})}export{f as INTENT_KINDS,m as createIntentContract,V as fallbackIntent,w as isIntentKind,l as normalizeIntentCompilation,p as requiresHostVerification,j as stabilizeIntentCompilation};
1
+ import p from"node:crypto";import{CliError as f}from"../errors/cli-error.js";import{CLI_ERROR_CODES as d}from"../errors/error-codes.js";import{findUnexpectedRecordKey as s,isRecord as a}from"../validation/record-schema.js";const u=["answer","research","change","automation"];function l(t){return t==="change"||t==="automation"}function h(t,n=new Date().toISOString()){const e=m(t),i=l(e.kind);return{id:p.randomUUID(),kind:e.kind,objective:e.objective,steps:e.steps.map((o,c)=>({...o,requiresVerification:i||o.requiresVerification,id:`step-${c+1}`})),createdAt:n}}function m(t){if(!a(t))throw r("Intent compilation must be an object.");const n=s(t,["kind","objective","steps"]);if(n!==void 0)throw r(`Unsupported intent field: ${n}.`);const e=t.kind,i=t.objective,o=t.steps;if(!g(e))throw r("Intent kind is invalid.");if(typeof i!="string"||i.trim().length===0||i.length>16384)throw r("Intent objective is invalid.");if(!Array.isArray(o)||o.length===0||o.length>10)throw r("Intent requires between one and ten steps.");return{kind:e,objective:i.trim(),steps:o.map(I)}}function j(t){const n=t.trim();if(n.length===0)throw r("Intent objective is required.");return h({kind:"change",objective:n,steps:[{title:"Handle and verify the requested outcome",acceptanceCriteria:[n],requiresVerification:!0}]})}function g(t){return typeof t=="string"&&u.includes(t)}function I(t){if(!a(t))throw r("Intent step is invalid.");const n=s(t,["title","acceptanceCriteria","requiresVerification"]);if(n!==void 0)throw r(`Unsupported intent step field: ${n}.`);const e=t.title,i=t.acceptanceCriteria,o=t.requiresVerification;if(typeof e!="string"||e.trim().length===0||e.length>2048)throw r("Intent step title is invalid.");if(!Array.isArray(i)||i.length===0||i.length>16||i.some(c=>typeof c!="string"||c.trim().length===0||c.length>2048))throw r("Intent acceptance criteria are invalid.");if(typeof o!="boolean")throw r("Intent verification requirement is invalid.");return{title:e.trim(),acceptanceCriteria:i.map(c=>String(c).trim()),requiresVerification:o}}function r(t){return new f(d.INVALID_ARGUMENT,t,{category:"intent",userMessage:t})}export{u as INTENT_KINDS,h as createIntentContract,j as fallbackIntent,g as isIntentKind,m as normalizeIntentCompilation,l as requiresHostVerification};