@lotagate/cli 0.1.28 → 0.1.29

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 (77) hide show
  1. package/LICENSE.md +79 -21
  2. package/README.md +31 -2
  3. package/dist/application/agent/cli-agent-execution-service.d.ts +2 -0
  4. package/dist/application/agent/cli-agent-execution-service.js +1 -1
  5. package/dist/application/agent/context-compaction.d.ts +2 -0
  6. package/dist/application/agent/context-compaction.js +7 -7
  7. package/dist/application/agent/interactive-agent-guidance.js +1 -1
  8. package/dist/application/commands/cli-command-services.js +33 -33
  9. package/dist/application/extensions/extension-list-scope-policy.d.ts +9 -0
  10. package/dist/application/extensions/extension-list-scope-policy.js +1 -0
  11. package/dist/application/intent/completion-gate.js +1 -1
  12. package/dist/application/intent/evidence-ledger.d.ts +6 -3
  13. package/dist/application/intent/evidence-recording-tool-executor.d.ts +5 -2
  14. package/dist/application/intent/evidence-recording-tool-executor.js +1 -1
  15. package/dist/application/intent/intent-compiler.d.ts +15 -2
  16. package/dist/application/intent/intent-compiler.js +3 -2
  17. package/dist/application/intent/intent-execution-gate.d.ts +4 -1
  18. package/dist/application/intent/intent-execution-gate.js +1 -1
  19. package/dist/application/intent/intent-run-controller.d.ts +2 -1
  20. package/dist/application/intent/intent-run-controller.js +2 -2
  21. package/dist/application/model/model-response-retry.d.ts +21 -0
  22. package/dist/application/model/model-response-retry.js +1 -1
  23. package/dist/application/orchestration/cli-turn-event-projector.d.ts +1 -1
  24. package/dist/application/orchestration/cli-turn-event-projector.js +1 -1
  25. package/dist/application/orchestration/cli-turn-events.d.ts +7 -0
  26. package/dist/application/orchestration/cli-turn-events.js +1 -1
  27. package/dist/application/protocol/computer-host-tool-executor.d.ts +8 -0
  28. package/dist/application/protocol/computer-host-tool-executor.js +2 -2
  29. package/dist/application/protocol/desktop-agent-command.js +1 -1
  30. package/dist/application/protocol/desktop-command-runner.d.ts +19 -0
  31. package/dist/application/protocol/desktop-command-runner.js +1 -0
  32. package/dist/application/protocol/desktop-intent-event-writer.js +1 -1
  33. package/dist/application/protocol/desktop-turn-execution-service.d.ts +43 -0
  34. package/dist/application/protocol/desktop-turn-execution-service.js +1 -0
  35. package/dist/application/protocol/jsonl-agent-command.js +2 -2
  36. package/dist/application/security/tool-approval-service.js +1 -1
  37. package/dist/application/workspace/session-execution-workspace.d.ts +10 -1
  38. package/dist/application/workspace/session-execution-workspace.js +3 -3
  39. package/dist/application/workspace/session-worktree.d.ts +6 -0
  40. package/dist/application/workspace/session-worktree.js +1 -0
  41. package/dist/application/workspace/workspace-constants.d.ts +0 -1
  42. package/dist/application/workspace/workspace-constants.js +1 -1
  43. package/dist/bootstrap/runtime-factory.js +1 -1
  44. package/dist/domain/errors/error-codes.d.ts +1 -0
  45. package/dist/domain/errors/error-codes.js +1 -1
  46. package/dist/domain/intent/intent-contract.d.ts +0 -1
  47. package/dist/domain/intent/intent-contract.js +1 -1
  48. package/dist/domain/runtime/resource-limits.d.ts +4 -0
  49. package/dist/domain/runtime/resource-limits.js +1 -1
  50. package/dist/domain/workspace/workspace-materialization-policy.d.ts +6 -0
  51. package/dist/domain/workspace/workspace-materialization-policy.js +1 -0
  52. package/dist/infrastructure/agent-sdk/agent-instance-factory.d.ts +3 -0
  53. package/dist/infrastructure/agent-sdk/agent-instance-factory.js +1 -1
  54. package/dist/infrastructure/agent-sdk/tool-calling-completion-client.d.ts +2 -1
  55. package/dist/infrastructure/agent-sdk/tool-calling-completion-client.js +1 -1
  56. package/dist/infrastructure/agent-sdk/tool-calling-model-client.d.ts +2 -1
  57. package/dist/infrastructure/agent-sdk/tool-calling-model-client.js +1 -1
  58. package/dist/infrastructure/agent-sdk/tool-calling-model-normalization.d.ts +7 -0
  59. package/dist/infrastructure/agent-sdk/tool-calling-model-normalization.js +1 -0
  60. package/dist/infrastructure/clipboard/windows-clipboard-adapter.js +1 -1
  61. package/dist/infrastructure/credentials/composite-credential-store.js +1 -1
  62. package/dist/infrastructure/extensions/skill-tool-executor.js +4 -2
  63. package/dist/infrastructure/observability/tool-execution-logger.js +1 -1
  64. package/dist/infrastructure/platform/host-process.js +1 -1
  65. package/dist/infrastructure/platform/platform-constants.d.ts +1 -0
  66. package/dist/infrastructure/platform/platform-constants.js +1 -1
  67. package/dist/infrastructure/platform/process-termination.js +1 -1
  68. package/dist/infrastructure/workspace/workspace-materializer.d.ts +26 -0
  69. package/dist/infrastructure/workspace/workspace-materializer.js +2 -0
  70. package/dist/presentation/tui/tui-agent-event-runner.js +1 -1
  71. package/dist/presentation/tui/tui-agent-turn-controller.js +1 -1
  72. package/dist/presentation/tui/tui-application.js +2 -2
  73. package/dist/presentation/tui/tui-context-compaction.d.ts +2 -1
  74. package/dist/presentation/tui/tui-context-compaction.js +1 -1
  75. package/dist/version.d.ts +1 -1
  76. package/dist/version.js +1 -1
  77. package/package.json +10 -10
@@ -0,0 +1 @@
1
+ import{randomUUID as Y}from"node:crypto";import{AuthenticationService as q}from"../auth/authentication-service.js";import{createLotaGateClient as V}from"../../infrastructure/sdk/lotagate-client-factory.js";import{loadExecutionConfig as X}from"../config/execution-config.js";import{prepareCliAgent as Z}from"../agent/cli-agent-execution-service.js";import{createContextManagement as tt}from"../agent/context-compaction.js";import{persistContextCompaction as et}from"../agent/context-compaction-persistence.js";import{AgentRunTracker as ot}from"../agent/agent-run-tracker.js";import{formatContinuationCheckpoint as at}from"../agent/continuation-checkpoint.js";import{CliTurnEventProjector as it}from"../orchestration/cli-turn-event-projector.js";import{persistCliTurnEvent as st}from"../orchestration/cli-turn-persistence.js";import{recordTurnCompletion as nt,recordTurnFailure as rt,recordTurnStart as ct}from"../session/session-turn-lifecycle.js";import{permissionRuleForRequest as pt}from"../security/workspace-permission-policy.js";import{agentLimitNotice as dt,classifyAgentLimit as lt}from"../agent/agent-limit.js";import{CliError as b}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as S}from"../../domain/errors/error-codes.js";import{subagentDesktopPayload as mt}from"./desktop-orchestration-events.js";import{resolveModelContextWindow as ft}from"../model/model-context-window.js";import{ContextUsageService as ut}from"../agent/context-usage-service.js";import{desktopApprovalMode as wt}from"./desktop-protocol-helpers.js";import{buildUserMessage as gt}from"../../infrastructure/clipboard/image-normalizer.js";import{desktopMcpEvent as W}from"./desktop-mcp-events.js";import{artifactIdsData as B}from"./desktop-agent-helpers.js";import{createIsolatedGuestPlatform as ht}from"../../infrastructure/platform/host-platform.js";import{evaluateGatewayRequestBudget as yt}from"../../domain/runtime/gateway-request-budget.js";import{BoundedTextAccumulator as kt}from"../agent/bounded-text-accumulator.js";class Qt{options;constructor(a){this.options=a}async execute(a,o,r,d,i,u,x,s){try{await this.executeBody(a,o,r,d,i,u,x)}finally{await s()}}async executeBody(a,o,r,d,i,u,x){const{runtime:s,executionWorkspaces:C,approvalBroker:T,writeEvent:l}=this.options,N=await X(s,this.options.cwd);if(!await s.projectTrust.isTrusted(r)){const e=Y();if(await l("trust.requested",{trustRequestId:e,sessionId:o.id,path:r.canonicalPath}),!await T.waitForTrust(e,u.signal))throw new b(S.PROJECT_TRUST_REQUIRED,"Project trust was not granted.",{category:"project",userMessage:"Trust this project in the Desktop application before running tools."});await s.projectTrust.grant(r),s.agentPreparation?.clear(r.canonicalPath),await s.workspaceSettings.ensureInitialized(r.canonicalPath)}const f=a.params.model??o.model??N.config.model;if(f==null)throw new b(S.MODEL_NOT_FOUND,"No model is selected.",{category:"model",userMessage:"Select a model before starting a turn."});const $=a.params.reasoningEffort??N.config.effort;s.logger.info("CLI Desktop turn model resolved.",{sessionId:o.id,turnId:i,requestedModel:a.params.model,sessionModel:o.model,resolvedModel:f});const M=o.profile??N.config.profile??q.defaultProfileName(),j=await s.auth.requireCredential(M),I=V(j.profile,j.apiKey),O=await ft(s,f,M),R=new ot,P=this.options.sessionStores.getOrCreate(o.id,this.options.activeTurnSessionIds()),k=new Set,G=new ut(s,r.canonicalPath),L=async()=>{try{const e=await G.buildForProject({sessionId:o.id,model:f,profileName:M,pluginNames:[],pendingAttachments:0,agentSessionStore:P});await l("usage.updated",{turnId:i,sessionId:o.id,model:f,...e.contextWindow===void 0?{}:{contextWindow:e.contextWindow},usage:{promptTokens:e.usedTokens,estimated:!0}})}catch(e){s.logger.warn("Desktop context usage update failed.",{sessionId:o.id,turnId:i,reason:e instanceof Error?e.message:String(e)})}},h=new kt,y=[];for(const e of x){const c=e.attachment.storagePath===void 0?await s.sessionStore.saveAttachment(o.id,e.attachment,e.bytes):e.attachment;y.push({...e,attachment:c})}await ct(s.sessionStore,o.id,i,a.params.prompt,y.map(e=>e.attachment.id)),await s.sessionStore.updateStatus(o.id,"active"),await l("turn.started",{turnId:i,sessionId:o.id,model:f});const z={onSubagentLifecycle:e=>l(`subagent.${e.type}`,mt(e,i),{delivery:"best-effort"})},J={start:e=>{if(e.source!=="shell"&&e.source!=="computer"&&e.source!=="custom"&&e.toolName!=="filesystem.read"&&e.toolName!=="filesystem.write"&&e.toolName!=="filesystem.exists")return;const c={turnId:i,sessionId:o.id,actionId:e.key,toolName:e.toolName,displayName:e.label,...e.source==="shell"?{command:e.label}:{},kind:e.source??"tool",source:e.source},p=(w,m)=>{l(w,m,{delivery:"best-effort"}).catch(g=>s.logger.warn("Desktop tool activity event failed.",{event:w,reason:g instanceof Error?g.message:String(g)}))};return p("tool.activity.started",{...c,status:"running"}),{complete:(w,m)=>p("tool.activity.completed",{...c,...m??{},status:w?"failed":"completed",isError:w})}}},v={onReconnect:({attempt:e,maxAttempts:c,delayMs:p})=>l("network.reconnecting",{turnId:i,sessionId:o.id,actionId:`${i}:network-reconnect`,displayName:`Reconnecting ${e}/${c}`,attempt:e,maxAttempts:c,delayMs:p,status:"running",kind:"network"}),onReconnected:({attempt:e,maxAttempts:c})=>l("network.reconnected",{turnId:i,sessionId:o.id,actionId:`${i}:network-reconnect`,displayName:"Reconnected",attempt:e,maxAttempts:c,status:"completed",kind:"network"}),onReconnectFailed:({attempt:e,maxAttempts:c})=>l("network.reconnect.failed",{turnId:i,sessionId:o.id,actionId:`${i}:network-reconnect`,displayName:"Reconnecting failed",attempt:e,maxAttempts:c,status:"failed",isError:!0,kind:"network"})};let A,D=!1;const K=setTimeout(()=>u.abort(),a.params.execution.timeoutMs);try{const e=a.params.execution,c=this.options.hostCapabilities(),p=await Z({runtime:s,projectRoot:r.canonicalPath,executionCwd:d.executionCwd,executionWorkspaceId:d.id,model:f,client:I,reasoningEffort:$,profile:"interactive-trusted",approvalMode:wt(e.permissionPolicy),...e.allowedTools===void 0?{}:{allowedTools:e.allowedTools},...a.params.skills===void 0?{}:{selectedSkills:a.params.skills},browserAccess:e.browserAccess,subagentLifecycle:z,subagentJobs:this.options.subagentJobs,...this.options.isBrowserHostEnabled()?{browserHost:(t,n)=>this.options.hostBridge.requestBrowser(t,n)}:{},...this.options.isDesktopHostEnabled()?{desktopHost:((t,n)=>this.options.hostBridge.requestDesktop(t,n))}:{},...this.options.isComputerHostEnabled()?{computerHost:((t,n)=>this.options.hostBridge.requestComputer(t,n))}:{},onArtifacts:t=>{for(const n of t)k.add(n.id)},...c===void 0?{}:{hostCapabilities:c},executionBoundary:e.isolation,executionPlatform:e.isolation==="sandbox"?ht():s.platform,browserExecution:e.browserExecution,hostFallback:e.hostFallback,...this.options.isBrowserHostEnabled()||this.options.isDesktopHostEnabled()?{onExecutionFallbackApproval:(t,n)=>T.waitForApproval(t,o.id,i,u.signal,"host",n)}:{},toolActivity:J,networkRecovery:v,onIntentLifecycle:t=>this.options.intentEvents.write(t,o.id,i),contextManagement:tt({client:I,model:f,...O===void 0?{}:{contextWindow:O},onCompactionStart:()=>l("context.compacting",{turnId:i,sessionId:o.id}),onSummaryFailure:t=>s.logger.warn("Context summarization failed; using fallback summary.",{reason:t instanceof Error?t.message:String(t)}),continuationContext:()=>at({snapshot:R.snapshot()}),networkRecovery:v}),agentSessionStore:P,prompt:(t,n)=>T.waitForApproval(t,o.id,i,n??u.signal,e.isolation),rememberApproval:t=>s.workspaceSettings.rememberAllow(r.canonicalPath,pt(t.toolName,t.input)),audit:async t=>{const n={toolName:t.toolName,stage:t.stage,sessionId:t.sessionId,runId:t.runId,decision:t.decision,reason:t.reason,...t.source===void 0?{}:{source:t.source},...t.executorId===void 0?{}:{executorId:t.executorId},...t.ruleId===void 0?{}:{ruleId:t.ruleId},...t.skillName===void 0?{}:{skillName:t.skillName},...t.riskCategory===void 0?{}:{riskCategory:t.riskCategory}};s.logger.info("Tool authorization decision.",n),await s.sessionStore.appendEvent({type:"tool.approval",timestamp:new Date().toISOString(),sessionId:o.id,turnId:i,data:n})},onModelComplete:t=>{R.observeModel(t)},onWrite:t=>{l("file.changed",{turnId:i,sessionId:o.id,change:t},{delivery:"best-effort"}).catch(n=>s.logger.warn("Desktop file event failed.",{reason:n instanceof Error?n.message:String(n)}))},mcpLifecycle:t=>this.writeMcpRuntimeEvent(t,o.id,i)});A=p.close;const w=new it,m=await p.buildInput(a.params.prompt),g=await s.sessionStore.readHistory(o.id);P.hydrate(o.id,g.transcript,g.events,m.input);const E=yt(m.input,y.map(({attachment:t,bytes:n})=>({byteLength:n.byteLength,mimeType:t.mimeType,name:t.name})));if(!E.isWithinLimit)throw new b(S.ATTACHMENT_TOO_LARGE,"The prompt and attachments exceed the Gateway JSON body limit.",{category:"attachment",userMessage:`The prompt and attachments exceed the ${E.limitBytes/1e6} MB decimal Gateway JSON limit. Remove an attachment or shorten the prompt and retry.`,details:{kind:"gateway-json-body",maxBytes:E.limitBytes,projectedBytes:E.projectedBytes}});const F=y.length===0?void 0:gt(m.input,y),_=F?.content===null?void 0:F?.content,Q=await p.agent.initialize();for(const t of Q)(t.type==="mcp.server.status"||t.type==="mcp.tool.catalog.updated")&&await this.writeMcpEvent(t,o.id,i);for await(const t of p.run({input:m.input,userInput:m.userInput,...m.workspaceContext===void 0?{}:{workspaceContext:m.workspaceContext},..._===void 0?{}:{inputContent:_},model:f,sessionId:o.id,stream:!0,signal:u.signal,metadata:{taskId:a.params.taskId,turnId:i}})){R.observe(t),(t.type==="mcp.server.status"||t.type==="mcp.tool.catalog.updated")&&await this.writeMcpEvent(t,o.id,i),t.type==="context.compacted"&&(await et(s,p,o.id,t.metrics,i),await L());for(const n of w.observe(t))await this.emitProjected(n,o.id,i,h,k);if(t.type==="session.failed"){const n=lt(t.error);if(n===void 0)throw t.error;const H=dt(n);h.append(H);const U=`${i}:final`;await l("assistant.delta",{turnId:i,sessionId:o.id,segmentId:U,iteration:0,content:H}),await l("assistant.segment.completed",{turnId:i,sessionId:o.id,segmentId:U,iteration:0,phase:"final",...B(k)});break}}if(h.toString().trim().length===0)throw new b(S.MODEL_PROTOCOL_EMPTY_RESPONSE,"Agent completed without a final text response.",{category:"model",userMessage:"The model completed without a final text response.",retryable:!0});await C.apply(o.id),D=!0,await nt(s.sessionStore,o.id,i,h.toString()),await s.sessionStore.updateStatus(o.id,"completed"),await L(),await l("turn.completed",{turnId:i,sessionId:o.id,content:h.toString(),...B(k)})}catch(e){if(!D)try{const p=await C.apply(o.id);D=!0,p.appliedPaths.length>0&&s.logger.info("Applied session workspace changes after turn failure.",{sessionId:o.id,turnId:i,appliedPaths:p.appliedPaths})}catch(p){s.logger.error("Failed to apply session workspace changes after turn failure.",{sessionId:o.id,turnId:i,reason:p instanceof Error?p.message:String(p)})}const c=u.signal.aborted;throw await rt(s.sessionStore,o.id,i,e,c),await s.sessionStore.updateStatus(o.id,c?"cancelled":"failed"),e}finally{if(this.options.intentEvents.clear(i),clearTimeout(K),A!==void 0)try{await A()}catch(e){s.logger.warn("Desktop agent cleanup failed.",{reason:e instanceof Error?e.message:String(e)})}await C.markReady(o.id)}}async emitProjected(a,o,r,d,i){a.type==="assistant.segment.started"?await this.options.writeEvent("assistant.segment.started",{turnId:r,sessionId:o,segmentId:a.segmentId,iteration:a.iteration,phase:a.phase}):a.type==="assistant.delta"?(d.append(a.content),await this.options.writeEvent("assistant.delta",{turnId:r,sessionId:o,segmentId:a.segmentId,iteration:a.iteration,content:a.content})):a.type==="assistant.replaced"?(d.replace(a.content),await this.options.writeEvent("assistant.replaced",{turnId:r,sessionId:o,segmentId:a.segmentId,iteration:a.iteration,content:a.content})):a.type==="assistant.segment.completed"?await this.options.writeEvent("assistant.segment.completed",{turnId:r,sessionId:o,segmentId:a.segmentId,iteration:a.iteration,phase:a.phase,...a.phase==="final"?B(i):{}}):a.type==="action.started"?await this.options.writeEvent("tool.started",{turnId:r,sessionId:o,actionId:a.actionId,toolName:a.toolName,displayName:a.displayName,kind:a.kind,...a.source===void 0?{}:{source:a.source}}):a.type==="action.completed"?await this.options.writeEvent("tool.completed",{turnId:r,sessionId:o,actionId:a.actionId,toolName:a.toolName,displayName:a.displayName,kind:a.kind,status:a.status,isError:a.isError}):a.type==="context.compacted"&&await this.options.writeEvent("context.compacted",{turnId:r,sessionId:o}),await st(this.options.runtime.sessionStore,o,a,{turnId:r})}async writeMcpEvent(a,o,r){const d=W(a,o,r);await this.options.writeEvent(d.name,d.data)}async writeMcpRuntimeEvent(a,o,r){const d=W(a,o,r);await this.options.writeEvent(d.name,d.data)}}export{Qt as DesktopTurnExecutionService};
@@ -1,3 +1,3 @@
1
- import{AuthenticationService as L}from"../auth/authentication-service.js";import{JsonlProtocolRunner as O}from"./jsonl-protocol.js";import{createLotaGateClient as _}from"../../infrastructure/sdk/lotagate-client-factory.js";import{CliError as u}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as c}from"../../domain/errors/error-codes.js";import{prepareCliAgent as S}from"../agent/cli-agent-execution-service.js";import{AgentRunTracker as T}from"../agent/agent-run-tracker.js";import{loadExecutionConfig as b}from"../config/execution-config.js";import{agentLimitNotice as v,classifyAgentLimit as P}from"../agent/agent-limit.js";import{runDesktopAgentCommand as D}from"./desktop-agent-command.js";import{createContextManagement as I}from"../agent/context-compaction.js";import{formatContinuationCheckpoint as F}from"../agent/continuation-checkpoint.js";import{resolveModelContextWindow as U}from"../model/model-context-window.js";import{BoundedTextAccumulator as G}from"../agent/bounded-text-accumulator.js";async function to(R,t,l,C,h,w){const y=R[0]??"stdio";if(y==="desktop")return D(t,l,C,h,w);if(y!=="stdio")throw new u(c.INVALID_ARGUMENT,"Unsupported agent action.",{category:"arguments",userMessage:"Use `lotagate agent stdio` or `lotagate agent desktop`."});const i=await b(t,l);if(i.config.model===null)throw new u(c.MODEL_NOT_FOUND,"No model is selected.",{category:"model",userMessage:"Select a model before running the stdio agent."});const N=i.config.profile??L.defaultProfileName(),M=await t.auth.requireCredential(N);return(await new O(async function*(d,k){const n=d.params.model??i.config.model;t.logger.info("Protocol agent request started.",{model:n,promptLength:d.params.prompt.length});const a=new T,x=_(M.profile,M.apiKey),E=await U(t,n,N),A=e=>{a.observeModel(e),t.logger.debug("Model turn completed.",{model:e.model,stream:e.stream,contentLength:e.contentLength,toolCallCount:e.toolCallCount,toolNames:e.toolNames,finishReason:e.finishReason})},m=await S({runtime:t,projectRoot:l,executionCwd:l,model:n,client:x,profile:"protocol-safe",approvalMode:i.config.approvalMode,onModelComplete:A,contextManagement:I({client:x,model:n,...E===void 0?{}:{contextWindow:E},onSummaryFailure:e=>t.logger.warn("Context summarization failed; using fallback summary.",{reason:e instanceof Error?e.message:String(e)}),continuationContext:()=>F({snapshot:a.snapshot()})})});let f=!1;const r=new G;let s;try{const e=await m.buildInput(d.params.prompt);for await(const o of m.run({input:e.input,userInput:e.userInput,...e.workspaceContext===void 0?{}:{workspaceContext:e.workspaceContext},model:n,signal:k}))if(a.observe(o),o.type==="tool.called"&&t.logger.info("Agent tool called.",{toolName:o.toolName}),o.type==="tool.completed"&&t.logger.info("Agent tool completed.",{toolName:o.toolName,isError:o.isError}),o.type==="model.delta"&&o.content.length>0?(f=!0,r.append(o.content),yield{type:"delta",content:o.content}):o.type==="session.completed"&&r.replace(o.content),o.type==="session.failed"){const p=P(o.error);if(p===void 0)throw o.error;s=v(p);break}if(s!==void 0){const o=r.isEmpty?s:`
1
+ import{AuthenticationService as A}from"../auth/authentication-service.js";import{JsonlProtocolRunner as O}from"./jsonl-protocol.js";import{createLotaGateClient as _}from"../../infrastructure/sdk/lotagate-client-factory.js";import{CliError as u}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as c}from"../../domain/errors/error-codes.js";import{prepareCliAgent as S}from"../agent/cli-agent-execution-service.js";import{AgentRunTracker as T}from"../agent/agent-run-tracker.js";import{loadExecutionConfig as b}from"../config/execution-config.js";import{agentLimitNotice as v,classifyAgentLimit as P}from"../agent/agent-limit.js";import{runDesktopAgentCommand as D}from"./desktop-agent-command.js";import{createContextManagement as I}from"../agent/context-compaction.js";import{formatContinuationCheckpoint as F}from"../agent/continuation-checkpoint.js";import{resolveModelContextWindow as U}from"../model/model-context-window.js";import{BoundedTextAccumulator as G}from"../agent/bounded-text-accumulator.js";async function oe(R,o,i,C,h,w){const y=R[0]??"stdio";if(y==="desktop")return D(o,i,C,h,w);if(y!=="stdio")throw new u(c.INVALID_ARGUMENT,"Unsupported agent action.",{category:"arguments",userMessage:"Use `lotagate agent stdio` or `lotagate agent desktop`."});const l=await b(o,i);if(l.config.model===null)throw new u(c.MODEL_NOT_FOUND,"No model is selected.",{category:"model",userMessage:"Select a model before running the stdio agent."});const M=l.config.profile??A.defaultProfileName(),x=await o.auth.requireCredential(M);return(await new O(async function*(d,k){const n=d.params.model??l.config.model;o.logger.info("Protocol agent request started.",{model:n,promptLength:d.params.prompt.length});const a=new T,N=_(x.profile,x.apiKey),E=await U(o,n,M),L=t=>{a.observeModel(t),o.logger.debug("Model turn completed.",{model:t.model,stream:t.stream,contentLength:t.contentLength,toolCallCount:t.toolCallCount,toolNames:t.toolNames,finishReason:t.finishReason})},m=await S({runtime:o,projectRoot:i,executionCwd:i,model:n,client:N,profile:"protocol-safe",approvalMode:l.config.approvalMode,onModelComplete:L,contextManagement:I({client:N,model:n,...E===void 0?{}:{contextWindow:E},onSummaryFailure:t=>o.logger.warn("Context summarization failed; using fallback summary.",{reason:t instanceof Error?t.message:String(t)}),continuationContext:()=>F({snapshot:a.snapshot()})})});let f=!1;const r=new G;let s;try{const t=await m.buildInput(d.params.prompt);for await(const e of m.run({input:t.input,userInput:t.userInput,...t.workspaceContext===void 0?{}:{workspaceContext:t.workspaceContext},model:n,signal:k}))if(a.observe(e),e.type==="model.delta"&&e.content.length>0?(f=!0,r.append(e.content),yield{type:"delta",content:e.content}):e.type==="session.completed"&&r.replace(e.content),e.type==="session.failed"){const p=P(e.error);if(p===void 0)throw e.error;s=v(p);break}if(s!==void 0){const e=r.isEmpty?s:`
2
2
 
3
- ${s}`;f=!0,r.append(o),yield{type:"delta",content:o}}const g=r.toString();if(g.trim().length===0){const o=a.snapshot();o.toolCalls>0&&a.markStuck();const p=o.toolCalls>0?c.MODEL_EMPTY_FINAL:c.MODEL_PROTOCOL_EMPTY_RESPONSE;throw new u(p,"Agent completed without a final text response.",{category:"model",userMessage:"The model completed without a final text response.",retryable:!0,details:{toolCalls:o.toolCalls,toolCompletions:o.toolCompletions,toolNames:o.toolNames,finishReason:o.lastFinishReason}})}f||(yield{type:"delta",content:g}),yield{type:"completed",content:g},t.logger.info("Protocol agent request completed.",{model:n})}finally{await m.close()}}).run(C,h,w)).errorCount===0?0:1}export{to as runAgentCommand};
3
+ ${s}`;f=!0,r.append(e),yield{type:"delta",content:e}}const g=r.toString();if(g.trim().length===0){const e=a.snapshot();e.toolCalls>0&&a.markStuck();const p=e.toolCalls>0?c.MODEL_EMPTY_FINAL:c.MODEL_PROTOCOL_EMPTY_RESPONSE;throw new u(p,"Agent completed without a final text response.",{category:"model",userMessage:"The model completed without a final text response.",retryable:!0,details:{toolCalls:e.toolCalls,toolCompletions:e.toolCompletions,toolNames:e.toolNames,finishReason:e.lastFinishReason}})}f||(yield{type:"delta",content:g}),yield{type:"completed",content:g},o.logger.info("Protocol agent request completed.",{model:n})}finally{await m.close()}}).run(C,h,w)).errorCount===0?0:1}export{oe as runAgentCommand};
@@ -1 +1 @@
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};
1
+ import{requiresMutationApproval as r}from"./tool-risk-classifier.js";import{assessToolAction as a}from"./tool-action-risk-analyzer.js";import{workspacePermissionDecision as n}from"./workspace-permission-policy.js";import{matchesDesktopToolScope as l}from"./desktop-tool-scope-policy.js";class h{options;constructor(o){this.options=o}policy(){return{authorizationRules:[...this.options.desktopToolScopes===void 0?[]:[{id:"desktop-tool-scope",authorize:i=>this.authorizeDesktopScope(i)}],...this.options.skillScopes===void 0?[]:[{id:"cli-skill-scope",authorize:i=>this.authorizeSkill(i)}],{id:"cli-action-risk",authorize:i=>this.authorizeActionRisk(i)},{id:"cli-workspace-policy",authorize:i=>this.authorizeWorkspace(i)}],authorizationObserver:i=>this.observe(i),requireApproval:!1}}async authorizeDesktopScope(o){return await l(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 i=this.options.workspacePermissions===void 0?void 0:n(this.options.workspacePermissions,o.toolName,o.input);if(i==="deny")return{decision:"deny",reason:"workspace-policy-deny"};if(this.options.mode==="review")return this.requestApproval(o,"review-policy");const e=await r(o,this.options.resolveWorkspaceTarget),t=o.toolName.startsWith("computer.")&&e;return i==="allow"?t&&this.options.mode!=="autonomous"?this.requestApproval(o,"mutation-approval"):{decision:"allow",reason:"workspace-policy-allow"}:i==="ask"?this.requestApproval(o,"workspace-policy-ask"):e&&this.options.mode!=="autonomous"?this.requestApproval(o,"mutation-approval"):{decision:"allow",reason:this.options.mode==="auto"?"mode-auto":"read-only"}}async authorizeActionRisk(o){const i=a(o);if(i===void 0)return{decision:"allow",reason:"action-risk-clear"};if(i.risk==="deny")return{decision:"deny",reason:i.reason,metadata:{riskCategory:i.category}};const e=await this.resolvePrompt(o);return{...e,...e.reason===void 0?{reason:`${i.reason}-${e.decision}`}:{},metadata:{...e.metadata??{},riskCategory:i.category}}}authorizeSkill(o){const i=this.options.skillScopes?.get(o.context.runId);return i===void 0||d(o.toolName)?{decision:"allow",reason:"skill-policy-not-active"}:i.allowedTools.includes(o.toolName)?{decision:"allow",reason:"skill-policy-allow",metadata:{skillName:i.skillName}}:{decision:"deny",reason:"skill-policy-deny",metadata:{skillName:i.skillName}}}async requestApproval(o,i){const e=await this.resolvePrompt(o);return e.decision==="allow"&&await this.rememberApproval(o),e.reason===void 0?{...e,reason:`${i}-${e.decision}`}:e}async resolvePrompt(o){const i=await this.options.prompt?.(o)??!1;return typeof i=="boolean"?i?{decision:"allow"}:{decision:"deny"}:i}async rememberApproval(o){try{await this.options.rememberApproval?.(o)}catch(i){try{await this.options.onRememberApprovalFailure?.(o,i)}catch{}}}async observe(o){const i=typeof o.metadata?.skillName=="string"?o.metadata.skillName:void 0,e=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},...i===void 0?{}:{skillName:i},...e===void 0?{}:{riskCategory:e}})}}function d(s){return s==="skill.list"||s==="skill.load"}export{h as ToolApprovalService};
@@ -1,4 +1,6 @@
1
+ import { type WorkspaceMaterializationResult, type WorkspaceMaterializerKind, type WorkspaceMaterializerOptions } from '../../infrastructure/workspace/workspace-materializer.js';
1
2
  import type { HostPlatformContext } from '../../infrastructure/platform/host-platform.js';
3
+ import type { Logger } from '../../ports/logger.js';
2
4
  export type SessionIsolationMode = 'worktree-per-session';
3
5
  export type SessionExecutionWorkspaceState = 'ready' | 'active' | 'orphaned';
4
6
  export interface SessionExecutionWorkspace {
@@ -7,6 +9,7 @@ export interface SessionExecutionWorkspace {
7
9
  projectRoot: string;
8
10
  executionCwd: string;
9
11
  isolationMode: SessionIsolationMode;
12
+ materializerKind?: WorkspaceMaterializerKind;
10
13
  state: SessionExecutionWorkspaceState;
11
14
  branch?: string;
12
15
  worktreePath?: string;
@@ -17,14 +20,17 @@ export interface PrepareInput {
17
20
  sessionId: string;
18
21
  projectRoot: string;
19
22
  }
23
+ type WorkspaceMaterializer = (source: string, destination: string, platform: HostPlatformContext, options?: WorkspaceMaterializerOptions) => Promise<WorkspaceMaterializationResult>;
20
24
  /** Owns durable, session-scoped execution directories for all CLI surfaces. */
21
25
  export declare class SessionExecutionWorkspaceService {
22
26
  private readonly platform;
23
27
  private readonly now;
28
+ private readonly logger?;
29
+ private readonly materializer;
24
30
  private readonly indexFile;
25
31
  private readonly rootDirectory;
26
32
  private readonly baselineDirectory;
27
- constructor(globalConfigDir: string, platform: HostPlatformContext, now?: () => number);
33
+ constructor(globalConfigDir: string, platform: HostPlatformContext, now?: () => number, logger?: Logger | undefined, materializer?: WorkspaceMaterializer);
28
34
  prepare(input: PrepareInput): Promise<SessionExecutionWorkspace>;
29
35
  get(sessionId: string): Promise<SessionExecutionWorkspace | undefined>;
30
36
  /** Holds one durable session turn lease across CLI processes. */
@@ -39,6 +45,8 @@ export declare class SessionExecutionWorkspaceService {
39
45
  gc(maxAgeMs: number): Promise<number>;
40
46
  private gcLocked;
41
47
  private create;
48
+ private registerProvisionalEntry;
49
+ private cleanupFailedCreation;
42
50
  /** Synchronizes root changes into an existing session workspace at a lifecycle boundary. */
43
51
  private synchronizeFromProjectRoot;
44
52
  /**
@@ -57,3 +65,4 @@ export declare class SessionExecutionWorkspaceService {
57
65
  private withWorkspaceLock;
58
66
  private updateEntry;
59
67
  }
68
+ export {};
@@ -1,3 +1,3 @@
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};
1
+ import p from"node:crypto";import{createReadStream as B}from"node:fs";import h from"node:fs/promises";import d from"node:path";import{acquireFileLock as _,atomicWriteFile as v,withFileLock as T}from"../../infrastructure/filesystem/atomic-file-store.js";import{readJsonFileBounded as b}from"../../infrastructure/filesystem/bounded-json-reader.js";import{isFileNotFound as k}from"../../infrastructure/filesystem/fs-errors.js";import{materializeWorkspace as U}from"../../infrastructure/workspace/workspace-materializer.js";import{COPY_EXCLUDED as S}from"../../domain/workspace/workspace-materialization-policy.js";import{addGitWorktree as $,findGitRoot as C,removeSessionBranch as K,runGit as N}from"./session-worktree.js";import{MAX_BASELINE_BYTES as V,MAX_INDEX_BYTES as X,SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS as H,WORKSPACE_BASELINE_DIRECTORY as Y,WORKSPACE_DIRECTORY as q,WORKSPACE_INDEX_FILE as G,WORKSPACE_LOCK_OPTIONS as j}from"./workspace-constants.js";class fe{platform;now;logger;materializer;indexFile;rootDirectory;baselineDirectory;constructor(e,t,i=Date.now,r,n=U){this.platform=t,this.now=i,this.logger=r,this.materializer=n,this.indexFile=d.join(e,G),this.rootDirectory=d.join(e,q),this.baselineDirectory=d.join(e,Y)}async prepare(e){const t=await h.realpath(d.resolve(e.projectRoot));return this.withWorkspaceLock(async()=>{await this.gcLocked(H);const i=await this.readIndex(),r=i.entries.find(a=>a.sessionId===e.sessionId&&a.projectRoot===t);if(r!==void 0){const a=await this.normalizeExecutionRoot(r);if(a.executionCwd!==r.executionCwd&&!await F(a.executionCwd)){await h.mkdir(a.executionCwd,{recursive:!0});const o=await this.materializer(t,a.executionCwd,this.platform,{sessionId:e.sessionId,...this.logger===void 0?{}:{logger:this.logger}});a.materializerKind=o.kind}if(await F(a.executionCwd)){await this.synchronizeFromProjectRoot(a);const o={...a,state:"active",lastUsedAt:new Date(this.now()).toISOString()};return await this.writeIndex(i.entries.map(u=>u.id===r.id?o:u)),o}}const n=await this.create(e.sessionId,t,i.entries);return await this.writeIndex([...i.entries.filter(a=>a.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 _(d.join(this.rootDirectory,"turn-locks",t),j)}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 r=await this.normalizeExecutionRoot(i);r.executionCwd!==i.executionCwd&&await this.writeIndex(t.entries.map(w=>w.id===r.id?r:w));const n=await this.readBaseline(r.id),[a,o]=await Promise.all([y(r.projectRoot,n.entries),y(r.executionCwd,n.entries)]),c=[...new Set([...Object.keys(n.entries),...a.keys(),...o.keys()])].filter(w=>!m(o.get(w),n.entries[w])).sort();await R(r.projectRoot,c);const f=c.filter(w=>{const O=!m(a.get(w),n.entries[w]),W=!m(o.get(w),n.entries[w]);return O&&W&&!m(a.get(w),o.get(w))});if(f.length>0)throw new Error(`Cannot apply session changes because the project changed concurrently: ${f.join(", ")}.`);const l=await z(r.projectRoot,c,a);try{for(const w of c)await x(r.projectRoot,w,o.get(w),r.executionCwd)}catch(w){throw await D(r.projectRoot,l,c).catch(()=>{}),w}await this.writeBaseline(r.id,o);const L=await this.readIndex();return await this.writeIndex(L.entries.map(w=>w.id===r.id?{...w,lastUsedAt:new Date(this.now()).toISOString()}:w)),{appliedPaths:c}})}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(a=>a.sessionId!==e));return}if(i.worktreePath!==void 0){let n=!1;for(let a=0;a<3;a+=1)try{await N(["worktree","remove","--force",i.worktreePath],i.projectRoot,this.platform),n=!0;break}catch{a<2&&await new Promise(o=>setTimeout(o,100))}if(!n){this.logger?.error("workspace.cleanup.worktree_remove_failed",{sessionId:i.sessionId,entryId:i.id,worktreePath:i.worktreePath});const a=await this.readIndex();await this.writeIndex(a.entries.map(o=>o.id===i.id?{...o,state:"orphaned"}:o));return}i.branch!==void 0&&await K(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,i){const r=p.randomUUID(),n=new Date(this.now()).toISOString();await h.mkdir(this.rootDirectory,{recursive:!0});const a=d.join(this.rootDirectory,r),o=await y(t),u=await C(t,this.platform);if(u!==void 0){const c=`lotagate/session-${r}`,f=A(u,t,a);await this.registerProvisionalEntry(i,{id:r,sessionId:e,projectRoot:t,executionCwd:f,isolationMode:"worktree-per-session",state:"orphaned",branch:c,worktreePath:a,createdAt:n,lastUsedAt:n});try{await $(u,a,c,t,this.platform,this.logger),await h.mkdir(f,{recursive:!0});const l=await this.materializer(t,f,this.platform,{sessionId:e,...this.logger===void 0?{}:{logger:this.logger}});return await this.writeBaseline(r,o),{id:r,sessionId:e,projectRoot:t,executionCwd:f,isolationMode:"worktree-per-session",materializerKind:l.kind,state:"active",branch:c,worktreePath:a,createdAt:n,lastUsedAt:n}}catch(l){throw await this.cleanupFailedCreation(e,r,l),l}}await this.registerProvisionalEntry(i,{id:r,sessionId:e,projectRoot:t,executionCwd:a,isolationMode:"worktree-per-session",state:"orphaned",createdAt:n,lastUsedAt:n});try{const c=await this.materializer(t,a,this.platform,{sessionId:e,...this.logger===void 0?{}:{logger:this.logger}});return await this.writeBaseline(r,o),{id:r,sessionId:e,projectRoot:t,executionCwd:a,isolationMode:"worktree-per-session",materializerKind:c.kind,state:"active",createdAt:n,lastUsedAt:n}}catch(c){throw await this.cleanupFailedCreation(e,r,c),c}}async registerProvisionalEntry(e,t){await this.writeIndex([...e.filter(i=>i.sessionId!==t.sessionId),t])}async cleanupFailedCreation(e,t,i){try{await this.removeEntryLocked(e,t)}catch(r){this.logger?.error("workspace.creation.cleanup_failed",{sessionId:e,entryId:t,reason:r instanceof Error?r.message:String(r),originalFailure:i instanceof Error?i.message:String(i)})}}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(c=>!m(i.get(c),t.entries[c])).sort();if(n.length===0)return;await R(e.executionCwd,n);const a=await y(e.executionCwd,t.entries),o=n.filter(c=>!m(a.get(c),t.entries[c])&&!m(a.get(c),i.get(c)));if(o.length>0)throw new Error(`Cannot synchronize unresolved session changes: ${o.join(", ")}.`);const u=await z(e.executionCwd,n,a);try{for(const c of n)await x(e.executionCwd,c,i.get(c),e.projectRoot)}catch(c){throw await D(e.executionCwd,u,n).catch(()=>{}),c}await this.writeBaseline(e.id,i)}async normalizeExecutionRoot(e){if(e.worktreePath===void 0)return e;const t=await C(e.projectRoot,this.platform);return t===void 0?e:{...e,executionCwd:A(t,e.projectRoot,e.worktreePath)}}baselinePath(e){return d.join(this.baselineDirectory,`${e}.json`)}async readBaseline(e){const t=await b(this.baselinePath(e),V);if(t.schemaVersion!==2||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:2,entries:Object.fromEntries(Object.entries(t.entries).filter(([i,r])=>M(i)&&Z(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 v(this.baselinePath(e),`${JSON.stringify({schemaVersion:2,entries:i})}
2
+ `)}async readIndex(){try{const e=await b(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 v(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 T(this.indexFile,e,j)}async updateEntry(e,t){await this.writeEntries(i=>i.map(r=>r.id===e?t(r):r))}}async function y(s,e){const t=new Map;return await i(s,""),t;async function i(r,n){for(const a of await h.readdir(r,{withFileTypes:!0})){if(S.has(a.name))continue;const o=n.length===0?a.name:d.join(n,a.name),u=d.join(s,o),c=await h.lstat(u);if(c.isDirectory()){t.set(o,{kind:"directory",hash:ee(),size:0}),await i(u,o);continue}if(c.isSymbolicLink()){const l=await h.readlink(u);t.set(o,{kind:"symlink",hash:p.createHash("sha256").update(`symlink\0${l}`).digest("hex"),size:Buffer.byteLength(l),bytes:Buffer.alloc(0),target:l});continue}if(!c.isFile())continue;const f=e instanceof Map?e.get(o):e?.[o];if(f!==void 0&&f.kind==="file"&&f.size===c.size&&f.mtimeMs!==void 0&&Math.abs(f.mtimeMs-c.mtimeMs)<1&&P(f.mode,c.mode&4095)){t.set(o,{kind:"file",hash:f.hash,size:c.size,mtimeMs:c.mtimeMs,mode:c.mode&4095});continue}t.set(o,{kind:"file",hash:await J(u),size:c.size,mtimeMs:c.mtimeMs,mode:c.mode&4095})}}}async function z(s,e,t){const i=new Map;for(const r of e){const n=t.get(r);n!==void 0&&(n.kind==="directory"||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 B(s))e.update(t);return e.digest("hex")}function A(s,e,t){const i=d.relative(d.resolve(s),d.resolve(e));if(i===""||i===".")return d.resolve(t);if(i===".."||i.startsWith(`..${d.sep}`)||d.isAbsolute(i))throw new Error("The project root is outside the Git worktree root.");return d.resolve(t,i)}function P(s,e){return s===void 0||e===void 0||process.platform==="win32"?!0:(s&73)===(e&73)}function m(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 x(s,e,t,i=s){const r=g(s,e);if(await I(s,r),t===void 0){await E(r),await h.rm(r,{recursive:!0,force:!0});return}const n=d.dirname(r);await h.mkdir(n,{recursive:!0}),await I(s,r);const a=await h.lstat(r).catch(u=>{if(!k(u))throw u});if(t.kind==="directory"){a!==void 0&&!a.isDirectory()&&await h.rm(r,{recursive:!0,force:!0}),await h.mkdir(r,{recursive:!0});return}a?.isDirectory()&&(await E(r),await h.rm(r,{recursive:!0,force:!0}));const o=`${r}.${p.randomUUID()}.tmp`;try{t.kind==="symlink"?await h.symlink(t.target??"",o):await h.writeFile(o,t.bytes??await h.readFile(g(i,e)),{mode:t.mode}),t.kind==="file"&&t.mode!==void 0&&await h.chmod(o,t.mode),await h.rename(o,r)}finally{await h.rm(o,{force:!0})}}async function R(s,e){for(const t of e)await I(s,g(s,t))}async function E(s){const e=await h.lstat(s).catch(i=>{if(!k(i))throw i});if(e===void 0||!e.isDirectory())return;const t=await h.readdir(s,{withFileTypes:!0});for(const i of t){if(S.has(i.name))throw new Error(`Cannot replace a workspace directory containing excluded content: ${i.name}.`);i.isDirectory()&&await E(d.join(s,i.name))}}async function I(s,e){const t=d.resolve(s),i=await h.realpath(t);let r=d.dirname(e);for(;;){const n=d.resolve(r),a=d.relative(t,n);if(a===".."||a.startsWith(`..${d.sep}`)||d.isAbsolute(a))throw new Error("The workspace path escapes the project root.");const o=await h.lstat(n).catch(u=>{if(!k(u))throw u});if(o?.isSymbolicLink())throw new Error("The workspace path contains a symbolic-link parent.");if(o!==void 0&&!Q(i,await h.realpath(n)))throw new Error("The workspace path escapes the project root.");if(n===t)return;r=d.dirname(n)}}function Q(s,e){const t=d.relative(s,e);return t===""||t!==".."&&!t.startsWith(`..${d.sep}`)&&!d.isAbsolute(t)}async function D(s,e,t){for(const i of[...t].reverse())await x(s,i,e.get(i))}function g(s,e){if(!M(e))throw new Error("The workspace path is invalid.");const t=d.resolve(s),i=d.resolve(t,e),r=d.relative(t,i);if(r===".."||r.startsWith(`..${d.sep}`)||d.isAbsolute(r))throw new Error("The workspace path escapes the project root.");return i}function M(s){return s.length>0&&!d.isAbsolute(s)&&s!=="."&&s!==".."&&!s.startsWith(`..${d.sep}`)&&!s.includes("\0")}function Z(s){if(typeof s!="object"||s===null)return!1;const e=s;return(e.kind==="directory"||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")}function ee(){return p.createHash("sha256").update("directory","utf8").digest("hex")}async function F(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.materializerKind===void 0||e.materializerKind==="native-cow"||e.materializerKind==="copy")&&(e.state==="ready"||e.state==="active"||e.state==="orphaned")&&typeof e.createdAt=="string"&&typeof e.lastUsedAt=="string"}export{fe as SessionExecutionWorkspaceService};
@@ -0,0 +1,6 @@
1
+ import type { HostPlatformContext } from '../../infrastructure/platform/host-platform.js';
2
+ import type { Logger } from '../../ports/logger.js';
3
+ export declare function findGitRoot(cwd: string, platform: HostPlatformContext): Promise<string | undefined>;
4
+ export declare function addGitWorktree(gitRoot: string, destination: string, branch: string, projectRoot: string, platform: HostPlatformContext, logger?: Logger): Promise<void>;
5
+ export declare function removeSessionBranch(branch: string, cwd: string, platform: HostPlatformContext): Promise<void>;
6
+ export declare function runGit(args: readonly string[], cwd: string, platform: HostPlatformContext): Promise<string>;
@@ -0,0 +1 @@
1
+ import h from"node:fs/promises";import{execPlatformCommand as f}from"../../infrastructure/platform/host-process.js";import{RESOURCE_LIMITS as c}from"../../domain/runtime/resource-limits.js";async function E(e,r){try{return(await s(["rev-parse","--show-toplevel"],e,r)).trim()||void 0}catch{return}}async function k(e,r,t,o,a,u){try{await s(["worktree","add","--no-checkout","-b",t,r,"HEAD"],e,a),await s(["read-tree","HEAD"],r,a)}catch(w){const i=[];await h.rm(r,{recursive:!0,force:!0}).catch(n=>{i.push(n)}),await s(["worktree","prune"],e,a).catch(n=>{i.push(n)}),await d(t,o,a).catch(n=>{i.push(n)}),i.length>0&&u?.warn("workspace.git.setup_cleanup_failed",{branch:t,cleanupErrorCount:i.length});try{await s(["worktree","add","-b",t,r,"HEAD"],e,a)}catch(n){throw new AggregateError([w,n],"Unable to create the Git session worktree.")}}}async function d(e,r,t){if(!/^lotagate\/session-[a-z0-9-]+$/iu.test(e))throw new Error("The session workspace branch name is invalid.");try{await s(["branch","--delete","--force","--",e],r,t)}catch(o){const a=o instanceof Error?o.message:String(o);if(!/not found|not a valid branch|unknown revision/iu.test(a))throw o}}function s(e,r,t){return f("git",e,t,{cwd:r,maxBufferBytes:c.internalProcessOutputBytes,timeoutMs:c.internalProcessTimeoutMs}).then(o=>o.stdout)}export{k as addGitWorktree,E as findGitRoot,d as removeSessionBranch,s as runGit};
@@ -10,7 +10,6 @@ export declare const MAX_INDEX_BYTES: number;
10
10
  export declare const MAX_BASELINE_BYTES: number;
11
11
  export declare const SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS: number;
12
12
  export declare const SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS: number;
13
- export declare const COPY_EXCLUDED: Set<string>;
14
13
  export declare const WORKSPACE_LOCK_OPTIONS: {
15
14
  readonly timeoutMs: number;
16
15
  readonly userMessage: "Another session is updating workspace state. Try again shortly.";
@@ -1 +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
+ const s=new Set([".git",".lotagate","node_modules","dist","build","coverage",".next",".nuxt",".cache",".turbo","vendor"]),o=2e3,E=["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"],n=new Set([".md",".mdc"]),r="session-execution-workspaces.json",c="session-execution-workspaces",S="session-execution-workspace-baselines",_=2*1024*1024,I=8*1024*1024,N=720*60*60*1e3,e=60*1e3,O={timeoutMs:e,userMessage:"Another session is updating workspace state. Try again shortly."};export{s as DEFAULT_IGNORED_WORKSPACE_DIRECTORIES,E as INSTRUCTION_PATHS,I as MAX_BASELINE_BYTES,o as MAX_INDEXED_ENTRIES,_ as MAX_INDEX_BYTES,t as RULE_DIRECTORIES,n as RULE_EXTENSIONS,e as SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS,N as SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS,S as WORKSPACE_BASELINE_DIRECTORY,c as WORKSPACE_DIRECTORY,r as WORKSPACE_INDEX_FILE,O as WORKSPACE_LOCK_OPTIONS};
@@ -1 +1 @@
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};
1
+ import{ConfigLoader as D}from"../infrastructure/config/config-loader.js";import{StructuredLogger as M}from"../infrastructure/logging/structured-logger.js";import{resolvePlatformPaths as R}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=R(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 M({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 D(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,Date.now,r),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};
@@ -17,6 +17,7 @@ export declare const CLI_ERROR_CODES: {
17
17
  readonly MODEL_STREAM_FAILED: "MODEL_STREAM_FAILED";
18
18
  readonly MODEL_EMPTY_RESPONSE: "MODEL_EMPTY_RESPONSE";
19
19
  readonly MODEL_PROTOCOL_EMPTY_RESPONSE: "MODEL_PROTOCOL_EMPTY_RESPONSE";
20
+ readonly INTENT_CLASSIFICATION_UNAVAILABLE: "INTENT_CLASSIFICATION_UNAVAILABLE";
20
21
  readonly MEDIA_REQUEST_FAILED: "MEDIA_REQUEST_FAILED";
21
22
  readonly MEDIA_RESPONSE_TOO_LARGE: "MEDIA_RESPONSE_TOO_LARGE";
22
23
  readonly MODEL_EMPTY_FINAL: "MODEL_EMPTY_FINAL";
@@ -1 +1 @@
1
- const _={INVALID_ARGUMENT:"CLI_INVALID_ARGUMENT",MISSING_ARGUMENT:"CLI_MISSING_ARGUMENT",INTERRUPTED:"CLI_INTERRUPTED",INTERNAL_ERROR:"CLI_INTERNAL_ERROR",CONFIG_NOT_FOUND:"CONFIG_NOT_FOUND",CONFIG_INVALID_JSON:"CONFIG_INVALID_JSON",CONFIG_SCHEMA_INVALID:"CONFIG_SCHEMA_INVALID",CONFIG_LOCKED:"CONFIG_LOCKED",PROJECT_PATH_INVALID:"PROJECT_PATH_INVALID",AUTH_API_KEY_INVALID:"AUTH_API_KEY_INVALID",AUTH_PROFILE_NOT_FOUND:"AUTH_PROFILE_NOT_FOUND",AUTH_CREDENTIAL_STORE_UNAVAILABLE:"AUTH_CREDENTIAL_STORE_UNAVAILABLE",AUTH_BASE_URL_INVALID:"AUTH_BASE_URL_INVALID",PROJECT_TRUST_REQUIRED:"PROJECT_TRUST_REQUIRED",MODEL_NOT_FOUND:"MODEL_NOT_FOUND",MODEL_STREAM_FAILED:"MODEL_STREAM_FAILED",MODEL_EMPTY_RESPONSE:"MODEL_EMPTY_RESPONSE",MODEL_PROTOCOL_EMPTY_RESPONSE:"MODEL_PROTOCOL_EMPTY_RESPONSE",MEDIA_REQUEST_FAILED:"MEDIA_REQUEST_FAILED",MEDIA_RESPONSE_TOO_LARGE:"MEDIA_RESPONSE_TOO_LARGE",MODEL_EMPTY_FINAL:"MODEL_EMPTY_FINAL",AGENT_STUCK:"AGENT_STUCK",ATTACHMENT_CLIPBOARD_UNAVAILABLE:"ATTACHMENT_CLIPBOARD_UNAVAILABLE",ATTACHMENT_FORMAT_UNSUPPORTED:"ATTACHMENT_FORMAT_UNSUPPORTED",ATTACHMENT_TOO_LARGE:"ATTACHMENT_TOO_LARGE",ATTACHMENT_INVALID_IMAGE:"ATTACHMENT_INVALID_IMAGE",TOOL_ARGUMENT_INVALID:"TOOL_ARGUMENT_INVALID",TOOL_DENIED:"CLI_TOOL_DENIED",TOOL_EXECUTION_FAILED:"CLI_TOOL_EXECUTION_FAILED",PROJECT_SYMLINK_ESCAPE:"PROJECT_SYMLINK_ESCAPE",SESSION_NOT_FOUND:"SESSION_NOT_FOUND",SESSION_LOCKED:"SESSION_LOCKED",SESSION_CORRUPTED:"SESSION_CORRUPTED",TASK_DEPENDENCY_CYCLE:"TASK_DEPENDENCY_CYCLE",TASK_SCHEDULER_OVERLOADED:"TASK_SCHEDULER_OVERLOADED",TASK_PLAN_APPROVAL_REQUIRED:"TASK_PLAN_APPROVAL_REQUIRED",PLUGIN_MANIFEST_INVALID:"PLUGIN_MANIFEST_INVALID",PLUGIN_NOT_FOUND:"PLUGIN_NOT_FOUND",SKILL_FRONTMATTER_INVALID:"SKILL_FRONTMATTER_INVALID",SKILL_NOT_FOUND:"SKILL_NOT_FOUND",MCP_CONFIG_INVALID:"MCP_CONFIG_INVALID",MCP_SERVER_NOT_FOUND:"MCP_SERVER_NOT_FOUND",GOAL_NOT_FOUND:"GOAL_NOT_FOUND",GOAL_INVALID_STATE:"GOAL_INVALID_STATE",GOAL_LIMIT_REACHED:"GOAL_LIMIT_REACHED",MEMORY_NOT_FOUND:"MEMORY_NOT_FOUND",MEMORY_INVALID:"MEMORY_INVALID",MEMORY_LIMIT_REACHED:"MEMORY_LIMIT_REACHED"};export{_ as CLI_ERROR_CODES};
1
+ const _={INVALID_ARGUMENT:"CLI_INVALID_ARGUMENT",MISSING_ARGUMENT:"CLI_MISSING_ARGUMENT",INTERRUPTED:"CLI_INTERRUPTED",INTERNAL_ERROR:"CLI_INTERNAL_ERROR",CONFIG_NOT_FOUND:"CONFIG_NOT_FOUND",CONFIG_INVALID_JSON:"CONFIG_INVALID_JSON",CONFIG_SCHEMA_INVALID:"CONFIG_SCHEMA_INVALID",CONFIG_LOCKED:"CONFIG_LOCKED",PROJECT_PATH_INVALID:"PROJECT_PATH_INVALID",AUTH_API_KEY_INVALID:"AUTH_API_KEY_INVALID",AUTH_PROFILE_NOT_FOUND:"AUTH_PROFILE_NOT_FOUND",AUTH_CREDENTIAL_STORE_UNAVAILABLE:"AUTH_CREDENTIAL_STORE_UNAVAILABLE",AUTH_BASE_URL_INVALID:"AUTH_BASE_URL_INVALID",PROJECT_TRUST_REQUIRED:"PROJECT_TRUST_REQUIRED",MODEL_NOT_FOUND:"MODEL_NOT_FOUND",MODEL_STREAM_FAILED:"MODEL_STREAM_FAILED",MODEL_EMPTY_RESPONSE:"MODEL_EMPTY_RESPONSE",MODEL_PROTOCOL_EMPTY_RESPONSE:"MODEL_PROTOCOL_EMPTY_RESPONSE",INTENT_CLASSIFICATION_UNAVAILABLE:"INTENT_CLASSIFICATION_UNAVAILABLE",MEDIA_REQUEST_FAILED:"MEDIA_REQUEST_FAILED",MEDIA_RESPONSE_TOO_LARGE:"MEDIA_RESPONSE_TOO_LARGE",MODEL_EMPTY_FINAL:"MODEL_EMPTY_FINAL",AGENT_STUCK:"AGENT_STUCK",ATTACHMENT_CLIPBOARD_UNAVAILABLE:"ATTACHMENT_CLIPBOARD_UNAVAILABLE",ATTACHMENT_FORMAT_UNSUPPORTED:"ATTACHMENT_FORMAT_UNSUPPORTED",ATTACHMENT_TOO_LARGE:"ATTACHMENT_TOO_LARGE",ATTACHMENT_INVALID_IMAGE:"ATTACHMENT_INVALID_IMAGE",TOOL_ARGUMENT_INVALID:"TOOL_ARGUMENT_INVALID",TOOL_DENIED:"CLI_TOOL_DENIED",TOOL_EXECUTION_FAILED:"CLI_TOOL_EXECUTION_FAILED",PROJECT_SYMLINK_ESCAPE:"PROJECT_SYMLINK_ESCAPE",SESSION_NOT_FOUND:"SESSION_NOT_FOUND",SESSION_LOCKED:"SESSION_LOCKED",SESSION_CORRUPTED:"SESSION_CORRUPTED",TASK_DEPENDENCY_CYCLE:"TASK_DEPENDENCY_CYCLE",TASK_SCHEDULER_OVERLOADED:"TASK_SCHEDULER_OVERLOADED",TASK_PLAN_APPROVAL_REQUIRED:"TASK_PLAN_APPROVAL_REQUIRED",PLUGIN_MANIFEST_INVALID:"PLUGIN_MANIFEST_INVALID",PLUGIN_NOT_FOUND:"PLUGIN_NOT_FOUND",SKILL_FRONTMATTER_INVALID:"SKILL_FRONTMATTER_INVALID",SKILL_NOT_FOUND:"SKILL_NOT_FOUND",MCP_CONFIG_INVALID:"MCP_CONFIG_INVALID",MCP_SERVER_NOT_FOUND:"MCP_SERVER_NOT_FOUND",GOAL_NOT_FOUND:"GOAL_NOT_FOUND",GOAL_INVALID_STATE:"GOAL_INVALID_STATE",GOAL_LIMIT_REACHED:"GOAL_LIMIT_REACHED",MEMORY_NOT_FOUND:"MEMORY_NOT_FOUND",MEMORY_INVALID:"MEMORY_INVALID",MEMORY_LIMIT_REACHED:"MEMORY_LIMIT_REACHED"};export{_ as CLI_ERROR_CODES};
@@ -29,5 +29,4 @@ export interface CompletionAssessment {
29
29
  export declare function requiresHostVerification(kind: IntentKind): boolean;
30
30
  export declare function createIntentContract(input: IntentCompilationInput, timestamp?: string): IntentContract;
31
31
  export declare function normalizeIntentCompilation(value: unknown): IntentCompilationInput;
32
- export declare function fallbackIntent(prompt: string): IntentContract;
33
32
  export declare function isIntentKind(value: unknown): value is IntentKind;
@@ -1 +1 @@
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};
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 m=["answer","research","change","automation"];function h(t){return t==="change"||t==="automation"}function q(t,o=new Date().toISOString()){const e=l(t),i=h(e.kind);return{id:p.randomUUID(),kind:e.kind,objective:e.objective,steps:e.steps.map((n,c)=>({...n,requiresVerification:i||n.requiresVerification,id:`step-${c+1}`})),createdAt:o}}function l(t){if(!a(t))throw r("Intent compilation must be an object.");const o=s(t,["kind","objective","steps"]);if(o!==void 0)throw r(`Unsupported intent field: ${o}.`);const e=t.kind,i=t.objective,n=t.steps;if(!u(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(n)||n.length===0||n.length>10)throw r("Intent requires between one and ten steps.");return{kind:e,objective:i.trim(),steps:n.map(g)}}function u(t){return typeof t=="string"&&m.includes(t)}function g(t){if(!a(t))throw r("Intent step is invalid.");const o=s(t,["title","acceptanceCriteria","requiresVerification"]);if(o!==void 0)throw r(`Unsupported intent step field: ${o}.`);const e=t.title,i=t.acceptanceCriteria,n=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 n!="boolean")throw r("Intent verification requirement is invalid.");return{title:e.trim(),acceptanceCriteria:i.map(c=>String(c).trim()),requiresVerification:n}}function r(t){return new f(d.INVALID_ARGUMENT,t,{category:"intent",userMessage:t})}export{m as INTENT_KINDS,q as createIntentContract,u as isIntentKind,l as normalizeIntentCompilation,h as requiresHostVerification};
@@ -66,6 +66,7 @@ export declare const RESOURCE_LIMITS: {
66
66
  readonly subagentMaxToolCallsPerTurn: 100;
67
67
  readonly agentMaxIterations: 500;
68
68
  readonly agentMaxToolCallsPerTurn: 1;
69
+ readonly intentMaxCompilationAttempts: 2;
69
70
  readonly intentMaxCompletionAttempts: 2;
70
71
  readonly subagentToolArgumentBytes: number;
71
72
  readonly subagentToolResultBytes: number;
@@ -95,6 +96,9 @@ export declare const RESOURCE_LIMITS: {
95
96
  readonly logQueueBytes: number;
96
97
  readonly internalProcessTimeoutMs: number;
97
98
  readonly internalProcessOutputBytes: number;
99
+ readonly workspaceMaterializationTimeoutMs: number;
100
+ readonly workspaceMaterializationRetryAttempts: 2;
101
+ readonly workspaceMaterializationRetryBackoffMs: 100;
98
102
  readonly hostShellTimeoutMs: 120000;
99
103
  readonly guestShellTimeoutMs: number;
100
104
  readonly defaultShellTimeoutMs: 30000;
@@ -1 +1 @@
1
- const e=1e6,t={processTerminationGraceMs:500,processTerminationTimeoutMs:2e3,configFileBytes:262144,sessionIndexBytes:8388608,workspaceSettingsBytes:262144,mcpConfigBytes:524288,sessionBundleBytes:20971520,sessionJournalBytes:20971520,sessionJournalCacheMaxEntries:8,sessionJournalCacheMaxBytes:8e6,sessionEvents:1e5,sessionTranscriptEntries:5e4,sessionAttachments:32,sessionAttachmentTotalBytes:5e7,sessionTextBytes:524288,agentStreamBytes:4194304,agentToolArgumentBytes:262144,agentToolMetadataBytes:262144,memoryJournalBytes:8388608,memoryIndexBytes:8388608,memoryBundleBytes:8388608,memoryRecords:2e3,memoryStatementBytes:4096,memoryRationaleBytes:2048,memoryTopics:16,memoryTopicBytes:256,memorySupersedes:16,memoryEvidenceReferences:32,memoryEvidenceReferenceBytes:512,memoryContextRecords:12,jsonlLineBytes:1048576,desktopJsonlLineBytes:4194304,desktopAttachmentChunkBytes:524288,jsonlIdBytes:256,jsonlPathBytes:4096,jsonlPromptBytes:524288,pendingAttachments:16,pendingAttachmentTotalBytes:5e7,desktopAttachmentTtlMs:9e5,maxAttachmentBytes:1e7,clipboardTextBytes:1e7,clipboardTimeoutMs:15e3,instructionFileBytes:131072,instructionTotalBytes:262144,instructionFiles:32,skillDocumentBytes:524288,pluginManifestBytes:262144,pluginMaxEnabled:64,pluginMaxAgentFiles:64,pluginMaxAgentContributions:256,pluginDiscoveryConcurrency:4,subagentTaskBytes:16384,subagentContextBytes:16384,subagentMaxWriteScopeItems:32,subagentWriteScopeItemBytes:512,subagentSummaryBytes:24576,subagentMaxDurationMs:18e5,subagentMaxTokens:2e5,subagentMaxConcurrent:4,subagentMaxRetainedJobs:32,desktopSessionStoreMaxEntries:20,subagentMaxIterations:200,subagentMaxToolCallsPerTurn:100,agentMaxIterations:500,agentMaxToolCallsPerTurn:1,intentMaxCompletionAttempts:2,subagentToolArgumentBytes:65536,subagentToolResultBytes:262144,goalObjectiveBytes:16384,goalReasonBytes:2048,goalEvidenceItems:8,goalEvidenceBytes:4096,goalDefaultMaxTurns:100,goalMaximumMaxTurns:1e4,goalMaximumTokenBudget:1e7,goalDefaultMaxDurationMs:72e5,goalMaximumMaxDurationMs:288e5,goalDefaultMaxEvaluatorRuns:100,tuiTranscriptMessages:2e3,tuiAgentSessionMaxEntries:4,tuiAgentSessionMaxBytes:8388608,agentPreparationCacheMaxEntries:8,agentPreparationCacheMaxBytes:16777216,contextTokenCacheMaxEntries:8,contextTokenCacheMaxBytes:8388608,jsonlMaxInFlight:4,protocolWriteQueueEntries:256,protocolWriteQueueBytes:16777216,workspaceReferenceCount:32,workspaceReferenceInstructionBytes:16384,logQueueEntries:1e4,logQueueBytes:4194304,internalProcessTimeoutMs:12e4,internalProcessOutputBytes:4194304,hostShellTimeoutMs:12e4,guestShellTimeoutMs:6e5,defaultShellTimeoutMs:3e4};export{t as RESOURCE_LIMITS};
1
+ const e=1e6,t={processTerminationGraceMs:500,processTerminationTimeoutMs:2e3,configFileBytes:262144,sessionIndexBytes:8388608,workspaceSettingsBytes:262144,mcpConfigBytes:524288,sessionBundleBytes:20971520,sessionJournalBytes:20971520,sessionJournalCacheMaxEntries:8,sessionJournalCacheMaxBytes:8e6,sessionEvents:1e5,sessionTranscriptEntries:5e4,sessionAttachments:32,sessionAttachmentTotalBytes:5e7,sessionTextBytes:524288,agentStreamBytes:4194304,agentToolArgumentBytes:262144,agentToolMetadataBytes:262144,memoryJournalBytes:8388608,memoryIndexBytes:8388608,memoryBundleBytes:8388608,memoryRecords:2e3,memoryStatementBytes:4096,memoryRationaleBytes:2048,memoryTopics:16,memoryTopicBytes:256,memorySupersedes:16,memoryEvidenceReferences:32,memoryEvidenceReferenceBytes:512,memoryContextRecords:12,jsonlLineBytes:1048576,desktopJsonlLineBytes:4194304,desktopAttachmentChunkBytes:524288,jsonlIdBytes:256,jsonlPathBytes:4096,jsonlPromptBytes:524288,pendingAttachments:16,pendingAttachmentTotalBytes:5e7,desktopAttachmentTtlMs:9e5,maxAttachmentBytes:1e7,clipboardTextBytes:1e7,clipboardTimeoutMs:15e3,instructionFileBytes:131072,instructionTotalBytes:262144,instructionFiles:32,skillDocumentBytes:524288,pluginManifestBytes:262144,pluginMaxEnabled:64,pluginMaxAgentFiles:64,pluginMaxAgentContributions:256,pluginDiscoveryConcurrency:4,subagentTaskBytes:16384,subagentContextBytes:16384,subagentMaxWriteScopeItems:32,subagentWriteScopeItemBytes:512,subagentSummaryBytes:24576,subagentMaxDurationMs:18e5,subagentMaxTokens:2e5,subagentMaxConcurrent:4,subagentMaxRetainedJobs:32,desktopSessionStoreMaxEntries:20,subagentMaxIterations:200,subagentMaxToolCallsPerTurn:100,agentMaxIterations:500,agentMaxToolCallsPerTurn:1,intentMaxCompilationAttempts:2,intentMaxCompletionAttempts:2,subagentToolArgumentBytes:65536,subagentToolResultBytes:262144,goalObjectiveBytes:16384,goalReasonBytes:2048,goalEvidenceItems:8,goalEvidenceBytes:4096,goalDefaultMaxTurns:100,goalMaximumMaxTurns:1e4,goalMaximumTokenBudget:1e7,goalDefaultMaxDurationMs:72e5,goalMaximumMaxDurationMs:288e5,goalDefaultMaxEvaluatorRuns:100,tuiTranscriptMessages:2e3,tuiAgentSessionMaxEntries:4,tuiAgentSessionMaxBytes:8388608,agentPreparationCacheMaxEntries:8,agentPreparationCacheMaxBytes:16777216,contextTokenCacheMaxEntries:8,contextTokenCacheMaxBytes:8388608,jsonlMaxInFlight:4,protocolWriteQueueEntries:256,protocolWriteQueueBytes:16777216,workspaceReferenceCount:32,workspaceReferenceInstructionBytes:16384,logQueueEntries:1e4,logQueueBytes:4194304,internalProcessTimeoutMs:12e4,internalProcessOutputBytes:4194304,workspaceMaterializationTimeoutMs:18e5,workspaceMaterializationRetryAttempts:2,workspaceMaterializationRetryBackoffMs:100,hostShellTimeoutMs:12e4,guestShellTimeoutMs:6e5,defaultShellTimeoutMs:3e4};export{t as RESOURCE_LIMITS};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Files that belong to the source/repository boundary rather than a session
3
+ * content view. Everything else is materialized, including hidden files,
4
+ * generated project files, assets, tests, empty directories, and symlinks.
5
+ */
6
+ export declare const COPY_EXCLUDED: ReadonlySet<string>;
@@ -0,0 +1 @@
1
+ const e=new Set([".git",".lotagate","node_modules"]);export{e as COPY_EXCLUDED};
@@ -3,9 +3,11 @@ import { type ToolExecutor } from '@lotagate/agent-sdk';
3
3
  import type { LotaGate } from '@lotagate/sdk';
4
4
  import type { ModelCallSummary } from '../../ports/model-diagnostics.js';
5
5
  import type { HostPlatformContext } from '../platform/host-platform.js';
6
+ import type { ModelNetworkRecoveryObserver } from '../../application/model/model-response-retry.js';
6
7
  export interface AgentInstanceOptions extends Omit<LotaGateAgentOptions, 'modelClient'> {
7
8
  client: LotaGate;
8
9
  onModelComplete?: (summary: ModelCallSummary) => void;
10
+ networkRecovery?: ModelNetworkRecoveryObserver;
9
11
  }
10
12
  export declare function createAgentInstance(options: AgentInstanceOptions): LotaGateAgent;
11
13
  export interface LocalAgentInstanceOptions extends Omit<AgentInstanceOptions, 'toolExecutor'> {
@@ -18,5 +20,6 @@ export interface LocalAgentInstanceOptions extends Omit<AgentInstanceOptions, 't
18
20
  authorizationRules?: readonly ToolAuthorizationRule[];
19
21
  authorizationObserver?: (event: ToolAuthorizationEvent) => void | Promise<void>;
20
22
  onModelComplete?: (summary: ModelCallSummary) => void;
23
+ networkRecovery?: ModelNetworkRecoveryObserver;
21
24
  }
22
25
  export declare function createLocalAgentInstance(options: LocalAgentInstanceOptions): LotaGateAgent;
@@ -1 +1 @@
1
- import{LotaGateAgent as f}from"@lotagate/agent-sdk";import{CompositeToolExecutor as m}from"@lotagate/agent-sdk";import{LocalFilesystemToolExecutor as s}from"../filesystem/local-filesystem-tool-executor.js";import{ShellToolExecutor as x}from"../shell/shell-tool-executor.js";import{createToolCallingModelClient as C}from"./tool-calling-model-client.js";function g(n){const{client:t,onModelComplete:e,...o}=n;return new f({...o,modelClient:C(t,e===void 0?{}:{onComplete:e})})}function v(n){const{toolExecutors:t,platform:e,allowedTools:o,deniedTools:l,requireApproval:r,approvalHandler:i,authorizationRules:d,authorizationObserver:a,onModelComplete:u,...c}=n,p=new m([...t??[new s,new x({...e===void 0?{}:{platform:e}})]]);return g({...c,...u===void 0?{}:{onModelComplete:u},toolExecutor:p,toolPolicy:{...o===void 0?{}:{allowedTools:o},...l===void 0?{}:{deniedTools:l},...r===void 0?{}:{requireApproval:r},...i===void 0?{}:{approvalHandler:i},...d===void 0?{}:{authorizationRules:d},...a===void 0?{}:{authorizationObserver:a}}})}export{g as createAgentInstance,v as createLocalAgentInstance};
1
+ import{LotaGateAgent as f}from"@lotagate/agent-sdk";import{CompositeToolExecutor as m}from"@lotagate/agent-sdk";import{LocalFilesystemToolExecutor as s}from"../filesystem/local-filesystem-tool-executor.js";import{ShellToolExecutor as x}from"../shell/shell-tool-executor.js";import{createToolCallingModelClient as C}from"./tool-calling-model-client.js";function g(t){const{client:r,onModelComplete:e,networkRecovery:o,...n}=t;return new f({...n,modelClient:C(r,e===void 0?{}:{onComplete:e},o)})}function h(t){const{toolExecutors:r,platform:e,allowedTools:o,deniedTools:n,requireApproval:l,approvalHandler:i,authorizationRules:d,authorizationObserver:a,onModelComplete:u,...c}=t,p=new m([...r??[new s,new x({...e===void 0?{}:{platform:e}})]]);return g({...c,...u===void 0?{}:{onModelComplete:u},toolExecutor:p,toolPolicy:{...o===void 0?{}:{allowedTools:o},...n===void 0?{}:{deniedTools:n},...l===void 0?{}:{requireApproval:l},...i===void 0?{}:{approvalHandler:i},...d===void 0?{}:{authorizationRules:d},...a===void 0?{}:{authorizationObserver:a}}})}export{g as createAgentInstance,h as createLocalAgentInstance};
@@ -1,4 +1,5 @@
1
1
  import type { LotaGate } from '@lotagate/sdk';
2
2
  import type { ModelCompletionClient } from '../../ports/model-completion-client.js';
3
+ import type { ModelNetworkRecoveryObserver } from '../../application/model/model-response-retry.js';
3
4
  /** Reuses the agent model boundary for non-streaming host-owned completions. */
4
- export declare function createToolCallingCompletionClient(client: LotaGate): ModelCompletionClient;
5
+ export declare function createToolCallingCompletionClient(client: LotaGate, recovery?: ModelNetworkRecoveryObserver): ModelCompletionClient;
@@ -1 +1 @@
1
- import{createToolCallingModelClient as l}from"./tool-calling-model-client.js";function i(e){const n=l(e);return{chat:{completions:{create:async(o,r)=>{const t=await n.chat.completions.create({...o,stream:!1},r);if(a(t))throw new Error("The completion adapter returned a streaming response unexpectedly.");return t}}}}}function a(e){return typeof e=="object"&&e!==null&&Symbol.asyncIterator in e}export{i as createToolCallingCompletionClient};
1
+ import{createToolCallingModelClient as a}from"./tool-calling-model-client.js";function s(e,n){const o=a(e,{},n);return{chat:{completions:{create:async(r,l)=>{const t=await o.chat.completions.create({...r,stream:!1},l);if(c(t))throw new Error("The completion adapter returned a streaming response unexpectedly.");return t}}}}}function c(e){return typeof e=="object"&&e!==null&&Symbol.asyncIterator in e}export{s as createToolCallingCompletionClient};
@@ -1,11 +1,12 @@
1
1
  import { type LotaGate } from '@lotagate/sdk';
2
2
  import type { LotaGateAgentOptions } from '@lotagate/agent-sdk';
3
3
  import type { ModelCallObserver } from '../../ports/model-diagnostics.js';
4
+ import { type ModelNetworkRecoveryObserver } from '../../application/model/model-response-retry.js';
4
5
  type AgentModelClient = LotaGateAgentOptions['modelClient'];
5
6
  /**
6
7
  * Adapts the published SDK client to the Agent SDK model port and makes the
7
8
  * intended tool-calling mode explicit for gateways that do not infer it from
8
9
  * the presence of `tools` alone.
9
10
  */
10
- export declare function createToolCallingModelClient(client: LotaGate, diagnostics?: ModelCallObserver): AgentModelClient;
11
+ export declare function createToolCallingModelClient(client: LotaGate, diagnostics?: ModelCallObserver, recovery?: ModelNetworkRecoveryObserver): AgentModelClient;
11
12
  export {};
@@ -1 +1 @@
1
- import"@lotagate/sdk";import{AssistantDeltaNormalizer as st}from"../../domain/runtime/assistant-delta-normalizer.js";import{createModelToolNameMap as rt,mapChunkToolNames as it,mapRequestToolNames as K,mapResponseToolNames as L}from"./model-tool-name-mapper.js";import{isRetryableModelResponseError as at,isRetryableToolResultFollowUpError as lt,MODEL_RESPONSE_MAX_RETRIES as ct,retryModelStream as ft}from"../../application/model/model-response-retry.js";import{mapUsage as N,textLength as F}from"./model-response-metrics.js";import{assertTextWithinLimit as ut,modelResponseLimitError as w}from"../../application/agent/bounded-text-accumulator.js";import{RESOURCE_LIMITS as u}from"../../domain/runtime/resource-limits.js";const G=ct;function Ft(t,n={}){return{chat:{completions:{create:((e,s)=>{const r=rt(e.tools),a=e.tools!==void 0&&e.tools.length>0?1:void 0;if(e.stream===!0){const l=K(D({...e,stream:!0}),r),g=yt(e)?ht(t,l,s,a):ft({create:async()=>await t.chat.completions.create(l,s),isObservable:pt,...s?.signal===void 0?{}:{signal:s.signal}});return gt(t,l,e.tools,s,g,e.model,n,r,a)}const i=K(D({...e,stream:!1}),r);return dt(t.chat.completions.create(i,s),e.model,n,r,a)})}}}}async function dt(t,n,o,e,s){const r=H(L(S(await t),e),s);U(r);const a=r.choices[0]?.message;return o.onComplete?.({model:n,stream:!1,contentLength:F(a?.content),toolCallCount:a?.tool_calls?.length??0,toolNames:(a?.tool_calls??[]).map(i=>i.function.name),...r.usage===void 0?{}:{usage:N(r.usage)},...r.choices[0]?.finish_reason===void 0?{}:{finishReason:r.choices[0].finish_reason}}),r}async function*gt(t,n,o,e,s,r,a,i,l){let g=0,h=0,M=0,f;const m=new Set,B=new Set,E=new wt(o);let x=!1,A,J,R=!1;const ot=new st;try{for await(const C of s){const d=it(Ct(C,ot),i);if(h+=Buffer.byteLength(JSON.stringify(d),"utf8"),h>u.agentStreamBytes)throw w("stream",u.agentStreamBytes);const p=E.consume(d).chunk,_=p.choices[0];p.usage!==void 0&&(A=N(p.usage));const W=F(_?.delta.content);if(M+=Buffer.byteLength(z(_?.delta.content),"utf8"),M>u.sessionTextBytes)throw w("text",u.sessionTextBytes);if(g+=W,f=_?.finish_reason??f,W>0&&(x=!0),_?.finish_reason==="tool_calls"&&!R){const P=E.flush(p);if(!x&&j(P)){const T=L(S(await v(t,n,e,l)),i);T.usage!==void 0&&(A=N(T.usage)),Z(T,B,m),f=T.choices[0]?.finish_reason??f,yield k(T);return}const X=Q(P,l);Y(X,B,m),R=!0,yield p,yield X}else yield p;J=p}if(!R&&J!==void 0&&E.hasCalls()){const C=E.flush(J);if(!x&&j(C)){const y=L(S(await v(t,n,e,l)),i);y.usage!==void 0&&(A=N(y.usage)),Z(y,B,m),f=y.choices[0]?.finish_reason??f,yield k(y);return}const d=Q(C,l);Y(d,B,m),R=!0,yield d}}catch(C){if(!x&&!R&&et(C)&&e?.signal?.aborted!==!0){const d=L(S(await v(t,n,e,l)),i);d.usage!==void 0&&(A=N(d.usage));const y=d.choices[0]?.message,p=F(y?.content);U(d),g+=p;for(const _ of y?.tool_calls??[])_.id.length>0&&B.add(_.id),_.function.name.length>0&&m.add(_.function.name);f=d.choices[0]?.finish_reason??f,yield k(d);return}throw C}finally{a.onComplete?.({model:r,stream:!0,contentLength:g,toolCallCount:B.size||m.size,toolNames:[...m],...f===void 0?{}:{finishReason:f},...A===void 0?{}:{usage:A}})}}async function v(t,n,o,e,s=!1){const r=D({...n,stream:!1});for(let a=0;;a+=1)try{const i=S(await t.chat.completions.create(r,o));if(a<G&&j(i))continue;const l=H(i,e);return U(l),l}catch(i){const l=s?lt(i):et(i);if(a>=G||!l||o?.signal?.aborted===!0)throw i}}async function*ht(t,n,o,e){yield k(await v(t,n,o,e,!0))}function D(t){return t.tools===void 0||t.tools.length===0||mt(t)?t:{...t,tool_choice:"auto"}}function mt(t){return t.tool_choice!==void 0||t.toolChoice!==void 0||t.toolConfig!==void 0}function yt(t){const n=t.messages.at(-1);return n!==void 0&&"role"in n&&n.role==="tool"}function pt(t){return t.choices.some(n=>{const o=n.delta.content,e=n.delta.tool_calls,s=n.delta;return typeof o=="string"&&o.length>0||Array.isArray(o)&&o.length>0||Array.isArray(e)&&e.length>0||typeof s.reasoning_content=="string"&&s.reasoning_content.length>0||c(s.function_call)})}function H(t,n){return n===void 0?t:{...t,choices:t.choices.map(o=>{const e=o.message.tool_calls;return e===void 0||e.length<=n?o:{...o,message:{...o.message,tool_calls:e.slice(0,n)}}})}}function Q(t,n){return n===void 0?t:{...t,choices:t.choices.map(o=>{const e=o.delta.tool_calls;return e===void 0||e.length<=n?o:{...o,delta:{...o.delta,tool_calls:e.slice(0,n)}}})}}function k(t){const n=S(t),o=n.choices[0],e=o?.message,s=_t(e);return{id:n.id,object:"chat.completion.chunk",created:n.created,model:n.model,choices:[{index:o?.index??0,delta:{role:"assistant",content:z(e?.content),...s===void 0?{}:{reasoning_content:s},...e?.tool_calls===void 0?{}:{tool_calls:e.tool_calls.map((r,a)=>({...r,index:a}))}},...o?.finish_reason===void 0?{}:{finish_reason:o.finish_reason}}],...n.usage===void 0?{}:{usage:n.usage}}}function _t(t){if(!c(t))return;const n=t.reasoning_content;return typeof n=="string"&&n.length>0?n:void 0}function Ct(t,n){return{...t,choices:t.choices.map(o=>{const e=o.delta.content,r=Array.isArray(e)?n.normalize(z(e)):typeof e=="string"?n.normalize(e):e,a=o.delta,i=[...Array.isArray(e)?q(e):[],...tt(a.function_call,0)];return r===e&&i.length===0?o:{...o,delta:{...o.delta,...r===e?{}:{content:r},...i.length===0?{}:{tool_calls:[...o.delta.tool_calls??[],...i]}}}})}}class wt{knownNames;calls=new Map;order=[];keysByPosition=new Map;constructor(n){this.knownNames=new Set((n??[]).flatMap(o=>Tt(o)))}consume(n){let o=!1;const e=n.choices.map(s=>{const r=s.delta.tool_calls;if(r===void 0||r.length===0)return s;o=!0,r.forEach((i,l)=>{c(i)&&this.append(i,l)});const a={...s.delta};return delete a.tool_calls,{...s,delta:a}});return{chunk:{...n,choices:e},hadToolCalls:o}}hasCalls(){return this.order.length>0}flush(n){const o=this.order.map((a,i)=>{const l=this.calls.get(a);return{id:l.id||`tool-call-${i}`,type:l.type,function:{name:l.name,arguments:l.arguments},...l.providerMetadata===void 0?{}:{provider_metadata:l.providerMetadata}}}),e=new Set,s=o.filter(a=>{const i=`${a.function.name}\0${a.function.arguments}`;return e.has(i)?!1:(e.add(i),!0)}),r=n.choices.map((a,i)=>i===0?{...a,delta:{...a.delta,tool_calls:s}}:a);return{...n,choices:r}}append(n,o){const e=I(n),s=At(n),r=$(n),a=V(n),i=b(n),l=bt(n,o),g=this.keysByPosition.get(l)??Bt(e,l);this.keysByPosition.set(l,g);const h=this.calls.get(g),M=St(h?.name??"",r,this.knownNames),f=Mt(h?.arguments??"",a);if(Buffer.byteLength(f,"utf8")>u.agentToolArgumentBytes)throw w("tool arguments",u.agentToolArgumentBytes);if(i!==void 0&&Buffer.byteLength(JSON.stringify(i),"utf8")>u.agentToolMetadataBytes)throw w("tool metadata",u.agentToolMetadataBytes);if(h===void 0){this.calls.set(g,{id:e,type:s,name:M,arguments:f,...i===void 0?{}:{providerMetadata:i}}),this.order.push(g);return}const m=h.providerMetadata??i;this.calls.set(g,{id:h.id.length===0&&e.length>0?e:h.id,type:s||h.type,name:h.name+M,arguments:f,...m===void 0?{}:{providerMetadata:m}})}}function b(t){if(!c(t))return;const n=t.provider_metadata??t.providerMetadata;if(c(n))return n;const o=t.thoughtSignature??t.thought_signature;return typeof o=="string"&&o.length>0?{google:{thought_signature:o}}:void 0}function bt(t,n){const o=t.index;return typeof o=="number"&&Number.isInteger(o)?o:n}function Bt(t,n){return t.length>0?`id:${t}`:`index:${n}`}function I(t){const n=t;return c(n)&&typeof n.id=="string"?n.id:""}function At(t){const n=t;return c(n)&&typeof n.type=="string"&&n.type.length>0?n.type:"function"}function $(t){const n=t;return c(n)&&c(n.function)&&typeof n.function.name=="string"?n.function.name:""}function V(t){const n=t;return c(n)&&c(n.function)&&typeof n.function.arguments=="string"?n.function.arguments:""}function St(t,n,o){return n.length===0||n===t?"":o!==void 0&&o.has(n)&&n.startsWith(t)||n.startsWith(t)&&t.length>0?n.slice(t.length):n}function Mt(t,n){if(n.length===0)return t;if(t.length===0||n===t)return t.length===0?n:t;if(n.startsWith(t))return n;const o=Rt(t,n);return o!==void 0?o:t+n}function j(t){const n=t.choices[0];return((n!==void 0&&"message"in n?n.message.tool_calls:n?.delta.tool_calls)??[]).some(e=>O(V(e))===void 0)}function Rt(t,n){if(t.length===0||n.length===0)return;const o=O(t),e=O(n);if(!(o===void 0||e===void 0))return JSON.stringify({...o,...e})}function O(t){try{const n=JSON.parse(t);return c(n)?n:void 0}catch{return}}function U(t){if(Buffer.byteLength(JSON.stringify(t),"utf8")>u.agentStreamBytes)throw w("response",u.agentStreamBytes);for(const o of t.choices){ut(z(o.message.content));for(const e of o.message.tool_calls??[]){if(Buffer.byteLength(e.function.arguments,"utf8")>u.agentToolArgumentBytes)throw w("tool arguments",u.agentToolArgumentBytes);const s=e.provider_metadata;if(s!==void 0&&Buffer.byteLength(JSON.stringify(s),"utf8")>u.agentToolMetadataBytes)throw w("tool metadata",u.agentToolMetadataBytes)}}}function Y(t,n,o){for(const e of t.choices[0]?.delta.tool_calls??[]){const s=I(e),r=$(e);s.length>0&&n.add(s),r.length>0&&o.add(r)}}function Z(t,n,o){for(const e of t.choices[0]?.message?.tool_calls??[]){const s=I(e),r=$(e);s.length>0&&n.add(s),r.length>0&&o.add(r)}}function Tt(t){return"function"in t&&typeof t.function.name=="string"?[t.function.name]:"name"in t&&typeof t.name=="string"?[t.name]:"functionDeclarations"in t?t.functionDeclarations.flatMap(n=>typeof n.name=="string"?[n.name]:[]):[]}function S(t){return{...t,choices:t.choices.map(n=>({...n,message:Nt(n.message)}))}}function Nt(t){const n=t,o=[...Array.isArray(t.content)?q(t.content):[],...tt(n.function_call,0)],e=Array.isArray(t.content)?z(t.content):typeof t.content=="string"?t.content:void 0,s=e??null,r=Array.isArray(t.content)||typeof t.content=="string"&&e!==t.content;return!r&&o.length===0?t:{...t,...r?{content:s}:{},...o.length===0?{}:{tool_calls:[...t.tool_calls??[],...o]}}}function q(t){const n=[];for(const[o,e]of t.entries())if(!(typeof e!="object"||e===null)){if("functionCall"in e&&c(e.functionCall)&&typeof e.functionCall.name=="string"){const s=e.functionCall.args;n.push({id:typeof e.functionCall.id=="string"&&e.functionCall.id.length>0?e.functionCall.id:`provider-call-${o}`,type:"function",function:{name:e.functionCall.name,arguments:nt(s)},...b(e)===void 0?{}:{provider_metadata:b(e)}});continue}if("tool_use"in e&&c(e.tool_use)&&typeof e.tool_use.name=="string"){const s=e.tool_use.input;n.push({id:typeof e.tool_use.id=="string"&&e.tool_use.id.length>0?e.tool_use.id:`provider-call-${o}`,type:"function",function:{name:e.tool_use.name,arguments:JSON.stringify(s??{})},...b(e)===void 0?{}:{provider_metadata:b(e)}})}}return n}function tt(t,n){if(!c(t)||typeof t.name!="string")return[];const o=t.arguments;return[{id:typeof t.id=="string"&&t.id.length>0?t.id:`provider-call-${n}`,type:"function",function:{name:t.name,arguments:nt(o)},...b(t)===void 0?{}:{provider_metadata:b(t)}}]}function nt(t){if(t===void 0)return"";if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return""}}function c(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function et(t){return at(t)}function z(t){return typeof t=="string"?t:Array.isArray(t)?t.reduce((n,o)=>{if(typeof o!="object"||o===null||!("text"in o))return n;const e=o.text;return n+(typeof e=="string"?e:"")},""):""}export{Ft as createToolCallingModelClient};
1
+ import"@lotagate/sdk";import{AssistantDeltaNormalizer as ne}from"../../domain/runtime/assistant-delta-normalizer.js";import{createModelToolNameMap as oe,mapChunkToolNames as se,mapRequestToolNames as O,mapResponseToolNames as z}from"./model-tool-name-mapper.js";import{isRetryableModelResponseError as ae,isRetryableToolResultFollowUpError as ie,MODEL_RESPONSE_MAX_RETRIES as le,retryModelRequest as G,retryModelStream as re}from"../../application/model/model-response-retry.js";import{mapUsage as N,textLength as D}from"./model-response-metrics.js";import{assertTextWithinLimit as ce,modelResponseLimitError as w}from"../../application/agent/bounded-text-accumulator.js";import{RESOURCE_LIMITS as d}from"../../domain/runtime/resource-limits.js";import{extractLegacyFunctionCall as fe,extractProviderToolCalls as de,isRecord as m,normalizeCompletionResponse as M,readProviderMetadata as ue,textContent as v}from"./tool-calling-model-normalization.js";const H=le;function Ie(t,e={},n){return{chat:{completions:{create:((s,a)=>{const l=oe(s.tools),i=s.tools!==void 0&&s.tools.length>0?1:void 0;if(s.stream===!0){const c=O(I({...s,stream:!0}),l),f=ye(s)?he(t,c,a,i,n):re({create:async()=>await t.chat.completions.create(c,a),isObservable:Ce,...a?.signal===void 0?{}:{signal:a.signal},...n===void 0?{}:{recovery:n}});return me(t,c,s.tools,a,f,s.model,e,l,i,n)}const r=O(I({...s,stream:!1}),l);return ge(G({create:()=>t.chat.completions.create(r,a),...a?.signal===void 0?{}:{signal:a.signal},...n===void 0?{}:{recovery:n}}),s.model,e,l,i)})}}}}async function ge(t,e,n,o,s){const a=Q(z(M(await t),o),s);j(a);const l=a.choices[0]?.message;return n.onComplete?.({model:e,stream:!1,contentLength:D(l?.content),toolCallCount:l?.tool_calls?.length??0,toolNames:(l?.tool_calls??[]).map(i=>i.function.name),...a.usage===void 0?{}:{usage:N(a.usage)},...a.choices[0]?.finish_reason===void 0?{}:{finishReason:a.choices[0].finish_reason}}),a}async function*me(t,e,n,o,s,a,l,i,r,c){let f=0,S=0,B=0,u;const C=new Set,b=new Set,E=new Be(n);let L=!1,R,F,T=!1;const te=new ne;try{for await(const _ of s){const g=se(we(_,te),i);if(S+=Buffer.byteLength(JSON.stringify(g),"utf8"),S>d.agentStreamBytes)throw w("stream",d.agentStreamBytes);const p=E.consume(g).chunk,y=p.choices[0];p.usage!==void 0&&(R=N(p.usage));const P=D(y?.delta.content);if(B+=Buffer.byteLength(v(y?.delta.content),"utf8"),B>d.sessionTextBytes)throw w("text",d.sessionTextBytes);if(f+=P,u=y?.finish_reason??u,P>0&&(L=!0),y?.finish_reason==="tool_calls"&&!T){const X=E.flush(p);if(!L&&W(X)){const A=z(M(await k(t,e,o,r,!1,c)),i);A.usage!==void 0&&(R=N(A.usage)),q(A,b,C),u=A.choices[0]?.finish_reason??u,yield x(A);return}const K=V(X,r);Z(K,b,C),T=!0,yield p,yield K}else yield p;F=p}if(!T&&F!==void 0&&E.hasCalls()){const _=E.flush(F);if(!L&&W(_)){const h=z(M(await k(t,e,o,r,!1,c)),i);h.usage!==void 0&&(R=N(h.usage)),q(h,b,C),u=h.choices[0]?.finish_reason??u,yield x(h);return}const g=V(_,r);Z(g,b,C),T=!0,yield g}}catch(_){if(!L&&!T&&ee(_)&&o?.signal?.aborted!==!0){const g=z(M(await k(t,e,o,r,!1,c)),i);g.usage!==void 0&&(R=N(g.usage));const h=g.choices[0]?.message,p=D(h?.content);j(g),f+=p;for(const y of h?.tool_calls??[])y.id.length>0&&b.add(y.id),y.function.name.length>0&&C.add(y.function.name);u=g.choices[0]?.finish_reason??u,yield x(g);return}throw _}finally{l.onComplete?.({model:a,stream:!0,contentLength:f,toolCallCount:b.size||C.size,toolNames:[...C],...u===void 0?{}:{finishReason:u},...R===void 0?{}:{usage:R}})}}async function k(t,e,n,o,s=!1,a){const l=I({...e,stream:!1});for(let i=0;;i+=1)try{const r=M(await G({create:()=>t.chat.completions.create(l,n),...n?.signal===void 0?{}:{signal:n.signal},...a===void 0?{}:{recovery:a}}));if(i<H&&W(r))continue;const c=Q(r,o);return j(c),c}catch(r){const c=s?ie(r):ee(r);if(i>=H||!c||n?.signal?.aborted===!0)throw r}}async function*he(t,e,n,o,s){yield x(await k(t,e,n,o,!0,s))}function I(t){return t.tools===void 0||t.tools.length===0||pe(t)?t:{...t,tool_choice:"auto"}}function pe(t){return t.tool_choice!==void 0||t.toolChoice!==void 0||t.toolConfig!==void 0}function ye(t){const e=t.messages.at(-1);return e!==void 0&&"role"in e&&e.role==="tool"}function Ce(t){return t.choices.some(e=>{const n=e.delta.content,o=e.delta.tool_calls,s=e.delta;return typeof n=="string"&&n.length>0||Array.isArray(n)&&n.length>0||Array.isArray(o)&&o.length>0||typeof s.reasoning_content=="string"&&s.reasoning_content.length>0||m(s.function_call)})}function Q(t,e){return e===void 0?t:{...t,choices:t.choices.map(n=>{const o=n.message.tool_calls;return o===void 0||o.length<=e?n:{...n,message:{...n.message,tool_calls:o.slice(0,e)}}})}}function V(t,e){return e===void 0?t:{...t,choices:t.choices.map(n=>{const o=n.delta.tool_calls;return o===void 0||o.length<=e?n:{...n,delta:{...n.delta,tool_calls:o.slice(0,e)}}})}}function x(t){const e=M(t),n=e.choices[0],o=n?.message,s=_e(o);return{id:e.id,object:"chat.completion.chunk",created:e.created,model:e.model,choices:[{index:n?.index??0,delta:{role:"assistant",content:v(o?.content),...s===void 0?{}:{reasoning_content:s},...o?.tool_calls===void 0?{}:{tool_calls:o.tool_calls.map((a,l)=>({...a,index:l}))}},...n?.finish_reason===void 0?{}:{finish_reason:n.finish_reason}}],...e.usage===void 0?{}:{usage:e.usage}}}function _e(t){if(!m(t))return;const e=t.reasoning_content;return typeof e=="string"&&e.length>0?e:void 0}function we(t,e){return{...t,choices:t.choices.map(n=>{const o=n.delta.content,a=Array.isArray(o)?e.normalize(v(o)):typeof o=="string"?e.normalize(o):o,l=n.delta,i=[...Array.isArray(o)?de(o):[],...fe(l.function_call,0)];return a===o&&i.length===0?n:{...n,delta:{...n.delta,...a===o?{}:{content:a},...i.length===0?{}:{tool_calls:[...n.delta.tool_calls??[],...i]}}}})}}class Be{knownNames;calls=new Map;order=[];keysByPosition=new Map;constructor(e){this.knownNames=new Set((e??[]).flatMap(n=>Ne(n)))}consume(e){let n=!1;const o=e.choices.map(s=>{const a=s.delta.tool_calls;if(a===void 0||a.length===0)return s;n=!0,a.forEach((i,r)=>{m(i)&&this.append(i,r)});const l={...s.delta};return delete l.tool_calls,{...s,delta:l}});return{chunk:{...e,choices:o},hadToolCalls:n}}hasCalls(){return this.order.length>0}flush(e){const n=this.order.map((l,i)=>{const r=this.calls.get(l);return{id:r.id||`tool-call-${i}`,type:r.type,function:{name:r.name,arguments:r.arguments},...r.providerMetadata===void 0?{}:{provider_metadata:r.providerMetadata}}}),o=new Set,s=n.filter(l=>{const i=`${l.function.name}\0${l.function.arguments}`;return o.has(i)?!1:(o.add(i),!0)}),a=e.choices.map((l,i)=>i===0?{...l,delta:{...l.delta,tool_calls:s}}:l);return{...e,choices:a}}append(e,n){const o=J(e),s=Me(e),a=U(e),l=Y(e),i=ue(e),r=be(e,n),c=this.keysByPosition.get(r)??Re(o,r);this.keysByPosition.set(r,c);const f=this.calls.get(c),S=Se(f?.name??"",a,this.knownNames),B=Te(f?.arguments??"",l);if(Buffer.byteLength(B,"utf8")>d.agentToolArgumentBytes)throw w("tool arguments",d.agentToolArgumentBytes);if(i!==void 0&&Buffer.byteLength(JSON.stringify(i),"utf8")>d.agentToolMetadataBytes)throw w("tool metadata",d.agentToolMetadataBytes);if(f===void 0){this.calls.set(c,{id:o,type:s,name:S,arguments:B,...i===void 0?{}:{providerMetadata:i}}),this.order.push(c);return}const u=f.providerMetadata??i;this.calls.set(c,{id:f.id.length===0&&o.length>0?o:f.id,type:s||f.type,name:f.name+S,arguments:B,...u===void 0?{}:{providerMetadata:u}})}}function be(t,e){const n=t.index;return typeof n=="number"&&Number.isInteger(n)?n:e}function Re(t,e){return t.length>0?`id:${t}`:`index:${e}`}function J(t){const e=t;return m(e)&&typeof e.id=="string"?e.id:""}function Me(t){const e=t;return m(e)&&typeof e.type=="string"&&e.type.length>0?e.type:"function"}function U(t){const e=t;return m(e)&&m(e.function)&&typeof e.function.name=="string"?e.function.name:""}function Y(t){const e=t;return m(e)&&m(e.function)&&typeof e.function.arguments=="string"?e.function.arguments:""}function Se(t,e,n){return e.length===0||e===t?"":n!==void 0&&n.has(e)&&e.startsWith(t)||e.startsWith(t)&&t.length>0?e.slice(t.length):e}function Te(t,e){if(e.length===0)return t;if(t.length===0||e===t)return t.length===0?e:t;if(e.startsWith(t))return e;const n=Ae(t,e);return n!==void 0?n:t+e}function W(t){const e=t.choices[0];return((e!==void 0&&"message"in e?e.message.tool_calls:e?.delta.tool_calls)??[]).some(o=>$(Y(o))===void 0)}function Ae(t,e){if(t.length===0||e.length===0)return;const n=$(t),o=$(e);if(!(n===void 0||o===void 0))return JSON.stringify({...n,...o})}function $(t){try{const e=JSON.parse(t);return m(e)?e:void 0}catch{return}}function j(t){if(Buffer.byteLength(JSON.stringify(t),"utf8")>d.agentStreamBytes)throw w("response",d.agentStreamBytes);for(const n of t.choices){ce(v(n.message.content));for(const o of n.message.tool_calls??[]){if(Buffer.byteLength(o.function.arguments,"utf8")>d.agentToolArgumentBytes)throw w("tool arguments",d.agentToolArgumentBytes);const s=o.provider_metadata;if(s!==void 0&&Buffer.byteLength(JSON.stringify(s),"utf8")>d.agentToolMetadataBytes)throw w("tool metadata",d.agentToolMetadataBytes)}}}function Z(t,e,n){for(const o of t.choices[0]?.delta.tool_calls??[]){const s=J(o),a=U(o);s.length>0&&e.add(s),a.length>0&&n.add(a)}}function q(t,e,n){for(const o of t.choices[0]?.message?.tool_calls??[]){const s=J(o),a=U(o);s.length>0&&e.add(s),a.length>0&&n.add(a)}}function Ne(t){return"function"in t&&typeof t.function.name=="string"?[t.function.name]:"name"in t&&typeof t.name=="string"?[t.name]:"functionDeclarations"in t?t.functionDeclarations.flatMap(e=>typeof e.name=="string"?[e.name]:[]):[]}function ee(t){return ae(t)}export{Ie as createToolCallingModelClient};
@@ -0,0 +1,7 @@
1
+ import type { ChatCompletionResponse, ToolCall } from '@lotagate/sdk';
2
+ export declare function normalizeCompletionResponse(response: ChatCompletionResponse): ChatCompletionResponse;
3
+ export declare function extractProviderToolCalls(content: readonly unknown[]): ToolCall[];
4
+ export declare function extractLegacyFunctionCall(value: unknown, index: number): ToolCall[];
5
+ export declare function readProviderMetadata(value: unknown): Record<string, unknown> | undefined;
6
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
7
+ export declare function textContent(content: unknown): string;
@@ -0,0 +1 @@
1
+ function p(t){return{...t,choices:t.choices.map(r=>({...r,message:a(r.message)}))}}function a(t){const r=t,o=[...Array.isArray(t.content)?d(t.content):[],...l(r.function_call,0)],n=Array.isArray(t.content)?s(t.content):typeof t.content=="string"?t.content:void 0,f=n??null,c=Array.isArray(t.content)||typeof t.content=="string"&&n!==t.content;return!c&&o.length===0?t:{...t,...c?{content:f}:{},...o.length===0?{}:{tool_calls:[...t.tool_calls??[],...o]}}}function d(t){const r=[];for(const[o,n]of t.entries())if(i(n)){if("functionCall"in n&&i(n.functionCall)&&typeof n.functionCall.name=="string"){r.push({id:typeof n.functionCall.id=="string"&&n.functionCall.id.length>0?n.functionCall.id:`provider-call-${o}`,type:"function",function:{name:n.functionCall.name,arguments:u(n.functionCall.args)},...e(n)===void 0?{}:{provider_metadata:e(n)}});continue}"tool_use"in n&&i(n.tool_use)&&typeof n.tool_use.name=="string"&&r.push({id:typeof n.tool_use.id=="string"&&n.tool_use.id.length>0?n.tool_use.id:`provider-call-${o}`,type:"function",function:{name:n.tool_use.name,arguments:JSON.stringify(n.tool_use.input??{})},...e(n)===void 0?{}:{provider_metadata:e(n)}})}return r}function l(t,r){return!i(t)||typeof t.name!="string"?[]:[{id:typeof t.id=="string"&&t.id.length>0?t.id:`provider-call-${r}`,type:"function",function:{name:t.name,arguments:u(t.arguments)},...e(t)===void 0?{}:{provider_metadata:e(t)}}]}function u(t){if(t===void 0)return"";if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return""}}function e(t){if(!i(t))return;const r=t.provider_metadata??t.providerMetadata;if(i(r))return r;const o=t.thoughtSignature??t.thought_signature;return typeof o=="string"&&o.length>0?{google:{thought_signature:o}}:void 0}function i(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function s(t){return typeof t=="string"?t:Array.isArray(t)?t.reduce((r,o)=>{if(!i(o)||!("text"in o))return r;const n=o.text;return r+(typeof n=="string"?n:"")},""):""}export{l as extractLegacyFunctionCall,d as extractProviderToolCalls,i as isRecord,p as normalizeCompletionResponse,e as readProviderMetadata,s as textContent};
@@ -1 +1 @@
1
- import n from"node:crypto";import p from"node:fs/promises";import d from"node:os";import s from"node:path";import{CliError as m}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as c}from"../../domain/errors/error-codes.js";import{DEFAULT_MAX_IMAGE_BYTES as l}from"./image-normalizer.js";import{readFileBounded as f}from"../filesystem/bounded-file-reader.js";import{detectHostPlatform as g}from"../platform/host-platform.js";import{CLIPBOARD_POLICY as i,clipboardUnavailableError as e}from"./clipboard-policy.js";import{runBoundedClipboardProcess as h}from"./clipboard-process.js";class _{platform;constructor(r=g()){this.platform=r}async readImage(){if(!this.platform.isWindows)throw e("Windows clipboard image adapter cannot run on this platform.");const r=s.join(d.tmpdir(),`lotagate-clipboard-${process.pid}-${n.randomUUID()}.png`);try{await u(r,this.platform);const t=await f(r,l);if(t.truncated)throw new m(c.ATTACHMENT_TOO_LARGE,"Clipboard image exceeds the configured size limit.",{category:"attachment",userMessage:"The clipboard image is too large to attach."});return{bytes:t.bytes,mimeType:"image/png"}}catch(t){throw t instanceof m?t:e("Unable to read an image from the clipboard.",t)}finally{await p.rm(r,{force:!0})}}}function u(a,r){return h({command:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command","$ErrorActionPreference='Stop'; $image=Get-Clipboard -Format Image; if ($null -eq $image) { exit 3 }; $image.Save($env:LOTAGATE_CLIPBOARD_OUTPUT, [System.Drawing.Imaging.ImageFormat]::Png)"],platform:r,env:{...process.env,LOTAGATE_CLIPBOARD_OUTPUT:a},maxStdoutBytes:i.maxImageBytes,maxStderrBytes:i.maxImageBytes,timeoutMs:i.timeoutMs,stdoutLimitError:e("Clipboard image helper produced unexpected output."),stderrLimitError:e("Clipboard image helper diagnostics exceeded the supported limit.")}).then(o=>{if(o.exitCode!==0)throw new Error(o.stderr.toString("utf8").trim()||`PowerShell exited with code ${String(o.exitCode)}.`)})}export{_ as WindowsClipboardAdapter};
1
+ import n from"node:crypto";import p from"node:fs/promises";import d from"node:os";import s from"node:path";import{CliError as m}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as c}from"../../domain/errors/error-codes.js";import{DEFAULT_MAX_IMAGE_BYTES as l}from"./image-normalizer.js";import{readFileBounded as f}from"../filesystem/bounded-file-reader.js";import{createSafeChildEnvironment as g}from"../platform/host-process.js";import{detectHostPlatform as h}from"../platform/host-platform.js";import{CLIPBOARD_POLICY as i,clipboardUnavailableError as e}from"./clipboard-policy.js";import{runBoundedClipboardProcess as u}from"./clipboard-process.js";class L{platform;constructor(r=h()){this.platform=r}async readImage(){if(!this.platform.isWindows)throw e("Windows clipboard image adapter cannot run on this platform.");const r=s.join(d.tmpdir(),`lotagate-clipboard-${process.pid}-${n.randomUUID()}.png`);try{await w(r,this.platform);const t=await f(r,l);if(t.truncated)throw new m(c.ATTACHMENT_TOO_LARGE,"Clipboard image exceeds the configured size limit.",{category:"attachment",userMessage:"The clipboard image is too large to attach."});return{bytes:t.bytes,mimeType:"image/png"}}catch(t){throw t instanceof m?t:e("Unable to read an image from the clipboard.",t)}finally{await p.rm(r,{force:!0})}}}function w(a,r){return u({command:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command","$ErrorActionPreference='Stop'; $image=Get-Clipboard -Format Image; if ($null -eq $image) { exit 3 }; $image.Save($env:LOTAGATE_CLIPBOARD_OUTPUT, [System.Drawing.Imaging.ImageFormat]::Png)"],platform:r,env:{...g(r),LOTAGATE_CLIPBOARD_OUTPUT:a},maxStdoutBytes:i.maxImageBytes,maxStderrBytes:i.maxImageBytes,timeoutMs:i.timeoutMs,stdoutLimitError:e("Clipboard image helper produced unexpected output."),stderrLimitError:e("Clipboard image helper diagnostics exceeded the supported limit.")}).then(o=>{if(o.exitCode!==0)throw new Error(o.stderr.toString("utf8").trim()||`PowerShell exited with code ${String(o.exitCode)}.`)})}export{L as WindowsClipboardAdapter};
@@ -1 +1 @@
1
- class r{stores;writableStore;constructor(t,e){this.stores=t,this.writableStore=e}async list(){const t=new Map;for(const e of this.stores)for(const s of await e.list())t.set(s.name,s);return[...t.values()].sort((e,s)=>e.name.localeCompare(s.name))}async get(t){for(const e of this.stores){const s=await e.get(t);if(s!==void 0)return s}}async set(t){await this.writableStore.set(t)}async delete(t){let e=!1;for(const s of this.stores)e=await s.delete(t)||e;return e}}export{r as CompositeCredentialStore};
1
+ class i{stores;writableStore;constructor(t,e){this.stores=t,this.writableStore=e}async list(){const t=new Map;for(const e of this.stores)for(const s of await e.list())t.has(s.name)||t.set(s.name,s);return[...t.values()].sort((e,s)=>e.name.localeCompare(s.name))}async get(t){for(const e of this.stores){const s=await e.get(t);if(s!==void 0)return s}}async set(t){await this.writableStore.set(t)}async delete(t){const e=this.stores.indexOf(this.writableStore),s=e<0?[]:this.stores.slice(0,e);for(const r of s)if(await r.get(t)!==void 0)return!1;return this.writableStore.delete(t)}}export{i as CompositeCredentialStore};
@@ -1,2 +1,4 @@
1
- import{withToolExecutionLogging as f}from"../observability/tool-execution-logger.js";const a=[u("skill.list","List enabled skills available to the agent.",{type:"object",properties:{},additionalProperties:!1}),u("skill.load","Load instructions for one enabled skill by name when its description matches the task.",{type:"object",properties:{name:{type:"string",description:"Enabled skill name."}},required:["name"],additionalProperties:!1})];function d(){return a}class g{scopes;logger;skills;constructor(e,i,r){this.scopes=i,this.logger=r,this.skills=e.filter(n=>n.enabled&&n.modelInvocable)}listTools(){return d()}getToolInfo(e){return a.some(i=>k(i)===e)?{toolName:e,source:"custom",executorId:"skill-catalog",metadata:{category:"skill",risk:"read"}}:void 0}async execute(e,i,r){return f(this.logger,{toolName:e,source:"custom",context:r,details:{skillName:typeof i.name=="string"?i.name:void 0}},async()=>{if(e==="skill.list")return c(JSON.stringify(this.skills.map(s=>({name:s.skillKey??s.name,description:s.description}))));if(e!=="skill.load")return l(`Unknown skill tool: ${e}`);const n=i.name;if(typeof n!="string")return l("skill.load requires a skill name.");const o=this.skills.find(s=>(s.skillKey??s.name)===n);return o===void 0?l(`Skill is unavailable: ${n}`):(this.scopes.activate(r.runId,o),c(m(o.body,r.maxResultBytes)))})}}function u(t,e,i){return{type:"function",function:{name:t,description:e,parameters:i}}}function k(t){return"function"in t?t.function.name:void 0}function c(t){return{content:t,isError:!1}}function l(t){return{content:t,isError:!0}}function m(t,e){const i=Buffer.from(t,"utf8");return i.byteLength<=e?t:`${i.subarray(0,e).toString("utf8")}
2
- [truncated]`}export{g as SkillToolExecutor,d as skillToolDefinitions};
1
+ import{withToolExecutionLogging as d}from"../observability/tool-execution-logger.js";const a=[u("skill.list","List enabled skills available to the agent.",{type:"object",properties:{},additionalProperties:!1}),u("skill.load","Load instructions for one enabled skill by name when its description matches the task.",{type:"object",properties:{name:{type:"string",description:"Enabled skill name."}},required:["name"],additionalProperties:!1})];function f(){return a}class k{scopes;logger;skills;constructor(t,n,s){this.scopes=n,this.logger=s,this.skills=t.filter(o=>o.enabled&&o.modelInvocable)}listTools(){return f()}getToolInfo(t){return a.some(n=>m(n)===t)?{toolName:t,source:"custom",executorId:"skill-catalog",metadata:{category:"skill",risk:"read"}}:void 0}async execute(t,n,s){return d(this.logger,{toolName:t,source:"custom",context:s,details:{skillName:typeof n.name=="string"?n.name:void 0}},async()=>{if(t==="skill.list")return c(JSON.stringify(this.skills.map(i=>({name:i.skillKey??i.name,description:i.description}))));if(t!=="skill.load")return l(`Unknown skill tool: ${t}`);const o=n.name;if(typeof o!="string")return l("skill.load requires a skill name.");const r=this.skills.find(i=>(i.skillKey??i.name)===o);return r===void 0?l(`Skill is unavailable: ${o}`):(this.scopes.activate(s.runId,r),c(y(p(r),s.maxResultBytes)))})}}function u(e,t,n){return{type:"function",function:{name:e,description:t,parameters:n}}}function m(e){return"function"in e?e.function.name:void 0}function c(e){return{content:e,isError:!1}}function l(e){return{content:e,isError:!0}}function p(e){const t=e.allowedTools.length===0?"(none)":e.allowedTools.map(n=>`- ${n}`).join(`
2
+ `);return["## ACTIVE SKILL TOOL BOUNDARY",`Skill: ${e.skillKey??e.name}`,"This is a hard capability boundary for the current agent run.","You may call only the exact tool names listed below. Do not call, infer, substitute, or retry any other tool.","If the requested action needs a tool outside this list, stop and explain that the active skill does not permit it.","Allowed tools:",t,"","## SKILL INSTRUCTIONS",e.body].join(`
3
+ `)}function y(e,t){const n=Buffer.from(e,"utf8");return n.byteLength<=t?e:`${n.subarray(0,t).toString("utf8")}
4
+ [truncated]`}export{k as SkillToolExecutor,f as skillToolDefinitions};
@@ -1 +1 @@
1
- async function u(t,e,s){const r=Date.now(),n={toolName:e.toolName,source:e.source,sessionId:e.context.sessionId,runId:e.context.runId,iteration:e.context.iteration,...e.details??{}};t?.info("tool.execution.started",n);try{const o=await s(),i={...n,durationMs:Date.now()-r,outcome:o.isError?"error":"success",...c(o)};return o.isError?t?.warn("tool.execution.failed",i):t?.info("tool.execution.completed",i),o}catch(o){const i=a(o);throw t?.error("tool.execution.failed",{...n,durationMs:Date.now()-r,outcome:"exception",error:o instanceof Error?o.message:String(o),...i===void 0?{}:{errorCode:i}}),o}}function c(t){const e=t.metadata;if(e===void 0)return{};const s={};for(const r of["errorCode","exitCode","timedOut"]){const n=e[r];(typeof n=="string"||typeof n=="number"||typeof n=="boolean")&&(s[r]=n)}return s}function a(t){if(t===null||typeof t!="object"||!("code"in t))return;const e=t.code;return typeof e=="string"&&e.length>0?e:void 0}export{u as withToolExecutionLogging};
1
+ async function d(t,e,c){const a=Date.now(),n={toolName:e.toolName,source:e.source,sessionId:e.context.sessionId,runId:e.context.runId,iteration:e.context.iteration,...e.details??{}};t?.info("tool.execution.started",n);try{const o=await c(),r={...n,durationMs:Date.now()-a,outcome:o.metadata?.cancelled===!0?"cancelled":o.isError?"error":"success",...i(o)};return o.metadata?.cancelled===!0?t?.info("tool.execution.cancelled",r):o.isError?t?.warn("tool.execution.failed",r):t?.info("tool.execution.completed",r),o}catch(o){const r=s(o);throw t?.error("tool.execution.failed",{...n,durationMs:Date.now()-a,outcome:"exception",error:o instanceof Error?o.message:String(o),...r===void 0?{}:{errorCode:r}}),o}}function i(t){const e=t.metadata;if(e===void 0)return{};const c={};for(const a of["errorCode","exitCode","timedOut","verification","computer","cancelled","retryable","queueWaitMs","providerDurationMs"]){const n=e[a];(typeof n=="string"||typeof n=="number"||typeof n=="boolean")&&(c[a]=n)}return c}function s(t){if(t===null||typeof t!="object"||!("code"in t))return;const e=t.code;return typeof e=="string"&&e.length>0?e:void 0}export{d as withToolExecutionLogging};