@lotagate/cli 0.1.25 → 0.1.26
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.
- package/README.md +5 -4
- package/bin/lotagate.mjs +50 -8
- package/dist/application/agent/agent-constants.d.ts +6 -0
- package/dist/application/agent/agent-constants.js +1 -0
- package/dist/application/agent/agent-session-store-registry.d.ts +16 -0
- package/dist/application/agent/agent-session-store-registry.js +1 -0
- package/dist/application/agent/agent-session-store.d.ts +4 -0
- package/dist/application/agent/agent-session-store.js +5 -5
- package/dist/application/agent/capability-profile.d.ts +0 -38
- package/dist/application/agent/capability-profile.js +0 -1
- package/dist/application/agent/cli-agent-execution-service.d.ts +22 -12
- package/dist/application/agent/cli-agent-execution-service.js +1 -1
- package/dist/application/agent/cli-agent-preparation-cache.d.ts +39 -0
- package/dist/application/agent/cli-agent-preparation-cache.js +1 -0
- package/dist/application/agent/context-compaction.d.ts +1 -0
- package/dist/application/agent/context-compaction.js +7 -6
- package/dist/application/agent/context-token-cache.d.ts +21 -0
- package/dist/application/agent/context-token-cache.js +4 -0
- package/dist/application/agent/context-usage-service.d.ts +52 -0
- package/dist/application/agent/context-usage-service.js +1 -0
- package/dist/application/agent/continuation-checkpoint.d.ts +15 -0
- package/dist/application/agent/continuation-checkpoint.js +2 -0
- package/dist/application/agent/interactive-agent-guidance.d.ts +3 -3
- package/dist/application/agent/interactive-agent-guidance.js +2 -2
- package/dist/application/chat/pending-attachment-store.d.ts +5 -2
- package/dist/application/chat/pending-attachment-store.js +1 -1
- package/dist/application/commands/application-command-executor.js +1 -1
- package/dist/application/commands/command-catalog.js +1 -1
- package/dist/application/commands/goal-command-handlers.js +6 -6
- package/dist/application/commands/media-command-handlers.js +7 -6
- package/dist/application/commands/runtime-command-handlers.js +9 -9
- package/dist/application/intent/completion-gate.d.ts +2 -5
- package/dist/application/intent/completion-gate.js +1 -1
- package/dist/application/intent/evidence-ledger.d.ts +2 -1
- package/dist/application/intent/evidence-recording-tool-executor.js +1 -1
- package/dist/application/intent/intent-compiler.js +2 -2
- package/dist/application/memory/memory-extractor.js +2 -2
- package/dist/application/model/cached-model-catalog.d.ts +7 -1
- package/dist/application/model/cached-model-catalog.js +1 -1
- package/dist/application/model/model-catalog-service.js +1 -1
- package/dist/application/model/model-context-window.js +1 -1
- package/dist/application/model/model-response-retry.d.ts +7 -1
- package/dist/application/model/model-response-retry.js +1 -1
- package/dist/application/orchestration/cli-subagent-service.d.ts +4 -0
- package/dist/application/orchestration/cli-subagent-service.js +3 -3
- package/dist/application/orchestration/cli-turn-event-projector.js +1 -1
- package/dist/application/orchestration/cli-turn-events.d.ts +0 -7
- package/dist/application/orchestration/goal-input.d.ts +1 -1
- package/dist/application/orchestration/goal-input.js +1 -1
- package/dist/application/orchestration/headless-agent-turn.d.ts +1 -0
- package/dist/application/orchestration/headless-agent-turn.js +3 -3
- package/dist/application/orchestration/orchestration-constants.d.ts +3 -0
- package/dist/application/orchestration/orchestration-constants.js +1 -0
- package/dist/application/orchestration/subagent-handoff.js +3 -3
- package/dist/application/project-intelligence/project-intelligence-constants.d.ts +56 -0
- package/dist/application/project-intelligence/project-intelligence-constants.js +1 -0
- package/dist/application/project-intelligence/project-intelligence-service.js +1 -1
- package/dist/application/protocol/browser-host-tool-executor.d.ts +13 -3
- package/dist/application/protocol/browser-host-tool-executor.js +2 -2
- package/dist/application/protocol/computer-host-tool-executor.d.ts +3 -0
- package/dist/application/protocol/computer-host-tool-executor.js +2 -2
- package/dist/application/protocol/desktop-agent-command.d.ts +2 -2
- package/dist/application/protocol/desktop-agent-command.js +2 -2
- package/dist/application/protocol/desktop-agent-contracts.d.ts +34 -0
- package/dist/application/protocol/desktop-agent-contracts.js +1 -0
- package/dist/application/protocol/desktop-agent-helpers.d.ts +5 -0
- package/dist/application/protocol/desktop-agent-helpers.js +1 -0
- package/dist/application/protocol/desktop-agent-request-parser.d.ts +31 -6
- package/dist/application/protocol/desktop-agent-request-parser.js +1 -1
- package/dist/application/protocol/desktop-approval-broker.d.ts +14 -4
- package/dist/application/protocol/desktop-approval-broker.js +1 -1
- package/dist/application/protocol/desktop-attachment-store.d.ts +19 -2
- package/dist/application/protocol/desktop-attachment-store.js +1 -1
- package/dist/application/protocol/desktop-execution-policy.d.ts +2 -0
- package/dist/application/protocol/desktop-execution-policy.js +1 -1
- package/dist/application/protocol/desktop-host-bridge.d.ts +33 -0
- package/dist/application/protocol/desktop-host-bridge.js +1 -0
- package/dist/application/protocol/desktop-host-capabilities.d.ts +12 -0
- package/dist/application/protocol/desktop-host-capabilities.js +1 -0
- package/dist/application/protocol/desktop-host-tool-executor.d.ts +15 -2
- package/dist/application/protocol/desktop-host-tool-executor.js +2 -2
- package/dist/application/protocol/desktop-intent-event-writer.js +1 -1
- package/dist/application/protocol/desktop-protocol-helpers.js +1 -1
- package/dist/application/protocol/json-line-writer.d.ts +24 -2
- package/dist/application/protocol/json-line-writer.js +2 -2
- package/dist/application/protocol/jsonl-agent-command.d.ts +1 -1
- package/dist/application/protocol/jsonl-agent-command.js +2 -2
- package/dist/application/protocol/jsonl-protocol.d.ts +1 -1
- package/dist/application/protocol/jsonl-protocol.js +2 -2
- package/dist/application/security/desktop-tool-scope-policy.js +1 -1
- package/dist/application/security/tool-action-risk-analyzer.js +1 -1
- package/dist/application/security/tool-approval-service.d.ts +9 -3
- package/dist/application/security/tool-approval-service.js +1 -1
- package/dist/application/security/tool-policy-registry.d.ts +20 -0
- package/dist/application/security/tool-policy-registry.js +1 -0
- package/dist/application/security/tool-risk-classifier.d.ts +2 -1
- package/dist/application/security/tool-risk-classifier.js +1 -1
- package/dist/application/security/workspace-permission-policy.js +1 -1
- package/dist/application/workspace/session-execution-workspace.d.ts +2 -2
- package/dist/application/workspace/session-execution-workspace.js +3 -3
- package/dist/application/workspace/workspace-constants.d.ts +17 -0
- package/dist/application/workspace/workspace-constants.js +1 -0
- package/dist/application/workspace/workspace-file-index.d.ts +0 -1
- package/dist/application/workspace/workspace-file-index.js +1 -1
- package/dist/application/workspace/workspace-instruction-loader.js +1 -1
- package/dist/bootstrap/composition-root.d.ts +1 -0
- package/dist/bootstrap/runtime-factory.d.ts +5 -0
- package/dist/bootstrap/runtime-factory.js +1 -1
- package/dist/domain/errors/cli-error.js +1 -1
- package/dist/domain/extensions/extension-constants.d.ts +1 -0
- package/dist/domain/extensions/extension-constants.js +1 -0
- package/dist/domain/extensions/host-tool-plugin-ids.d.ts +0 -4
- package/dist/domain/extensions/host-tool-plugin-ids.js +1 -1
- package/dist/domain/extensions/plugin-manifest.js +1 -1
- package/dist/domain/intent/intent-contract.d.ts +0 -8
- package/dist/domain/intent/intent-contract.js +1 -1
- package/dist/domain/media/gateway-media-contract.js +1 -1
- package/dist/domain/media/media-constants.d.ts +3 -0
- package/dist/domain/media/media-constants.js +1 -0
- package/dist/domain/media/media-execution-policy.js +1 -1
- package/dist/domain/memory/memory-constants.d.ts +3 -0
- package/dist/domain/memory/memory-constants.js +1 -0
- package/dist/domain/memory/memory-search.js +2 -2
- package/dist/domain/orchestration/goal.d.ts +0 -1
- package/dist/domain/orchestration/goal.js +1 -1
- package/dist/domain/orchestration/work-plan.d.ts +0 -62
- package/dist/domain/orchestration/work-plan.js +0 -1
- package/dist/domain/runtime/assistant-stream-text.d.ts +11 -0
- package/dist/domain/runtime/assistant-stream-text.js +1 -0
- package/dist/domain/runtime/gateway-request-budget.d.ts +19 -0
- package/dist/domain/runtime/gateway-request-budget.js +1 -0
- package/dist/domain/runtime/resource-limits.d.ts +17 -0
- package/dist/domain/runtime/resource-limits.js +1 -1
- package/dist/domain/session/attachment.d.ts +2 -0
- package/dist/domain/workspace/workspace-settings.d.ts +2 -0
- package/dist/domain/workspace/workspace-settings.js +1 -1
- package/dist/infrastructure/agent-sdk/model-response-metrics.d.ts +7 -0
- package/dist/infrastructure/agent-sdk/model-response-metrics.js +1 -0
- package/dist/infrastructure/agent-sdk/model-tool-name-mapper.js +1 -1
- package/dist/infrastructure/agent-sdk/sdk-constants.d.ts +2 -0
- package/dist/infrastructure/agent-sdk/sdk-constants.js +1 -0
- package/dist/infrastructure/agent-sdk/tool-calling-model-client.js +1 -1
- package/dist/infrastructure/cache/cache-policy.d.ts +2 -0
- package/dist/infrastructure/cache/cache-policy.js +1 -1
- package/dist/infrastructure/cache/file-cache-store.d.ts +8 -0
- package/dist/infrastructure/cache/file-cache-store.js +2 -2
- package/dist/infrastructure/clipboard/clipboard-constants.d.ts +1 -0
- package/dist/infrastructure/clipboard/clipboard-constants.js +1 -0
- package/dist/infrastructure/clipboard/image-normalizer.js +1 -1
- package/dist/infrastructure/extensions/extensions-constants.d.ts +6 -0
- package/dist/infrastructure/extensions/extensions-constants.js +1 -0
- package/dist/infrastructure/extensions/mcp-runtime.d.ts +7 -0
- package/dist/infrastructure/extensions/mcp-runtime.js +1 -1
- package/dist/infrastructure/extensions/plugin-manager.js +2 -2
- package/dist/infrastructure/extensions/skill-tool-executor.d.ts +3 -1
- package/dist/infrastructure/extensions/skill-tool-executor.js +2 -2
- package/dist/infrastructure/filesystem/atomic-file-store.d.ts +11 -0
- package/dist/infrastructure/filesystem/atomic-file-store.js +1 -1
- package/dist/infrastructure/filesystem/filesystem-constants.d.ts +8 -0
- package/dist/infrastructure/filesystem/filesystem-constants.js +1 -0
- package/dist/infrastructure/filesystem/local-filesystem-tool-executor.d.ts +3 -0
- package/dist/infrastructure/filesystem/local-filesystem-tool-executor.js +3 -3
- package/dist/infrastructure/logging/daily-rotating-file-writer.d.ts +1 -1
- package/dist/infrastructure/logging/daily-rotating-file-writer.js +2 -2
- package/dist/infrastructure/logging/log-redactor.js +1 -1
- package/dist/infrastructure/logging/logging-constants.d.ts +3 -0
- package/dist/infrastructure/logging/logging-constants.js +1 -0
- package/dist/infrastructure/logging/structured-logger.d.ts +1 -1
- package/dist/infrastructure/logging/structured-logger.js +2 -2
- package/dist/infrastructure/observability/tool-execution-logger.d.ts +11 -0
- package/dist/infrastructure/observability/tool-execution-logger.js +1 -0
- package/dist/infrastructure/platform/host-platform.d.ts +2 -0
- package/dist/infrastructure/platform/host-platform.js +1 -1
- package/dist/infrastructure/platform/host-process.d.ts +3 -1
- package/dist/infrastructure/platform/host-process.js +1 -1
- package/dist/infrastructure/platform/platform-constants.d.ts +4 -0
- package/dist/infrastructure/platform/platform-constants.js +1 -0
- package/dist/infrastructure/platform/process-identity.d.ts +8 -0
- package/dist/infrastructure/platform/process-identity.js +1 -0
- package/dist/infrastructure/platform/read-only-executable.d.ts +2 -1
- package/dist/infrastructure/platform/read-only-executable.js +1 -1
- package/dist/infrastructure/sdk/lotagate-client-factory.js +1 -1
- package/dist/infrastructure/sdk/sdk-media-gateway-client.d.ts +4 -0
- package/dist/infrastructure/sdk/sdk-media-gateway-client.js +1 -1
- package/dist/infrastructure/sessions/file-session-store.d.ts +3 -0
- package/dist/infrastructure/sessions/file-session-store.js +4 -4
- package/dist/infrastructure/sessions/session-constants.d.ts +3 -0
- package/dist/infrastructure/sessions/session-constants.js +1 -0
- package/dist/infrastructure/sessions/session-index.js +3 -3
- package/dist/infrastructure/sessions/session-journal-health.d.ts +7 -0
- package/dist/infrastructure/sessions/session-journal-health.js +1 -0
- package/dist/infrastructure/shell/shell-tool-executor.d.ts +5 -1
- package/dist/infrastructure/shell/shell-tool-executor.js +2 -2
- package/dist/infrastructure/tokens/tiktoken-token-estimator.js +1 -1
- package/dist/infrastructure/tokens/token-constants.d.ts +1 -0
- package/dist/infrastructure/tokens/token-constants.js +1 -0
- package/dist/infrastructure/workspace/workspace-settings-store.d.ts +1 -0
- package/dist/infrastructure/workspace/workspace-settings-store.js +4 -4
- package/dist/main.js +3 -3
- package/dist/ports/media-gateway-client.d.ts +6 -0
- package/dist/ports/session-store.d.ts +1 -0
- package/dist/presentation/tui/ink/components/composer.js +4 -4
- package/dist/presentation/tui/ink/components/transcript.d.ts +1 -0
- package/dist/presentation/tui/ink/components/transcript.js +5 -5
- package/dist/presentation/tui/ink/tui-bridge.d.ts +2 -2
- package/dist/presentation/tui/ink/tui-bridge.js +1 -1
- package/dist/presentation/tui/tui-agent-turn-controller.d.ts +45 -0
- package/dist/presentation/tui/tui-agent-turn-controller.js +1 -0
- package/dist/presentation/tui/tui-application-contract.d.ts +1 -0
- package/dist/presentation/tui/tui-application.d.ts +1 -4
- package/dist/presentation/tui/tui-application.js +3 -3
- package/dist/presentation/tui/tui-clipboard-paste-handlers.d.ts +2 -2
- package/dist/presentation/tui/tui-clipboard-paste-handlers.js +1 -1
- package/dist/presentation/tui/tui-command-executor.js +3 -3
- package/dist/presentation/tui/tui-context-compaction.d.ts +4 -1
- package/dist/presentation/tui/tui-context-compaction.js +1 -1
- package/dist/presentation/tui/tui-context-service.d.ts +2 -34
- package/dist/presentation/tui/tui-context-service.js +1 -2
- package/dist/presentation/tui/tui-initial-model.js +1 -1
- package/dist/presentation/tui/tui-tool-approval.d.ts +1 -1
- package/dist/presentation/tui/tui-tool-approval.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/native-targets.mjs +1 -1
- package/package.json +9 -10
- package/scripts/install-native.mjs +5 -13
- package/bin/lotagate.exe +0 -1
- package/dist/application/protocol/document-host-tool-definitions.d.ts +0 -4
- package/dist/application/protocol/document-host-tool-definitions.js +0 -1
- package/dist/application/protocol/document-host-tool-executor.d.ts +0 -49
- package/dist/application/protocol/document-host-tool-executor.js +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{randomUUID as
|
|
2
|
-
[truncated]`}function
|
|
1
|
+
import{randomUUID as y}from"node:crypto";import{isReadOnlyShellRequest as b}from"../security/tool-risk-classifier.js";import{resolveWorkspacePath as x}from"../../infrastructure/filesystem/path-resolver.js";import{readOnlyArguments as g,resolveReadOnlyExecutable as E}from"../../infrastructure/platform/read-only-executable.js";import{filesystemToolDefinitions as k,filesystemToolRisk as I}from"../../infrastructure/filesystem/local-filesystem-tool-executor.js";import{shellToolDefinitions as w}from"../../infrastructure/shell/shell-tool-executor.js";import{formatFilesystemActivityName as C,formatShellCommandForDisplay as O}from"../agent/tool-display.js";import{normalizePowerShellScriptInput as R}from"../../infrastructure/platform/host-process.js";import{detectHostPlatform as T}from"../../infrastructure/platform/host-platform.js";class W{options;definitions;constructor(t){this.options=t,this.definitions=[...k(),...w(t.executionBoundary==="sandbox"?"linux-guest":"host"),_()]}listTools(){return this.definitions}getToolInfo(t){if(!this.definitions.some(i=>h(i)===t))return;const o=t==="artifact.publish"?"write":I(t);return{toolName:t,source:t==="shell.exec"?"shell":t==="artifact.publish"?"custom":"filesystem",executorId:t==="artifact.publish"?"desktop-artifact-publisher":"desktop-host-execution",metadata:{boundary:this.options.executionBoundary,...o===void 0?{}:{risk:o}}}}async execute(t,o,r){if(!this.definitions.some(e=>h(e)===t))return{content:`Unknown Desktop host tool: ${t}`,isError:!0};const i=t==="shell.exec"?"shell":t==="artifact.publish"?"artifact":"filesystem";let s;const f=this.options.executionPlatform??T();try{s=t==="shell.exec"?R(o,f,{allowNonWindows:this.options.executionBoundary!=="sandbox"}):o}catch(e){return{content:e instanceof Error?e.message:"Invalid shell.exec PowerShell script.",isError:!0}}const p=t==="shell.exec"?await b(s.command,s.args,r,x,s.cwd,f):!1;if(t==="shell.exec"&&this.options.readOnly&&!p)return{content:"This subagent is limited to read-only shell commands inside the trusted workspace.",isError:!0,metadata:{code:"READ_ONLY_SHELL_REQUIRED"}};if(t==="shell.exec"&&p){const e=s.command,a=this.options.executionBoundary==="sandbox"?e:await E(e,r.workspaceRoot??r.cwd??process.cwd(),f);if(a===void 0)return{content:"Read-only executable is no longer available.",isError:!0};s={...s,command:a,args:g(e,s.args)}}const m=t==="shell.exec"&&typeof s.command=="string"?O(s.command,Array.isArray(s.args)?s.args.filter(e=>typeof e=="string"):[]):C(t,s.path),u=this.options.onActivity?.start({key:`${r.runId}:${t}`,toolName:t,source:i==="artifact"?"custom":i,label:m});try{let e=await this.options.request(this.request(i,t,s,r),r.signal);if(!e.ok&&e.error?.code==="SANDBOX_FALLBACK_REQUIRED"&&this.options.hostFallback==="ask"){const d=this.getToolInfo(t),c=await this.options.onFallbackApproval?.({toolName:t,input:s,context:r,...d===void 0?{}:{toolInfo:d}},e.error.message)??!1;if(typeof c=="boolean"?c:c.decision==="allow")e=await this.options.request({...this.request(i,t,s,r),executionBoundary:"host",hostFallback:"deny"},r.signal);else if(typeof c!="boolean"&&c.decision==="redirect")return u?.complete(!0,{userRedirect:!0}),{content:c.message,isError:!0,metadata:{code:"USER_REDIRECTED_ACTION",boundary:this.options.executionBoundary,userRedirect:!0}}}if(!e.ok)return u?.complete(!0),{content:e.error?.message??"Desktop rejected the execution request.",isError:!0,metadata:{code:e.error?.code??"HOST_EXECUTION_ERROR",boundary:e.executionBoundary??this.options.executionBoundary,retryable:e.error?.retryable??!1}};const a=S(i,e.result);if(a!==void 0){const d={code:a.code,boundary:e.executionBoundary??this.options.executionBoundary,retryable:a.retryable,...a.exitCode===void 0?{}:{exitCode:a.exitCode}};return u?.complete(!0,d),{content:a.message,isError:!0,metadata:d}}const l=e.artifacts??[];return l.length>0&&await this.options.onArtifacts?.(l,r),u?.complete(!1,e.fileChange===void 0?void 0:{fileChange:{path:e.fileChange.path,additions:e.fileChange.additions,deletions:e.fileChange.deletions}}),e.fileChange!==void 0&&await this.options.onWrite?.(e.fileChange),{content:D(e.result,r.maxResultBytes),isError:!1,metadata:{boundary:e.executionBoundary??this.options.executionBoundary,...e.environmentId===void 0?{}:{environmentId:e.environmentId},...e.fallbackReason===void 0?{}:{fallbackReason:e.fallbackReason},...l.length===0?{}:{artifactIds:l.map(d=>d.id)}}}}catch(e){return u?.complete(!0),{content:e instanceof Error?e.message:"Desktop execution failed.",isError:!0,metadata:{boundary:this.options.executionBoundary}}}}request(t,o,r,i){return{version:1,type:"host.request",requestId:y(),tool:t,sessionId:i.sessionId,runId:i.runId,action:o,params:r,executionBoundary:this.options.executionBoundary,hostFallback:this.options.hostFallback,...this.options.projectRoot===void 0?{}:{projectRoot:this.options.projectRoot},...this.options.executionCwd===void 0?{}:{executionCwd:this.options.executionCwd},...this.options.executionWorkspaceId===void 0?{}:{executionWorkspaceId:this.options.executionWorkspaceId},...typeof i.metadata?.taskId=="string"?{taskId:i.metadata.taskId}:{}}}}function _(){return{type:"function",function:{name:"artifact.publish",description:"Publish one completed output file from the execution workspace to the current task artifacts. The path must be workspace-relative and the file must already exist.",parameters:{type:"object",properties:{path:{type:"string",description:"Workspace-relative path of the completed output file."}},required:["path"],additionalProperties:!1}}}}function h(n){return"function"in n?n.function.name:void 0}function D(n,t){const o=typeof n=="string"?n:JSON.stringify(n??null);return Buffer.byteLength(o,"utf8")<=t?o:`${o.slice(0,Math.max(0,t-12))}
|
|
2
|
+
[truncated]`}function S(n,t){if(n!=="shell"||typeof t!="object"||t===null||Array.isArray(t))return;const o=t,r=typeof o.stderr=="string"?o.stderr.trim():"",i=typeof o.stdout=="string"?o.stdout.trim():"";if(o.diskLimitExceeded===!0)return{code:"HOST_EXECUTION_DISK_LIMIT",message:r||"The sandbox workspace disk limit was exceeded while the command was running.",retryable:!1};if(o.processLimitExceeded===!0)return{code:"HOST_EXECUTION_PROCESS_LIMIT",message:r||"The sandbox process limit was exceeded while the command was running.",retryable:!1};if(o.cancelled===!0)return{code:"HOST_EXECUTION_CANCELLED",message:r||"Desktop host execution was cancelled.",retryable:!1};if(o.timedOut===!0)return{code:"HOST_EXECUTION_TIMEOUT",message:r||"Desktop host execution timed out.",retryable:!0};if(o.error===!0)return{code:"HOST_EXECUTION_PROCESS_ERROR",message:r||"Desktop host process failed to start or communicate.",retryable:!0};if(Object.hasOwn(o,"exitCode")&&o.exitCode!==0){const s=typeof o.exitCode=="number"?o.exitCode:null;return{code:"HOST_COMMAND_FAILED",message:r||i||`Desktop host command exited with code ${String(s)}.`,retryable:!1,exitCode:s}}}export{W as DesktopHostToolExecutor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class o{options;progress=new Map;constructor(i){this.options=i}clear(i){this.progress.delete(i)}async write(i,t,e){if(this.options.log("Intent lifecycle updated.",{lifecycle:i.type,intentId:i.contract.id,sessionId:t,turnId:e,...i.type==="intent.evidence"?{evidenceKind:i.evidence.kind,evidenceStatus:i.evidence.status}:{},...i.type==="intent.verification.required"||i.type==="intent.blocked"?{missingCount:i.missing.length}:{}}),i.type==="intent.compiled")return this.writeCompiled(i,t,e);if(i.type==="intent.evidence")return this.writeEvidence(i,t,e);if(i.type==="intent.verification.required")return this.writeVerificationRequired(i,t,e);if(i.type==="intent.blocked")return this.writeBlocked(i,t,e);await this.options.writeEvent("intent.completed",{turnId:e,sessionId:t,intentId:i.contract.id});for(const n of i.contract.steps)await this.options.writeEvent("work.task.completed",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),stepId:n.id});await this.options.writeEvent("work.plan.completed",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e)}),this.clear(e)}async writeCompiled(i,t,e){const n=i.contract.steps[0]?.id;n!==void 0&&(this.progress.set(e,{version:1,activeStepId:n}),await this.options.writeEvent("intent.compiled",{turnId:e,sessionId:t,contract:i.contract}),await this.options.writeEvent("work.plan.created",{turnId:e,sessionId:t,planId:i.contract.id,version:1,goal:i.contract.objective,language:"und",totalSteps:i.contract.steps.length,steps:i.contract.steps.map((c,r)=>({index:r,id:c.id,title:c.title,description:c.title,dependencies:[],scope:[],acceptanceCriteria:c.acceptanceCriteria,verificationHints:c.requiresVerification?["Host-observed verification required"]:[],evidenceIds:[],status:r===0?"active":"queued"}))}))}async writeEvidence(i,t,e){const n=this.evidenceStep(e,i.contract,i.evidence.kind);await this.options.writeEvent("intent.evidence.recorded",{turnId:e,sessionId:t,intentId:i.contract.id,evidence:i.evidence}),await this.options.writeEvent("work.evidence.recorded",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),evidence:{id:i.evidence.id,stepId:n,kind:i.evidence.kind
|
|
1
|
+
class o{options;progress=new Map;constructor(i){this.options=i}clear(i){this.progress.delete(i)}async write(i,t,e){if(this.options.log("Intent lifecycle updated.",{lifecycle:i.type,intentId:i.contract.id,sessionId:t,turnId:e,...i.type==="intent.evidence"?{evidenceKind:i.evidence.kind,evidenceStatus:i.evidence.status}:{},...i.type==="intent.verification.required"||i.type==="intent.blocked"?{missingCount:i.missing.length}:{}}),i.type==="intent.compiled")return this.writeCompiled(i,t,e);if(i.type==="intent.evidence")return this.writeEvidence(i,t,e);if(i.type==="intent.verification.required")return this.writeVerificationRequired(i,t,e);if(i.type==="intent.blocked")return this.writeBlocked(i,t,e);await this.options.writeEvent("intent.completed",{turnId:e,sessionId:t,intentId:i.contract.id});for(const n of i.contract.steps)await this.options.writeEvent("work.task.completed",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),stepId:n.id});await this.options.writeEvent("work.plan.completed",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e)}),this.clear(e)}async writeCompiled(i,t,e){const n=i.contract.steps[0]?.id;n!==void 0&&(this.progress.set(e,{version:1,activeStepId:n}),await this.options.writeEvent("intent.compiled",{turnId:e,sessionId:t,contract:i.contract}),await this.options.writeEvent("work.plan.created",{turnId:e,sessionId:t,planId:i.contract.id,version:1,goal:i.contract.objective,language:"und",totalSteps:i.contract.steps.length,steps:i.contract.steps.map((c,r)=>({index:r,id:c.id,title:c.title,description:c.title,dependencies:[],scope:[],acceptanceCriteria:c.acceptanceCriteria,verificationHints:c.requiresVerification?["Host-observed verification required"]:[],evidenceIds:[],status:r===0?"active":"queued"}))}))}async writeEvidence(i,t,e){const n=this.evidenceStep(e,i.contract,i.evidence.kind);await this.options.writeEvent("intent.evidence.recorded",{turnId:e,sessionId:t,intentId:i.contract.id,evidence:i.evidence}),await this.options.writeEvent("work.evidence.recorded",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),evidence:{id:i.evidence.id,stepId:n,kind:i.evidence.kind,summary:i.evidence.summary,status:i.evidence.status,...i.evidence.command===void 0?{}:{command:i.evidence.command},...i.evidence.paths===void 0?{}:{paths:i.evidence.paths},...i.evidence.exitCode===void 0?{}:{exitCode:i.evidence.exitCode},createdAt:i.evidence.timestamp}})}async writeVerificationRequired(i,t,e){await this.options.writeEvent("intent.verification.required",{turnId:e,sessionId:t,intentId:i.contract.id,missing:i.missing});const n=i.contract.steps.find(c=>c.requiresVerification);n!==void 0&&(this.setActiveStep(e,n.id),await this.options.writeEvent("work.task.started",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),stepId:n.id}))}async writeBlocked(i,t,e){await this.options.writeEvent("intent.blocked",{turnId:e,sessionId:t,intentId:i.contract.id,missing:i.missing}),await this.options.writeEvent("work.plan.blocked",{turnId:e,sessionId:t,planId:i.contract.id,version:this.nextVersion(e),reason:i.missing.join(", ")}),this.clear(e)}nextVersion(i){const t=this.progress.get(i);return t===void 0?1:(t.version+=1,t.version)}setActiveStep(i,t){const e=this.progress.get(i);e!==void 0&&(e.activeStepId=t)}evidenceStep(i,t,e){return e!=="read"?t.steps.find(n=>n.requiresVerification)?.id??t.steps.at(-1)?.id??t.steps[0].id:this.progress.get(i)?.activeStepId??t.steps[0].id}}export{o as DesktopIntentEventWriter};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{asCliError as
|
|
1
|
+
import{asCliError as s}from"../../domain/errors/cli-error.js";import{formatShellCommandForDisplay as p,formatToolActivityName as c}from"../agent/tool-display.js";function l(e){return e==="allowlist"?"auto":e==="review"?"review":e==="autonomous"?"autonomous":"ask"}function f(e){if(typeof e=="object"&&e!==null){const t=e;if(typeof t.code=="string"&&typeof t.category=="string"&&typeof t.userMessage=="string"&&typeof t.retryable=="boolean")return{code:t.code,category:t.category,message:t.userMessage,retryable:t.retryable}}const r=s(e);return{code:r.code,category:r.category,message:r.userMessage,retryable:r.retryable}}function y(e){return{session:e}}function g(e){if(e.toolName==="filesystem.write")return{summary:`Write workspace file: ${a(e.input.path)}`,path:a(e.input.path)};if(e.toolName==="shell.exec"){const r=typeof e.input.command=="string"?e.input.command:"",t=Array.isArray(e.input.args)?e.input.args.filter(i=>typeof i=="string"):[],o=typeof e.input.script=="string"?a(e.input.script):void 0,n=o===void 0?t:[...t,"-Command",o];return{summary:`Run command: ${p(r,n,240)}`,command:r,args:t,...o===void 0?{}:{script:o}}}return{summary:`This ${c(e.toolName)} operation may change workspace or external state.`}}function a(e){return String(e??"").replace(/Bearer\s+[^\s]+/giu,"Bearer [REDACTED]").replace(/sk-[A-Za-z0-9_-]{8,}/gu,"[REDACTED]").slice(0,240)}export{g as describeApproval,l as desktopApprovalMode,y as sessionResult,f as toDesktopError};
|
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
|
+
export type JsonLineDelivery = 'reliable' | 'best-effort';
|
|
3
|
+
export interface JsonLineWriteOptions {
|
|
4
|
+
readonly delivery?: JsonLineDelivery;
|
|
5
|
+
}
|
|
6
|
+
export interface JsonLineWriterOptions {
|
|
7
|
+
readonly maxQueuedEntries?: number;
|
|
8
|
+
readonly maxQueuedBytes?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function waitForWritableDrain(output: Writable): Promise<void>;
|
|
2
11
|
/** Serializes protocol messages in order and applies Writable backpressure. */
|
|
3
12
|
export declare class JsonLineWriter<T> {
|
|
4
13
|
private readonly output;
|
|
5
14
|
private tail;
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
private activeEntries;
|
|
16
|
+
private activeBytes;
|
|
17
|
+
private waitingBytes;
|
|
18
|
+
private readonly waiting;
|
|
19
|
+
private closed;
|
|
20
|
+
private readonly maxQueuedEntries;
|
|
21
|
+
private readonly maxQueuedBytes;
|
|
22
|
+
constructor(output: Writable, options?: JsonLineWriterOptions);
|
|
23
|
+
write(value: T, options?: JsonLineWriteOptions): Promise<void>;
|
|
8
24
|
flush(): Promise<void>;
|
|
25
|
+
close(error?: Error): void;
|
|
26
|
+
private schedule;
|
|
27
|
+
private readonly complete;
|
|
28
|
+
private admitWaiting;
|
|
29
|
+
private canSchedule;
|
|
30
|
+
private canWait;
|
|
9
31
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
|
|
1
|
+
import{RESOURCE_LIMITS as c}from"../../domain/runtime/resource-limits.js";function h(i){return i.destroyed||i.writableEnded?Promise.reject(new Error("The protocol output is closed.")):new Promise((e,t)=>{const s=()=>{i.removeListener("drain",r),i.removeListener("error",o),i.removeListener("close",n),i.removeListener("finish",n)},r=()=>{s(),e()},o=a=>{s(),t(a)},n=()=>{s(),t(new Error("The protocol output is closed."))};i.once("drain",r),i.once("error",o),i.once("close",n),i.once("finish",n),(i.destroyed||i.writableEnded)&&n()})}class u{output;tail=Promise.resolve();activeEntries=0;activeBytes=0;waitingBytes=0;waiting=[];closed=!1;maxQueuedEntries;maxQueuedBytes;constructor(e,t={}){this.output=e,this.maxQueuedEntries=t.maxQueuedEntries??c.protocolWriteQueueEntries,this.maxQueuedBytes=t.maxQueuedBytes??c.protocolWriteQueueBytes}write(e,t={}){const s=`${JSON.stringify(e)}
|
|
2
|
+
`,r=Buffer.byteLength(s,"utf8"),o=t.delivery??"reliable";return this.closed?Promise.reject(new Error("The protocol writer is closed.")):this.waiting.length>0||!this.canSchedule(r)?o==="best-effort"?Promise.reject(new Error("The protocol output queue is full.")):this.canWait(r)?new Promise((n,a)=>{this.waiting.push({serialized:s,bytes:r,resolve:n,reject:a}),this.waitingBytes+=r}):Promise.reject(new Error("The protocol output queue limit was exceeded.")):this.schedule(s,r)}async flush(){for(;;){const e=this.tail;if(await e,await new Promise(t=>setImmediate(t)),e===this.tail&&this.activeEntries===0&&this.waiting.length===0)return}}close(e=new Error("The protocol writer is closed.")){this.closed=!0;const t=this.waiting.splice(0);this.waitingBytes=0;for(const s of t)s.reject(e)}schedule(e,t){this.activeEntries+=1,this.activeBytes+=t;const s=this.tail.then(async()=>{this.output.write(e)||await h(this.output)});return this.tail=s.catch(()=>{}),s.then(()=>this.complete(t),()=>this.complete(t)),s}complete=e=>{this.activeEntries-=1,this.activeBytes-=e,this.admitWaiting()};admitWaiting(){for(;this.waiting.length>0;){const e=this.waiting[0];if(!this.canSchedule(e.bytes))return;this.waiting.shift(),this.waitingBytes-=e.bytes,this.schedule(e.serialized,e.bytes).then(e.resolve,e.reject)}}canSchedule(e){return this.activeEntries<this.maxQueuedEntries&&this.activeBytes+e<=this.maxQueuedBytes}canWait(e){return this.activeEntries+this.waiting.length<this.maxQueuedEntries&&this.activeBytes+this.waitingBytes+e<=this.maxQueuedBytes}}export{u as JsonLineWriter,h as waitForWritableDrain};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Readable, Writable } from 'node:stream';
|
|
2
2
|
import type { createCompositionRoot } from '../../bootstrap/composition-root.js';
|
|
3
|
-
export declare function runAgentCommand(positionals: readonly string[], runtime: ReturnType<typeof createCompositionRoot>, cwd: string, stdin: Readable, stdout: Writable): Promise<number>;
|
|
3
|
+
export declare function runAgentCommand(positionals: readonly string[], runtime: ReturnType<typeof createCompositionRoot>, cwd: string, stdin: Readable, stdout: Writable, signal?: AbortSignal): Promise<number>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{AuthenticationService as
|
|
1
|
+
import{AuthenticationService as O}from"../auth/authentication-service.js";import{JsonlProtocolRunner as _}from"./jsonl-protocol.js";import{createLotaGateClient as b}from"../../infrastructure/sdk/lotagate-client-factory.js";import{CliError as C}from"../../domain/errors/cli-error.js";import{CLI_ERROR_CODES as d}from"../../domain/errors/error-codes.js";import{prepareCliAgent as v}from"../agent/cli-agent-execution-service.js";import{AgentRunTracker as P}from"../agent/agent-run-tracker.js";import{loadExecutionConfig as S}from"../config/execution-config.js";import{agentLimitNotice as T,classifyAgentLimit as D}from"../agent/agent-limit.js";import{runDesktopAgentCommand as I}from"./desktop-agent-command.js";import{createContextManagement as F}from"../agent/context-compaction.js";import{formatContinuationCheckpoint as U}from"../agent/continuation-checkpoint.js";import{resolveModelContextWindow as G}from"../model/model-context-window.js";async function oe(k,t,i,h,w,y){const N=k[0]??"stdio";if(N==="desktop")return I(t,i,h,w,y);if(N!=="stdio")throw new C(d.INVALID_ARGUMENT,"Unsupported agent action.",{category:"arguments",userMessage:"Use `lotagate agent stdio` or `lotagate agent desktop`."});const s=await S(t,i);if(s.config.model===null)throw new C(d.MODEL_NOT_FOUND,"No model is selected.",{category:"model",userMessage:"Select a model before running the stdio agent."});const M=s.config.profile??O.defaultProfileName(),x=await t.auth.requireCredential(M);return(await new _(async function*(m,L){const n=m.params.model??s.config.model;t.logger.info("Protocol agent request started.",{model:n,promptLength:m.params.prompt.length});const a=new P,E=b(x.profile,x.apiKey),R=await G(t,n,M),A=o=>{a.observeModel(o),t.logger.debug("Model turn completed.",{model:o.model,stream:o.stream,contentLength:o.contentLength,toolCallCount:o.toolCallCount,toolNames:o.toolNames,finishReason:o.finishReason})},f=await v({runtime:t,projectRoot:i,executionCwd:i,model:n,client:E,profile:"protocol-safe",approvalMode:s.config.approvalMode,onModelComplete:A,contextManagement:F({client:E,model:n,...R===void 0?{}:{contextWindow:R},onSummaryFailure:o=>t.logger.warn("Context summarization failed; using fallback summary.",{reason:o instanceof Error?o.message:String(o)}),continuationContext:()=>U({snapshot:a.snapshot()})})});let g=!1,l="",r,c;try{const o=await f.buildInput(m.params.prompt);for await(const e of f.run({input:o.input,userInput:o.userInput,...o.workspaceContext===void 0?{}:{workspaceContext:o.workspaceContext},model:n,signal:L}))if(a.observe(e),e.type==="tool.called"&&t.logger.info("Agent tool called.",{toolName:e.toolName}),e.type==="tool.completed"&&t.logger.info("Agent tool completed.",{toolName:e.toolName,isError:e.isError}),e.type==="model.delta"&&e.content.length>0?(g=!0,l+=e.content,yield{type:"delta",content:e.content}):e.type==="session.completed"&&(r=e.content),e.type==="session.failed"){const p=D(e.error);if(p===void 0)throw e.error;c=T(p);break}if(c!==void 0){const e=l.length===0?c:`
|
|
2
2
|
|
|
3
|
-
${c}`;g=!0,
|
|
3
|
+
${c}`;g=!0,l+=e,r=l,yield{type:"delta",content:e}}const u=r===void 0||r.trim().length===0?l:r;if(u.trim().length===0){const e=a.snapshot();e.toolCalls>0&&a.markStuck();const p=e.toolCalls>0?d.MODEL_EMPTY_FINAL:d.MODEL_PROTOCOL_EMPTY_RESPONSE;throw new C(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}})}g||(yield{type:"delta",content:u}),yield{type:"completed",content:u},t.logger.info("Protocol agent request completed.",{model:n})}finally{await f.close()}}).run(h,w,y)).errorCount===0?0:1}export{oe as runAgentCommand};
|
|
@@ -76,7 +76,7 @@ export declare class JsonlProtocolRunner {
|
|
|
76
76
|
private readonly executor;
|
|
77
77
|
private readonly options;
|
|
78
78
|
constructor(executor: JsonlExecutor, options?: JsonlProtocolOptions);
|
|
79
|
-
run(input: Readable, output: Writable): Promise<JsonlProtocolResult>;
|
|
79
|
+
run(input: Readable, output: Writable, signal?: AbortSignal): Promise<JsonlProtocolResult>;
|
|
80
80
|
private executeOne;
|
|
81
81
|
}
|
|
82
82
|
export declare function readLinesBounded(input: Readable, maxBytes: number): AsyncGenerator<string>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)||await
|
|
1
|
+
import{RESOURCE_LIMITS as y}from"../../domain/runtime/resource-limits.js";import{waitForWritableDrain as I}from"./json-line-writer.js";const m=1;class J{executor;options;constructor(e,n={}){this.executor=e,this.options=n}async run(e,n,r){const o=new Map,i=new Set,l=this.options.maxLineBytes??y.jsonlLineBytes,u=this.options.maxInFlight??y.jsonlMaxInFlight;let c=0;const d=()=>{for(const s of o.values())s.abort(r?.reason);e.destroy()};r?.addEventListener("abort",d,{once:!0});try{for await(const s of v(e,l)){if(Buffer.byteLength(s,"utf8")>l){c+=1,await f(n,p("unknown",h("JSONL_REQUEST_TOO_LARGE","Request line exceeds the maximum size.")));continue}let a;try{a=R(JSON.parse(s))}catch(L){c+=1,await f(n,p("unknown",w(L)));continue}if(a.method==="cancel"){o.get(a.params.requestId)?.abort();continue}if(o.has(a.id)){c+=1,await f(n,p(a.id,h("JSONL_DUPLICATE_REQUEST","Request id is already in flight.")));continue}if(i.size>=u){c+=1,await f(n,p(a.id,h("JSONL_OVERLOADED","Too many in-flight requests.",!0)));continue}const E=new AbortController;o.set(a.id,E);const x=this.executeOne(a,E.signal,n).then(L=>{L||(c+=1)}).finally(()=>{o.delete(a.id),i.delete(x)});i.add(x)}await Promise.allSettled(i)}catch(s){if(!(s instanceof O))throw s;c+=1,await f(n,p("unknown",w(s)))}finally{r?.removeEventListener("abort",d);for(const s of o.values())s.abort();await Promise.allSettled([...i])}return{errorCount:c}}async executeOne(e,n,r){try{await f(r,{version:m,id:e.id,type:"started"});for await(const o of this.executor(e,n))o.type==="event"?await f(r,{version:m,id:e.id,type:"event",event:o.event,...o.data===void 0?{}:{data:o.data}}):await f(r,{version:m,id:e.id,type:o.type,content:o.content});return!0}catch(o){return await f(r,p(e.id,w(o))),!1}}}function R(t){if(typeof t!="object"||t===null)throw g("Request must be an object.");const e=t;if(e.version!==1||typeof e.id!="string"||e.id.length===0||Buffer.byteLength(e.id,"utf8")>y.jsonlIdBytes||typeof e.method!="string"||typeof e.params!="object"||e.params===null)throw g("Invalid JSONL request envelope.");if(e.method==="cancel"){const r=e.params;if(typeof r.requestId!="string"||r.requestId.length===0||Buffer.byteLength(r.requestId,"utf8")>y.jsonlIdBytes)throw g("Invalid cancel request.");return{version:m,id:e.id,method:"cancel",params:{requestId:r.requestId}}}if(e.method!=="exec")throw g("Unsupported JSONL method.");const n=e.params;if(typeof n.prompt!="string"||n.prompt.trim().length===0||Buffer.byteLength(n.prompt,"utf8")>y.jsonlPromptBytes||n.model!==void 0&&(typeof n.model!="string"||Buffer.byteLength(n.model,"utf8")>y.jsonlIdBytes))throw g("Invalid exec params.");return{version:m,id:e.id,method:"exec",params:{prompt:n.prompt,...n.model===void 0?{}:{model:n.model}}}}async function f(t,e){t.write(`${JSON.stringify(e)}
|
|
2
|
+
`)||await I(t)}function p(t,e){return{version:m,id:t,type:"error",error:e}}function g(t){return new b(h("JSONL_INVALID_REQUEST",t))}function h(t,e,n=!1){return{code:t,category:"protocol",message:e,retryable:n}}function w(t){return t instanceof b?t.payload:S(t)?{code:t.code,category:t.category,message:t.userMessage,retryable:t.retryable}:h("CLI_INTERNAL_ERROR","The request could not be completed. Retry the request or inspect CLI diagnostics.",!0)}function S(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.code=="string"&&typeof e.category=="string"&&typeof e.userMessage=="string"&&typeof e.retryable=="boolean"}class b extends Error{payload;constructor(e){super(e.message),this.payload=e}}class O extends b{constructor(e){super(h("JSONL_REQUEST_TOO_LARGE",e))}}async function*v(t,e){let n=[],r=0;for await(const o of t){const i=Buffer.isBuffer(o)?o:Buffer.from(o);let l=0;for(;l<i.byteLength;){const u=i.indexOf(10,l),c=u<0?i.byteLength:u,d=i.subarray(l,c);if(r+d.byteLength>e)throw new O("Request line exceeds the maximum size.");if(d.byteLength>0&&n.push(d),r+=d.byteLength,u<0)break;const s=Buffer.concat(n,r);yield(s[s.byteLength-1]===13?s.subarray(0,s.byteLength-1):s).toString("utf8"),n=[],r=0,l=u+1}}r>0&&(yield Buffer.concat(n,r).toString("utf8"))}export{m as JSONL_PROTOCOL_VERSION,J as JsonlProtocolRunner,v as readLinesBounded};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isReadOnlyShellRequest as
|
|
1
|
+
import{isReadOnlyShellRequest as u}from"./tool-risk-classifier.js";import{BROWSER_INSPECTION_TOOLS as f,BROWSER_NAVIGATION_TOOLS as m,COMPUTER_LAUNCH_TOOLS as c,READ_ONLY_COMPUTER_TOOLS as d,READ_ONLY_GIT_COMMANDS as h}from"./tool-policy-registry.js";async function C(t,r,n){for(const e of r)if(await l(e,t,n))return!0;return!1}async function l(t,r,n){const e=r.toolName;if(t===e)return!0;if(t==="filesystem.read")return e==="filesystem.read"||e==="filesystem.list"||e==="filesystem.exists";if(t==="filesystem.write")return e==="filesystem.write";if(e!=="shell.exec")return O(t,e)||w(t,e);const s=y(r.input),i=S(r.input);if(s===void 0||i===void 0)return!1;if(t==="terminal.read")return await u(s,i,r.context,n,r.input.cwd);if(t==="terminal.execute")return!0;if(!g(s,i))return!1;const a=o(i);return t==="git.read"?a!==void 0&&h.has(a)&&await u(s,i,r.context,n,r.input.cwd):t==="git.stage"?a==="add":t==="git.commit"?a==="commit":t==="git.push"?a==="push":!1}function O(t,r){return r.startsWith("browser.")?t==="browser.navigate"?m.has(r):t==="browser.inspect"?f.has(r):t==="browser.interact"?!m.has(r)&&!f.has(r):!1:!1}function w(t,r){return r.startsWith("computer.")?t==="computer.read"?d.has(r):t==="computer.interact"?!d.has(r)&&!c.has(r):t==="computer.launch"?c.has(r):!1:!1}function y(t){return typeof t.command=="string"?t.command.trim():void 0}function S(t){const r=t.args;return Array.isArray(r)&&r.every(n=>typeof n=="string")?r:void 0}function g(t,r){return(t.split(/[\\/]/u).at(-1)??"").replace(/\.(?:exe|cmd|bat)$/iu,"").toLowerCase()==="git"&&o(r)!==void 0}function o(t){return t.find(r=>!r.startsWith("-"))?.toLowerCase()}export{C as matchesDesktopToolScope};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function x(e){const n=typeof e.input.path=="string"?e.input.path.trim():void 0;if(n!==void 0&&a(n))return{risk:"review",category:"sensitive-target",reason:"sensitive-target-review"};const t=d(e);if(t!==void 0){if(f.test(t))return{risk:"review",category:"download-and-execute",reason:"download-and-execute-review"};if(u.test(t))return{risk:"deny",category:"credential-exfiltration",reason:"credential-exfiltration-deny"}}if(c(e))return{risk:"review",category:"hidden-control-data",reason:"hidden-control-data-review"}}function d(e){if(e.toolName!=="shell.exec")return;const n=e.input.command,t=e.input.args,i=e.input.script;if(typeof n!="string"||i!==void 0&&typeof i!="string")return;const r=t===void 0?[]:t;if(!(!Array.isArray(r)||r.some(s=>typeof s!="string")))return typeof i=="string"?[n,...r,"-Command",i].join(" "):[n,...r].join(" ")}function a(e){const n=e.replace(/\\/gu,"/").toLowerCase();return n===".env"||n.endsWith("/.env")||n.includes("/.git/config")||n.includes("/.git/credentials")||n.includes("/.lotagate/auth")||n.includes("/.lotagate/credentials")||n.includes("/.codex/auth")||n.includes("/.ssh/")||n.endsWith("/id_rsa")||n.endsWith("/id_ed25519")}function c(e){return o(e.input).some(n=>[...n].some(t=>l.has(t.codePointAt(0)??0)))}function o(e){return typeof e=="string"?[e]:Array.isArray(e)?e.flatMap(o):e!==null&&typeof e=="object"?Object.values(e).flatMap(o):[]}const f=/(?:curl|wget|invoke-webrequest|irm)\b[^\n|]*\|\s*(?:sh|bash|zsh|pwsh|powershell|cmd)\b|(?:powershell|pwsh)\b[^\n]*-(?:enc|encodedcommand)\b|\b(?:invoke-expression|iex)\b/iu,u=/(?:curl|wget|invoke-webrequest|irm)\b[^\n]*(?:api[_-]?key|token|secret|password|credential|\.env|process\.env|\$env:)/iu,l=new Set([1564,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8288,8289,8290,8291,8292,8294,8295,8297,8298,8299,8300,8301,8302,8303,65279]);export{x as assessToolAction};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolApprovalRequest, ToolPolicyOptions } from '@lotagate/agent-sdk';
|
|
1
|
+
import type { ToolApprovalRequest, ToolAuthorizationDecision, ToolAuthorizationEvent, ToolPolicyOptions } from '@lotagate/agent-sdk';
|
|
2
2
|
import type { SkillScopeStore } from '../extensions/skill-scope-store.js';
|
|
3
3
|
import type { WorkspacePermissionPolicy } from '../../domain/workspace/workspace-settings.js';
|
|
4
4
|
import type { WorkspaceTargetResolver } from './tool-risk-classifier.js';
|
|
@@ -6,7 +6,7 @@ export type CliApprovalMode = 'ask' | 'auto' | 'deny' | 'review' | 'autonomous';
|
|
|
6
6
|
export interface ToolApprovalServiceOptions {
|
|
7
7
|
mode: CliApprovalMode;
|
|
8
8
|
trustedProject: boolean;
|
|
9
|
-
prompt?: (request: ToolApprovalRequest) => boolean | Promise<boolean>;
|
|
9
|
+
prompt?: (request: ToolApprovalRequest) => boolean | ToolAuthorizationDecision | Promise<boolean | ToolAuthorizationDecision>;
|
|
10
10
|
rememberApproval?: (request: ToolApprovalRequest) => void | Promise<void>;
|
|
11
11
|
onRememberApprovalFailure?: (request: ToolApprovalRequest, error: unknown) => void | Promise<void>;
|
|
12
12
|
audit?: (decision: ToolApprovalDecision) => void | Promise<void>;
|
|
@@ -17,9 +17,14 @@ export interface ToolApprovalServiceOptions {
|
|
|
17
17
|
}
|
|
18
18
|
export interface ToolApprovalDecision {
|
|
19
19
|
toolName: string;
|
|
20
|
+
stage: ToolAuthorizationEvent['stage'];
|
|
21
|
+
sessionId: string;
|
|
22
|
+
runId: string;
|
|
20
23
|
source?: string;
|
|
21
|
-
|
|
24
|
+
executorId?: string;
|
|
25
|
+
decision: 'allow' | 'deny' | 'redirect';
|
|
22
26
|
reason: string;
|
|
27
|
+
ruleId?: string;
|
|
23
28
|
skillName?: string;
|
|
24
29
|
riskCategory?: string;
|
|
25
30
|
}
|
|
@@ -32,6 +37,7 @@ export declare class ToolApprovalService {
|
|
|
32
37
|
private authorizeActionRisk;
|
|
33
38
|
private authorizeSkill;
|
|
34
39
|
private requestApproval;
|
|
40
|
+
private resolvePrompt;
|
|
35
41
|
private rememberApproval;
|
|
36
42
|
private observe;
|
|
37
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{requiresMutationApproval as t}from"./tool-risk-classifier.js";import{assessToolAction as
|
|
1
|
+
import{requiresMutationApproval as t}from"./tool-risk-classifier.js";import{assessToolAction as r}from"./tool-action-risk-analyzer.js";import{workspacePermissionDecision as a}from"./workspace-permission-policy.js";import{matchesDesktopToolScope as n}from"./desktop-tool-scope-policy.js";class m{options;constructor(o){this.options=o}policy(){return{authorizationRules:[...this.options.desktopToolScopes===void 0?[]:[{id:"desktop-tool-scope",authorize:e=>this.authorizeDesktopScope(e)}],...this.options.skillScopes===void 0?[]:[{id:"cli-skill-scope",authorize:e=>this.authorizeSkill(e)}],{id:"cli-action-risk",authorize:e=>this.authorizeActionRisk(e)},{id:"cli-workspace-policy",authorize:e=>this.authorizeWorkspace(e)}],authorizationObserver:e=>this.observe(e),requireApproval:!1}}async authorizeDesktopScope(o){return await n(o,this.options.desktopToolScopes??[],this.options.resolveWorkspaceTarget)?{decision:"allow",reason:"desktop-tool-scope-allow"}:{decision:"deny",reason:"desktop-tool-scope-deny"}}async authorizeWorkspace(o){if(!this.options.trustedProject)return{decision:"deny",reason:"project-untrusted"};if(this.options.mode==="deny")return{decision:"deny",reason:"mode-deny"};const e=this.options.workspacePermissions===void 0?void 0:a(this.options.workspacePermissions,o.toolName,o.input);return e==="deny"?{decision:"deny",reason:"workspace-policy-deny"}:this.options.mode==="review"?this.requestApproval(o,"review-policy"):e==="allow"?{decision:"allow",reason:"workspace-policy-allow"}:e==="ask"?this.requestApproval(o,"workspace-policy-ask"):await t(o,this.options.resolveWorkspaceTarget)&&this.options.mode!=="autonomous"?this.requestApproval(o,"mutation-approval"):{decision:"allow",reason:this.options.mode==="auto"?"mode-auto":"read-only"}}async authorizeActionRisk(o){const e=r(o);if(e===void 0)return{decision:"allow",reason:"action-risk-clear"};if(e.risk==="deny")return{decision:"deny",reason:e.reason,metadata:{riskCategory:e.category}};const i=await this.resolvePrompt(o);return{...i,...i.reason===void 0?{reason:`${e.reason}-${i.decision}`}:{},metadata:{...i.metadata??{},riskCategory:e.category}}}authorizeSkill(o){const e=this.options.skillScopes?.get(o.context.runId);return e===void 0||l(o.toolName)?{decision:"allow",reason:"skill-policy-not-active"}:e.allowedTools.includes(o.toolName)?{decision:"allow",reason:"skill-policy-allow",metadata:{skillName:e.skillName}}:{decision:"deny",reason:"skill-policy-deny",metadata:{skillName:e.skillName}}}async requestApproval(o,e){const i=await this.resolvePrompt(o);return i.decision==="allow"&&await this.rememberApproval(o),i.reason===void 0?{...i,reason:`${e}-${i.decision}`}:i}async resolvePrompt(o){const e=await this.options.prompt?.(o)??!1;return typeof e=="boolean"?e?{decision:"allow"}:{decision:"deny"}:e}async rememberApproval(o){try{await this.options.rememberApproval?.(o)}catch(e){try{await this.options.onRememberApprovalFailure?.(o,e)}catch{}}}async observe(o){const e=typeof o.metadata?.skillName=="string"?o.metadata.skillName:void 0,i=typeof o.metadata?.riskCategory=="string"?o.metadata.riskCategory:void 0;await this.options.audit?.({toolName:o.toolName,stage:o.stage,sessionId:o.sessionId,runId:o.runId,...o.source===void 0?{}:{source:o.source},...o.executorId===void 0?{}:{executorId:o.executorId},decision:o.decision,reason:o.reason,...o.ruleId===void 0?{}:{ruleId:o.ruleId},...e===void 0?{}:{skillName:e},...i===void 0?{}:{riskCategory:i}})}}function l(s){return s==="skill.list"||s==="skill.load"}export{m as ToolApprovalService};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concrete tool policy owned by the CLI security boundary.
|
|
3
|
+
*
|
|
4
|
+
* Desktop sends stable scopes; this registry is the single place where those
|
|
5
|
+
* scopes and tool metadata are expanded into concrete CLI capabilities.
|
|
6
|
+
*/
|
|
7
|
+
export declare const READ_ONLY_EXECUTABLES: ReadonlySet<string>;
|
|
8
|
+
export declare const READ_ONLY_GIT_COMMANDS: ReadonlySet<string>;
|
|
9
|
+
export declare const READ_ONLY_GIT_FLAGS: ReadonlySet<string>;
|
|
10
|
+
export declare const MUTATING_GIT_FLAGS: ReadonlySet<string>;
|
|
11
|
+
export declare const MUTATING_GIT_SUBCOMMANDS: ReadonlySet<string>;
|
|
12
|
+
export declare const GIT_GLOBAL_EXECUTION_FLAGS: ReadonlySet<string>;
|
|
13
|
+
export declare const GIT_UNSAFE_READ_FLAGS: ReadonlySet<string>;
|
|
14
|
+
export declare const READ_ONLY_EXECUTABLE_FLAGS: Readonly<Record<string, readonly string[]>>;
|
|
15
|
+
export declare const READ_ONLY_TOOL_NAMES: ReadonlySet<string>;
|
|
16
|
+
export declare const BROWSER_NAVIGATION_TOOLS: ReadonlySet<string>;
|
|
17
|
+
export declare const BROWSER_INSPECTION_TOOLS: ReadonlySet<string>;
|
|
18
|
+
export declare const READ_ONLY_BROWSER_TOOLS: ReadonlySet<string>;
|
|
19
|
+
export declare const READ_ONLY_COMPUTER_TOOLS: ReadonlySet<string>;
|
|
20
|
+
export declare const COMPUTER_LAUNCH_TOOLS: ReadonlySet<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t=new Set(["read-file","read_file","get-content","cat","type","more","head","tail","sed","rg","grep","ls","dir","pwd","where","which","stat","wc","uniq","file"]),r=new Set(["status","diff","log","show","branch","tag","remote","rev-parse","ls-files"]),o=new Set(["--","--short","--porcelain","--branch","--stat","--name-only","--name-status","--oneline","--all","--show-toplevel","--abbrev-ref","--verify","--cached","--staged","-l","-n"]),s=new Set(["-d","-D","-m","-M","-c","-C","--delete","--move","--force","--unset-upstream"]),n=new Set(["add","remove","rename","set-url","set-head","delete","-d"]),c=new Set(["-c","--config-env","--exec-path"]),a=new Set(["-o","--output","--ext-diff","--textconv"]),i={cat:["-n","-b","-s"],head:["-n","-c"],tail:["-n","-c"],rg:["--files","-n","-i","-l","-g","--glob","--hidden","--no-ignore","--fixed-strings","-f"],grep:["-n","-i","-l","-r","-e","-f"],ls:["-l","-a","-la","-al","-h"],pwd:[],stat:[],wc:["-l","-w","-c"],uniq:["-c","-d","-u"],file:["-b","--mime-type"]},l=new Set(["filesystem.read","filesystem.list","filesystem.exists","skill.list","skill.load","agent.wait"]),w=new Set(["browser.navigate","browser.back","browser.forward","browser.reload"]),e=new Set(["browser.inspect","browser.inspectElement","browser.extractTable","browser.listFrames","browser.console","browser.network","browser.accessibility","browser.setViewport","browser.resetViewport","browser.screenshot","browser.tabs","browser.readField"]),p=new Set([...e,"browser.scroll","browser.focus","browser.hover","browser.waitFor"]),_=new Set(["computer.listWindows","computer.inspect","computer.screenshot","computer.readText","computer.readSelection","computer.readGrid","computer.recognizeText","computer.listDisplays","computer.wait","computer.readClipboard","computer.waitForState"]),d=new Set(["computer.launch"]);export{e as BROWSER_INSPECTION_TOOLS,w as BROWSER_NAVIGATION_TOOLS,d as COMPUTER_LAUNCH_TOOLS,c as GIT_GLOBAL_EXECUTION_FLAGS,a as GIT_UNSAFE_READ_FLAGS,s as MUTATING_GIT_FLAGS,n as MUTATING_GIT_SUBCOMMANDS,p as READ_ONLY_BROWSER_TOOLS,_ as READ_ONLY_COMPUTER_TOOLS,t as READ_ONLY_EXECUTABLES,i as READ_ONLY_EXECUTABLE_FLAGS,r as READ_ONLY_GIT_COMMANDS,o as READ_ONLY_GIT_FLAGS,l as READ_ONLY_TOOL_NAMES};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ToolApprovalRequest } from '@lotagate/agent-sdk';
|
|
2
|
+
import { type HostPlatformContext } from '../../infrastructure/platform/host-platform.js';
|
|
2
3
|
export type WorkspaceTargetResolver = (input: unknown, context: Readonly<{
|
|
3
4
|
cwd?: string;
|
|
4
5
|
workspaceRoot?: string;
|
|
@@ -15,4 +16,4 @@ export declare function requiresMutationApproval(request: ToolApprovalRequest, r
|
|
|
15
16
|
export declare function isReadOnlyShellRequest(commandValue: unknown, inputArgs: unknown, context?: Readonly<{
|
|
16
17
|
cwd?: string;
|
|
17
18
|
workspaceRoot?: string;
|
|
18
|
-
}>, resolveTarget?: WorkspaceTargetResolver, workingDirectory?: unknown): Promise<boolean>;
|
|
19
|
+
}>, resolveTarget?: WorkspaceTargetResolver, workingDirectory?: unknown, platform?: HostPlatformContext): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveReadOnlyExecutable as
|
|
1
|
+
import{resolveReadOnlyExecutable as m}from"../../infrastructure/platform/read-only-executable.js";import{GIT_GLOBAL_EXECUTION_FLAGS as p,GIT_UNSAFE_READ_FLAGS as h,MUTATING_GIT_FLAGS as _,MUTATING_GIT_SUBCOMMANDS as w,READ_ONLY_EXECUTABLE_FLAGS as A,READ_ONLY_EXECUTABLES as I,READ_ONLY_GIT_COMMANDS as y,READ_ONLY_GIT_FLAGS as O,READ_ONLY_TOOL_NAMES as E}from"./tool-policy-registry.js";import{createIsolatedGuestPlatform as L}from"../../infrastructure/platform/host-platform.js";async function N(t,e){const o=t.toolInfo?.metadata?.risk;if((t.toolInfo?.source==="filesystem"||t.toolInfo?.executorId==="desktop-artifact-publisher"||t.toolInfo?.executorId==="desktop-browser-host"||t.toolInfo?.executorId==="desktop-computer-host")&&(o==="read"||o==="write"||o==="unknown"))return o;if(E.has(t.toolName))return"read";if(t.toolName==="agent.spawn")return t.input.mode==="worker"?"unknown":"read";if(t.toolName==="filesystem.write"||/(?:^|[._-])(delete|remove|move|copy|rename)(?:$|[._-])/iu.test(t.toolName))return"write";if(t.toolName==="shell.exec"){const r=t.toolInfo?.metadata?.boundary==="sandbox"?L():void 0;return await G(t.input.command,t.input.args,t.context,e,t.input.cwd,r)?"read":"unknown"}return"unknown"}async function C(t,e){return await N(t,e)!=="read"}async function G(t,e,o,r,n,l){if(typeof t!="string"||!Array.isArray(e)||e.some(s=>typeof s!="string"))return!1;const a=t.trim();if(/[\\/:]/u.test(a)||/\.(?:cmd|bat|ps1)$/iu.test(a))return!1;const f=e,i=a.split(/[\\/]/u).at(-1)?.toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u,"")??"",d=f.map(s=>s.toLowerCase()),c=I.has(i)?!S(i,d):i==="git"&&k(d);if(!c||o===void 0||o.cwd===void 0&&o.workspaceRoot===void 0)return c;if(r===void 0||await m(a,o.workspaceRoot??o.cwd,l)===void 0)return!1;const u=typeof n=="string"?{...o,cwd:await r(n,o).catch(()=>"")}:o;return u.cwd===""?!1:await R(f,u,r)}async function R(t,e,o){const r=t.flatMap(T);for(const n of r)try{await o(n,e,!0)}catch{return!1}return!0}function T(t){const e=[];for(const o of[t,...t.includes("=")?[t.slice(t.indexOf("=")+1)]:[]]){const r=o.trim().replace(/^['"]|['"]$/gu,"");r.length!==0&&(r.startsWith("-")||e.push(r))}return e}function k(t){if(t.some(n=>n.startsWith("-")&&!O.has(n)&&!/^-(?:\d+)$|^--max-count=\d+$/u.test(n))||t.some(n=>p.has(n)||n.startsWith("--config-env=")||n.startsWith("-c")))return!1;const e=t.find(n=>!n.startsWith("-"));if(e===void 0||!y.has(e)||t.some(n=>_.has(n))||(e==="remote"||e==="tag")&&t.some(n=>w.has(n)))return!1;const o=t.indexOf(e),r=t.slice(o+1).filter(n=>!n.startsWith("-"));return!((e==="branch"||e==="tag"||e==="remote")&&r.length>0||t.some(n=>h.has(n)||n.startsWith("--output=")))}function S(t,e){const o=A[t];return o===void 0||e.some(r=>r.startsWith("-")&&r!=="--"&&!o.includes(r))?!0:t==="uniq"&&e.filter(r=>!r.startsWith("-")).length>1}export{N as classifyToolRisk,G as isReadOnlyShellRequest,C as requiresMutationApproval};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
import d from"node:crypto";import h from"node:path";function l(s,r,t){const i=$(r,t);if(s.deny.some(e=>i.some(n=>a(e,n))))return"deny";if(s.ask.some(e=>i.some(n=>a(e,n))))return"ask";if(s.allow.some(e=>i.some(n=>a(e,n))))return"allow"}function u(s,r){if(typeof r.path=="string"&&r.path.trim().length>0)return`${s}:${c(r.path)}`;if(typeof r.command=="string"&&r.command.trim().length>0){const t=r.command.trim(),e=(Array.isArray(r.args)?r.args.filter(o=>typeof o=="string"&&o.trim().length>0):[]).find(o=>!o.startsWith("-"))?.trim(),n=`${s}:${t}${e===void 0?"":` ${e}`}`;return typeof r.script=="string"?`${n} script-sha256:${f(r.script)}`:n}return s}function $(s,r){const t=[s];if(typeof r.command=="string"){const i=Array.isArray(r.args)?r.args.filter(n=>typeof n=="string"):[];t.push(`${s}:${r.command}${i.length===0?"":` ${i.join(" ")}`}`);const e=i.find(n=>!n.startsWith("-"));e!==void 0&&t.push(`${s}:${r.command} ${e}`),typeof r.script=="string"&&t.push(`${s}:${r.command} script-sha256:${f(r.script)}`)}return typeof r.path=="string"&&t.push(`${s}:${c(r.path)}`),t}function a(s,r){const t=m(s),i=m(r);if(t===i)return!0;if(!t.includes("*"))return!1;const e=t.replace(/[.+?^${}()|[\]\\]/gu,"\\$&").replaceAll("*",".*");return new RegExp(`^${e}$`,"u").test(i)}function c(s){const r=s.trim().replaceAll("\\","/"),t=h.posix.normalize(r);return t==="."?"":t.startsWith("./")?t.slice(2):t}function m(s){const r=s.indexOf(":");return r<0||!s.slice(0,r).startsWith("filesystem.")?s:`${s.slice(0,r)}:${c(s.slice(r+1))}`}function f(s){return d.createHash("sha256").update(s,"utf8").digest("hex")}export{u as permissionRuleForRequest,l as workspacePermissionDecision};
|
|
@@ -17,8 +17,6 @@ export interface PrepareInput {
|
|
|
17
17
|
sessionId: string;
|
|
18
18
|
projectRoot: string;
|
|
19
19
|
}
|
|
20
|
-
export declare const SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS: number;
|
|
21
|
-
export declare const SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS: number;
|
|
22
20
|
/** Owns durable, session-scoped execution directories for all CLI surfaces. */
|
|
23
21
|
export declare class SessionExecutionWorkspaceService {
|
|
24
22
|
private readonly platform;
|
|
@@ -29,6 +27,8 @@ export declare class SessionExecutionWorkspaceService {
|
|
|
29
27
|
constructor(globalConfigDir: string, platform: HostPlatformContext, now?: () => number);
|
|
30
28
|
prepare(input: PrepareInput): Promise<SessionExecutionWorkspace>;
|
|
31
29
|
get(sessionId: string): Promise<SessionExecutionWorkspace | undefined>;
|
|
30
|
+
/** Holds one durable session turn lease across CLI processes. */
|
|
31
|
+
acquireTurn(sessionId: string): Promise<() => Promise<void>>;
|
|
32
32
|
markReady(sessionId: string): Promise<void>;
|
|
33
33
|
remove(sessionId: string): Promise<void>;
|
|
34
34
|
apply(sessionId: string): Promise<{
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import p from"node:crypto";import{createReadStream as
|
|
2
|
-
`)}async readIndex(){try{const e=await
|
|
3
|
-
`)}async writeEntries(e){await this.withWorkspaceLock(async()=>{const t=await this.readIndex();await this.writeIndex(e(t.entries))})}async withWorkspaceLock(e){return
|
|
1
|
+
import p from"node:crypto";import{createReadStream as _}from"node:fs";import h from"node:fs/promises";import a from"node:path";import{acquireFileLock as $,atomicWriteFile as S,withFileLock as U}from"../../infrastructure/filesystem/atomic-file-store.js";import{readJsonFileBounded as j}from"../../infrastructure/filesystem/bounded-json-reader.js";import{isFileNotFound as k}from"../../infrastructure/filesystem/fs-errors.js";import{execPlatformCommand as N}from"../../infrastructure/platform/host-process.js";import{RESOURCE_LIMITS as v}from"../../domain/runtime/resource-limits.js";import{COPY_EXCLUDED as x,MAX_BASELINE_BYTES as V,MAX_INDEX_BYTES as X,SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS as K,WORKSPACE_BASELINE_DIRECTORY as Y,WORKSPACE_DIRECTORY as q,WORKSPACE_INDEX_FILE as H,WORKSPACE_LOCK_OPTIONS as C}from"./workspace-constants.js";class we{platform;now;indexFile;rootDirectory;baselineDirectory;constructor(e,t,i=Date.now){this.platform=t,this.now=i,this.indexFile=a.join(e,H),this.rootDirectory=a.join(e,q),this.baselineDirectory=a.join(e,Y)}async prepare(e){const t=await h.realpath(a.resolve(e.projectRoot));return this.withWorkspaceLock(async()=>{await this.gcLocked(K);const i=await this.readIndex(),r=i.entries.find(o=>o.sessionId===e.sessionId&&o.projectRoot===t);if(r!==void 0){const o=await this.normalizeExecutionRoot(r);if(o.executionCwd!==r.executionCwd&&!await B(o.executionCwd)&&(await h.mkdir(o.executionCwd,{recursive:!0}),await I(t,o.executionCwd)),await B(o.executionCwd)){await this.synchronizeFromProjectRoot(o);const c={...o,state:"active",lastUsedAt:new Date(this.now()).toISOString()};return await this.writeIndex(i.entries.map(w=>w.id===r.id?c:w)),c}}const n=await this.create(e.sessionId,t);return await this.writeIndex([...i.entries.filter(o=>o.sessionId!==e.sessionId),n]),n})}async get(e){return(await this.readIndex()).entries.find(t=>t.sessionId===e)}async acquireTurn(e){const t=p.createHash("sha256").update(e,"utf8").digest("hex");return $(a.join(this.rootDirectory,"turn-locks",t),C)}async markReady(e){const t=await this.get(e);t!==void 0&&await this.updateEntry(t.id,i=>({...i,state:"ready",lastUsedAt:new Date(this.now()).toISOString()}))}async remove(e){await this.removeEntry(e)}async apply(e){return this.withWorkspaceLock(async()=>{const t=await this.readIndex(),i=t.entries.find(u=>u.sessionId===e);if(i===void 0)throw new Error("The session execution workspace was not found.");const r=await this.normalizeExecutionRoot(i);r.executionCwd!==i.executionCwd&&await this.writeIndex(t.entries.map(u=>u.id===r.id?r:u));const n=await this.readBaseline(r.id),[o,c]=await Promise.all([y(r.projectRoot,n.entries),y(r.executionCwd,n.entries)]),d=[...new Set([...Object.keys(n.entries),...o.keys(),...c.keys()])].filter(u=>!l(c.get(u),n.entries[u])).sort(),f=d.filter(u=>{const F=!l(o.get(u),n.entries[u]),z=!l(c.get(u),n.entries[u]);return F&&z&&!l(o.get(u),c.get(u))});if(f.length>0)throw new Error(`Cannot apply session changes because the project changed concurrently: ${f.join(", ")}.`);const m=await A(r.projectRoot,d,o);try{for(const u of d)await b(r.projectRoot,u,c.get(u),r.executionCwd)}catch(u){throw await O(r.projectRoot,m,d).catch(()=>{}),u}await this.writeBaseline(r.id,c);const W=await this.readIndex();return await this.writeIndex(W.entries.map(u=>u.id===r.id?{...u,lastUsedAt:new Date(this.now()).toISOString()}:u)),{appliedPaths:d}})}async removeEntry(e,t){await this.withWorkspaceLock(()=>this.removeEntryLocked(e,t))}async removeEntryLocked(e,t){const i=(await this.readIndex()).entries.find(n=>n.sessionId===e&&(t===void 0||n.id===t));if(i===void 0){const n=await this.readIndex();await this.writeIndex(n.entries.filter(o=>o.sessionId!==e));return}if(i.worktreePath!==void 0){let n=!1;for(let o=0;o<3;o+=1)try{await E(["worktree","remove","--force",i.worktreePath],i.projectRoot,this.platform),n=!0;break}catch{o<2&&await new Promise(c=>setTimeout(c,100))}if(!n){const o=await this.readIndex();await this.writeIndex(o.entries.map(c=>c.id===i.id?{...c,state:"orphaned"}:c));return}i.branch!==void 0&&await Z(i.branch,i.projectRoot,this.platform)}else await h.rm(i.executionCwd,{recursive:!0,force:!0});await h.rm(this.baselinePath(i.id),{force:!0});const r=await this.readIndex();await this.writeIndex(r.entries.filter(n=>n.id!==i.id))}async gc(e){return this.withWorkspaceLock(()=>this.gcLocked(e))}async gcLocked(e){const t=this.now()-e,r=(await this.readIndex()).entries.filter(n=>n.state==="orphaned"||Date.parse(n.lastUsedAt)<t);for(const n of r)await this.removeEntryLocked(n.sessionId,n.id);return r.length}async create(e,t){const i=p.randomUUID(),r=new Date(this.now()).toISOString();await h.mkdir(this.rootDirectory,{recursive:!0});const n=a.join(this.rootDirectory,i),o=await y(t),c=await T(t,this.platform);if(c!==void 0){const w=`lotagate/session-${i}`;await E(["worktree","add","-b",w,n,"HEAD"],c,this.platform);const d=M(c,t,n);return await h.mkdir(d,{recursive:!0}),await I(t,d),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:d,isolationMode:"worktree-per-session",state:"active",branch:w,worktreePath:n,createdAt:r,lastUsedAt:r}}return await I(t,n),await this.writeBaseline(i,o),{id:i,sessionId:e,projectRoot:t,executionCwd:n,isolationMode:"worktree-per-session",state:"active",createdAt:r,lastUsedAt:r}}async synchronizeFromProjectRoot(e){const t=await this.readBaseline(e.id),i=await y(e.projectRoot,t.entries),n=[...new Set([...Object.keys(t.entries),...i.keys()])].filter(d=>!l(i.get(d),t.entries[d])).sort();if(n.length===0)return;const o=await y(e.executionCwd,t.entries),c=n.filter(d=>!l(o.get(d),t.entries[d])&&!l(o.get(d),i.get(d)));if(c.length>0)throw new Error(`Cannot synchronize unresolved session changes: ${c.join(", ")}.`);const w=await A(e.executionCwd,n,o);try{for(const d of n)await b(e.executionCwd,d,i.get(d),e.projectRoot)}catch(d){throw await O(e.executionCwd,w,n).catch(()=>{}),d}await this.writeBaseline(e.id,i)}async normalizeExecutionRoot(e){if(e.worktreePath===void 0)return e;const t=await T(e.projectRoot,this.platform);return t===void 0?e:{...e,executionCwd:M(t,e.projectRoot,e.worktreePath)}}baselinePath(e){return a.join(this.baselineDirectory,`${e}.json`)}async readBaseline(e){const t=await j(this.baselinePath(e),V);if(t.schemaVersion!==1||typeof t.entries!="object"||t.entries===null||Array.isArray(t.entries))throw new Error("The session execution workspace baseline is missing or invalid.");return{schemaVersion:1,entries:Object.fromEntries(Object.entries(t.entries).filter(([i,r])=>L(i)&&Q(r)))}}async writeBaseline(e,t){const i={};for(const[r,n]of t)i[r]={kind:n.kind,hash:n.hash,size:n.size,...n.mode===void 0?{}:{mode:n.mode},...n.mtimeMs===void 0?{}:{mtimeMs:n.mtimeMs},...n.target===void 0?{}:{target:n.target}};await h.mkdir(this.baselineDirectory,{recursive:!0}),await S(this.baselinePath(e),`${JSON.stringify({schemaVersion:1,entries:i})}
|
|
2
|
+
`)}async readIndex(){try{const e=await j(this.indexFile,X);return e.schemaVersion!==2||!Array.isArray(e.entries)?{schemaVersion:2,entries:[]}:{schemaVersion:2,entries:e.entries.filter(te)}}catch(e){if(k(e))return{schemaVersion:2,entries:[]};throw e}}async writeIndex(e){await S(this.indexFile,`${JSON.stringify({schemaVersion:2,entries:e})}
|
|
3
|
+
`)}async writeEntries(e){await this.withWorkspaceLock(async()=>{const t=await this.readIndex();await this.writeIndex(e(t.entries))})}async withWorkspaceLock(e){return U(this.indexFile,e,C)}async updateEntry(e,t){await this.writeEntries(i=>i.map(r=>r.id===e?t(r):r))}}async function I(s,e){await h.cp(s,e,{recursive:!0,force:!0,filter:r=>{const n=a.relative(s,r);return n.length===0||!n.split(a.sep).some(o=>x.has(o))}});const[t,i]=await Promise.all([R(s),R(e)]);for(const r of[...i].filter(n=>!t.has(n)).sort((n,o)=>o.split(a.sep).length-n.split(a.sep).length))await h.rm(g(e,r),{recursive:!0,force:!0})}async function R(s){const e=new Set;return await t(s,""),e;async function t(i,r){for(const n of await h.readdir(i,{withFileTypes:!0})){if(x.has(n.name))continue;const o=r.length===0?n.name:a.join(r,n.name);e.add(o),n.isDirectory()&&await t(a.join(i,n.name),o)}}}async function y(s,e){const t=new Map;return await i(s,""),t;async function i(r,n){for(const o of await h.readdir(r,{withFileTypes:!0})){if(x.has(o.name))continue;const c=n.length===0?o.name:a.join(n,o.name),w=a.join(s,c),d=await h.lstat(w);if(d.isDirectory()){await i(w,c);continue}if(d.isSymbolicLink()){const m=await h.readlink(w);t.set(c,{kind:"symlink",hash:p.createHash("sha256").update(`symlink\0${m}`).digest("hex"),size:Buffer.byteLength(m),bytes:Buffer.alloc(0),target:m});continue}if(!d.isFile())continue;const f=e instanceof Map?e.get(c):e?.[c];if(f!==void 0&&f.kind==="file"&&f.size===d.size&&f.mtimeMs!==void 0&&Math.abs(f.mtimeMs-d.mtimeMs)<1&&P(f.mode,d.mode&4095)){t.set(c,{kind:"file",hash:f.hash,size:d.size,mtimeMs:d.mtimeMs,mode:d.mode&4095});continue}t.set(c,{kind:"file",hash:await J(w),size:d.size,mtimeMs:d.mtimeMs,mode:d.mode&4095})}}}async function A(s,e,t){const i=new Map;for(const r of e){const n=t.get(r);n!==void 0&&(n.kind==="symlink"?i.set(r,n):i.set(r,{...n,bytes:await h.readFile(g(s,r))}))}return i}async function J(s){const e=p.createHash("sha256");for await(const t of _(s))e.update(t);return e.digest("hex")}function M(s,e,t){const i=a.relative(a.resolve(s),a.resolve(e));if(i===""||i===".")return a.resolve(t);if(i===".."||i.startsWith(`..${a.sep}`)||a.isAbsolute(i))throw new Error("The project root is outside the Git worktree root.");return a.resolve(t,i)}function P(s,e){return s===void 0||e===void 0||process.platform==="win32"?!0:(s&73)===(e&73)}function l(s,e){return s===void 0||e===void 0?s===e:s.kind===e.kind&&s.hash===e.hash&&(s.kind!=="file"||P(s.mode,e.mode))&&(s.kind!=="symlink"||s.target===e.target)}async function b(s,e,t,i=s){const r=g(s,e);if(await D(s,r),t===void 0){await h.unlink(r).catch(w=>{if(!k(w))throw w});return}const n=a.dirname(r);if(await h.mkdir(n,{recursive:!0}),await D(s,r),(await h.lstat(r).catch(w=>{if(!k(w))throw w}))?.isDirectory())throw new Error(`Cannot apply ${e}: the project root contains a directory at that path.`);const c=`${r}.${p.randomUUID()}.tmp`;try{t.kind==="symlink"?await h.symlink(t.target??"",c):await h.writeFile(c,t.bytes??await h.readFile(g(i,e)),{mode:t.mode}),t.kind==="file"&&t.mode!==void 0&&await h.chmod(c,t.mode),await h.rename(c,r)}finally{await h.rm(c,{force:!0})}}async function D(s,e){const t=a.resolve(s),i=await h.realpath(t);let r=a.dirname(e);for(;;){const n=a.resolve(r),o=a.relative(t,n);if(o===".."||o.startsWith(`..${a.sep}`)||a.isAbsolute(o))throw new Error("The workspace path escapes the project root.");const c=await h.lstat(n).catch(w=>{if(!k(w))throw w});if(c?.isSymbolicLink())throw new Error("The workspace path contains a symbolic-link parent.");if(c!==void 0&&!G(i,await h.realpath(n)))throw new Error("The workspace path escapes the project root.");if(n===t)return;r=a.dirname(n)}}function G(s,e){const t=a.relative(s,e);return t===""||t!==".."&&!t.startsWith(`..${a.sep}`)&&!a.isAbsolute(t)}async function O(s,e,t){for(const i of[...t].reverse())await b(s,i,e.get(i))}function g(s,e){if(!L(e))throw new Error("The workspace path is invalid.");const t=a.resolve(s),i=a.resolve(t,e),r=a.relative(t,i);if(r===".."||r.startsWith(`..${a.sep}`)||a.isAbsolute(r))throw new Error("The workspace path escapes the project root.");return i}function L(s){return s.length>0&&!a.isAbsolute(s)&&s!=="."&&s!==".."&&!s.startsWith(`..${a.sep}`)&&!s.includes("\0")}function Q(s){if(typeof s!="object"||s===null)return!1;const e=s;return(e.kind==="file"||e.kind==="symlink")&&typeof e.hash=="string"&&typeof e.size=="number"&&(e.mode===void 0||typeof e.mode=="number"&&Number.isInteger(e.mode)&&e.mode>=0&&e.mode<=4095)&&(e.mtimeMs===void 0||typeof e.mtimeMs=="number")&&(e.target===void 0||typeof e.target=="string")}async function T(s,e){try{return(await E(["rev-parse","--show-toplevel"],s,e)).trim()||void 0}catch{return}}async function Z(s,e,t){if(!/^lotagate\/session-[a-z0-9-]+$/iu.test(s))throw new Error("The session workspace branch name is invalid.");try{await E(["branch","--delete","--force","--",s],e,t)}catch(i){const r=i instanceof Error?i.message:String(i);if(!/not found|not a valid branch|unknown revision/iu.test(r))throw i}}async function E(s,e,t){return ee("git",s,e,t)}function ee(s,e,t,i){return N(s,e,i,{cwd:t,maxBufferBytes:v.internalProcessOutputBytes,timeoutMs:v.internalProcessTimeoutMs}).then(r=>r.stdout)}async function B(s){try{return(await h.stat(s)).isDirectory()}catch{return!1}}function te(s){if(typeof s!="object"||s===null)return!1;const e=s;return typeof e.id=="string"&&typeof e.sessionId=="string"&&typeof e.projectRoot=="string"&&typeof e.executionCwd=="string"&&e.isolationMode==="worktree-per-session"&&(e.state==="ready"||e.state==="active"||e.state==="orphaned")&&typeof e.createdAt=="string"&&typeof e.lastUsedAt=="string"}export{we as SessionExecutionWorkspaceService};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const DEFAULT_IGNORED_WORKSPACE_DIRECTORIES: Set<string>;
|
|
2
|
+
export declare const MAX_INDEXED_ENTRIES = 2000;
|
|
3
|
+
export declare const INSTRUCTION_PATHS: readonly ["AGENTS.md", "CLAUDE.md", "CLAUDE.local.md", "QWEN.md", "QWEN.local.md", "GEMINI.md", "CONTEXT.md", "CONVENTIONS.md", ".claude/CLAUDE.md", ".qwen/QWEN.md", ".qwen/QWEN.local.md", ".github/copilot-instructions.md", ".cursorrules", ".windsurfrules"];
|
|
4
|
+
export declare const RULE_DIRECTORIES: readonly [".claude/rules", ".cursor/rules", ".windsurf/rules", ".devin/rules", ".clinerules"];
|
|
5
|
+
export declare const RULE_EXTENSIONS: Set<string>;
|
|
6
|
+
export declare const WORKSPACE_INDEX_FILE = "session-execution-workspaces.json";
|
|
7
|
+
export declare const WORKSPACE_DIRECTORY = "session-execution-workspaces";
|
|
8
|
+
export declare const WORKSPACE_BASELINE_DIRECTORY = "session-execution-workspace-baselines";
|
|
9
|
+
export declare const MAX_INDEX_BYTES: number;
|
|
10
|
+
export declare const MAX_BASELINE_BYTES: number;
|
|
11
|
+
export declare const SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS: number;
|
|
12
|
+
export declare const SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS: number;
|
|
13
|
+
export declare const COPY_EXCLUDED: Set<string>;
|
|
14
|
+
export declare const WORKSPACE_LOCK_OPTIONS: {
|
|
15
|
+
readonly timeoutMs: number;
|
|
16
|
+
readonly userMessage: "Another session is updating workspace state. Try again shortly.";
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o=new Set([".git",".lotagate","node_modules","dist","build","coverage",".next",".nuxt",".cache",".turbo","vendor"]),s=2e3,t=["AGENTS.md","CLAUDE.md","CLAUDE.local.md","QWEN.md","QWEN.local.md","GEMINI.md","CONTEXT.md","CONVENTIONS.md",".claude/CLAUDE.md",".qwen/QWEN.md",".qwen/QWEN.local.md",".github/copilot-instructions.md",".cursorrules",".windsurfrules"],E=[".claude/rules",".cursor/rules",".windsurf/rules",".devin/rules",".clinerules"],n=new Set([".md",".mdc"]),r="session-execution-workspaces.json",c="session-execution-workspaces",_="session-execution-workspace-baselines",S=2*1024*1024,d=8*1024*1024,I=720*60*60*1e3,e=60*1e3,O=new Set([".git",".lotagate","node_modules"]),u={timeoutMs:e,userMessage:"Another session is updating workspace state. Try again shortly."};export{O as COPY_EXCLUDED,o as DEFAULT_IGNORED_WORKSPACE_DIRECTORIES,t as INSTRUCTION_PATHS,d as MAX_BASELINE_BYTES,s as MAX_INDEXED_ENTRIES,S as MAX_INDEX_BYTES,E as RULE_DIRECTORIES,n as RULE_EXTENSIONS,e as SESSION_EXECUTION_WORKSPACE_LOCK_TIMEOUT_MS,I as SESSION_EXECUTION_WORKSPACE_MAX_IDLE_MS,_ as WORKSPACE_BASELINE_DIRECTORY,c as WORKSPACE_DIRECTORY,r as WORKSPACE_INDEX_FILE,u as WORKSPACE_LOCK_OPTIONS};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import a from"node:fs/promises";import
|
|
1
|
+
import a from"node:fs/promises";import e from"node:path";import{DEFAULT_IGNORED_WORKSPACE_DIRECTORIES as h,MAX_INDEXED_ENTRIES as n}from"./workspace-constants.js";class u{root;ignoredDirectories;constructor(i,t=h){this.root=i,this.ignoredDirectories=t}async list(){return(await this.listEntries()).filter(i=>i.kind==="file").map(i=>i.path)}async listEntries(){const i=[];return await this.visit(this.root,i),i.sort((t,s)=>t.path.localeCompare(s.path))}async visit(i,t){if(t.length>=n)return;let s;try{s=await a.readdir(i,{withFileTypes:!0})}catch{return}for(const r of s){if(t.length>=n)return;const o=e.join(i,r.name);if(!r.isSymbolicLink())if(r.isDirectory()){if(this.ignoredDirectories.has(r.name))continue;t.push({path:e.relative(this.root,o).split(e.sep).join("/"),kind:"directory"}),await this.visit(o,t)}else r.isFile()&&t.push({path:e.relative(this.root,o).split(e.sep).join("/"),kind:"file"})}}}export{u as WorkspaceFileIndex};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import p from"node:fs/promises";import o from"node:path";import{readFileBounded as F}from"../../infrastructure/filesystem/bounded-file-reader.js";import{isFileNotFound as h}from"../../infrastructure/filesystem/fs-errors.js";import{RESOURCE_LIMITS as y}from"../../domain/runtime/resource-limits.js";import{INSTRUCTION_PATHS as g,RULE_DIRECTORIES as I,RULE_EXTENSIONS as L}from"./workspace-constants.js";class ${async load(r,n=r){const t=await p.realpath(r),s=await p.realpath(n);if(s!==t&&!s.startsWith(`${t}${o.sep}`))return[];const u=E(t,s),e=[];let a=0;for(const l of u){for(const c of g)if(e.length>=y.instructionFiles||await w(o.join(l,c),t,e,()=>a,m=>{a=m})==="limit")return e;for(const c of I){const f=await R(o.join(l,c));for(const m of f)if(e.length>=y.instructionFiles||await w(m,t,e,()=>a,d=>{a=d},d=>T(d))==="limit")return e}}return e}}async function w(i,r,n,t,s,u){try{const e=await p.lstat(i);if(!e.isFile()||e.isSymbolicLink())return"skipped";const a=await F(i,y.instructionFileBytes);if(a.truncated)return"skipped";const l=a.bytes.toString("utf8");if(u!==void 0&&!u(l))return"skipped";const c=t()+a.bytes.byteLength;if(c>y.instructionTotalBytes)return"limit";s(c);const f=o.relative(r,i)||o.basename(i);return n.push({path:f.split(o.sep).join("/"),content:l}),"added"}catch(e){if(!h(e))throw e;return"skipped"}}async function R(i){const r=[];return await S(i,r),r.sort((n,t)=>n.localeCompare(t))}async function S(i,r){try{const n=await p.readdir(i,{withFileTypes:!0});for(const t of n.sort((s,u)=>s.name.localeCompare(u.name))){const s=o.join(i,t.name);t.isSymbolicLink()||(t.isDirectory()?await S(s,r):t.isFile()&&L.has(o.extname(t.name).toLowerCase())&&r.push(s))}}catch(n){if(h(n))return;throw n}}function T(i){const r=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(i)?.[1];return r===void 0||/^\s*(?:alwaysApply|always_apply)\s*:\s*true\s*$/imu.test(r)||/^\s*trigger\s*:\s*(?:always|always_on)\s*$/imu.test(r)?!0:!/^\s*(?:alwaysApply|always_apply|globs|paths|trigger)\s*:/imu.test(r)}function E(i,r){const n=[];let t=r;for(;;){if(n.unshift(t),t===i)return n;const s=o.dirname(t);if(s===t)return[];t=s}}export{$ as WorkspaceInstructionLoader};
|
|
@@ -2,5 +2,6 @@ import type { Writable } from 'node:stream';
|
|
|
2
2
|
import { type CliRuntime } from './runtime-factory.js';
|
|
3
3
|
export interface CompositionRootOptions {
|
|
4
4
|
stderr?: Writable;
|
|
5
|
+
interactive?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export declare function createCompositionRoot(options?: CompositionRootOptions): CliRuntime;
|
|
@@ -16,6 +16,8 @@ import { type HostPlatformContext } from '../infrastructure/platform/host-platfo
|
|
|
16
16
|
import { McpRuntime } from '../infrastructure/extensions/mcp-runtime.js';
|
|
17
17
|
import { MemoryService } from '../application/memory/memory-service.js';
|
|
18
18
|
import { SessionExecutionWorkspaceService } from '../application/workspace/session-execution-workspace.js';
|
|
19
|
+
import { ModelCatalogInFlightRegistry } from '../application/model/cached-model-catalog.js';
|
|
20
|
+
import { CliAgentPreparationCache } from '../application/agent/cli-agent-preparation-cache.js';
|
|
19
21
|
export interface CliRuntime {
|
|
20
22
|
readonly platform: HostPlatformContext;
|
|
21
23
|
readonly paths: PlatformPaths;
|
|
@@ -33,9 +35,12 @@ export interface CliRuntime {
|
|
|
33
35
|
readonly mcpRuntime: McpRuntime;
|
|
34
36
|
readonly memory: MemoryService;
|
|
35
37
|
readonly executionWorkspaces: SessionExecutionWorkspaceService;
|
|
38
|
+
readonly modelCatalogInFlight: ModelCatalogInFlightRegistry;
|
|
39
|
+
readonly agentPreparation?: CliAgentPreparationCache;
|
|
36
40
|
readonly shutdown: ShutdownManager;
|
|
37
41
|
}
|
|
38
42
|
export interface RuntimeFactoryOptions {
|
|
39
43
|
stderr?: Writable;
|
|
44
|
+
interactive?: boolean;
|
|
40
45
|
}
|
|
41
46
|
export declare function createCliRuntime(options?: RuntimeFactoryOptions): CliRuntime;
|