@tencent-ai/agent-harness 0.2.0-beta.1 → 0.2.0-beta.2

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 (137) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/cli/CHANGELOG.md +71 -0
  4. package/cli/dist-server/shared.cjs +318 -314
  5. package/cli/dist-server/types/node/acp/acp-protocol.d.ts +40 -12
  6. package/cli/dist-server/types/node/acp/usage-by-category-calculator.d.ts +21 -0
  7. package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +15 -1
  8. package/cli/dist-server/types/node/data-fs/index.d.ts +13 -1
  9. package/cli/dist-server/types/node/hooks/hook-protocol.d.ts +2 -2
  10. package/cli/dist-server/types/node/server/sessions.d.ts +24 -0
  11. package/cli/dist-server/types/node/server/types.d.ts +6 -0
  12. package/cli/dist-server/types/node/settings/settings-protocol.d.ts +5 -0
  13. package/cli/dist-server/types/node/tools/tool-protocol.d.ts +112 -2
  14. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +29 -0
  15. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +2 -0
  16. package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +1 -0
  17. package/cli/dist-server/types/vendor/cbc-core/node/agent/interceptors/input-interceptors.d.ts +1 -6
  18. package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +31 -11
  19. package/cli/dist-server/types/vendor/cbc-core/node/agent/speaker-label.d.ts +44 -0
  20. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-detector-service.d.ts +5 -4
  21. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  22. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +15 -4
  23. package/cli/dist-server/types/vendor/cbc-core/node/hooks/agent-trigger.d.ts +6 -22
  24. package/cli/dist-server/types/vendor/cbc-core/node/hooks/hook-protocol.d.ts +4 -1
  25. package/cli/dist-server/types/vendor/cbc-core/node/session/idle-queue-drain-service.d.ts +4 -56
  26. package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +3 -0
  27. package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +55 -9
  28. package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +18 -0
  29. package/cli/dist-server/types/vendor/cbc-core/node/session/recovery-budget.d.ts +55 -0
  30. package/cli/dist-server/types/vendor/cbc-core/node/session/session-hook-manager.d.ts +15 -0
  31. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +10 -1
  32. package/cli/dist-server/types/vendor/cbc-core/node/session/session-persistence-error.d.ts +43 -0
  33. package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +63 -4
  34. package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +1 -0
  35. package/cli/dist-server/types/vendor/cbc-core/node/session/session-runtime-lifecycle.d.ts +5 -0
  36. package/cli/dist-server/types/vendor/cbc-core/node/session/session-store.d.ts +150 -4
  37. package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +13 -1
  38. package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +23 -0
  39. package/cli/dist-server/types/vendor/cbc-core/node/utils/index.d.ts +1 -0
  40. package/cli/dist-server/types/vendor/cbc-core/node/utils/message-utils.d.ts +12 -0
  41. package/cli/dist-server/types/vendor/cbc-core/node/utils/model-utils.d.ts +7 -0
  42. package/cli/dist-server/types/vendor/cbc-core/node/utils/queue-dispatch-utils.d.ts +24 -2
  43. package/cli/dist-server/types/vendor/cbc-core/node/utils/session-utils.d.ts +4 -1
  44. package/cli/dist-server/types/vendor/cbc-core/node/utils/string-retention-utils.d.ts +4 -0
  45. package/cli/dist-server/types/vendor/cbc-shared/node/hooks/hook-types.d.ts +7 -1
  46. package/cli/dist-server/types/vendor/cbc-shared/node/index.d.ts +2 -0
  47. package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +7 -3
  48. package/cli/dist-server/types/vendor/cbc-shared/node/tools/tool-names.d.ts +1 -0
  49. package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-backoff.d.ts +30 -0
  50. package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-policy.d.ts +26 -0
  51. package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +2 -2
  52. package/cli/dist-server/types/workspace/authentication/lib/common/account-utils.d.ts +25 -0
  53. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +2 -2
  54. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +19 -2
  55. package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +2 -2
  56. package/cli/dist-server/types/workspace/authentication/lib/common/wx-authentication-provider.d.ts +2 -2
  57. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +29 -0
  58. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +2 -0
  59. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +1 -0
  60. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/interceptors/input-interceptors.d.ts +1 -6
  61. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +31 -11
  62. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/speaker-label.d.ts +44 -0
  63. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-detector-service.d.ts +5 -4
  64. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  65. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +15 -4
  66. package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/agent-trigger.d.ts +6 -22
  67. package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/hook-protocol.d.ts +4 -1
  68. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/idle-queue-drain-service.d.ts +4 -56
  69. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +3 -0
  70. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +55 -9
  71. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +18 -0
  72. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/recovery-budget.d.ts +55 -0
  73. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-hook-manager.d.ts +15 -0
  74. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +10 -1
  75. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-persistence-error.d.ts +43 -0
  76. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +63 -4
  77. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +1 -0
  78. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-runtime-lifecycle.d.ts +5 -0
  79. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-store.d.ts +150 -4
  80. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +13 -1
  81. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +23 -0
  82. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/index.d.ts +1 -0
  83. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/message-utils.d.ts +12 -0
  84. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/model-utils.d.ts +7 -0
  85. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/queue-dispatch-utils.d.ts +24 -2
  86. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/session-utils.d.ts +4 -1
  87. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/string-retention-utils.d.ts +4 -0
  88. package/cli/dist-server/types/workspace/cbc-shared/lib/node/hooks/hook-types.d.ts +7 -1
  89. package/cli/dist-server/types/workspace/cbc-shared/lib/node/index.d.ts +2 -0
  90. package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +7 -3
  91. package/cli/dist-server/types/workspace/cbc-shared/lib/node/tools/tool-names.d.ts +1 -0
  92. package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-backoff.d.ts +30 -0
  93. package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-policy.d.ts +26 -0
  94. package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-execution.d.ts +14 -1
  95. package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-manager.d.ts +7 -0
  96. package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-session.d.ts +3 -0
  97. package/cli/dist-server/types/workspace/product/lib/common/cloud-product-provider.d.ts +9 -0
  98. package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
  99. package/cli/dist-server/types/workspace/product/lib/common/pick-market-skill-id.d.ts +13 -0
  100. package/cli/dist-server/types/workspace/product/lib/common/tool-control-catalog.d.ts +2 -2
  101. package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +62 -2
  102. package/cli/dist-server/types/workspace/product/lib/common/types/language-model.d.ts +66 -0
  103. package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +7 -1
  104. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/backup-policy.d.ts +10 -1
  105. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +370 -4
  106. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +1 -1
  107. package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +216 -0
  108. package/cli/package.json +1 -1
  109. package/cli/product.cloudhosted.json +2 -2
  110. package/cli/product.internal.json +259 -40
  111. package/cli/product.ioa.json +333 -148
  112. package/cli/product.json +309 -351
  113. package/cli/product.selfhosted.json +2 -2
  114. package/docs/README.md +1 -0
  115. package/docs/in-process.md +16 -0
  116. package/lib/application/services.d.ts +3 -1
  117. package/lib/application/services.js +1 -1
  118. package/lib/components/sandbox-center.d.mts +2 -0
  119. package/lib/components/sandbox-center.mjs +1 -0
  120. package/lib/components/session-config.d.mts +2 -0
  121. package/lib/components/session-config.mjs +1 -1
  122. package/lib/harness/create-harness.js +1 -1
  123. package/lib/harness/runtime.js +1 -1
  124. package/lib/harness/types.d.ts +3 -0
  125. package/lib/integration/executor-supervisor.js +1 -1
  126. package/lib/public.d.ts +1 -0
  127. package/lib/runtime/sandbox-center.d.ts +21 -0
  128. package/lib/runtime/sandbox-center.js +1 -0
  129. package/lib/server/public.d.ts +1 -0
  130. package/lib/session/agent-backend.d.ts +2 -0
  131. package/lib/session/agent-backend.js +1 -1
  132. package/lib/session/local-fs.js +1 -1
  133. package/lib/session/server-config.js +1 -1
  134. package/lib/session/server-interactions.js +1 -1
  135. package/package.json +25 -15
  136. package/lib/session/local-options.d.ts +0 -50
  137. package/lib/session/local-options.js +0 -1
@@ -359,6 +359,6 @@
359
359
  "ScheduledTasks": true,
360
360
  "SkipToolCallSupportCheck": true
361
361
  },
362
- "commit": "dc049917f83480787e2618027a5efef739dfc3e0",
363
- "date": "2026-09-22T06:02:01.816Z"
362
+ "commit": "7c203b70e58175d4ef590d9ad8cdb355d2f1887c",
363
+ "date": "2026-09-24T06:35:18.914Z"
364
364
  }
package/docs/README.md CHANGED
@@ -16,6 +16,7 @@ npm 包名为 `@tencent-ai/agent-harness`。以下文档描述当前公开接口
16
16
  | [遥测](telemetry.md) | 日志、事件与宿主注入 |
17
17
  | [启动性能分析](startup-profiling.md) | 初始化分段、CPU profile |
18
18
  | [发布与分发](distribution.md) | Node 主包、Bun SFE 平台包与制品布局 |
19
+ | [更新记录](../CHANGELOG.md) | beta 版本变化与接入注意事项 |
19
20
 
20
21
  精确的调用签名以同版本发布包的 TypeScript 导出为准。
21
22
 
@@ -60,6 +60,7 @@ await harness.close();
60
60
  | `host` | 应用身份。支持 `ideName`、`ideType`、`ideVersion`、`extName`、`extVersion`、`userAgent`;`extName` 与 `extVersion` 成对填写。与 CLI 的身份参数一致。 |
61
61
  | `productConfig` | 应用的完整 Product 配置对象,或版本化配置文件的绝对路径。显式提供时不读取、补入 Agent CLI 的 Product;省略时使用包内默认配置。 |
62
62
  | `configDir` | 本进程的配置目录,必须是绝对路径。默认继承 `CODEBUDDY_CONFIG_DIR`,再回落到 `~/.codebuddy`。 |
63
+ | `sandboxCenter` | 默认由 Harness 在首次需要时启动并关闭原生 center。传 `{ address }` 可连接宿主已启动的 center;Harness 不会停止借用的进程。`'managed'` 可在已有进程环境地址时仍选择 Harness 管理。 |
63
64
  | `tools` | 工具预设或显式工具数组,见下文。默认使用 `default`。 |
64
65
  | `mcp.toolsSyncTtlMs` | 工具目录的兜底刷新间隔,默认 15 分钟;`null` 关闭过期刷新,变更通知仍生效。 |
65
66
  | `strictMcpConfig` | 为 `true` 时只使用会话显式传入的 MCP;默认还发现用户和插件 MCP。 |
@@ -68,6 +69,8 @@ await harness.close();
68
69
 
69
70
  当前每个进程支持一个 Harness,关闭后不能在同一进程重启 Agent runtime。不同窗口或工作区使用同一 Harness 的多个 Client/Session。配置目录是进程级设置;文件系统、会话历史及 user/project/local settings 使用现有本地实现。
70
71
 
72
+ 项目 Skills、命令、Agent 定义及已启用插件的 persona、MCP、Skills、命令、Agent 和 hooks 随会话的 `cwd` 装载并隔离。磁盘文件与插件提供的 output style、插件 LSP 暂不在多工作区库模式下启用;应用仍可通过 Product 提供 output style。
73
+
71
74
  `host` 描述应用,`clientInfo` 描述具体连接;账号、Product 模式和凭据仍通过 Client 协商和设置。模型、权限、工作区目录、插件和 Skills 使用现有会话及领域 API。参见 [认证接入](authentication-guide.md)、[Product 配置](product.md) 和 [Client 指南](client.md)。
72
75
 
73
76
  `productConfig` 在创建时复制;后续修改原对象不会改变 Harness。应用应先解析自己的配置文件和环境选择,再传入结果。需要指定公开 feature 名称时,也可传入 [Product 配置文件](product.md#2-product-文件) 的版本化对象及 `presentation`。
@@ -77,6 +80,19 @@ managed Product 由 Harness 基于这份启动配置和账号解析;external P
77
80
 
78
81
  库入口不安装进程信号处理器,也不会调用 `process.exit()`。独立进程的 listener、网络认证以及 Windows 宿主进程树回收由入口负责,见 [Server 装配](server.md)。
79
82
 
83
+ Windows 上的 Bash 使用非交互 pipe 输出,支持前台、后台任务和终端输出通知;沙箱规则与权限审批照常生效。
84
+ Linux 上安装了对应架构的 `@tencent-ai/sandbox-cli-linux-*` 原生包时,Harness 默认开启平台支持,Session Config Options 提供 `sandbox` 开关。宿主也可通过 `WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI=0` 关闭,或设为 `1` 显式开启(需提供可用的原生程序)。工作区外的 `ask` 规则通过 ACP 请求权限。
85
+
86
+ `sandbox-center` 使用进程内所有 Agent 和 sandbox-cli 共享的 IPC 地址。Harness 默认在首次带账号的 query 前按需启动 center,切换账号时先收口旧会话再重启,关闭 Harness 时仅回收自己启动的进程。若宿主已经管理 center,传入其监听地址即可:
87
+
88
+ ```ts
89
+ const harness = await createHarness({
90
+ sandboxCenter: { address: centerAddress },
91
+ });
92
+ ```
93
+
94
+ 只有进程句柄不足以连接 center,宿主还需提供它启动时设置的 IPC 地址。未显式传入时,如果进程环境已有 `SANDBOX_CENTER_IPC_ADDRESS`,Harness 会借用该地址;需要由 Harness 接管启动时可显式传 `sandboxCenter: 'managed'`。借用模式下账号切换由宿主先切换 center;Harness 不会替宿主停止进程。
95
+
80
96
  ## 工具选择
81
97
 
82
98
  以下是独立配置示例:
@@ -3,6 +3,7 @@ import { composeAgentHarnessModules } from '../module/compose.js';
3
3
  import { type AgentHarnessClientIdentity } from '../runtime/client-identity.js';
4
4
  import { CodeBuddyProcessContainment } from '../runtime/process-containment.js';
5
5
  import { type AgentHarnessProductInput } from '../runtime/product-config.js';
6
+ import { type SandboxCenterOption } from '../runtime/sandbox-center.js';
6
7
  import type { TelemetryOptions } from '../telemetry/public.js';
7
8
  import { createTelemetry, type RuntimeLifecycleRecorder } from '../telemetry/runtime.js';
8
9
  import { AgentHarnessShutdownCoordinator } from './lifecycle.js';
@@ -14,6 +15,7 @@ export interface ApplicationServicesOptions {
14
15
  readonly packageVersion: string;
15
16
  readonly processRuntime: ApplicationProcessRuntime;
16
17
  readonly productConfig?: string | AgentHarnessProductInput;
18
+ readonly sandboxCenter?: SandboxCenterOption;
17
19
  readonly signal?: AbortSignal;
18
20
  readonly tools?: QueryOptions['tools'];
19
21
  readonly strictMcpConfig: boolean;
@@ -31,4 +33,4 @@ export interface ApplicationServices {
31
33
  readonly runtimeShutdown: AbortController;
32
34
  readonly recordLifecycle: RuntimeLifecycleRecorder;
33
35
  }
34
- export declare function createApplicationServices({ clientIdentity, clientIdentityEnv, dependencies, packageVersion, processRuntime, productConfig, tools, strictMcpConfig, mcp, shutdown, telemetryOptions, signal, }: ApplicationServicesOptions): Promise<ApplicationServices>;
36
+ export declare function createApplicationServices({ clientIdentity, clientIdentityEnv, dependencies, packageVersion, processRuntime, productConfig, sandboxCenter, tools, strictMcpConfig, mcp, shutdown, telemetryOptions, signal, }: ApplicationServicesOptions): Promise<ApplicationServices>;
@@ -1 +1 @@
1
- var We=Object.defineProperty;var t=(y,U)=>We(y,"name",{value:U,configurable:!0});import{homedir as Ye}from"node:os";import*as O from"node:path";import{isDeepStrictEqual as Ne}from"node:util";import{Context as p,Effect as m,Exit as g,Layer as s,Logger as c,Option as je,Scope as h}from"effect";import{createAgentProtocolModule as Ge}from"../agent/router.js";import{createAgentV2Facade as qe}from"../agent/v2.js";import{AgentDiscovery as Ke}from"../agent-registry/discovery.js";import{ManagedAuthLocal as Ve}from"../auth/local.js";import{ManagedAuth as Qe}from"../auth/managed.js";import{createAuthProtocolModule as Je}from"../auth/module.js";import{Checkpoints as ve}from"../checkpoint/service.js";import{ConfigFiles as Z}from"../config/files.js";import{createDefaultAgentMcpIntegration as Xe}from"../integration/agent-integration.js";import{PluginMcp as Se}from"../integration/plugin-mcp.js";import{UserMcp as Pe}from"../integration/user-mcp.js";import{requestWithEnvironment as Ze}from"../internal/http.js";import{createMcpServerProtocolModule as $e}from"../mcp-server/module.js";import{composeAgentHarnessModules as er}from"../module/compose.js";import{PluginComponents as $}from"../plugin/components.js";import{createProductProtocolModule as rr}from"../product/module.js";import{preflightCodeBuddyCode as tr}from"../runtime/agent-runtime.js";import{buildAgentHarnessClientIdentityEnv as or,buildAgentHarnessClientIdentityHeaders as nr}from"../runtime/client-identity.js";import{createCodeBuddyAuthRuntime as ir}from"../runtime/codebuddy-auth.js";import{createCodeBuddyProductLifecycle as ar}from"../runtime/codebuddy-product.js";import{DEFAULT_HOST_HEALTH_TIMEOUT_MS as sr,DEFAULT_READY_TIMEOUT_MS as cr}from"../runtime/codebuddy-resource-timeouts.js";import{CodeBuddyProcessContainment as dr}from"../runtime/process-containment.js";import{parseAgentHarnessProductConfig as pr,parseHarnessProductInput as ur}from"../runtime/product-config.js";import{ProductManager as mr}from"../runtime/product-manager.js";import{ProductResolver as we}from"../runtime/product-resolver.js";import{ProductResolverRequestError as lr}from"../runtime/product-resolver-error.js";import{loadProductSource as fr}from"../runtime/product-source.js";import{AgentHarnessServer as hr,DEFAULT_LIFECYCLE_HOOK_TIMEOUT_MS as gr}from"../server/index.js";import{makeServiceRpcs as yr}from"../server/rpc-services.js";import{AgentBackend as Er}from"../session/agent-backend.js";import{AgentServer as Ce}from"../session/agent-server.js";import{SessionConfigStore as vr}from"../session/config-store.js";import{SessionFiles as Sr}from"../session/files.js";import{localFs as Ae}from"../session/local-fs.js";import{localQueryOptions as Pr}from"../session/local-options.js";import{SessionReplay as ke}from"../session/replay.js";import{SessionRuntime as wr}from"../session/runtime.js";import{Sessions as be}from"../session/service.js";import{toExecutorPrivateProxyPolicy as _e}from"../settings/proxy-policy.js";import{createHarnessSettingsRuntime as Cr}from"../settings/runtime.js";import{Settings as Ar}from"../settings/service.js";import{createSubagentProtocolModule as kr}from"../subagent/module.js";import{createEffectTelemetryMetricAggregator as br}from"../telemetry/effect-metric-aggregation.js";import{createTelemetry as _r}from"../telemetry/runtime.js";import{measureStartup as ee,startupProfiler as i}from"../telemetry/startup-profile.js";import{closeInPhases as re,closeTelemetry as Mr,createCloseOnce as b,DEFAULT_TELEMETRY_CLOSE_TIMEOUT_MS as Lr}from"./lifecycle.js";export async function createApplicationServices({clientIdentity:y,clientIdentityEnv:U,dependencies:S,packageVersion:Me,processRuntime:E,productConfig:T,tools:te,strictMcpConfig:Le,mcp:Ie,shutdown:x,telemetryOptions:oe,signal:u}){u?.throwIfAborted();const P=t(e=>m.runPromise(e,{signal:u}),"runStartupEffect"),z=x,ne={name:"@genie/agent-harness",title:"Agent Harness",version:Me},ie=(S.preflightCodeBuddyCode??tr)(),_=new dr,F=new AbortController,l=_r(oe),B=b(()=>Mr(l,E,Math.max(1,Math.min(x.remainingMs(),oe.flushTimeoutMs??Lr))));x.registerTelemetryCloser(B);const ae=br(e=>l.recordEffectMetrics(e));try{E.addFinalizer(B)}catch(e){throw await B(),e}try{E.setTelemetryObserver({log:t(e=>l.recordEffectLog(e),"log"),metrics:t(e=>ae.record("harness",e),"metrics"),span:t(e=>l.recordEffectSpan(e),"span")})}catch{}const k=t(e=>l.recordLifecycle(e),"recordLifecycle");let se=!1;const W=t((e,d,D)=>{se||(se=!0,k({component:"server",error:e,phase:"runtime",process:{pid:process.pid},reason:D,state:d}))},"recordRootFailure");_.signal.addEventListener("abort",()=>{W(_.signal.reason,"containment_tripped","containment_failed")},{once:!0});const De={log(e){try{l.recordEffectLog(e)}catch{}},metrics(e){ae.record("executor",e)},span(e){try{l.recordEffectSpan(e)}catch{}}};let w,n,R,M,a,A,L,C;const I=h.makeUnsafe(),Y=b(e=>m.runPromise(h.close(I,e===void 0?g.void:g.fail(e))));E.addFinalizer(()=>Y(void 0));const N=t(()=>{R&&m.runPromise(m.forkIn(R.prepare,I,{startImmediately:!0})).catch(()=>{})},"prepareRuntime"),ce=h.makeUnsafe(),j=b(async e=>{try{await a?.close(e)}finally{await m.runPromise(h.close(ce,e===void 0?g.void:g.fail(e)))}});E.addFinalizer(()=>j(void 0));const G=h.makeUnsafe(),q=b(e=>m.runPromise(h.close(G,e===void 0?g.void:g.fail(e))));E.addFinalizer(()=>q(void 0));const de=h.makeUnsafe(),K=b(e=>m.runPromise(h.close(de,e===void 0?g.void:g.fail(e))));E.addFinalizer(()=>K(void 0));const pe=h.makeUnsafe(),V=b(async e=>{try{await n?.close(e)}finally{await m.runPromise(h.close(pe,e===void 0?g.void:g.fail(e)))}});E.addFinalizer(()=>V(void 0));try{const e={...process.env},d={...U},D=typeof T=="object"?ur(T):fr(T,{parse:pr});u?.throwIfAborted(),i()?.markStart("harness.product");const Te=await P(s.buildWithScope(we.layer({projection:D.projection,baseConfiguration:T===void 0?void 0:{},packageRoot:ie.productRoot??O.dirname(ie.packageJsonPath),clientIdentity:{ideName:y.ideName,ideType:y.ideType,ideVersion:y.ideVersion,...y.userAgent===void 0?{}:{userAgent:y.userAgent}},environment:t(()=>({...e,...d}),"environment")}),ce));a=await(S.createProductManager??((r,o)=>mr.create(r,o)))({bootstrap:D.bootstrap,projection:D.projection,resolver:p.get(Te,we)},u),i()?.markEnd("harness.product");const Fe=t(()=>{if(!a)throw new Error("Product manager is not ready");return a.getLaunchSnapshot()},"productLaunch");u?.throwIfAborted(),i()?.markStart("harness.config");const Re=await P(s.buildWithScope(Z.layer.pipe(s.provide(c.layer([c.withConsoleError(c.formatLogFmt)]))),G));i()?.markEnd("harness.config");const me=p.get(Re,Z);u?.throwIfAborted(),i()?.markStart("harness.settings"),A=await(S.createSettingsRuntime??Cr)({ambientEnvironment:e,config:me,environment:d,observe:t(r=>l.recordEffectLog({annotations:{component:"harness",operation:"refresh",reason:r.reason,resource:"policy","runtime.role":"harness",status:r.status,...r.policy===void 0?{}:{mode:r.policy.mode,noProxyCount:r.policy.noProxyCount,proxyConfigured:r.policy.proxyConfigured,proxySupport:r.policy.proxySupport,revision:r.policy.revision}},level:r.status==="failed"?"warn":"info",message:"harness.settings.proxy"}),"observe"),processRuntime:E}),i()?.markEnd("harness.settings");const le=vr.layer(O.join(e.CODEBUDDY_CONFIG_DIR?.trim()?O.resolve(e.CODEBUDDY_CONFIG_DIR.trim()):O.join(Ye(),".codebuddy"),"harness","sessions"));u?.throwIfAborted(),i()?.markStart("harness.session-runtime");const fe=await P(s.buildWithScope(S.sessionRuntimeLayer??Er({checkpoints:!0,headers:nr(y),resolveOptions:t(r=>m.map(Pr(r),o=>({...o,...te===void 0?{}:{tools:te}})),"resolveOptions")}).pipe(s.provideMerge(Ce.layer({product:{},fs:Ae,settingSources:["user","project","local"],env:{...or(y),CODEBUDDY_API_KEY_DISABLED:"1",CODEBUDDY_REMOTE_CONFIG_DISABLED:"1",CODEBUDDY_INCLUDE_TOPIC_MESSAGE:"true",CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING:e.CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING??"0"}})),s.provide(le),s.provide(Ke.layer.pipe(s.provide(c.layer([c.withConsoleError(c.formatLogFmt)]))))),I));i()?.markEnd("harness.session-runtime"),R=p.get(fe,wr),u?.throwIfAborted(),i()?.markStart("harness.replay");const He=p.get(await P(s.buildWithScope(ke.layer({},r=>Ae.readFileBuffer(r)).pipe(s.provide(le)),I)),ke);i()?.markEnd("harness.replay"),u?.throwIfAborted(),i()?.markStart("harness.storage");const he=await P(s.buildWithScope(s.mergeAll(be.layer,ve.layer).pipe(s.provide(Sr.layer),s.provide(c.layer([c.withConsoleError(c.formatLogFmt)]))),I));i()?.markEnd("harness.storage");const Oe=p.get(he,be),Ue=p.get(he,ve);M=(S.createMcpIntegration??(r=>Xe({containment:r.containment,recordEffectTelemetry:r.recordEffectTelemetry,recordLifecycle:r.recordLifecycle,supervisor:{environment:r.environment,toolsSyncTtlMs:Ie?.toolsSyncTtlMs,proxyPolicy:r.proxyPolicy}})))({containment:_,environment:d,proxyPolicy:_e(A.currentProxyPolicy,d),recordEffectTelemetry:De,recordLifecycle:k}),L=A.subscribe(r=>{const o=_e(r,d);M?.configureProxy?.(o).catch(()=>{l.recordEffectLog({annotations:{component:"harness",operation:"update",resource:"policy","runtime.role":"harness",status:"failed"},level:"warn",message:"harness.settings.proxy"})})});const ge=je.getOrUndefined(p.getOption(fe,Ce));u?.throwIfAborted(),i()?.markStart("harness.mcp-services");const Q=await P(s.buildWithScope(s.mergeAll(Pe.layer({environment:t(()=>({...e,...d}),"environment")}),Se.layer).pipe(s.provideMerge($.layer({environment:t(()=>({...e,...d}),"environment"),product:t(()=>a.getConfiguration(),"product"),writeContext:t(async()=>{await n?.prepareHostExecution(F.signal);const r=t(()=>({environment:{...e,...d},product:structuredClone(a.getConfiguration()),authentication:n?.currentSessionAuthentication()}),"capture");return n?n.runConsistentRead(r):r()},"writeContext"),onConfigChange:ge?async(r,o)=>{const f=o.authentication;ge.notifyConfigChange({source:r.source,filePath:r.file_path,cwd:r.cwd},{product:o.product,environment:o.environment,fetch:t((X,H)=>Ze(X,H,o.environment),"fetch"),auth:f?{accessToken:f.credential.accessToken,method:f.credential.type,refresh:t(async({signal:X})=>{if(!n||!a)throw new Error("Hook authentication is unavailable");const H=t(()=>{if(!Ne(o.product,a.getConfiguration()))throw new Error("Hook Product changed")},"checkProduct");await n.runConsistentRead(H);const Ee=await n.refreshHostAuthentication(f,X);return await n.runConsistentRead(H),{accessToken:Ee.credential.accessToken,method:Ee.credential.type}},"refresh")}:void 0,account:f?{uid:f.account.id,enterpriseId:f.account.organization?.id}:void 0}).catch(()=>m.runSync(m.logWarning("harness.config-change.failed").pipe(m.provide(c.layer([c.withConsoleError(c.formatLogFmt)])))))}:void 0,reloadUserConfig:t(r=>w?.reloadUserConfig(r)??Promise.resolve(),"reloadUserConfig")})),s.provide(c.layer([c.withConsoleError(c.formatLogFmt)]))),de));i()?.markEnd("harness.mcp-services"),u?.throwIfAborted(),i()?.markStart("harness.agent-facade"),w=await(S.createAgentFacade??qe)({userMcp:p.get(Q,Pe),pluginMcp:p.get(Q,Se),checkpoints:Ue,sessions:Oe,initialProductGeneration:Fe().productGeneration,mcpIntegration:M,strictMcpConfig:Le,onPermanentFailure:t(r=>{W(r,"fused","recovery_failed"),F.abort(r)},"onPermanentFailure"),prepareSessionRuntime:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.prepareSessionRuntime(r,o.connectionSignal)},"prepareSessionRuntime"),prepareSessionWorkspace:t(async(r,o)=>{if(!n||!a)throw new Error("Product manager is not ready");try{return await a.prepareWorkspace(r,{signal:o})}catch(f){if(!(f instanceof lr&&f.code==="AUTH_REFRESH_REQUIRED"))throw f;return await n.refreshProductAuthentication(o),a.prepareWorkspace(r,{force:!0,signal:o})}},"prepareSessionWorkspace"),releaseSessionWorkspace:t((r,o)=>a?a.releaseWorkspace(r,o):Promise.resolve(),"releaseSessionWorkspace"),refreshAuthentication:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.refreshAuthentication(r,{signal:o?.signal??AbortSignal.abort(new Error("Authentication refresh has no operation signal"))})},"refreshAuthentication"),serverInfo:ne,sessionRuntime:R,sessionReplay:He}),i()?.markEnd("harness.agent-facade");const ye=ar({facade:w,onExecutionProductCommitted:N,product:a});u?.throwIfAborted(),i()?.markStart("harness.auth-service");const xe=await P(s.buildWithScope(S.managedAuthLayer??Ve({...a.resolveLoginProduct?{resolveLoginProduct:t((r,o)=>a.resolveLoginProduct(r,o),"resolveLoginProduct")}:{},environment:t(()=>({...e,...d}),"environment"),product:t(()=>a.getConfiguration(),"product")}).pipe(s.provide(c.layer([c.withConsoleError(c.formatLogFmt)]))),pe));i()?.markEnd("harness.auth-service"),n=ir({consumer:w,getAuthMethods:t(()=>a.getAuthMethods(),"getAuthMethods"),managedAuth:p.get(xe,Qe),onRuntimePreparing:N,onRuntimePrepared:N,productLifecycle:ye});const v=await Je(n);n.bindProtocolBridge(v.bridge);const J=rr({selectConnectionProductProfile:t((r,o)=>n.selectConnectionProductProfile(r,o),"selectConnectionProductProfile"),provisionProduct:t((r,o)=>v.runAuthMutation(()=>n.provisionProduct(r,o)),"provisionProduct"),readProduct:t((r,o)=>n.readProduct(r,o),"readProduct"),provisionWorkspaceProduct:t((r,o)=>v.runAuthMutation(()=>n.provisionWorkspaceProduct(r,o)),"provisionWorkspaceProduct"),readWorkspaceProduct:t((r,o)=>a.readWorkspaceProduct(r,o),"readWorkspaceProduct")});a.bindPublisher({notifyProductUpdated:t(()=>J.publisher.notifyProductUpdated(ye.currentProductSnapshot()),"notifyProductUpdated"),notifyWorkspaceProductUpdated:t(r=>J.publisher.notifyWorkspaceProductUpdated(r),"notifyWorkspaceProductUpdated")});const ze=p.empty().pipe(p.add(Ar,A),p.add(Z,me),p.add($,p.get(Q,$)));u?.throwIfAborted(),i()?.markStart("harness.rpc-services");const Be=await P(m.provide(yr.pipe(h.provide(G)),ze));i()?.markEnd("harness.rpc-services"),C=er([{name:"private-runtime-lifecycle",capabilities:{},initialize:t(async(r,o)=>{await ee("harness.initialize.settings",()=>A?.initialize(o.connectionSignal))},"initialize"),close:t(async r=>{L?.(),L=void 0,await K(r),await A?.close(r),await re([[()=>Y(r),()=>M?.close(r)??Promise.resolve()],[()=>j(r)]],z,"private runtime shutdown")},"close")},Ge({v2:w}),$e({backend:w}),kr({backend:w}),J,{name:v.name,capabilities:v.capabilities,initialize:t(async(r,o)=>ee("harness.initialize.auth",()=>v.initialize(r,o)),"initialize"),initialized:v.initialized,notificationHandlers:v.notificationHandlers,requestHandlers:v.requestHandlers,close:V},{...Be,close:q}])}catch(e){throw L?.(),L=void 0,k({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"}),await re([[()=>q(e)],[()=>V(e)],[()=>w?.close(e)??Promise.resolve(),()=>Y(e)],[()=>M?.close(e)??Promise.resolve()],[()=>K(e)],[()=>A?.close(e)??Promise.resolve()],[()=>j(e)]],z,"module startup cleanup").catch(()=>{}),e}let ue;try{u?.throwIfAborted(),ue=(S.createServer??(e=>new hr(e)))({serverInfo:ne,capabilities:C.capabilities,initializeHookTimeoutMs:cr+sr+gr,initialize:t(async(e,d)=>(i()?.markEnd("harness.wait-initialize"),ee("harness.initialize",()=>C.initialize(e,d))),"initialize"),initialized:C.initialized,notificationHandlers:C.notificationHandlers,onContainmentFailure:t(e=>{W(e,"containment_tripped","containment_failed"),F.abort(e)},"onContainmentFailure"),readinessSignal:_.signal,requestHandlers:C.requestHandlers,telemetryRuntime:l})}catch(e){k({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"});try{await re([[()=>C.close(e)]],z,"server construction cleanup")}catch(d){k({component:"server",error:d,phase:"cleanup",process:{pid:process.pid},reason:"cleanup_failed",state:"shutdown_failed"})}throw e}return{server:ue,modules:C,telemetry:l,containment:_,runtimeShutdown:F,recordLifecycle:k}}t(createApplicationServices,"createApplicationServices");
1
+ var Ke=Object.defineProperty;var t=(E,H)=>Ke(E,"name",{value:H,configurable:!0});import{homedir as Pe}from"node:os";import*as k from"node:path";import{isDeepStrictEqual as Ve}from"node:util";import{WORKBUDDY_ENABLE_LINUX_SANDBOX_CLI as we}from"@genie/product";import{Context as d,Effect as m,Exit as y,Layer as s,Logger as p,Option as Xe,Scope as h}from"effect";import{createAgentProtocolModule as Qe}from"../agent/router.js";import{createAgentV2Facade as Je}from"../agent/v2.js";import{ManagedAuthLocal as Ze}from"../auth/local.js";import{ManagedAuth as $e}from"../auth/managed.js";import{createAuthProtocolModule as er}from"../auth/module.js";import{Checkpoints as Ae}from"../checkpoint/service.js";import{ConfigFiles as ee}from"../config/files.js";import{createDefaultAgentMcpIntegration as rr}from"../integration/agent-integration.js";import{PluginMcp as _e}from"../integration/plugin-mcp.js";import{UserMcp as be}from"../integration/user-mcp.js";import{requestWithEnvironment as tr}from"../internal/http.js";import{createMcpServerProtocolModule as or}from"../mcp-server/module.js";import{composeAgentHarnessModules as nr}from"../module/compose.js";import{PluginComponents as re}from"../plugin/components.js";import{createProductProtocolModule as ir}from"../product/module.js";import{preflightCodeBuddyCode as ar}from"../runtime/agent-runtime.js";import{buildAgentHarnessClientIdentityEnv as sr,buildAgentHarnessClientIdentityHeaders as cr}from"../runtime/client-identity.js";import{createCodeBuddyAuthRuntime as dr}from"../runtime/codebuddy-auth.js";import{createCodeBuddyProductLifecycle as pr}from"../runtime/codebuddy-product.js";import{DEFAULT_HOST_HEALTH_TIMEOUT_MS as ur,DEFAULT_READY_TIMEOUT_MS as mr}from"../runtime/codebuddy-resource-timeouts.js";import{CodeBuddyProcessContainment as lr}from"../runtime/process-containment.js";import{parseAgentHarnessProductConfig as fr,parseHarnessProductInput as hr}from"../runtime/product-config.js";import{ProductManager as gr}from"../runtime/product-manager.js";import{ProductResolver as ke}from"../runtime/product-resolver.js";import{ProductResolverRequestError as yr}from"../runtime/product-resolver-error.js";import{loadProductSource as Er}from"../runtime/product-source.js";import{HarnessSandboxCenter as Sr}from"../runtime/sandbox-center.js";import{AgentHarnessServer as vr,DEFAULT_LIFECYCLE_HOOK_TIMEOUT_MS as Cr}from"../server/index.js";import{makeServiceRpcs as Pr}from"../server/rpc-services.js";import{AgentBackend as wr,workspaceQueryOptions as Ar}from"../session/agent-backend.js";import{AgentServer as De}from"../session/agent-server.js";import{SessionConfigStore as _r}from"../session/config-store.js";import{SessionFiles as br}from"../session/files.js";import{localFs as Ie}from"../session/local-fs.js";import{SessionReplay as Me}from"../session/replay.js";import{SessionRuntime as kr}from"../session/runtime.js";import{Sessions as Le}from"../session/service.js";import{toExecutorPrivateProxyPolicy as Te}from"../settings/proxy-policy.js";import{createHarnessSettingsRuntime as Dr}from"../settings/runtime.js";import{Settings as Ir}from"../settings/service.js";import{createSubagentProtocolModule as Mr}from"../subagent/module.js";import{createEffectTelemetryMetricAggregator as Lr}from"../telemetry/effect-metric-aggregation.js";import{createTelemetry as Tr}from"../telemetry/runtime.js";import{measureStartup as te,startupProfiler as i}from"../telemetry/startup-profile.js";import{closeInPhases as oe,closeTelemetry as Or,createCloseOnce as _,DEFAULT_TELEMETRY_CLOSE_TIMEOUT_MS as xr}from"./lifecycle.js";export async function createApplicationServices({clientIdentity:E,clientIdentityEnv:H,dependencies:v,packageVersion:Oe,processRuntime:g,productConfig:O,sandboxCenter:xe,tools:ne,strictMcpConfig:Re,mcp:Fe,shutdown:B,telemetryOptions:ie,signal:u}){u?.throwIfAborted();const C=t(e=>m.runPromise(e,{signal:u}),"runStartupEffect"),z=B,ae={name:"@genie/agent-harness",title:"Agent Harness",version:Oe},se=(v.preflightCodeBuddyCode??ar)(),D=new lr,x=new AbortController,l=Tr(ie),W=_(()=>Or(l,g,Math.max(1,Math.min(B.remainingMs(),ie.flushTimeoutMs??xr))));B.registerTelemetryCloser(W);const ce=Lr(e=>l.recordEffectMetrics(e));try{g.addFinalizer(W)}catch(e){throw await W(),e}try{g.setTelemetryObserver({log:t(e=>l.recordEffectLog(e),"log"),metrics:t(e=>ce.record("harness",e),"metrics"),span:t(e=>l.recordEffectSpan(e),"span")})}catch{}const b=t(e=>l.recordLifecycle(e),"recordLifecycle"),R=new Sr(process.env.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(process.env.CODEBUDDY_CONFIG_DIR.trim()):k.join(Pe(),".codebuddy"),xe,process.env.SANDBOX_CENTER_IPC_ADDRESS?.trim()),N=_(()=>R.close());g.addFinalizer(N);let de=!1;const Y=t((e,c,T)=>{de||(de=!0,b({component:"server",error:e,phase:"runtime",process:{pid:process.pid},reason:T,state:c}))},"recordRootFailure");D.signal.addEventListener("abort",()=>{Y(D.signal.reason,"containment_tripped","containment_failed")},{once:!0});const Ue={log(e){try{l.recordEffectLog(e)}catch{}},metrics(e){ce.record("executor",e)},span(e){try{l.recordEffectSpan(e)}catch{}}};let P,n,F,I,a,A,M,w;const L=h.makeUnsafe(),G=_(e=>m.runPromise(h.close(L,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>G(void 0));const j=t(()=>{F&&m.runPromise(m.forkIn(F.prepare,L,{startImmediately:!0})).catch(()=>{})},"prepareRuntime"),pe=h.makeUnsafe(),q=_(async e=>{try{await a?.close(e)}finally{await m.runPromise(h.close(pe,e===void 0?y.void:y.fail(e)))}});g.addFinalizer(()=>q(void 0));const K=h.makeUnsafe(),V=_(e=>m.runPromise(h.close(K,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>V(void 0));const ue=h.makeUnsafe(),X=_(e=>m.runPromise(h.close(ue,e===void 0?y.void:y.fail(e))));g.addFinalizer(()=>X(void 0));const me=h.makeUnsafe(),Q=_(async e=>{try{await n?.close(e)}finally{await m.runPromise(h.close(me,e===void 0?y.void:y.fail(e)))}});g.addFinalizer(()=>Q(void 0));try{const e={...process.env},c={...H,...R.environment},T=typeof O=="object"?hr(O):Er(O,{parse:fr});u?.throwIfAborted(),i()?.markStart("harness.product");const He=await C(s.buildWithScope(ke.layer({projection:T.projection,baseConfiguration:O===void 0?void 0:{},packageRoot:se.productRoot??k.dirname(se.packageJsonPath),clientIdentity:{ideName:E.ideName,ideType:E.ideType,ideVersion:E.ideVersion,...E.userAgent===void 0?{}:{userAgent:E.userAgent}},environment:t(()=>({...e,...c}),"environment")}),pe));a=await(v.createProductManager??((r,o)=>gr.create(r,o)))({bootstrap:T.bootstrap,projection:T.projection,resolver:d.get(He,ke)},u),i()?.markEnd("harness.product");const Be=t(()=>{if(!a)throw new Error("Product manager is not ready");return a.getLaunchSnapshot()},"productLaunch");u?.throwIfAborted(),i()?.markStart("harness.config");const ze=await C(s.buildWithScope(ee.layer.pipe(s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),K));i()?.markEnd("harness.config");const fe=d.get(ze,ee);u?.throwIfAborted(),i()?.markStart("harness.settings"),A=await(v.createSettingsRuntime??Dr)({ambientEnvironment:e,config:fe,environment:c,observe:t(r=>l.recordEffectLog({annotations:{component:"harness",operation:"refresh",reason:r.reason,resource:"policy","runtime.role":"harness",status:r.status,...r.policy===void 0?{}:{mode:r.policy.mode,noProxyCount:r.policy.noProxyCount,proxyConfigured:r.policy.proxyConfigured,proxySupport:r.policy.proxySupport,revision:r.policy.revision}},level:r.status==="failed"?"warn":"info",message:"harness.settings.proxy"}),"observe"),processRuntime:g}),i()?.markEnd("harness.settings");const he=_r.layer(k.join(e.CODEBUDDY_CONFIG_DIR?.trim()?k.resolve(e.CODEBUDDY_CONFIG_DIR.trim()):k.join(Pe(),".codebuddy"),"harness","sessions"));u?.throwIfAborted(),i()?.markStart("harness.session-runtime");const ge=process.platform==="linux"?e[we]??((await import("#agent-harness-components/session-config")).isLinuxSandboxCLIInstalled()?"1":"0"):void 0,ye=await C(s.buildWithScope(v.sessionRuntimeLayer??wr({checkpoints:!0,headers:cr(E),prepareSandboxCenter:t((r,o)=>R.prepare(r.account?.uid,o),"prepareSandboxCenter"),resolveOptions:t(r=>m.map(Ar(r),o=>({...o,...ne===void 0?{}:{tools:ne}})),"resolveOptions")}).pipe(s.provideMerge(De.layer({product:{},fs:Ie,settingSources:["user","project","local"],env:{...sr(E),CODEBUDDY_API_KEY_DISABLED:"1",CODEBUDDY_REMOTE_CONFIG_DISABLED:"1",CODEBUDDY_INCLUDE_TOPIC_MESSAGE:"true",...ge===void 0?{}:{[we]:ge},...R.environment,CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING:e.CODEBUDDY_CODE_DISABLE_FILE_CHECKPOINTING??"0"}})),s.provide(he)),L));i()?.markEnd("harness.session-runtime"),F=d.get(ye,kr),u?.throwIfAborted(),i()?.markStart("harness.replay");const We=d.get(await C(s.buildWithScope(Me.layer({},r=>Ie.readFileBuffer(r)).pipe(s.provide(he)),L)),Me);i()?.markEnd("harness.replay"),u?.throwIfAborted(),i()?.markStart("harness.storage");const Ee=await C(s.buildWithScope(s.mergeAll(Le.layer,Ae.layer).pipe(s.provide(br.layer),s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),L));i()?.markEnd("harness.storage");const Ne=d.get(Ee,Le),Ye=d.get(Ee,Ae);I=(v.createMcpIntegration??(r=>rr({containment:r.containment,recordEffectTelemetry:r.recordEffectTelemetry,recordLifecycle:r.recordLifecycle,supervisor:{environment:r.environment,toolsSyncTtlMs:Fe?.toolsSyncTtlMs,proxyPolicy:r.proxyPolicy}})))({containment:D,environment:c,proxyPolicy:Te(A.currentProxyPolicy,c),recordEffectTelemetry:Ue,recordLifecycle:b}),M=A.subscribe(r=>{const o=Te(r,c);I?.configureProxy?.(o).catch(()=>{l.recordEffectLog({annotations:{component:"harness",operation:"update",resource:"policy","runtime.role":"harness",status:"failed"},level:"warn",message:"harness.settings.proxy"})})});const Se=Xe.getOrUndefined(d.getOption(ye,De));u?.throwIfAborted(),i()?.markStart("harness.mcp-services");const J=await C(s.buildWithScope(s.mergeAll(be.layer({environment:t(()=>({...e,...c}),"environment")}),_e.layer).pipe(s.provideMerge(re.layer({environment:t(()=>({...e,...c}),"environment"),product:t(()=>a.getConfiguration(),"product"),writeContext:t(async()=>{await n?.prepareHostExecution(x.signal);const r=t(()=>({environment:{...e,...c},product:structuredClone(a.getConfiguration()),authentication:n?.currentSessionAuthentication()}),"capture");return n?n.runConsistentRead(r):r()},"writeContext"),onConfigChange:Se?async(r,o)=>{const f=o.authentication;Se.notifyConfigChange({source:r.source,filePath:r.file_path,cwd:r.cwd},{product:o.product,environment:o.environment,fetch:t(($,U)=>tr($,U,o.environment),"fetch"),auth:f?{accessToken:f.credential.accessToken,method:f.credential.type,refresh:t(async({signal:$})=>{if(!n||!a)throw new Error("Hook authentication is unavailable");const U=t(()=>{if(!Ve(o.product,a.getConfiguration()))throw new Error("Hook Product changed")},"checkProduct");await n.runConsistentRead(U);const Ce=await n.refreshHostAuthentication(f,$);return await n.runConsistentRead(U),{accessToken:Ce.credential.accessToken,method:Ce.credential.type}},"refresh")}:void 0,account:f?{uid:f.account.id,enterpriseId:f.account.organization?.id}:void 0}).catch(()=>m.runSync(m.logWarning("harness.config-change.failed").pipe(m.provide(p.layer([p.withConsoleError(p.formatLogFmt)])))))}:void 0,reloadUserConfig:t(r=>P?.reloadUserConfig(r)??Promise.resolve(),"reloadUserConfig")})),s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),ue));i()?.markEnd("harness.mcp-services"),u?.throwIfAborted(),i()?.markStart("harness.agent-facade"),P=await(v.createAgentFacade??Je)({userMcp:d.get(J,be),pluginMcp:d.get(J,_e),checkpoints:Ye,sessions:Ne,initialProductGeneration:Be().productGeneration,mcpIntegration:I,strictMcpConfig:Re,onPermanentFailure:t(r=>{Y(r,"fused","recovery_failed"),x.abort(r)},"onPermanentFailure"),prepareSessionRuntime:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.prepareSessionRuntime(r,o.connectionSignal)},"prepareSessionRuntime"),prepareSessionWorkspace:t(async(r,o)=>{if(!n||!a)throw new Error("Product manager is not ready");try{return await a.prepareWorkspace(r,{signal:o})}catch(f){if(!(f instanceof yr&&f.code==="AUTH_REFRESH_REQUIRED"))throw f;return await n.refreshProductAuthentication(o),a.prepareWorkspace(r,{force:!0,signal:o})}},"prepareSessionWorkspace"),releaseSessionWorkspace:t((r,o)=>a?a.releaseWorkspace(r,o):Promise.resolve(),"releaseSessionWorkspace"),refreshAuthentication:t((r,o)=>{if(!n)throw new Error("Authentication runtime is not ready");return n.refreshAuthentication(r,{signal:o?.signal??AbortSignal.abort(new Error("Authentication refresh has no operation signal"))})},"refreshAuthentication"),serverInfo:ae,sessionRuntime:F,sessionReplay:We}),i()?.markEnd("harness.agent-facade");const ve=pr({facade:P,onExecutionProductCommitted:j,product:a});u?.throwIfAborted(),i()?.markStart("harness.auth-service");const Ge=await C(s.buildWithScope(v.managedAuthLayer??Ze({...a.resolveLoginProduct?{resolveLoginProduct:t((r,o)=>a.resolveLoginProduct(r,o),"resolveLoginProduct")}:{},environment:t(()=>({...e,...c}),"environment"),product:t(()=>a.getConfiguration(),"product")}).pipe(s.provide(p.layer([p.withConsoleError(p.formatLogFmt)]))),me));i()?.markEnd("harness.auth-service"),n=dr({consumer:P,getAuthMethods:t(()=>a.getAuthMethods(),"getAuthMethods"),managedAuth:d.get(Ge,$e),onRuntimePreparing:j,onRuntimePrepared:j,productLifecycle:ve});const S=await er(n);n.bindProtocolBridge(S.bridge);const Z=ir({selectConnectionProductProfile:t((r,o)=>n.selectConnectionProductProfile(r,o),"selectConnectionProductProfile"),provisionProduct:t((r,o)=>S.runAuthMutation(()=>n.provisionProduct(r,o)),"provisionProduct"),readProduct:t((r,o)=>n.readProduct(r,o),"readProduct"),provisionWorkspaceProduct:t((r,o)=>S.runAuthMutation(()=>n.provisionWorkspaceProduct(r,o)),"provisionWorkspaceProduct"),readWorkspaceProduct:t((r,o)=>a.readWorkspaceProduct(r,o),"readWorkspaceProduct")});a.bindPublisher({notifyProductUpdated:t(()=>Z.publisher.notifyProductUpdated(ve.currentProductSnapshot()),"notifyProductUpdated"),notifyWorkspaceProductUpdated:t(r=>Z.publisher.notifyWorkspaceProductUpdated(r),"notifyWorkspaceProductUpdated")});const je=d.empty().pipe(d.add(Ir,A),d.add(ee,fe),d.add(re,d.get(J,re)));u?.throwIfAborted(),i()?.markStart("harness.rpc-services");const qe=await C(m.provide(Pr.pipe(h.provide(K)),je));i()?.markEnd("harness.rpc-services"),w=nr([{name:"private-runtime-lifecycle",capabilities:{},initialize:t(async(r,o)=>{await te("harness.initialize.settings",()=>A?.initialize(o.connectionSignal))},"initialize"),close:t(async r=>{M?.(),M=void 0,await X(r),await A?.close(r),await oe([[()=>G(r),()=>I?.close(r)??Promise.resolve()],[()=>N()],[()=>q(r)]],z,"private runtime shutdown")},"close")},Qe({v2:P}),or({backend:P}),Mr({backend:P}),Z,{name:S.name,capabilities:S.capabilities,initialize:t(async(r,o)=>te("harness.initialize.auth",()=>S.initialize(r,o)),"initialize"),initialized:S.initialized,notificationHandlers:S.notificationHandlers,requestHandlers:S.requestHandlers,close:Q},{...qe,close:V}])}catch(e){throw M?.(),M=void 0,b({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"}),await oe([[()=>V(e)],[()=>Q(e)],[()=>P?.close(e)??Promise.resolve(),()=>G(e)],[()=>I?.close(e)??Promise.resolve()],[()=>X(e)],[()=>A?.close(e)??Promise.resolve()],[()=>N()],[()=>q(e)]],z,"module startup cleanup").catch(()=>{}),e}let le;try{u?.throwIfAborted(),le=(v.createServer??(e=>new vr(e)))({serverInfo:ae,capabilities:w.capabilities,initializeHookTimeoutMs:mr+ur+Cr,initialize:t(async(e,c)=>(i()?.markEnd("harness.wait-initialize"),te("harness.initialize",()=>w.initialize(e,c))),"initialize"),initialized:w.initialized,notificationHandlers:w.notificationHandlers,onContainmentFailure:t(e=>{Y(e,"containment_tripped","containment_failed"),x.abort(e)},"onContainmentFailure"),readinessSignal:D.signal,requestHandlers:w.requestHandlers,telemetryRuntime:l})}catch(e){b({component:"server",error:e,phase:"startup",process:{pid:process.pid},reason:"startup_failed",state:"startup_failed"});try{await oe([[()=>w.close(e)]],z,"server construction cleanup")}catch(c){b({component:"server",error:c,phase:"cleanup",process:{pid:process.pid},reason:"cleanup_failed",state:"shutdown_failed"})}throw e}return{server:le,modules:w,telemetry:l,containment:D,runtimeShutdown:x,recordLifecycle:b}}t(createApplicationServices,"createApplicationServices");
@@ -0,0 +1,2 @@
1
+ export { buildEpochCenterAddress, createSandboxCenterClient, SANDBOX_CENTER_IPC_ADDRESS_ENV, SANDBOX_CENTER_LIFECYCLE_COMMANDS, SANDBOX_CENTER_START_MODE_ENV, SANDBOX_RULES_COMMANDS, spawnSandboxCenter, } from '../../cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.js';
2
+ export { getSandboxCenterPath } from '../../cli/dist-server/types/workspace/sandbox-cli/lib/node/resolver.js';
@@ -0,0 +1 @@
1
+ import e from"#agent-harness-runtime";const n=e["component-sandbox-center"]();export const{buildEpochCenterAddress,createSandboxCenterClient,SANDBOX_CENTER_IPC_ADDRESS_ENV,SANDBOX_CENTER_LIFECYCLE_COMMANDS,SANDBOX_CENTER_START_MODE_ENV,SANDBOX_RULES_COMMANDS,spawnSandboxCenter,getSandboxCenterPath}=n;
@@ -1,6 +1,8 @@
1
1
  import type { QueryOptions } from '#agent-harness-codebuddy/server';
2
2
  import type { AcpV2ClientCapabilities } from '../protocol/acp-v2.js';
3
3
  import type { SessionConfigProjector } from '../session/server-config.js';
4
+ /** Harness opts in to the native Linux sandbox only when its executable is present. */
5
+ export declare function isLinuxSandboxCLIInstalled(): boolean;
4
6
  /** Both backends use the CLI's option vocabulary and ACP v2 projection. */
5
7
  export declare const projectSessionConfig: SessionConfigProjector;
6
8
  export declare function projectSessionContextSize(options: QueryOptions, modelId?: string): number | undefined;
@@ -1 +1 @@
1
- import o from"#agent-harness-runtime";const e=o["component-session-config"]();export const{projectSessionContextSize,createSessionConfigProjector,projectSessionConfig}=e;
1
+ import o from"#agent-harness-runtime";const e=o["component-session-config"]();export const{isLinuxSandboxCLIInstalled,projectSessionContextSize,createSessionConfigProjector,projectSessionConfig}=e;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var t=(e,r)=>a(e,"name",{value:r,configurable:!0});import{isAbsolute as f}from"node:path";const n=Symbol.for("codebuddy.ai/agent-harness/application-owner");export async function createHarness(e={}){if(e.signal?.throwIfAborted(),e.configDir!==void 0&&!f(e.configDir))throw new TypeError("Harness configDir must be an absolute path");const r=globalThis;if(r[n]!==void 0)throw new Error("This process already owns a Harness. Reuse it for additional Clients and Sessions; the Agent runtime cannot be restarted after close.");const i={};r[n]=i;const o=process.env.CODEBUDDY_CONFIG_DIR;e.configDir!==void 0&&(process.env.CODEBUDDY_CONFIG_DIR=e.configDir);try{const s={...e,host:e.host===void 0?void 0:{...e.host},productConfig:typeof e.productConfig=="object"?structuredClone(e.productConfig):e.productConfig},{startHarness:c}=await import("./runtime.js");return await c(s)}catch(s){throw r[n]===i&&delete r[n],e.configDir!==void 0&&process.env.CODEBUDDY_CONFIG_DIR===e.configDir&&(o===void 0?delete process.env.CODEBUDDY_CONFIG_DIR:process.env.CODEBUDDY_CONFIG_DIR=o),s}}t(createHarness,"createHarness");
1
+ var i=Object.defineProperty;var o=(e,r)=>i(e,"name",{value:r,configurable:!0});import{isAbsolute as c}from"node:path";const n=Symbol.for("codebuddy.ai/agent-harness/application-owner");export async function createHarness(e={}){if(e.signal?.throwIfAborted(),e.configDir!==void 0&&!c(e.configDir))throw new TypeError("Harness configDir must be an absolute path");if(typeof e.sandboxCenter=="object"&&!e.sandboxCenter.address?.trim())throw new TypeError("sandboxCenter.address must be a non-empty IPC address");const r=globalThis;if(r[n]!==void 0)throw new Error("This process already owns a Harness. Reuse it for additional Clients and Sessions; the Agent runtime cannot be restarted after close.");const t={};r[n]=t;const a=process.env.CODEBUDDY_CONFIG_DIR;e.configDir!==void 0&&(process.env.CODEBUDDY_CONFIG_DIR=e.configDir);try{const s={...e,host:e.host===void 0?void 0:{...e.host},productConfig:typeof e.productConfig=="object"?structuredClone(e.productConfig):e.productConfig,sandboxCenter:typeof e.sandboxCenter=="object"?{...e.sandboxCenter}:e.sandboxCenter},{startHarness:d}=await import("./runtime.js");return await d(s)}catch(s){throw r[n]===t&&delete r[n],e.configDir!==void 0&&process.env.CODEBUDDY_CONFIG_DIR===e.configDir&&(a===void 0?delete process.env.CODEBUDDY_CONFIG_DIR:process.env.CODEBUDDY_CONFIG_DIR=a),s}}o(createHarness,"createHarness");
@@ -1 +1 @@
1
- var S=Object.defineProperty;var i=(e,s)=>S(e,"name",{value:s,configurable:!0});import{readFileSync as C}from"node:fs";import{closeHarnessProcessRuntime as P,closeInPhases as v,closeWithLifecycleTelemetry as M,resolveShutdownCoordinator as R,runUntilClosed as L}from"../application/lifecycle.js";import{createApplicationServices as k}from"../application/services.js";import{createHarnessProcessRuntime as T}from"../effect-runtime/process-runtime.mjs";import{buildAgentHarnessClientIdentityEnv as x,resolveAgentHarnessClientIdentity as N}from"../runtime/client-identity.js";import{startupProfiler as O}from"../telemetry/startup-profile.js";export async function startHarness(e,s={}){e.signal?.throwIfAborted();const l=e.mcp?.toolsSyncTtlMs;if(l!=null&&(!Number.isSafeInteger(l)||l<=0))throw new RangeError("mcp.toolsSyncTtlMs must be a positive integer or null");const g=s.packageVersion??JSON.parse(C(new URL("../../package.json",import.meta.url),"utf8")).version,p=N(e.host??{},g),a=R(s),m=await(s.createProcessRuntime??T)(),w=Promise.withResolvers(),n=new AbortController,d=new Error("Agent Harness is shutting down"),u=i(()=>n.abort(e.signal?.reason??d),"cancel");e.signal?.addEventListener("abort",u,{once:!0}),e.signal?.aborted&&u();const I=Promise.resolve().then(()=>m.run(async t=>{n.signal.throwIfAborted();const{server:r,modules:o,telemetry:E,containment:A,runtimeShutdown:H,recordLifecycle:h}=await k({signal:AbortSignal.any([n.signal,t]),clientIdentity:p,clientIdentityEnv:x(p),dependencies:s,packageVersion:g,processRuntime:m,productConfig:e.productConfig,tools:e.tools,strictMcpConfig:e.strictMcpConfig??!1,mcp:e.mcp,shutdown:a,telemetryOptions:e.telemetry??{}});if(!("connectInMemory"in r)||typeof r.connectInMemory!="function")throw await v([[()=>r.close(),()=>o.close()]],a),new TypeError("Application Server does not implement the in-memory endpoint");O()?.markEvent("harness-services-ready"),h({component:"server",phase:"startup",process:{pid:process.pid},reason:"startup_completed",state:"started"}),w.resolve(r),await L(new Promise(()=>{}),b=>M(E,()=>v([[()=>r.close(b),()=>o.close(b)]],a,"in-memory shutdown")),void 0,n.signal,[A.signal,H.signal,t],{timeouts:a}),h({component:"server",phase:"shutdown",process:{pid:process.pid},reason:"shutdown_completed",state:"stopped"})})),c=(async()=>{let t,r=!1;try{await I}catch(o){t=o,r=!0}n.abort(d),a.start();try{await P(m,a)}catch(o){throw r?new AggregateError([t,o],"Harness execution and cleanup failed"):o}finally{e.signal?.removeEventListener("abort",u)}if(r)throw t})();c.catch(()=>{});const f=await Promise.race([w.promise,c.then(()=>{throw new Error("Harness closed before startup completed")})]);e.signal?.aborted&&(await c,e.signal.throwIfAborted());const y=i(()=>(n.abort(d),c),"close");return{get ready(){return!n.signal.aborted&&f.ready},closed:c,connect:i((t,r)=>{if(n.signal.aborted)throw new Error("Harness is closing");return f.connect(t,r)},"connect"),connectInMemory:i(t=>{if(n.signal.aborted)throw new Error("Harness is closing");return f.connectInMemory(t)},"connectInMemory"),close:y,[Symbol.asyncDispose]:y}}i(startHarness,"startHarness");
1
+ var H=Object.defineProperty;var i=(e,s)=>H(e,"name",{value:s,configurable:!0});import{readFileSync as S}from"node:fs";import{closeHarnessProcessRuntime as P,closeInPhases as v,closeWithLifecycleTelemetry as M,resolveShutdownCoordinator as R,runUntilClosed as L}from"../application/lifecycle.js";import{createApplicationServices as k}from"../application/services.js";import{createHarnessProcessRuntime as x}from"../effect-runtime/process-runtime.mjs";import{buildAgentHarnessClientIdentityEnv as T,resolveAgentHarnessClientIdentity as N}from"../runtime/client-identity.js";import{startupProfiler as O}from"../telemetry/startup-profile.js";export async function startHarness(e,s={}){e.signal?.throwIfAborted();const l=e.mcp?.toolsSyncTtlMs;if(l!=null&&(!Number.isSafeInteger(l)||l<=0))throw new RangeError("mcp.toolsSyncTtlMs must be a positive integer or null");const g=s.packageVersion??JSON.parse(S(new URL("../../package.json",import.meta.url),"utf8")).version,p=N(e.host??{},g),a=R(s),m=await(s.createProcessRuntime??x)(),w=Promise.withResolvers(),n=new AbortController,d=new Error("Agent Harness is shutting down"),u=i(()=>n.abort(e.signal?.reason??d),"cancel");e.signal?.addEventListener("abort",u,{once:!0}),e.signal?.aborted&&u();const I=Promise.resolve().then(()=>m.run(async t=>{n.signal.throwIfAborted();const{server:r,modules:o,telemetry:E,containment:A,runtimeShutdown:C,recordLifecycle:h}=await k({signal:AbortSignal.any([n.signal,t]),clientIdentity:p,clientIdentityEnv:T(p),dependencies:s,packageVersion:g,processRuntime:m,productConfig:e.productConfig,sandboxCenter:e.sandboxCenter,tools:e.tools,strictMcpConfig:e.strictMcpConfig??!1,mcp:e.mcp,shutdown:a,telemetryOptions:e.telemetry??{}});if(!("connectInMemory"in r)||typeof r.connectInMemory!="function")throw await v([[()=>r.close(),()=>o.close()]],a),new TypeError("Application Server does not implement the in-memory endpoint");O()?.markEvent("harness-services-ready"),h({component:"server",phase:"startup",process:{pid:process.pid},reason:"startup_completed",state:"started"}),w.resolve(r),await L(new Promise(()=>{}),b=>M(E,()=>v([[()=>r.close(b),()=>o.close(b)]],a,"in-memory shutdown")),void 0,n.signal,[A.signal,C.signal,t],{timeouts:a}),h({component:"server",phase:"shutdown",process:{pid:process.pid},reason:"shutdown_completed",state:"stopped"})})),c=(async()=>{let t,r=!1;try{await I}catch(o){t=o,r=!0}n.abort(d),a.start();try{await P(m,a)}catch(o){throw r?new AggregateError([t,o],"Harness execution and cleanup failed"):o}finally{e.signal?.removeEventListener("abort",u)}if(r)throw t})();c.catch(()=>{});const f=await Promise.race([w.promise,c.then(()=>{throw new Error("Harness closed before startup completed")})]);e.signal?.aborted&&(await c,e.signal.throwIfAborted());const y=i(()=>(n.abort(d),c),"close");return{get ready(){return!n.signal.aborted&&f.ready},closed:c,connect:i((t,r)=>{if(n.signal.aborted)throw new Error("Harness is closing");return f.connect(t,r)},"connect"),connectInMemory:i(t=>{if(n.signal.aborted)throw new Error("Harness is closing");return f.connectInMemory(t)},"connectInMemory"),close:y,[Symbol.asyncDispose]:y}}i(startHarness,"startHarness");
@@ -1,6 +1,7 @@
1
1
  import type { QueryOptions, SdkMcpToolDefinition } from '#agent-harness-codebuddy/server';
2
2
  import type { AgentHarnessClientIdentity } from '../runtime/client-identity.js';
3
3
  import type { AgentHarnessProductInput } from '../runtime/product-config.js';
4
+ import type { SandboxCenterOption } from '../runtime/sandbox-center.js';
4
5
  import type { TelemetryOptions } from '../telemetry/public.js';
5
6
  import type { InMemoryEndpoint } from '../transport/effect.js';
6
7
  import type { AgentHarnessConnectionAcceptor } from '../transport/types.js';
@@ -14,6 +15,8 @@ export interface HarnessOptions {
14
15
  readonly productConfig?: ProductConfig | string;
15
16
  /** Application-wide directory; defaults to CODEBUDDY_CONFIG_DIR or ~/.codebuddy. */
16
17
  readonly configDir?: string;
18
+ /** Managed by Harness by default; pass an IPC address to borrow a Host-owned center. */
19
+ readonly sandboxCenter?: SandboxCenterOption;
17
20
  readonly tools?: HarnessTools;
18
21
  readonly strictMcpConfig?: boolean;
19
22
  readonly mcp?: {
@@ -1 +1 @@
1
- var O=Object.defineProperty;var u=(o,e)=>O(o,"name",{value:e,configurable:!0});import{fork as k,spawn as P}from"node:child_process";import{randomUUID as x}from"node:crypto";import v from"node:path";import{EXECUTOR_PRIVATE_MAX_MESSAGE_BYTES as S,EXECUTOR_PRIVATE_MAX_TELEMETRY_MESSAGE_BYTES as q,EXECUTOR_PRIVATE_PROTOCOL_VERSION as T,isExecutorPrivateCatalogNotification as I,isExecutorPrivateResponse as B,isExecutorPrivateResult as D,isExecutorPrivateReverseRequest as N,isExecutorPrivateTelemetryNotification as V,isExecutorPrivateTelemetryNotificationCandidate as U}from"#agent-harness-executor/private-protocol";import{currentHarnessTraceCarrier as H,parseHarnessTraceCarrier as j,withHarnessTraceContext as C}from"#agent-harness-executor/trace-context";import{DEFAULT_MCP_TOOLS_SYNC_TTL_MS as z}from"#agent-harness-executor/types";import{maybeCurrentHarnessProcessRuntime as W}from"../effect-runtime/process-runtime-context.js";import{normalizeError as g}from"../internal/errors.js";import{boundedStringifyJson as E}from"../protocol/bounded-json.js";import{applyNodeRuntimeEnvironment as G,resolveNodeRuntimeLaunch as M}from"../runtime/node-runtime.js";import{AGENT_HARNESS_PRIVATE_RUNTIME_ROLE as _,createPrivateRuntimeLaunchSpec as A,isAgentHarnessStandaloneBinary as X}from"../runtime/private-runtime-role.js";import{CodeBuddyProcessContainment as $}from"../runtime/process-containment.js";import{isMissingProcess as J}from"../runtime/process-tree.js";import{assertAgentHarnessProcessContainment as Y}from"../runtime/sfe-process-containment.js";import{measure as w}from"../telemetry/index.js";import{attachPosixStdioMcpGuardian as K,resolveStdioMcpContainment as Q}from"./stdio-guardian.js";const Z=3e4,ee=15e3,te=5e3,ie=3e3,se=1e3,re=1e4,ne=3e3,oe=1024,ae=8*1024*1024,he=5,ce=6e4,le=100,b=5e3,F=16;export class ExecutorPrivateProcessExitedError extends Error{static{u(this,"ExecutorPrivateProcessExitedError")}constructor(){super("Private Executor child exited unexpectedly"),this.name="ExecutorPrivateProcessExitedError"}}export class ExecutorPrivateProtocolError extends Error{static{u(this,"ExecutorPrivateProtocolError")}constructor(e){super(e),this.name="ExecutorPrivateProtocolError"}}export class ExecutorPrivateOverloadedError extends Error{static{u(this,"ExecutorPrivateOverloadedError")}constructor(){super("Private Executor IPC queue is overloaded"),this.name="ExecutorPrivateOverloadedError"}}class ue extends Error{static{u(this,"ExecutorPrivateOperationError")}constructor(e,t,i){super(i),this.code=e,this.retryable=t,this.name=e}}export class ExecutorPrivateStartupCleanupError extends AggregateError{static{u(this,"ExecutorPrivateStartupCleanupError")}constructor(e,t){super([e,t],"Private Executor startup and cleanup both failed"),this.startupFailure=e,this.cleanupFailure=t,this.name="ExecutorPrivateStartupCleanupError"}}export class ExecutorPrivateShutdownTimeoutError extends Error{static{u(this,"ExecutorPrivateShutdownTimeoutError")}constructor(e){super(`Private Executor cleanup timed out after ${e}ms`),this.timeoutMs=e,this._tag="ExecutorPrivateShutdownTimeoutError",this.name=this._tag}}function de(){return X()?process.execPath:v.resolve(import.meta.dirname,"../../executor/lib/capsule/entry.mjs")}u(de,"defaultChildEntryPath");const fe=Object.freeze(["ALL_PROXY","HTTP_PROXY","HTTPS_PROXY","LANG","LC_ALL","NODE_EXTRA_CA_CERTS","NODE_NO_WARNINGS","NO_PROXY","PATH","SSL_CERT_DIR","SSL_CERT_FILE","SystemRoot","TEMP","TMP","TMPDIR","TZ","WINDIR","http_proxy","https_proxy","all_proxy","no_proxy"]);function pe(o){const e=u(n=>{const a=n?.trim();if(a)try{const h=new URL(a.includes("://")?a:`http://${a}`);return h.protocol==="http:"||h.protocol==="https:"?h.toString():void 0}catch{return}},"normalize"),t=e(o.ALL_PROXY??o.all_proxy),i=e(o.HTTP_PROXY??o.http_proxy??t),s=e(o.HTTPS_PROXY??o.https_proxy??t??i),r=[...new Set([...(o.NO_PROXY??o.no_proxy??"").split(",").map(n=>n.trim()).filter(Boolean),"localhost","127.0.0.1","::1"])];return Object.freeze({...i===void 0?{}:{httpProxyUrl:i},...s===void 0?{}:{httpsProxyUrl:s},mode:"auto",noProxy:Object.freeze(r),revision:"environment"})}u(pe,"defaultExecutorProxyPolicy");export function createExecutorChildEnvironment(o=process.env,e=M()){const t={AGENT_HARNESS_PRIVATE_EXECUTOR:"1"};for(const i of fe){const s=o[i];s!==void 0&&(t[i]=s)}return G(t,e)}u(createExecutorChildEnvironment,"createExecutorChildEnvironment");export function createExecutorWindowsSpawnSpec(o,e){const{execArgv:t=process.execArgv,execPath:i=process.execPath,silent:s,...r}=e,a=A({entryPath:o,nodeRuntime:{environment:{},executable:i},role:_.executor}),h=a.args[0]===o;return{...{args:Object.freeze([...h?t:[],...a.args]),command:a.command},options:{...r,env:{...r.env},windowsHide:!0}}}u(createExecutorWindowsSpawnSpec,"createExecutorWindowsSpawnSpec");function me(o,e){Y();const t=createExecutorWindowsSpawnSpec(o,e);return P(t.command,[...t.args],t.options)}u(me,"spawnExecutorChildOnWindows");function ge(o,e,t,i){if(t==="win32")return me(o,e);const s=A({entryPath:o,nodeRuntime:i,role:_.executor});if(s.args[0]===o)return k(o,[],e);const{execArgv:r,execPath:n,silent:a,...h}=e;return P(s.command,[...s.args],h)}u(ge,"spawnExecutorChild");function we(o){const e=u((a,h,l)=>{const d=a??h;if(!Number.isSafeInteger(d)||d<=0)throw new RangeError(`${l} must be a positive integer`);return d},"positive"),t=u((a,h,l)=>{const d=a??h;if(!Number.isSafeInteger(d)||d<0)throw new RangeError(`${l} must be a non-negative integer`);return d},"nonNegative"),i=o.platform??process.platform,s=Q({platform:i,requested:o.allowStdio??!0,windowsProcessContainmentEnabled:o.windowsProcessContainmentEnabled,windowsJob:o.windowsJob}),r=o.nodeRuntime??M(),n=createExecutorChildEnvironment(o.environment,r);return{allowStdio:s.allowStdio,childEntryPath:o.childEntryPath??de(),closeTimeoutMs:e(o.closeTimeoutMs,te,"closeTimeoutMs"),containment:o.containment??new $,crashWindowMs:e(o.crashWindowMs,ce,"crashWindowMs"),environment:n,healthIntervalMs:t(o.healthIntervalMs,re,"healthIntervalMs"),healthTimeoutMs:e(o.healthTimeoutMs,ne,"healthTimeoutMs"),instanceId:o.instanceId??x(),maxCrashes:e(o.maxCrashes,he,"maxCrashes"),maxPendingRequestBytes:e(o.maxPendingRequestBytes,ae,"maxPendingRequestBytes"),maxPendingRequests:e(o.maxPendingRequests,oe,"maxPendingRequests"),nodeRuntime:r,toolsSyncTtlMs:o.toolsSyncTtlMs===null?null:e(o.toolsSyncTtlMs,z,"toolsSyncTtlMs"),onElicitation:o.onElicitation,...o.onFailure===void 0?{}:{onFailure:o.onFailure},platform:i,proxyPolicy:o.proxyPolicy??pe(n),...o.recordLifecycle===void 0?{}:{recordLifecycle:o.recordLifecycle},...o.recordEffectTelemetry===void 0?{}:{recordEffectTelemetry:o.recordEffectTelemetry},requestTimeoutMs:e(o.requestTimeoutMs,Z,"requestTimeoutMs"),restartBackoffMs:e(o.restartBackoffMs,le,"restartBackoffMs"),spawnChild:o.spawnChild??((a,h)=>ge(a,h,i,r)),startTimeoutMs:e(o.startTimeoutMs,ee,"startTimeoutMs"),...o.stdioGuardianEntryPath===void 0?{}:{stdioGuardianEntryPath:o.stdioGuardianEntryPath},stdioContainment:s.mode,...s.mode==="windows_native_job_object"?{windowsJob:s.windowsJob}:{},termTimeoutMs:e(o.termTimeoutMs,ie,"termTimeoutMs")}}u(we,"resolveOptions");function L(o,e){return e?.aborted?Promise.reject(e.reason):new Promise((t,i)=>{let s=!1;const r=u(h=>{s||(s=!0,clearTimeout(a),e?.removeEventListener("abort",n),h===void 0?t():i(h))},"finish"),n=u(()=>r(e?.reason),"onAbort"),a=setTimeout(()=>r(),o);a.unref?.(),e?.addEventListener("abort",n,{once:!0})})}u(L,"standaloneDelay");function R(o,e,t){const i=new AbortController,s=setTimeout(()=>i.abort(t),o);s.unref?.();const r=AbortSignal.any([...e,i.signal]),n=[];let a=!1;const h=u(()=>{if(!a){a=!0,clearTimeout(s);for(const[l,d]of n)l.removeEventListener("abort",d);n.length=0}},"close");for(const l of e)n.push([l,h]),l.addEventListener("abort",h,{once:!0});return Object.freeze({close:h,signal:r})}u(R,"standaloneDeadline");export class ExecutorProcessSupervisor{static{u(this,"ExecutorProcessSupervisor")}registerClientSource(e,t){if(this.assertAccepting(),this.clientSources.has(e))throw new Error("Duplicate Client MCP source");const i=t.subscribe(()=>{for(const s of this.registrations.values())s.transport.transport==="client"&&s.transport.sourceId===e&&this.invalidateCatalog(s.registrationId)});return this.clientSources.set(e,{source:t,release:i}),()=>{if(this.clientSources.get(e)?.source===t){this.clientSources.delete(e),i();for(const r of this.clientRequests.values())r.sourceId===e&&r.controller.abort(new Error("Client MCP source closed"))}}}invalidateCatalog(e){if(this.isStopping()||!this.registrations.has(e))return;const t=this.catalogRefreshes.get(e);if(t){t.dirty=!0;return}const i={dirty:!0,promise:Promise.resolve()};i.promise=Promise.resolve().then(async()=>{do{if(i.dirty=!1,this.isStopping()||!this.registrations.has(e))return;await this.refreshRegistration(e)}while(i.dirty)}).catch(()=>{}).finally(()=>{this.catalogRefreshes.delete(e),this.scheduleCatalogRefresh(e)}),this.catalogRefreshes.set(e,i)}scheduleCatalogRefresh(e){if(clearTimeout(this.catalogTimers.get(e)),this.catalogTimers.delete(e),this.isStopping()||!this.registrations.has(e)||this.options.toolsSyncTtlMs===null)return;const t=setTimeout(()=>{this.catalogTimers.delete(e),this.invalidateCatalog(e)},Math.min(this.options.toolsSyncTtlMs,2147483647));t.unref(),this.catalogTimers.set(e,t)}constructor(e){if(this.crashTimes=[],this.failureTasks=new Set,this.fuseOpenAttempt=0,this.fuseState="closed",this.nextRequestId=1,this.nextRegistrationRevision=1,this.pending=new Map,this.pendingSendBytes=0,this.pendingSends=0,this.proxyTask=Promise.resolve(),this.registrationRevisions=new Map,this.registrationTasks=new Map,this.restartAttempt=0,this.shutdownController=new AbortController,this.registrations=new Map,this.snapshots=new Map,this.clientSources=new Map,this.clientRequests=new Map,this.catalogTimers=new Map,this.catalogRefreshes=new Map,this.snapshotListeners=new Set,this.stateValue="idle",this.options=we(e),this.proxyPolicy=this.options.proxyPolicy,this.processRuntime=e.processRuntime??W(),this.processRuntime===void 0&&process.env.NODE_ENV!=="test")throw new Error("Executor supervisor requires the process-owned Effect runtime");this.releaseProcessOwnership=this.processRuntime?.addFinalizer(()=>this.close(new Error("Agent Harness process runtime is closing")));const t=this.processRuntime?.shutdownSignal;if(t){const i=u(()=>{this.close(t.reason).catch(()=>{})},"onProcessShutdown");t.addEventListener("abort",i,{once:!0}),this.releaseProcessShutdownListener=()=>t.removeEventListener("abort",i)}}get runtimeEpoch(){return this.active?.epoch}get state(){return this.stateValue}async start(){await this.ensureReady()}async configureProxy(e){this.assertAccepting(),this.proxyPolicy=e;const t=this.proxyTask.then(()=>this.reconcileProxyPolicy());this.proxyTask=t.catch(()=>{}),await t}subscribeSnapshots(e){return this.snapshotListeners.add(e),()=>this.snapshotListeners.delete(e)}async upsertRegistration(e,t){this.assertAccepting();const i=this.nextRegistrationRevision++;this.registrations.set(e.registrationId,e),this.registrationRevisions.set(e.registrationId,i);try{return await this.ensureReady(),await this.withRegistrationLock(e.registrationId,async()=>{if(this.assertCurrentRegistration(e.registrationId,i),t?.signal?.aborted)throw t.signal.reason;const s=this.active,r=this.snapshots.get(e.registrationId);if(this.stateValue==="ready"&&s?.initialized===!0&&s.child.connected&&s.child.exitCode===null&&s.child.signalCode===null&&s.appliedRegistrationRevisions.get(e.registrationId)===i&&r?.status==="available"&&r?.registrationId===e.registrationId&&r?.runtimeEpoch===s.epoch)return r;const n=await w("registrationReconcile",()=>this.request("registration/upsert",{registration:e},t));return this.assertCurrentRegistration(e.registrationId,i),this.setSnapshot(e.registrationId,n),n})}catch(s){throw this.isCurrentRegistration(e.registrationId,i)&&this.deleteSnapshot(e.registrationId),s}}async refreshRegistration(e,t){this.requireRegistration(e);const i=this.requireRegistrationRevision(e);return await this.ensureReady(),this.withRegistrationLock(e,async()=>{this.assertCurrentRegistration(e,i);const s=await this.request("registration/refresh",{registrationId:e},t);return this.assertCurrentRegistration(e,i),this.setSnapshot(e,s),s})}getSnapshot(e){return this.snapshots.get(e)}async removeRegistration(e,t){const i=this.nextRegistrationRevision++;this.registrations.delete(e),this.registrationRevisions.set(e,i),this.deleteSnapshot(e),this.registrations.size===0&&this.cancelFuseRecovery(new Error("Executor fuse recovery is no longer needed")),!(this.stateValue==="closed"||this.stateValue==="closing")&&(await this.withRegistrationLock(e,async()=>{if(!this.isCurrentRegistrationRevision(e,i)||this.isStopping())return;const s=this.active;if(s?.initialized)try{await this.requestOnActive(s,"registration/remove",{registrationId:e},t),s.appliedRegistrationRevisions.delete(e)}catch(r){if(this.active===s&&!this.isStopping())throw this.handleChildFailure(s,r),r}}),this.isCurrentRegistrationRevision(e,i)&&(this.deleteSnapshot(e),this.registrationRevisions.delete(e)))}async callTool(e,t,i,s,r={}){this.requireRegistration(e);const n=this.requireRegistrationRevision(e);await this.ensureReady(),this.assertCurrentRegistration(e,n);let a=!1;const h=u(()=>{a||(a=!0,this.request("tool/cancel",{invocationId:t},{timeoutMs:Math.min(r.timeoutMs??this.options.requestTimeoutMs,2e3)}).catch(()=>{}))},"cancelInvocation");let l;r.signal&&(l=h,r.signal.addEventListener("abort",l,{once:!0}));try{return await this.request("tool/call",{args:s,executorAddress:i,invocationId:t,registrationId:e},r)}catch(d){throw h(),d}finally{l&&r.signal?.removeEventListener("abort",l)}}async close(e){return this.closePromise??=this.closeInternal(e),this.closePromise}async closeInternal(e){for(const c of this.catalogTimers.values())clearTimeout(c);this.catalogTimers.clear();for(const c of this.clientRequests.values())c.controller.abort(e);for(const c of this.clientSources.values())c.release();if(this.clientSources.clear(),this.stateValue==="closed")return;const t=e??new Error("Executor supervisor is closing"),i=this.createShutdownBudget(this.options.closeTimeoutMs,this.processRuntime?.shutdownDeadlineAt),{timeoutError:s}=i;this.shutdownBudget=i,this.stateValue="closing",this.cancelFuseRecovery(t),this.shutdownController.abort(t);const r=[],n=[],a=u((c,p=r)=>{c===s&&(r.includes(s)||n.includes(s))||p.push(c)},"addFailure"),h=u(async(c,p=r)=>{const y=await this.settleWithinShutdown(c,i);y.status==="rejected"?a(y.reason,p):y.status==="timed_out"&&a(s,p)},"attempt");this.clearHealthTimer();const l=this.active,d=this.startPromise;if(this.rejectPending(t),l&&!d&&l.initialized){const c=this.gracefulCloseBudgetMs(i,l.guardian!==void 0);c>0&&await h(this.requestOnActive(l,"runtime/close",{},{signal:i.deadline.signal,timeoutMs:c}))}if(l)try{await this.terminateChild(l,i)}catch(c){a(c,n)}if(d){const c=await this.settleWithinShutdown(d,i);c.status==="rejected"?c.reason instanceof ExecutorPrivateStartupCleanupError&&r.push(...this.flattenCleanupFailure(c.reason.cleanupFailure)):c.status==="timed_out"&&a(s)}const f=await this.settleWithinShutdown(Promise.allSettled([...this.failureTasks,...this.registrationTasks.values(),...[...this.catalogRefreshes.values()].map(c=>c.promise)]),i);if(f.status==="fulfilled")for(const c of f.value)c.status==="rejected"&&r.push(c.reason);else f.status==="rejected"?r.push(f.reason):a(s);r.push(...n);const m=this.active;if(m&&(m!==l||m.child.exitCode===null&&m.child.signalCode===null))try{await this.terminateChild(m,i)}catch(c){a(c)}i.deadline.signal.aborted&&a(s),this.active=void 0,this.recoveryPromise=void 0,this.startPromise=void 0,this.registrations.clear(),this.registrationRevisions.clear(),this.registrationTasks.clear();for(const c of this.snapshots.keys())this.deleteSnapshot(c);if(this.snapshotListeners.clear(),this.stateValue="closed",this.releaseProcessShutdownListener?.(),this.releaseProcessOwnership?.(),i.deadline.close(),r.length>0){const c=r.length===1?r[0]:new AggregateError(r,"Private Executor cleanup failed"),p=m??l;throw this.recordLifecycle({component:"executor",error:c,phase:"cleanup",...p===void 0?{}:{process:{exitCode:p.child.exitCode,pid:p.child.pid,signal:p.child.signalCode}},reason:"cleanup_failed",state:"shutdown_failed"}),c}}async ensureReady(){for(;;){if(this.assertAccepting(),this.stateValue==="ready"&&this.active)return;if(this.fuseState!=="closed")throw new Error(`Executor supervisor fuse is ${this.fuseState}; recovery is pending`);const e=this.recoveryPromise;if(!e)break;await e}await this.startWithoutRecoveryWait()}async startWithoutRecoveryWait(e){this.assertAccepting();const t=[this.shutdownController.signal];this.processRuntime?.shutdownSignal&&t.push(this.processRuntime.shutdownSignal),e&&t.push(e);const i=t.length===1?t[0]:AbortSignal.any(t);if(i.aborted)throw i.reason;if(this.stateValue==="ready"&&this.active)return;const s=this.startPromise??this.startChild(i);this.startPromise=s;try{await s}finally{this.startPromise===s&&(this.startPromise=void 0)}}async startChild(e){if(this.options.containment.assertHealthy(),e?.aborted||(this.stateValue=this.stateValue==="idle"?"starting":"restarting",this.restartAttempt>0&&await this.waitForRestartBackoff(this.restartAttempt,e),this.assertAccepting(),e?.aborted))throw e.reason;const t=x(),i=this.options.spawnChild(this.options.childEntryPath,{cwd:v.dirname(this.options.childEntryPath),detached:this.options.platform!=="win32",env:this.options.environment,execArgv:[],execPath:this.options.nodeRuntime.executable,serialization:"json",stdio:["ignore","ignore","pipe","ipc"]});if(!i.pid||!i.send)throw i.kill(),new Error("Private Executor child did not expose PID and IPC");const s=i.pid;i.stderr?.resume();const r={appliedRegistrationRevisions:new Map,child:i,epoch:t,exit:i.exitCode!==null||i.signalCode!==null?Promise.resolve():new Promise(n=>{i.once("exit",()=>n())}),initialized:!1};this.active=r,i.on("message",n=>this.handleMessage(r,n)),i.once("error",n=>this.handleChildFailure(r,n)),i.once("exit",()=>this.handleChildFailure(r,new ExecutorPrivateProcessExitedError));try{if(this.options.windowsJob&&!this.options.windowsJob.isProcessInJob(s))throw new Error("Private Executor did not inherit the host Windows Job");this.options.stdioContainment==="posix_guardian"&&await w("guardianBind",async()=>{const h=await K({...this.options.stdioGuardianEntryPath===void 0?{}:{childEntryPath:this.options.stdioGuardianEntryPath},containment:this.options.containment,...e===void 0?{}:{signal:e},shutdownDeadlineAt:u(()=>this.processRuntime?.shutdownDeadlineAt,"shutdownDeadlineAt"),targetProcessGroupId:s,termTimeoutMs:this.options.termTimeoutMs});if(r.guardian=h,e?.aborted||this.isStopping())throw e?.reason??new Error("Executor supervisor is closing");await h.bindAnchor(s),r.guardianBound=!0});const n=this.proxyPolicy,a=await w("executorInitialize",()=>this.requestOnActive(r,"runtime/initialize",{allowStdio:this.options.allowStdio,proxy:n,protocolVersion:T,runtimeEpoch:t,stdioContainment:this.options.stdioContainment,...this.options.windowsJob===void 0?{}:{windowsJobAddonPath:this.options.windowsJob.addonPath},...!this.options.allowStdio||r.guardian===void 0?{}:{stdioGuardianPid:r.guardian.guardianPid},tenantId:this.options.instanceId},{...e===void 0?{}:{signal:e},timeoutMs:this.options.startTimeoutMs}));if(a.protocolVersion!==T||a.runtimeEpoch!==t||a.proxyRevision!==n.revision||(this.options.stdioContainment==="posix_guardian"?a.stdioAnchorPid===void 0||a.stdioAnchorPid<=0:a.stdioAnchorPid!==void 0))throw new ExecutorPrivateProtocolError("Private Executor initialize response did not match its epoch");r.anchorPid=a.stdioAnchorPid,r.appliedProxyRevision=a.proxyRevision,await this.reconcileProxyPolicyOnActive(r,e),r.initialized=!0,await w("registrationReconcile",()=>this.reconcileRegistrationsAndCommitReady(r,e))}catch(n){let a=!1,h;try{await this.terminateChild(r)}catch(l){a=!0,h=l}throw this.active===r&&(this.active=void 0),!this.isStopping()&&this.fuseState==="closed"&&(this.stateValue="idle"),a?(this.recordLifecycle({component:"executor",error:h,phase:"cleanup",process:{exitCode:r.child.exitCode,pid:r.child.pid,signal:r.child.signalCode},reason:"cleanup_failed",state:"shutdown_failed"}),new ExecutorPrivateStartupCleanupError(n,h)):n}}async reconcileProxyPolicy(){const e=this.active;e?.initialized!==!0||this.isStopping()||await this.reconcileProxyPolicyOnActive(e)}async reconcileProxyPolicyOnActive(e,t){for(let i=0;i<F;i+=1){if(this.active!==e||this.isStopping())return;const s=this.proxyPolicy;if(e.appliedProxyRevision===s.revision)return;const r=await this.requestOnActive(e,"runtime/proxy-configure",{proxy:s},{...t===void 0?{}:{signal:t},timeoutMs:this.options.requestTimeoutMs});if(r.proxyRevision!==s.revision)throw new ExecutorPrivateProtocolError("Private Executor proxy revision did not match its request");e.appliedProxyRevision=r.proxyRevision}throw new ExecutorPrivateProtocolError("Private Executor proxy policy did not converge")}async reconcileRegistrationsAndCommitReady(e,t){for(let i=0;i<F;i+=1){const s=new Set([...e.appliedRegistrationRevisions.keys(),...this.registrations.keys()]);for(const r of s)await this.withRegistrationLock(r,async()=>{if(this.active!==e||this.isStopping()||t?.aborted)throw t?.reason??new ExecutorPrivateProcessExitedError;const n=this.registrations.get(r),a=this.registrationRevisions.get(r),h=e.appliedRegistrationRevisions.get(r);if(n&&a!==void 0){if(h===a)return;const l=await this.requestOnActive(e,"registration/upsert",{registration:n},t===void 0?{}:{signal:t});e.appliedRegistrationRevisions.set(r,a),this.isCurrentRegistration(r,a)&&this.setSnapshot(r,l);return}h!==void 0&&(await this.requestOnActive(e,"registration/remove",{registrationId:r},t===void 0?{}:{signal:t}),e.appliedRegistrationRevisions.delete(r),this.deleteSnapshot(r))});if(this.active!==e||this.isStopping()||t?.aborted)throw t?.reason??new ExecutorPrivateProcessExitedError;if(this.registrationsConverged(e)){this.restartAttempt=0,this.stateValue="ready",this.scheduleHealthCheck(e);return}}throw new ExecutorPrivateProtocolError("Private Executor registration state did not converge during startup")}registrationsConverged(e){if(e.appliedRegistrationRevisions.size!==this.registrations.size)return!1;for(const t of this.registrations.keys()){const i=this.registrationRevisions.get(t);if(i===void 0||e.appliedRegistrationRevisions.get(t)!==i)return!1}return!0}handleMessage(e,t){if(this.active===e){if(U(t)){try{E(t,q)}catch{return}if(!V(t)||t.params.runtimeEpoch!==e.epoch)return;try{const{signal:i}=t.params;i.kind==="log"?this.options.recordEffectTelemetry?.log(i.value):i.kind==="metrics"?this.options.recordEffectTelemetry?.metrics(Object.freeze({...i.value,runtimeEpoch:e.epoch})):this.options.recordEffectTelemetry?.span(i.value)}catch{}return}try{E(t,S)}catch(i){this.failProtocol(e,new ExecutorPrivateProtocolError(`Private Executor sent an invalid or oversized IPC payload: ${g(i).message}`));return}if(B(t)){if(t.runtimeEpoch!==e.epoch)return;if(typeof t.id!="number"){this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor response used an invalid request id"));return}const i=this.pending.get(t.id);if(!i||i.epoch!==e.epoch)return;if(this.pending.delete(t.id),i.deadline.close(),"error"in t){const s=new ue(t.error.data?.code??"ExecutorPrivateError",t.error.data?.retryable,t.error.message);i.reject(s)}else{if(!D(i.method,t.result)){i.reject(new ExecutorPrivateProtocolError(`Private Executor returned an invalid ${i.method} result`)),this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor response violated its method contract"));return}i.resolve(t.result)}return}if(I(t)){if(t.params.runtimeEpoch!==e.epoch)return;if(t.method==="client-mcp/cancel")this.clientRequests.get(t.params.requestId)?.controller.abort(new Error("MCP request cancelled"));else for(const i of this.registrations.values())i.executorSlug===t.params.integration&&i.connectionName===t.params.connection&&this.invalidateCatalog(i.registrationId);return}if(N(t)){if(t.params.runtimeEpoch!==e.epoch)return;this.handleReverseRequest(e,t);return}this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor sent an unknown IPC message"))}}async handleClientMcpRequest(e,t){const i=new AbortController;try{const s=this.clientSources.get(t.params.sourceId)?.source;if(!s||this.clientRequests.size>=this.options.maxPendingRequests||this.clientRequests.has(t.id)||![...this.registrations.values()].some(n=>n.transport.transport==="client"&&n.transport.sourceId===t.params.sourceId))throw new Error("Client MCP source unavailable");this.clientRequests.set(t.id,{sourceId:t.params.sourceId,epoch:e.epoch,controller:i});const r=await s.request(t.params.method,t.params.params,i.signal);if(this.active!==e||i.signal.aborted)return;await this.send(e,{id:t.id,jsonrpc:"2.0",result:r,runtimeEpoch:e.epoch})}catch{await this.send(e,{id:t.id,jsonrpc:"2.0",error:{code:-32e3,message:"Client MCP request failed"},runtimeEpoch:e.epoch}).catch(()=>{})}finally{this.clientRequests.delete(t.id)}}async handleReverseRequest(e,t){if(t.method==="client-mcp/request")return this.handleClientMcpRequest(e,t);try{const i=t.trace===void 0?void 0:j(t.trace),s=await C(i,()=>this.options.onElicitation({invocationId:t.params.invocationId,request:t.params.request,runtimeEpoch:e.epoch}));await this.send(e,{id:t.id,jsonrpc:"2.0",result:s,runtimeEpoch:e.epoch})}catch{await this.send(e,{error:{code:-32e3,message:"Elicitation was cancelled"},id:t.id,jsonrpc:"2.0",runtimeEpoch:e.epoch}).catch(()=>{})}}failProtocol(e,t){this.handleChildFailure(e,t)}handleChildFailure(e,t){if(this.active!==e)return;this.active=void 0;for(const n of this.clientRequests.values())n.epoch===e.epoch&&n.controller.abort(t);if(this.clearHealthTimer(),this.rejectPending(t,e.epoch),this.stateValue==="closing"||this.stateValue==="closed")return;const i=g(t);if(this.fuseState==="half_open"){const n=this.recordHalfOpenFailure(e,i).catch(()=>{});this.failureTasks.add(n),n.finally(()=>this.failureTasks.delete(n)).catch(()=>{}),this.reportFailure(i);return}this.stateValue="idle";const r=this.finishChildFailure(e,i).catch(n=>this.reportFailure(g(n))).catch(()=>{}).then(()=>{});this.recoveryPromise=r,this.failureTasks.add(r),r.then(()=>{this.failureTasks.delete(r),this.recoveryPromise===r&&(this.recoveryPromise=void 0,this.fuseRecoveryController=void 0)}).catch(()=>{}),this.reportFailure(i)}async finishChildFailure(e,t){const i=this.readPolicyNow();for(this.crashTimes.push(i);this.crashTimes.length>0&&this.crashTimes[0]<i-this.options.crashWindowMs;)this.crashTimes.shift();const s=this.crashTimes.length>this.options.maxCrashes;s?this.openFuse(e.epoch,t,e):(this.restartAttempt+=1,this.stateValue="idle",this.publishUnavailable(e.epoch,!1),this.registrations.size>0&&this.recordLifecycle({component:"executor",counts:{attempt:this.restartAttempt,failuresInWindow:this.crashTimes.length},error:t,phase:"recovery",process:{exitCode:e.child.exitCode,pid:e.child.pid,signal:e.child.signalCode},reason:t instanceof ExecutorPrivateProcessExitedError?"process_exit":t instanceof ExecutorPrivateProtocolError?"protocol_error":"process_error",state:"restarting"}));const r=s?new AbortController:void 0;r&&(this.fuseRecoveryController=r),await this.recoverAfterChildFailure(e,s,r)}async recordHalfOpenFailure(e,t){const i=this.readPolicyNow();for(this.crashTimes.push(i);this.crashTimes.length>0&&this.crashTimes[0]<i-this.options.crashWindowMs;)this.crashTimes.shift();this.openFuse(e.epoch,t,e)}async recoverAfterChildFailure(e,t,i){try{await this.terminateChild(e)}catch(r){throw this.recordLifecycle({component:"executor",error:r,phase:"cleanup",process:{exitCode:e.child.exitCode,pid:e.child.pid,signal:e.child.signalCode},reason:"cleanup_failed",state:"shutdown_failed"}),r}const s=this.startPromise;if(s&&await s.catch(()=>{}),this.isStopping()||this.registrations.size===0){t&&!this.isStopping()&&this.closeUnusedFuse();return}if(!t){await this.startWithoutRecoveryWait();return}if(!i)throw new Error("Executor fuse recovery omitted its controller");await this.recoverOpenFuse(i.signal)}async recoverOpenFuse(e){let t=e;for(;!this.isStopping();){if(t.aborted){const i=this.renewFuseRecoveryAfterCancellation(t);if(!i)return;t=i}if(this.registrations.size===0){this.closeUnusedFuse();return}this.fuseState="open",this.stateValue="failed";try{await this.waitForRestartBackoff(Math.max(1,this.fuseOpenAttempt),t)}catch(i){if(t.aborted){const s=this.renewFuseRecoveryAfterCancellation(t);if(!s)return;t=s;continue}if(this.isStopping())return;throw i}if(this.isStopping()||this.registrations.size===0){this.registrations.size===0&&!this.isStopping()&&this.closeUnusedFuse();return}this.fuseState="half_open",this.stateValue="restarting";try{if(await this.startWithoutRecoveryWait(t),this.fuseState==="half_open"&&this.state==="ready"&&this.active){this.closeFuse();return}this.fuseState==="half_open"&&this.openFuse()}catch(i){if(t.aborted){const s=this.renewFuseRecoveryAfterCancellation(t);if(!s)return;t=s;continue}if(this.isStopping())return;this.fuseState==="half_open"&&this.openFuse(),this.reportFailure(g(i))}}}renewFuseRecoveryAfterCancellation(e){if(this.isStopping())return;if(this.registrations.size===0){this.closeUnusedFuse();return}const t=this.fuseRecoveryController;if(t&&t.signal!==e&&!t.signal.aborted)return t.signal;const i=new AbortController;return this.fuseRecoveryController=i,i.signal}openFuse(e,t,i){const s=this.fuseState!=="open";this.fuseState!=="open"&&(this.fuseOpenAttempt+=1),this.fuseState="open",this.stateValue="failed",this.publishUnavailable(e,!0),s&&this.recordLifecycle({component:"executor",counts:{attempt:this.fuseOpenAttempt,failuresInWindow:this.crashTimes.length},...t===void 0?{}:{error:t},phase:"recovery",...i===void 0?{}:{process:{exitCode:i.child.exitCode,pid:i.child.pid,signal:i.child.signalCode}},reason:t instanceof ExecutorPrivateProcessExitedError?"process_exit":t instanceof ExecutorPrivateProtocolError?"protocol_error":"recovery_failed",state:"fused"})}closeFuse(){this.fuseState="closed",this.fuseOpenAttempt=0,this.crashTimes.length=0,this.restartAttempt=0,this.stateValue="ready"}closeUnusedFuse(){this.fuseState="closed",this.fuseOpenAttempt=0,this.crashTimes.length=0,this.restartAttempt=0,this.stateValue="idle"}cancelFuseRecovery(e){this.fuseRecoveryController?.abort(e)}publishUnavailable(e,t){for(const[i,s]of this.snapshots)this.setSnapshot(i,{error:{code:t?"executor_failed":"executor_restarting",message:t?"MCP runtime exceeded its restart limit; recovery is pending":"MCP runtime is restarting",retryable:!0},generation:s.generation+1,registrationId:i,runtimeEpoch:e??s.runtimeEpoch,status:"unavailable",tools:[]})}setSnapshot(e,t){this.snapshots.set(e,t),this.scheduleCatalogRefresh(e),this.publishSnapshot(e,t)}deleteSnapshot(e){clearTimeout(this.catalogTimers.get(e)),this.catalogTimers.delete(e),this.snapshots.delete(e)&&this.publishSnapshot(e,void 0)}publishSnapshot(e,t){for(const i of this.snapshotListeners)try{i(e,t)}catch{}}request(e,t,i){const s=this.active;return!s||this.stateValue!=="ready"?Promise.reject(new Error("Private Executor is not ready")):this.requestOnActive(s,e,t,i)}scheduleHealthCheck(e){if(this.clearHealthTimer(),this.options.healthIntervalMs===0)return;const t=new AbortController,i={close:u(()=>t.abort(new Error("Executor health delay completed")),"close")};this.healthTimer=i,C(void 0,()=>{this.waitForPolicyDelay(this.options.healthIntervalMs,t.signal,"Executor health delay cancelled").then(()=>{if(this.healthTimer===i)return this.healthTimer=void 0,this.checkHealth(e)}).catch(s=>{this.healthTimer===i&&(this.healthTimer=void 0),!t.signal.aborted&&!this.isStopping()&&this.failProtocol(e,g(s))})})}async checkHealth(e){if(!(this.active!==e||this.stateValue!=="ready")){try{const t=await this.requestOnActive(e,"runtime/health",{},{timeoutMs:this.options.healthTimeoutMs});if(t.status!=="ready"||t.runtimeEpoch!==e.epoch||t.stdioAnchorPid!==e.anchorPid)throw new ExecutorPrivateProtocolError("Private Executor health response did not match its epoch")}catch(t){this.active===e&&!this.isStopping()&&this.failProtocol(e,g(t));return}this.active===e&&this.stateValue==="ready"&&this.scheduleHealthCheck(e)}}clearHealthTimer(){this.healthTimer&&(this.healthTimer.close(),this.healthTimer=void 0)}requestOnActive(e,t,i,s={}){if(s.signal?.aborted)return Promise.reject(s.signal.reason);if(this.pending.size>=this.options.maxPendingRequests)return Promise.reject(new ExecutorPrivateOverloadedError);const r=this.nextRequestId++,n=H(),a={id:r,jsonrpc:"2.0",method:t,params:i,...n===void 0?{}:{trace:n}},h=s.timeoutMs??this.options.requestTimeoutMs;return new Promise((l,d)=>{const f=this.createPolicyDeadline(h,s.signal===void 0?[]:[s.signal],new Error(`Private Executor ${t} timed out after ${h}ms`)),m=u(()=>{const c=this.pending.get(r);c&&(this.pending.delete(r),f.close(),c.reject(f.signal.reason))},"onAbort");f.signal.addEventListener("abort",m,{once:!0}),this.pending.set(r,{deadline:f,epoch:e.epoch,method:t,reject:u(c=>{f.signal.removeEventListener("abort",m),d(c)},"reject"),resolve:u(c=>{f.signal.removeEventListener("abort",m),l(c)},"resolve")}),this.send(e,a).catch(c=>{const p=this.pending.get(r);p&&(this.pending.delete(r),f.close(),p.reject(c))})})}send(e,t){const{bytes:i}=E(t,S);return this.pendingSends>=this.options.maxPendingRequests||this.pendingSendBytes+i>this.options.maxPendingRequestBytes?Promise.reject(new ExecutorPrivateOverloadedError):this.active!==e||!e.child.connected||!e.child.send?Promise.reject(new ExecutorPrivateProcessExitedError):(this.pendingSends+=1,this.pendingSendBytes+=i,new Promise((s,r)=>{let n=!1;const a=u(h=>{n||(n=!0,this.pendingSends-=1,this.pendingSendBytes-=i,h?r(h):s())},"finish");try{e.child.send?.(t,h=>a(h))}catch(h){a(g(h))}}))}rejectPending(e,t){for(const[i,s]of this.pending)t!==void 0&&s.epoch!==t||(this.pending.delete(i),s.deadline.close(),s.reject(e))}terminateChild(e,t=this.shutdownBudget){if(e.terminationPromise)return e.terminationPromise;const i=t===void 0,s=t??this.createShutdownBudget(Math.min(Number.MAX_SAFE_INTEGER,this.options.termTimeoutMs*2));return e.terminationPromise=this.terminateChildOnce(e,s).finally(()=>{i&&s.deadline.close()}),e.terminationPromise}async terminateChildOnce(e,t){let i=!1,s;if(e.guardian){const n=this.remainingBeforeHandleReleaseReserve(t),a=Date.now()+n;try{await e.guardian.close({deadlineAt:a})}catch(h){i=!0,s=h}if(!i&&(e.guardianBound===!0||e.anchorPid!==void 0)){if(await this.waitForChildExit(e,this.remainingBeforeKillReserve(t)))return;const h=new Error("Private Executor did not exit after guardian cleanup");this.options.containment.trip(h);const l=[h];try{await this.terminateWithSignals(e,!0,t)}catch(d){l.push(...this.flattenCleanupFailure(d))}this.throwCleanupFailures(l,"Private Executor guardian cleanup did not reap its child")}}if(e.child.exitCode!==null||e.child.signalCode!==null){if(i)throw s;return}const r=[];i&&r.push(s);try{await this.terminateWithSignals(e,e.guardian!==void 0||this.options.allowStdio&&this.options.platform!=="win32",t)}catch(n){r.push(...this.flattenCleanupFailure(n))}this.throwCleanupFailures(r,"Private Executor guardian and child cleanup failed")}async terminateWithSignals(e,t,i){const s=[];try{e.child.disconnect?.()}catch(r){s.push(r)}for(const r of["SIGTERM","SIGKILL"]){if(e.child.exitCode!==null||e.child.signalCode!==null)break;const n=r==="SIGTERM"?this.remainingBeforeKillReserve(i):this.remainingBeforeHandleReleaseReserve(i);try{if(await this.killAndWait(e,r,n,t))break}catch(a){s.push(a)}}if(e.child.exitCode===null&&e.child.signalCode===null){const r=new Error("Private Executor process cleanup timed out");this.options.containment.trip(r),s.push(r);try{this.releaseChildHandles(e)}catch(n){s.push(...this.flattenCleanupFailure(n))}}this.throwCleanupFailures(s,"Private Executor child cleanup failed")}async killAndWait(e,t,i,s=!1){let r,n=!1;try{s||this.options.platform==="win32"?n=!e.child.kill(t):e.child.pid?process.kill(-e.child.pid,t):r=new Error(`Private Executor child has no PID for ${t}`)}catch(h){J(h)||(r=h)}const a=await this.waitForChildExit(e,i)||e.child.exitCode!==null||e.child.signalCode!==null;if(r!==void 0)throw r;if(n&&!a)throw new Error(`Private Executor child refused ${t}`);return a}async waitForChildExit(e,t){if(e.child.exitCode!==null||e.child.signalCode!==null)return!0;if(t<=0)return!1;let i;return Promise.race([e.exit.then(()=>!0),new Promise(s=>{i=setTimeout(()=>s(!1),t),i.unref?.()})]).finally(()=>{i&&clearTimeout(i)})}releaseChildHandles(e){const t=[],i=u(s=>{try{s()}catch(r){t.push(r)}},"attempt");e.child.connected&&i(()=>e.child.disconnect?.()),i(()=>e.child.channel?.unref()),i(()=>e.child.stdin?.destroy()),i(()=>e.child.stdout?.destroy()),i(()=>e.child.stderr?.destroy()),i(()=>e.child.unref()),this.throwCleanupFailures(t,"Private Executor child handles could not be released")}flattenCleanupFailure(e){return e instanceof AggregateError?e.errors:[e]}throwCleanupFailures(e,t){if(e.length===1)throw e[0];if(e.length>1)throw new AggregateError(e,t)}assertCurrentRegistration(e,t){if(!this.isCurrentRegistration(e,t))throw new Error(`MCP registration "${e}" was superseded`)}isCurrentRegistration(e,t){return this.registrations.has(e)&&this.isCurrentRegistrationRevision(e,t)}isCurrentRegistrationRevision(e,t){return this.registrationRevisions.get(e)===t}requireRegistration(e){const t=this.registrations.get(e);if(!t)throw new Error(`Unknown MCP registration "${e}"`);return t}requireRegistrationRevision(e){const t=this.registrationRevisions.get(e);if(t===void 0)throw new Error(`Unknown MCP registration "${e}"`);return t}async withRegistrationLock(e,t){const i=this.registrationTasks.get(e);let s;const r=new Promise(n=>{s=n});this.registrationTasks.set(e,r),i&&await i;try{return await t()}finally{s(),this.registrationTasks.get(e)===r&&this.registrationTasks.delete(e)}}createShutdownBudget(e,t){const i=Date.now(),s=i+e,r=t===void 0?s:Math.min(s,t),n=Math.max(1,Math.ceil(r-i)),a=new ExecutorPrivateShutdownTimeoutError(n);return{deadlineAt:r,deadline:R(n,[],a),timeoutError:a}}gracefulCloseBudgetMs(e,t=!1){if(!t)return this.remainingBeforeKillReserve(e);const i=this.remainingShutdownMs(e),s=Math.min(i,this.options.termTimeoutMs+se);return Math.max(0,i-s)}remainingBeforeKillReserve(e){const t=this.remainingShutdownMs(e);if(t<=1)return 0;const i=Math.min(this.options.termTimeoutMs,Math.max(1,Math.ceil(t/2)));return Math.max(0,t-i)}remainingBeforeHandleReleaseReserve(e){const t=this.remainingShutdownMs(e);if(t<=1)return 0;const i=Math.min(10,Math.max(1,Math.ceil(t/10)));return Math.max(0,t-i)}remainingShutdownMs(e){return Math.max(0,Math.ceil(e.deadlineAt-Date.now()))}async settleWithinShutdown(e,t,i=this.remainingShutdownMs(t)){const s=Math.min(this.remainingShutdownMs(t),Math.max(0,i));if(s<=0||t.deadline.signal.aborted)return e.catch(()=>{}),{status:"timed_out"};const r=R(s,[t.deadline.signal],t.timeoutError);return new Promise(n=>{let a=!1;const h=u(d=>{a||(a=!0,r.signal.removeEventListener("abort",l),r.close(),n(d))},"finish"),l=u(()=>h({status:"timed_out"}),"onAbort");if(r.signal.addEventListener("abort",l,{once:!0}),r.signal.aborted){l(),e.catch(()=>{});return}e.then(d=>h({status:"fulfilled",value:d}),d=>h({reason:d,status:"rejected"}))})}createPolicyDeadline(e,t,i){return this.processRuntime?.createPolicyDeadline(e,{signals:t,timeoutReason:i})??R(e,t,i)}readPolicyNow(){return this.processRuntime?.policyNow()??Date.now()}waitForPolicyDelay(e,t,i){return this.processRuntime?.policyDelay(e,t,i)??L(e,t)}waitForRestartBackoff(e,t){const i=t??new AbortController().signal;return this.processRuntime?this.processRuntime.policyBackoff(this.options.restartBackoffMs,e,b,i,"Executor restart backoff cancelled"):L(Math.min(b,this.options.restartBackoffMs*2**(e-1)),i)}assertAccepting(){if(this.stateValue==="closing"||this.stateValue==="closed")throw new Error(`Executor supervisor is ${this.stateValue}`);this.options.containment.assertHealthy()}isStopping(){return this.stateValue==="closing"||this.stateValue==="closed"}reportFailure(e){Promise.resolve().then(()=>this.options.onFailure?.(e)).catch(()=>{})}recordLifecycle(e){try{this.options.recordLifecycle?.(e)}catch{}}}
1
+ var O=Object.defineProperty;var u=(o,e)=>O(o,"name",{value:e,configurable:!0});import{fork as k,spawn as P}from"node:child_process";import{randomUUID as x}from"node:crypto";import v from"node:path";import{EXECUTOR_PRIVATE_MAX_MESSAGE_BYTES as S,EXECUTOR_PRIVATE_MAX_TELEMETRY_MESSAGE_BYTES as q,EXECUTOR_PRIVATE_PROTOCOL_VERSION as T,isExecutorPrivateCatalogNotification as I,isExecutorPrivateResponse as B,isExecutorPrivateResult as D,isExecutorPrivateReverseRequest as N,isExecutorPrivateTelemetryNotification as V,isExecutorPrivateTelemetryNotificationCandidate as U}from"#agent-harness-executor/private-protocol";import{currentHarnessTraceCarrier as H,parseHarnessTraceCarrier as j,withHarnessTraceContext as C}from"#agent-harness-executor/trace-context";import{DEFAULT_MCP_TOOLS_SYNC_TTL_MS as z}from"#agent-harness-executor/types";import{maybeCurrentHarnessProcessRuntime as W}from"../effect-runtime/process-runtime-context.js";import{normalizeError as g}from"../internal/errors.js";import{boundedStringifyJson as E}from"../protocol/bounded-json.js";import{applyNodeRuntimeEnvironment as G,resolveNodeRuntimeLaunch as M}from"../runtime/node-runtime.js";import{AGENT_HARNESS_PRIVATE_RUNTIME_ROLE as _,createPrivateRuntimeLaunchSpec as A,isAgentHarnessStandaloneBinary as X}from"../runtime/private-runtime-role.js";import{CodeBuddyProcessContainment as $}from"../runtime/process-containment.js";import{isMissingProcess as J}from"../runtime/process-tree.js";import{assertAgentHarnessProcessContainment as Y}from"../runtime/sfe-process-containment.js";import{measure as w}from"../telemetry/index.js";import{attachPosixStdioMcpGuardian as K,resolveStdioMcpContainment as Q}from"./stdio-guardian.js";const Z=3e4,ee=15e3,te=5e3,ie=3e3,se=1e3,re=1e4,ne=3e3,oe=1024,ae=8*1024*1024,he=5,ce=6e4,le=100,b=5e3,F=16;export class ExecutorPrivateProcessExitedError extends Error{static{u(this,"ExecutorPrivateProcessExitedError")}constructor(){super("Private Executor child exited unexpectedly"),this.name="ExecutorPrivateProcessExitedError"}}export class ExecutorPrivateProtocolError extends Error{static{u(this,"ExecutorPrivateProtocolError")}constructor(e){super(e),this.name="ExecutorPrivateProtocolError"}}export class ExecutorPrivateOverloadedError extends Error{static{u(this,"ExecutorPrivateOverloadedError")}constructor(){super("Private Executor IPC queue is overloaded"),this.name="ExecutorPrivateOverloadedError"}}class ue extends Error{static{u(this,"ExecutorPrivateOperationError")}constructor(e,t,i){super(i),this.code=e,this.retryable=t,this.name=e}}export class ExecutorPrivateStartupCleanupError extends AggregateError{static{u(this,"ExecutorPrivateStartupCleanupError")}constructor(e,t){super([e,t],"Private Executor startup and cleanup both failed"),this.startupFailure=e,this.cleanupFailure=t,this.name="ExecutorPrivateStartupCleanupError"}}export class ExecutorPrivateShutdownTimeoutError extends Error{static{u(this,"ExecutorPrivateShutdownTimeoutError")}constructor(e){super(`Private Executor cleanup timed out after ${e}ms`),this.timeoutMs=e,this._tag="ExecutorPrivateShutdownTimeoutError",this.name=this._tag}}function de(){return X()?process.execPath:v.resolve(import.meta.dirname,"../../executor/lib/capsule/entry.mjs")}u(de,"defaultChildEntryPath");const fe=Object.freeze(["ALL_PROXY","HTTP_PROXY","HTTPS_PROXY","LANG","LC_ALL","NODE_EXTRA_CA_CERTS","NODE_NO_WARNINGS","NO_PROXY","PATH","SSL_CERT_DIR","SSL_CERT_FILE","SystemRoot","TEMP","TMP","TMPDIR","TZ","WINDIR","http_proxy","https_proxy","all_proxy","no_proxy"]);function pe(o){const e=u(n=>{const a=n?.trim();if(a)try{const h=new URL(a.includes("://")?a:`http://${a}`);return h.protocol==="http:"||h.protocol==="https:"?h.toString():void 0}catch{return}},"normalize"),t=e(o.ALL_PROXY??o.all_proxy),i=e(o.HTTP_PROXY??o.http_proxy??t),s=e(o.HTTPS_PROXY??o.https_proxy??t??i),r=[...new Set([...(o.NO_PROXY??o.no_proxy??"").split(",").map(n=>n.trim()).filter(Boolean),"localhost","127.0.0.1","::1"])];return Object.freeze({...i===void 0?{}:{httpProxyUrl:i},...s===void 0?{}:{httpsProxyUrl:s},mode:"auto",noProxy:Object.freeze(r),revision:"environment"})}u(pe,"defaultExecutorProxyPolicy");export function createExecutorChildEnvironment(o=process.env,e=M()){const t={AGENT_HARNESS_PRIVATE_EXECUTOR:"1"};for(const i of fe){const s=o[i];s!==void 0&&(t[i]=s)}return G(t,e)}u(createExecutorChildEnvironment,"createExecutorChildEnvironment");export function createExecutorWindowsSpawnSpec(o,e){const{execArgv:t=process.execArgv,execPath:i=process.execPath,silent:s,...r}=e,a=A({entryPath:o,nodeRuntime:{environment:{},executable:i},role:_.executor}),h=a.args[0]===o;return{...{args:Object.freeze([...h?t:[],...a.args]),command:a.command},options:{...r,env:{...r.env},windowsHide:!0}}}u(createExecutorWindowsSpawnSpec,"createExecutorWindowsSpawnSpec");function me(o,e){Y();const t=createExecutorWindowsSpawnSpec(o,e);return P(t.command,[...t.args],t.options)}u(me,"spawnExecutorChildOnWindows");function ge(o,e,t,i){if(t==="win32")return me(o,e);const s=A({entryPath:o,nodeRuntime:i,role:_.executor});if(s.args[0]===o)return k(o,[],e);const{execArgv:r,execPath:n,silent:a,...h}=e;return P(s.command,[...s.args],h)}u(ge,"spawnExecutorChild");function we(o){const e=u((a,h,l)=>{const d=a??h;if(!Number.isSafeInteger(d)||d<=0)throw new RangeError(`${l} must be a positive integer`);return d},"positive"),t=u((a,h,l)=>{const d=a??h;if(!Number.isSafeInteger(d)||d<0)throw new RangeError(`${l} must be a non-negative integer`);return d},"nonNegative"),i=o.platform??process.platform,s=Q({platform:i,requested:o.allowStdio??!0,windowsProcessContainmentEnabled:o.windowsProcessContainmentEnabled,windowsJob:o.windowsJob}),r=o.nodeRuntime??M(),n=createExecutorChildEnvironment(o.environment,r);return{allowStdio:s.allowStdio,childEntryPath:o.childEntryPath??de(),closeTimeoutMs:e(o.closeTimeoutMs,te,"closeTimeoutMs"),containment:o.containment??new $,crashWindowMs:e(o.crashWindowMs,ce,"crashWindowMs"),environment:n,healthIntervalMs:t(o.healthIntervalMs,re,"healthIntervalMs"),healthTimeoutMs:e(o.healthTimeoutMs,ne,"healthTimeoutMs"),instanceId:o.instanceId??x(),maxCrashes:e(o.maxCrashes,he,"maxCrashes"),maxPendingRequestBytes:e(o.maxPendingRequestBytes,ae,"maxPendingRequestBytes"),maxPendingRequests:e(o.maxPendingRequests,oe,"maxPendingRequests"),nodeRuntime:r,toolsSyncTtlMs:o.toolsSyncTtlMs===null?null:e(o.toolsSyncTtlMs,z,"toolsSyncTtlMs"),onElicitation:o.onElicitation,...o.onFailure===void 0?{}:{onFailure:o.onFailure},platform:i,proxyPolicy:o.proxyPolicy??pe(n),...o.recordLifecycle===void 0?{}:{recordLifecycle:o.recordLifecycle},...o.recordEffectTelemetry===void 0?{}:{recordEffectTelemetry:o.recordEffectTelemetry},requestTimeoutMs:e(o.requestTimeoutMs,Z,"requestTimeoutMs"),restartBackoffMs:e(o.restartBackoffMs,le,"restartBackoffMs"),spawnChild:o.spawnChild??((a,h)=>ge(a,h,i,r)),startTimeoutMs:e(o.startTimeoutMs,ee,"startTimeoutMs"),...o.stdioGuardianEntryPath===void 0?{}:{stdioGuardianEntryPath:o.stdioGuardianEntryPath},stdioContainment:s.mode,...s.mode==="windows_native_job_object"?{windowsJob:s.windowsJob}:{},termTimeoutMs:e(o.termTimeoutMs,ie,"termTimeoutMs")}}u(we,"resolveOptions");function L(o,e){return e?.aborted?Promise.reject(e.reason):new Promise((t,i)=>{let s=!1;const r=u(h=>{s||(s=!0,clearTimeout(a),e?.removeEventListener("abort",n),h===void 0?t():i(h))},"finish"),n=u(()=>r(e?.reason),"onAbort"),a=setTimeout(()=>r(),o);a.unref?.(),e?.addEventListener("abort",n,{once:!0})})}u(L,"standaloneDelay");function R(o,e,t){const i=new AbortController,s=setTimeout(()=>i.abort(t),o);s.unref?.();const r=AbortSignal.any([...e,i.signal]),n=[];let a=!1;const h=u(()=>{if(!a){a=!0,clearTimeout(s);for(const[l,d]of n)l.removeEventListener("abort",d);n.length=0}},"close");for(const l of e)n.push([l,h]),l.addEventListener("abort",h,{once:!0});return Object.freeze({close:h,signal:r})}u(R,"standaloneDeadline");export class ExecutorProcessSupervisor{static{u(this,"ExecutorProcessSupervisor")}registerClientSource(e,t){if(this.assertAccepting(),this.clientSources.has(e))throw new Error("Duplicate Client MCP source");const i=t.subscribe(()=>{for(const s of this.registrations.values())s.transport.transport==="client"&&s.transport.sourceId===e&&this.invalidateCatalog(s.registrationId)});return this.clientSources.set(e,{source:t,release:i}),()=>{if(this.clientSources.get(e)?.source===t){this.clientSources.delete(e),i();for(const r of this.clientRequests.values())r.sourceId===e&&r.controller.abort(new Error("Client MCP source closed"))}}}invalidateCatalog(e){if(this.isStopping()||!this.registrations.has(e))return;const t=this.catalogRefreshes.get(e);if(t){t.dirty=!0;return}const i={dirty:!0,promise:Promise.resolve()};i.promise=Promise.resolve().then(async()=>{do{if(i.dirty=!1,this.isStopping()||!this.registrations.has(e))return;await this.refreshRegistration(e)}while(i.dirty)}).catch(()=>{}).finally(()=>{this.catalogRefreshes.delete(e),this.scheduleCatalogRefresh(e)}),this.catalogRefreshes.set(e,i)}scheduleCatalogRefresh(e){if(clearTimeout(this.catalogTimers.get(e)),this.catalogTimers.delete(e),this.isStopping()||!this.registrations.has(e)||this.options.toolsSyncTtlMs===null)return;const t=setTimeout(()=>{this.catalogTimers.delete(e),this.invalidateCatalog(e)},Math.min(this.options.toolsSyncTtlMs,2147483647));t.unref(),this.catalogTimers.set(e,t)}constructor(e){if(this.crashTimes=[],this.failureTasks=new Set,this.fuseOpenAttempt=0,this.fuseState="closed",this.nextRequestId=1,this.nextRegistrationRevision=1,this.pending=new Map,this.pendingSendBytes=0,this.pendingSends=0,this.proxyTask=Promise.resolve(),this.registrationRevisions=new Map,this.registrationTasks=new Map,this.restartAttempt=0,this.shutdownController=new AbortController,this.registrations=new Map,this.snapshots=new Map,this.clientSources=new Map,this.clientRequests=new Map,this.catalogTimers=new Map,this.catalogRefreshes=new Map,this.snapshotListeners=new Set,this.stateValue="idle",this.options=we(e),this.proxyPolicy=this.options.proxyPolicy,this.processRuntime=e.processRuntime??W(),this.processRuntime===void 0&&process.env.NODE_ENV!=="test")throw new Error("Executor supervisor requires the process-owned Effect runtime");this.releaseProcessOwnership=this.processRuntime?.addFinalizer(()=>this.close(new Error("Agent Harness process runtime is closing")));const t=this.processRuntime?.shutdownSignal;if(t){const i=u(()=>{this.close(t.reason).catch(()=>{})},"onProcessShutdown");t.addEventListener("abort",i,{once:!0}),this.releaseProcessShutdownListener=()=>t.removeEventListener("abort",i)}}get runtimeEpoch(){return this.active?.epoch}get state(){return this.stateValue}async start(){await this.ensureReady()}async configureProxy(e){this.assertAccepting(),this.proxyPolicy=e;const t=this.proxyTask.then(()=>this.reconcileProxyPolicy());this.proxyTask=t.catch(()=>{}),await t}subscribeSnapshots(e){return this.snapshotListeners.add(e),()=>this.snapshotListeners.delete(e)}async upsertRegistration(e,t){this.assertAccepting();const i=this.nextRegistrationRevision++;this.registrations.set(e.registrationId,e),this.registrationRevisions.set(e.registrationId,i);try{return await this.ensureReady(),await this.withRegistrationLock(e.registrationId,async()=>{if(this.assertCurrentRegistration(e.registrationId,i),t?.signal?.aborted)throw t.signal.reason;const s=this.active,r=this.snapshots.get(e.registrationId);if(this.stateValue==="ready"&&s?.initialized===!0&&s.child.connected&&s.child.exitCode===null&&s.child.signalCode===null&&s.appliedRegistrationRevisions.get(e.registrationId)===i&&r?.status==="available"&&r?.registrationId===e.registrationId&&r?.runtimeEpoch===s.epoch)return r;const n=await w("registrationReconcile",()=>this.request("registration/upsert",{registration:e},t));return this.assertCurrentRegistration(e.registrationId,i),this.setSnapshot(e.registrationId,n),n})}catch(s){throw this.isCurrentRegistration(e.registrationId,i)&&this.deleteSnapshot(e.registrationId),s}}async refreshRegistration(e,t){this.requireRegistration(e);const i=this.requireRegistrationRevision(e);return await this.ensureReady(),this.withRegistrationLock(e,async()=>{this.assertCurrentRegistration(e,i);const s=await this.request("registration/refresh",{registrationId:e},t);return this.assertCurrentRegistration(e,i),this.setSnapshot(e,s),s})}getSnapshot(e){return this.snapshots.get(e)}async removeRegistration(e,t){const i=this.nextRegistrationRevision++;this.registrations.delete(e),this.registrationRevisions.set(e,i),this.deleteSnapshot(e),this.registrations.size===0&&this.cancelFuseRecovery(new Error("Executor fuse recovery is no longer needed")),!(this.stateValue==="closed"||this.stateValue==="closing")&&(await this.withRegistrationLock(e,async()=>{if(!this.isCurrentRegistrationRevision(e,i)||this.isStopping())return;const s=this.active;if(s?.initialized)try{await this.requestOnActive(s,"registration/remove",{registrationId:e},t),s.appliedRegistrationRevisions.delete(e)}catch(r){if(this.active===s&&!this.isStopping())throw this.handleChildFailure(s,r),r}}),this.isCurrentRegistrationRevision(e,i)&&(this.deleteSnapshot(e),this.registrationRevisions.delete(e)))}async callTool(e,t,i,s,r={}){this.requireRegistration(e);const n=this.requireRegistrationRevision(e);await this.ensureReady(),this.assertCurrentRegistration(e,n);let a=!1;const h=u(()=>{a||(a=!0,this.request("tool/cancel",{invocationId:t},{timeoutMs:Math.min(r.timeoutMs??this.options.requestTimeoutMs,2e3)}).catch(()=>{}))},"cancelInvocation");let l;r.signal&&(l=h,r.signal.addEventListener("abort",l,{once:!0}));try{return await this.request("tool/call",{args:s,executorAddress:i,invocationId:t,registrationId:e},r)}catch(d){throw h(),d}finally{l&&r.signal?.removeEventListener("abort",l)}}async close(e){return this.closePromise??=this.closeInternal(e),this.closePromise}async closeInternal(e){for(const c of this.catalogTimers.values())clearTimeout(c);this.catalogTimers.clear();for(const c of this.clientRequests.values())c.controller.abort(e);for(const c of this.clientSources.values())c.release();if(this.clientSources.clear(),this.stateValue==="closed")return;const t=e??new Error("Executor supervisor is closing"),i=this.createShutdownBudget(this.options.closeTimeoutMs,this.processRuntime?.shutdownDeadlineAt),{timeoutError:s}=i;this.shutdownBudget=i,this.stateValue="closing",this.cancelFuseRecovery(t),this.shutdownController.abort(t);const r=[],n=[],a=u((c,p=r)=>{c===s&&(r.includes(s)||n.includes(s))||p.push(c)},"addFailure"),h=u(async(c,p=r)=>{const y=await this.settleWithinShutdown(c,i);y.status==="rejected"?a(y.reason,p):y.status==="timed_out"&&a(s,p)},"attempt");this.clearHealthTimer();const l=this.active,d=this.startPromise;if(this.rejectPending(t),l&&!d&&l.initialized){const c=this.gracefulCloseBudgetMs(i,l.guardian!==void 0);c>0&&await h(this.requestOnActive(l,"runtime/close",{},{signal:i.deadline.signal,timeoutMs:c}))}if(l)try{await this.terminateChild(l,i)}catch(c){a(c,n)}if(d){const c=await this.settleWithinShutdown(d,i);c.status==="rejected"?c.reason instanceof ExecutorPrivateStartupCleanupError&&r.push(...this.flattenCleanupFailure(c.reason.cleanupFailure)):c.status==="timed_out"&&a(s)}const f=await this.settleWithinShutdown(Promise.allSettled([...this.failureTasks,...this.registrationTasks.values(),...[...this.catalogRefreshes.values()].map(c=>c.promise)]),i);if(f.status==="fulfilled")for(const c of f.value)c.status==="rejected"&&r.push(c.reason);else f.status==="rejected"?r.push(f.reason):a(s);r.push(...n);const m=this.active;if(m&&(m!==l||m.child.exitCode===null&&m.child.signalCode===null))try{await this.terminateChild(m,i)}catch(c){a(c)}i.deadline.signal.aborted&&a(s),this.active=void 0,this.recoveryPromise=void 0,this.startPromise=void 0,this.registrations.clear(),this.registrationRevisions.clear(),this.registrationTasks.clear();for(const c of this.snapshots.keys())this.deleteSnapshot(c);if(this.snapshotListeners.clear(),this.stateValue="closed",this.releaseProcessShutdownListener?.(),this.releaseProcessOwnership?.(),i.deadline.close(),r.length>0){const c=r.length===1?r[0]:new AggregateError(r,"Private Executor cleanup failed"),p=m??l;throw this.recordLifecycle({component:"executor",error:c,phase:"cleanup",...p===void 0?{}:{process:{exitCode:p.child.exitCode,pid:p.child.pid,signal:p.child.signalCode}},reason:"cleanup_failed",state:"shutdown_failed"}),c}}async ensureReady(){for(;;){if(this.assertAccepting(),this.stateValue==="ready"&&this.active)return;if(this.fuseState!=="closed")throw new Error(`Executor supervisor fuse is ${this.fuseState}; recovery is pending`);const e=this.recoveryPromise;if(!e)break;await e}await this.startWithoutRecoveryWait()}async startWithoutRecoveryWait(e){this.assertAccepting();const t=[this.shutdownController.signal];this.processRuntime?.shutdownSignal&&t.push(this.processRuntime.shutdownSignal),e&&t.push(e);const i=t.length===1?t[0]:AbortSignal.any(t);if(i.aborted)throw i.reason;if(this.stateValue==="ready"&&this.active)return;const s=this.startPromise??this.startChild(i);this.startPromise=s;try{await s}finally{this.startPromise===s&&(this.startPromise=void 0)}}async startChild(e){if(this.options.containment.assertHealthy(),e?.aborted||(this.stateValue=this.stateValue==="idle"?"starting":"restarting",this.restartAttempt>0&&await this.waitForRestartBackoff(this.restartAttempt,e),this.assertAccepting(),e?.aborted))throw e.reason;const t=x(),i=this.options.spawnChild(this.options.childEntryPath,{cwd:v.dirname(this.options.childEntryPath),detached:this.options.platform!=="win32",env:this.options.environment,execArgv:[],execPath:this.options.nodeRuntime.executable,serialization:"json",stdio:["ignore","ignore","pipe","ipc"]});if(!i.pid||!i.send)throw i.kill(),new Error("Private Executor child did not expose PID and IPC");const s=i.pid;i.stderr?.resume();const r={appliedRegistrationRevisions:new Map,child:i,epoch:t,exit:i.exitCode!==null||i.signalCode!==null?Promise.resolve():new Promise(n=>{i.once("exit",()=>n())}),initialized:!1};this.active=r,i.on("message",n=>this.handleMessage(r,n)),i.once("error",n=>this.handleChildFailure(r,n)),i.once("exit",()=>{this.isStopping()||this.handleChildFailure(r,new ExecutorPrivateProcessExitedError)}),i.once("disconnect",()=>{this.isStopping()&&this.handleChildFailure(r,new ExecutorPrivateProcessExitedError)});try{if(this.options.windowsJob&&!this.options.windowsJob.isProcessInJob(s))throw new Error("Private Executor did not inherit the host Windows Job");this.options.stdioContainment==="posix_guardian"&&await w("guardianBind",async()=>{const h=await K({...this.options.stdioGuardianEntryPath===void 0?{}:{childEntryPath:this.options.stdioGuardianEntryPath},containment:this.options.containment,...e===void 0?{}:{signal:e},shutdownDeadlineAt:u(()=>this.processRuntime?.shutdownDeadlineAt,"shutdownDeadlineAt"),targetProcessGroupId:s,termTimeoutMs:this.options.termTimeoutMs});if(r.guardian=h,e?.aborted||this.isStopping())throw e?.reason??new Error("Executor supervisor is closing");await h.bindAnchor(s),r.guardianBound=!0});const n=this.proxyPolicy,a=await w("executorInitialize",()=>this.requestOnActive(r,"runtime/initialize",{allowStdio:this.options.allowStdio,proxy:n,protocolVersion:T,runtimeEpoch:t,stdioContainment:this.options.stdioContainment,...this.options.windowsJob===void 0?{}:{windowsJobAddonPath:this.options.windowsJob.addonPath},...!this.options.allowStdio||r.guardian===void 0?{}:{stdioGuardianPid:r.guardian.guardianPid},tenantId:this.options.instanceId},{...e===void 0?{}:{signal:e},timeoutMs:this.options.startTimeoutMs}));if(a.protocolVersion!==T||a.runtimeEpoch!==t||a.proxyRevision!==n.revision||(this.options.stdioContainment==="posix_guardian"?a.stdioAnchorPid===void 0||a.stdioAnchorPid<=0:a.stdioAnchorPid!==void 0))throw new ExecutorPrivateProtocolError("Private Executor initialize response did not match its epoch");r.anchorPid=a.stdioAnchorPid,r.appliedProxyRevision=a.proxyRevision,await this.reconcileProxyPolicyOnActive(r,e),r.initialized=!0,await w("registrationReconcile",()=>this.reconcileRegistrationsAndCommitReady(r,e))}catch(n){let a=!1,h;try{await this.terminateChild(r)}catch(l){a=!0,h=l}throw this.active===r&&(this.active=void 0),!this.isStopping()&&this.fuseState==="closed"&&(this.stateValue="idle"),a?(this.recordLifecycle({component:"executor",error:h,phase:"cleanup",process:{exitCode:r.child.exitCode,pid:r.child.pid,signal:r.child.signalCode},reason:"cleanup_failed",state:"shutdown_failed"}),new ExecutorPrivateStartupCleanupError(n,h)):n}}async reconcileProxyPolicy(){const e=this.active;e?.initialized!==!0||this.isStopping()||await this.reconcileProxyPolicyOnActive(e)}async reconcileProxyPolicyOnActive(e,t){for(let i=0;i<F;i+=1){if(this.active!==e||this.isStopping())return;const s=this.proxyPolicy;if(e.appliedProxyRevision===s.revision)return;const r=await this.requestOnActive(e,"runtime/proxy-configure",{proxy:s},{...t===void 0?{}:{signal:t},timeoutMs:this.options.requestTimeoutMs});if(r.proxyRevision!==s.revision)throw new ExecutorPrivateProtocolError("Private Executor proxy revision did not match its request");e.appliedProxyRevision=r.proxyRevision}throw new ExecutorPrivateProtocolError("Private Executor proxy policy did not converge")}async reconcileRegistrationsAndCommitReady(e,t){for(let i=0;i<F;i+=1){const s=new Set([...e.appliedRegistrationRevisions.keys(),...this.registrations.keys()]);for(const r of s)await this.withRegistrationLock(r,async()=>{if(this.active!==e||this.isStopping()||t?.aborted)throw t?.reason??new ExecutorPrivateProcessExitedError;const n=this.registrations.get(r),a=this.registrationRevisions.get(r),h=e.appliedRegistrationRevisions.get(r);if(n&&a!==void 0){if(h===a)return;const l=await this.requestOnActive(e,"registration/upsert",{registration:n},t===void 0?{}:{signal:t});e.appliedRegistrationRevisions.set(r,a),this.isCurrentRegistration(r,a)&&this.setSnapshot(r,l);return}h!==void 0&&(await this.requestOnActive(e,"registration/remove",{registrationId:r},t===void 0?{}:{signal:t}),e.appliedRegistrationRevisions.delete(r),this.deleteSnapshot(r))});if(this.active!==e||this.isStopping()||t?.aborted)throw t?.reason??new ExecutorPrivateProcessExitedError;if(this.registrationsConverged(e)){this.restartAttempt=0,this.stateValue="ready",this.scheduleHealthCheck(e);return}}throw new ExecutorPrivateProtocolError("Private Executor registration state did not converge during startup")}registrationsConverged(e){if(e.appliedRegistrationRevisions.size!==this.registrations.size)return!1;for(const t of this.registrations.keys()){const i=this.registrationRevisions.get(t);if(i===void 0||e.appliedRegistrationRevisions.get(t)!==i)return!1}return!0}handleMessage(e,t){if(this.active===e){if(U(t)){try{E(t,q)}catch{return}if(!V(t)||t.params.runtimeEpoch!==e.epoch)return;try{const{signal:i}=t.params;i.kind==="log"?this.options.recordEffectTelemetry?.log(i.value):i.kind==="metrics"?this.options.recordEffectTelemetry?.metrics(Object.freeze({...i.value,runtimeEpoch:e.epoch})):this.options.recordEffectTelemetry?.span(i.value)}catch{}return}try{E(t,S)}catch(i){this.failProtocol(e,new ExecutorPrivateProtocolError(`Private Executor sent an invalid or oversized IPC payload: ${g(i).message}`));return}if(B(t)){if(t.runtimeEpoch!==e.epoch)return;if(typeof t.id!="number"){this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor response used an invalid request id"));return}const i=this.pending.get(t.id);if(!i||i.epoch!==e.epoch)return;if(this.pending.delete(t.id),i.deadline.close(),"error"in t){const s=new ue(t.error.data?.code??"ExecutorPrivateError",t.error.data?.retryable,t.error.message);i.reject(s)}else{if(!D(i.method,t.result)){i.reject(new ExecutorPrivateProtocolError(`Private Executor returned an invalid ${i.method} result`)),this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor response violated its method contract"));return}i.resolve(t.result)}return}if(I(t)){if(t.params.runtimeEpoch!==e.epoch)return;if(t.method==="client-mcp/cancel")this.clientRequests.get(t.params.requestId)?.controller.abort(new Error("MCP request cancelled"));else for(const i of this.registrations.values())i.executorSlug===t.params.integration&&i.connectionName===t.params.connection&&this.invalidateCatalog(i.registrationId);return}if(N(t)){if(t.params.runtimeEpoch!==e.epoch)return;this.handleReverseRequest(e,t);return}this.failProtocol(e,new ExecutorPrivateProtocolError("Private Executor sent an unknown IPC message"))}}async handleClientMcpRequest(e,t){const i=new AbortController;try{const s=this.clientSources.get(t.params.sourceId)?.source;if(!s||this.clientRequests.size>=this.options.maxPendingRequests||this.clientRequests.has(t.id)||![...this.registrations.values()].some(n=>n.transport.transport==="client"&&n.transport.sourceId===t.params.sourceId))throw new Error("Client MCP source unavailable");this.clientRequests.set(t.id,{sourceId:t.params.sourceId,epoch:e.epoch,controller:i});const r=await s.request(t.params.method,t.params.params,i.signal);if(this.active!==e||i.signal.aborted)return;await this.send(e,{id:t.id,jsonrpc:"2.0",result:r,runtimeEpoch:e.epoch})}catch{await this.send(e,{id:t.id,jsonrpc:"2.0",error:{code:-32e3,message:"Client MCP request failed"},runtimeEpoch:e.epoch}).catch(()=>{})}finally{this.clientRequests.delete(t.id)}}async handleReverseRequest(e,t){if(t.method==="client-mcp/request")return this.handleClientMcpRequest(e,t);try{const i=t.trace===void 0?void 0:j(t.trace),s=await C(i,()=>this.options.onElicitation({invocationId:t.params.invocationId,request:t.params.request,runtimeEpoch:e.epoch}));await this.send(e,{id:t.id,jsonrpc:"2.0",result:s,runtimeEpoch:e.epoch})}catch{await this.send(e,{error:{code:-32e3,message:"Elicitation was cancelled"},id:t.id,jsonrpc:"2.0",runtimeEpoch:e.epoch}).catch(()=>{})}}failProtocol(e,t){this.handleChildFailure(e,t)}handleChildFailure(e,t){if(this.active!==e)return;this.active=void 0;for(const n of this.clientRequests.values())n.epoch===e.epoch&&n.controller.abort(t);if(this.clearHealthTimer(),this.rejectPending(t,e.epoch),this.stateValue==="closing"||this.stateValue==="closed")return;const i=g(t);if(this.fuseState==="half_open"){const n=this.recordHalfOpenFailure(e,i).catch(()=>{});this.failureTasks.add(n),n.finally(()=>this.failureTasks.delete(n)).catch(()=>{}),this.reportFailure(i);return}this.stateValue="idle";const r=this.finishChildFailure(e,i).catch(n=>this.reportFailure(g(n))).catch(()=>{}).then(()=>{});this.recoveryPromise=r,this.failureTasks.add(r),r.then(()=>{this.failureTasks.delete(r),this.recoveryPromise===r&&(this.recoveryPromise=void 0,this.fuseRecoveryController=void 0)}).catch(()=>{}),this.reportFailure(i)}async finishChildFailure(e,t){const i=this.readPolicyNow();for(this.crashTimes.push(i);this.crashTimes.length>0&&this.crashTimes[0]<i-this.options.crashWindowMs;)this.crashTimes.shift();const s=this.crashTimes.length>this.options.maxCrashes;s?this.openFuse(e.epoch,t,e):(this.restartAttempt+=1,this.stateValue="idle",this.publishUnavailable(e.epoch,!1),this.registrations.size>0&&this.recordLifecycle({component:"executor",counts:{attempt:this.restartAttempt,failuresInWindow:this.crashTimes.length},error:t,phase:"recovery",process:{exitCode:e.child.exitCode,pid:e.child.pid,signal:e.child.signalCode},reason:t instanceof ExecutorPrivateProcessExitedError?"process_exit":t instanceof ExecutorPrivateProtocolError?"protocol_error":"process_error",state:"restarting"}));const r=s?new AbortController:void 0;r&&(this.fuseRecoveryController=r),await this.recoverAfterChildFailure(e,s,r)}async recordHalfOpenFailure(e,t){const i=this.readPolicyNow();for(this.crashTimes.push(i);this.crashTimes.length>0&&this.crashTimes[0]<i-this.options.crashWindowMs;)this.crashTimes.shift();this.openFuse(e.epoch,t,e)}async recoverAfterChildFailure(e,t,i){try{await this.terminateChild(e)}catch(r){throw this.recordLifecycle({component:"executor",error:r,phase:"cleanup",process:{exitCode:e.child.exitCode,pid:e.child.pid,signal:e.child.signalCode},reason:"cleanup_failed",state:"shutdown_failed"}),r}const s=this.startPromise;if(s&&await s.catch(()=>{}),this.isStopping()||this.registrations.size===0){t&&!this.isStopping()&&this.closeUnusedFuse();return}if(!t){await this.startWithoutRecoveryWait();return}if(!i)throw new Error("Executor fuse recovery omitted its controller");await this.recoverOpenFuse(i.signal)}async recoverOpenFuse(e){let t=e;for(;!this.isStopping();){if(t.aborted){const i=this.renewFuseRecoveryAfterCancellation(t);if(!i)return;t=i}if(this.registrations.size===0){this.closeUnusedFuse();return}this.fuseState="open",this.stateValue="failed";try{await this.waitForRestartBackoff(Math.max(1,this.fuseOpenAttempt),t)}catch(i){if(t.aborted){const s=this.renewFuseRecoveryAfterCancellation(t);if(!s)return;t=s;continue}if(this.isStopping())return;throw i}if(this.isStopping()||this.registrations.size===0){this.registrations.size===0&&!this.isStopping()&&this.closeUnusedFuse();return}this.fuseState="half_open",this.stateValue="restarting";try{if(await this.startWithoutRecoveryWait(t),this.fuseState==="half_open"&&this.state==="ready"&&this.active){this.closeFuse();return}this.fuseState==="half_open"&&this.openFuse()}catch(i){if(t.aborted){const s=this.renewFuseRecoveryAfterCancellation(t);if(!s)return;t=s;continue}if(this.isStopping())return;this.fuseState==="half_open"&&this.openFuse(),this.reportFailure(g(i))}}}renewFuseRecoveryAfterCancellation(e){if(this.isStopping())return;if(this.registrations.size===0){this.closeUnusedFuse();return}const t=this.fuseRecoveryController;if(t&&t.signal!==e&&!t.signal.aborted)return t.signal;const i=new AbortController;return this.fuseRecoveryController=i,i.signal}openFuse(e,t,i){const s=this.fuseState!=="open";this.fuseState!=="open"&&(this.fuseOpenAttempt+=1),this.fuseState="open",this.stateValue="failed",this.publishUnavailable(e,!0),s&&this.recordLifecycle({component:"executor",counts:{attempt:this.fuseOpenAttempt,failuresInWindow:this.crashTimes.length},...t===void 0?{}:{error:t},phase:"recovery",...i===void 0?{}:{process:{exitCode:i.child.exitCode,pid:i.child.pid,signal:i.child.signalCode}},reason:t instanceof ExecutorPrivateProcessExitedError?"process_exit":t instanceof ExecutorPrivateProtocolError?"protocol_error":"recovery_failed",state:"fused"})}closeFuse(){this.fuseState="closed",this.fuseOpenAttempt=0,this.crashTimes.length=0,this.restartAttempt=0,this.stateValue="ready"}closeUnusedFuse(){this.fuseState="closed",this.fuseOpenAttempt=0,this.crashTimes.length=0,this.restartAttempt=0,this.stateValue="idle"}cancelFuseRecovery(e){this.fuseRecoveryController?.abort(e)}publishUnavailable(e,t){for(const[i,s]of this.snapshots)this.setSnapshot(i,{error:{code:t?"executor_failed":"executor_restarting",message:t?"MCP runtime exceeded its restart limit; recovery is pending":"MCP runtime is restarting",retryable:!0},generation:s.generation+1,registrationId:i,runtimeEpoch:e??s.runtimeEpoch,status:"unavailable",tools:[]})}setSnapshot(e,t){this.snapshots.set(e,t),this.scheduleCatalogRefresh(e),this.publishSnapshot(e,t)}deleteSnapshot(e){clearTimeout(this.catalogTimers.get(e)),this.catalogTimers.delete(e),this.snapshots.delete(e)&&this.publishSnapshot(e,void 0)}publishSnapshot(e,t){for(const i of this.snapshotListeners)try{i(e,t)}catch{}}request(e,t,i){const s=this.active;return!s||this.stateValue!=="ready"?Promise.reject(new Error("Private Executor is not ready")):this.requestOnActive(s,e,t,i)}scheduleHealthCheck(e){if(this.clearHealthTimer(),this.options.healthIntervalMs===0)return;const t=new AbortController,i={close:u(()=>t.abort(new Error("Executor health delay completed")),"close")};this.healthTimer=i,C(void 0,()=>{this.waitForPolicyDelay(this.options.healthIntervalMs,t.signal,"Executor health delay cancelled").then(()=>{if(this.healthTimer===i)return this.healthTimer=void 0,this.checkHealth(e)}).catch(s=>{this.healthTimer===i&&(this.healthTimer=void 0),!t.signal.aborted&&!this.isStopping()&&this.failProtocol(e,g(s))})})}async checkHealth(e){if(!(this.active!==e||this.stateValue!=="ready")){try{const t=await this.requestOnActive(e,"runtime/health",{},{timeoutMs:this.options.healthTimeoutMs});if(t.status!=="ready"||t.runtimeEpoch!==e.epoch||t.stdioAnchorPid!==e.anchorPid)throw new ExecutorPrivateProtocolError("Private Executor health response did not match its epoch")}catch(t){this.active===e&&!this.isStopping()&&this.failProtocol(e,g(t));return}this.active===e&&this.stateValue==="ready"&&this.scheduleHealthCheck(e)}}clearHealthTimer(){this.healthTimer&&(this.healthTimer.close(),this.healthTimer=void 0)}requestOnActive(e,t,i,s={}){if(s.signal?.aborted)return Promise.reject(s.signal.reason);if(this.pending.size>=this.options.maxPendingRequests)return Promise.reject(new ExecutorPrivateOverloadedError);const r=this.nextRequestId++,n=H(),a={id:r,jsonrpc:"2.0",method:t,params:i,...n===void 0?{}:{trace:n}},h=s.timeoutMs??this.options.requestTimeoutMs;return new Promise((l,d)=>{const f=this.createPolicyDeadline(h,s.signal===void 0?[]:[s.signal],new Error(`Private Executor ${t} timed out after ${h}ms`)),m=u(()=>{const c=this.pending.get(r);c&&(this.pending.delete(r),f.close(),c.reject(f.signal.reason))},"onAbort");f.signal.addEventListener("abort",m,{once:!0}),this.pending.set(r,{deadline:f,epoch:e.epoch,method:t,reject:u(c=>{f.signal.removeEventListener("abort",m),d(c)},"reject"),resolve:u(c=>{f.signal.removeEventListener("abort",m),l(c)},"resolve")}),this.send(e,a).catch(c=>{const p=this.pending.get(r);p&&(this.pending.delete(r),f.close(),p.reject(c))})})}send(e,t){const{bytes:i}=E(t,S);return this.pendingSends>=this.options.maxPendingRequests||this.pendingSendBytes+i>this.options.maxPendingRequestBytes?Promise.reject(new ExecutorPrivateOverloadedError):this.active!==e||!e.child.connected||!e.child.send?Promise.reject(new ExecutorPrivateProcessExitedError):(this.pendingSends+=1,this.pendingSendBytes+=i,new Promise((s,r)=>{let n=!1;const a=u(h=>{n||(n=!0,this.pendingSends-=1,this.pendingSendBytes-=i,h?r(h):s())},"finish");try{e.child.send?.(t,h=>a(h))}catch(h){a(g(h))}}))}rejectPending(e,t){for(const[i,s]of this.pending)t!==void 0&&s.epoch!==t||(this.pending.delete(i),s.deadline.close(),s.reject(e))}terminateChild(e,t=this.shutdownBudget){if(e.terminationPromise)return e.terminationPromise;const i=t===void 0,s=t??this.createShutdownBudget(Math.min(Number.MAX_SAFE_INTEGER,this.options.termTimeoutMs*2));return e.terminationPromise=this.terminateChildOnce(e,s).finally(()=>{i&&s.deadline.close()}),e.terminationPromise}async terminateChildOnce(e,t){let i=!1,s;if(e.guardian){const n=this.remainingBeforeHandleReleaseReserve(t),a=Date.now()+n;try{await e.guardian.close({deadlineAt:a})}catch(h){i=!0,s=h}if(!i&&(e.guardianBound===!0||e.anchorPid!==void 0)){if(await this.waitForChildExit(e,this.remainingBeforeKillReserve(t)))return;const h=new Error("Private Executor did not exit after guardian cleanup");this.options.containment.trip(h);const l=[h];try{await this.terminateWithSignals(e,!0,t)}catch(d){l.push(...this.flattenCleanupFailure(d))}this.throwCleanupFailures(l,"Private Executor guardian cleanup did not reap its child")}}if(e.child.exitCode!==null||e.child.signalCode!==null){if(i)throw s;return}const r=[];i&&r.push(s);try{await this.terminateWithSignals(e,e.guardian!==void 0||this.options.allowStdio&&this.options.platform!=="win32",t)}catch(n){r.push(...this.flattenCleanupFailure(n))}this.throwCleanupFailures(r,"Private Executor guardian and child cleanup failed")}async terminateWithSignals(e,t,i){const s=[];try{e.child.disconnect?.()}catch(r){s.push(r)}for(const r of["SIGTERM","SIGKILL"]){if(e.child.exitCode!==null||e.child.signalCode!==null)break;const n=r==="SIGTERM"?this.remainingBeforeKillReserve(i):this.remainingBeforeHandleReleaseReserve(i);try{if(await this.killAndWait(e,r,n,t))break}catch(a){s.push(a)}}if(e.child.exitCode===null&&e.child.signalCode===null){const r=new Error("Private Executor process cleanup timed out");this.options.containment.trip(r),s.push(r);try{this.releaseChildHandles(e)}catch(n){s.push(...this.flattenCleanupFailure(n))}}this.throwCleanupFailures(s,"Private Executor child cleanup failed")}async killAndWait(e,t,i,s=!1){let r,n=!1;try{s||this.options.platform==="win32"?n=!e.child.kill(t):e.child.pid?process.kill(-e.child.pid,t):r=new Error(`Private Executor child has no PID for ${t}`)}catch(h){J(h)||(r=h)}const a=await this.waitForChildExit(e,i)||e.child.exitCode!==null||e.child.signalCode!==null;if(r!==void 0)throw r;if(n&&!a)throw new Error(`Private Executor child refused ${t}`);return a}async waitForChildExit(e,t){if(e.child.exitCode!==null||e.child.signalCode!==null)return!0;if(t<=0)return!1;let i;return Promise.race([e.exit.then(()=>!0),new Promise(s=>{i=setTimeout(()=>s(!1),t),i.unref?.()})]).finally(()=>{i&&clearTimeout(i)})}releaseChildHandles(e){const t=[],i=u(s=>{try{s()}catch(r){t.push(r)}},"attempt");e.child.connected&&i(()=>e.child.disconnect?.()),i(()=>e.child.channel?.unref()),i(()=>e.child.stdin?.destroy()),i(()=>e.child.stdout?.destroy()),i(()=>e.child.stderr?.destroy()),i(()=>e.child.unref()),this.throwCleanupFailures(t,"Private Executor child handles could not be released")}flattenCleanupFailure(e){return e instanceof AggregateError?e.errors:[e]}throwCleanupFailures(e,t){if(e.length===1)throw e[0];if(e.length>1)throw new AggregateError(e,t)}assertCurrentRegistration(e,t){if(!this.isCurrentRegistration(e,t))throw new Error(`MCP registration "${e}" was superseded`)}isCurrentRegistration(e,t){return this.registrations.has(e)&&this.isCurrentRegistrationRevision(e,t)}isCurrentRegistrationRevision(e,t){return this.registrationRevisions.get(e)===t}requireRegistration(e){const t=this.registrations.get(e);if(!t)throw new Error(`Unknown MCP registration "${e}"`);return t}requireRegistrationRevision(e){const t=this.registrationRevisions.get(e);if(t===void 0)throw new Error(`Unknown MCP registration "${e}"`);return t}async withRegistrationLock(e,t){const i=this.registrationTasks.get(e);let s;const r=new Promise(n=>{s=n});this.registrationTasks.set(e,r),i&&await i;try{return await t()}finally{s(),this.registrationTasks.get(e)===r&&this.registrationTasks.delete(e)}}createShutdownBudget(e,t){const i=Date.now(),s=i+e,r=t===void 0?s:Math.min(s,t),n=Math.max(1,Math.ceil(r-i)),a=new ExecutorPrivateShutdownTimeoutError(n);return{deadlineAt:r,deadline:R(n,[],a),timeoutError:a}}gracefulCloseBudgetMs(e,t=!1){if(!t)return this.remainingBeforeKillReserve(e);const i=this.remainingShutdownMs(e),s=Math.min(i,this.options.termTimeoutMs+se);return Math.max(0,i-s)}remainingBeforeKillReserve(e){const t=this.remainingShutdownMs(e);if(t<=1)return 0;const i=Math.min(this.options.termTimeoutMs,Math.max(1,Math.ceil(t/2)));return Math.max(0,t-i)}remainingBeforeHandleReleaseReserve(e){const t=this.remainingShutdownMs(e);if(t<=1)return 0;const i=Math.min(10,Math.max(1,Math.ceil(t/10)));return Math.max(0,t-i)}remainingShutdownMs(e){return Math.max(0,Math.ceil(e.deadlineAt-Date.now()))}async settleWithinShutdown(e,t,i=this.remainingShutdownMs(t)){const s=Math.min(this.remainingShutdownMs(t),Math.max(0,i));if(s<=0||t.deadline.signal.aborted)return e.catch(()=>{}),{status:"timed_out"};const r=R(s,[t.deadline.signal],t.timeoutError);return new Promise(n=>{let a=!1;const h=u(d=>{a||(a=!0,r.signal.removeEventListener("abort",l),r.close(),n(d))},"finish"),l=u(()=>h({status:"timed_out"}),"onAbort");if(r.signal.addEventListener("abort",l,{once:!0}),r.signal.aborted){l(),e.catch(()=>{});return}e.then(d=>h({status:"fulfilled",value:d}),d=>h({reason:d,status:"rejected"}))})}createPolicyDeadline(e,t,i){return this.processRuntime?.createPolicyDeadline(e,{signals:t,timeoutReason:i})??R(e,t,i)}readPolicyNow(){return this.processRuntime?.policyNow()??Date.now()}waitForPolicyDelay(e,t,i){return this.processRuntime?.policyDelay(e,t,i)??L(e,t)}waitForRestartBackoff(e,t){const i=t??new AbortController().signal;return this.processRuntime?this.processRuntime.policyBackoff(this.options.restartBackoffMs,e,b,i,"Executor restart backoff cancelled"):L(Math.min(b,this.options.restartBackoffMs*2**(e-1)),i)}assertAccepting(){if(this.stateValue==="closing"||this.stateValue==="closed")throw new Error(`Executor supervisor is ${this.stateValue}`);this.options.containment.assertHealthy()}isStopping(){return this.stateValue==="closing"||this.stateValue==="closed"}reportFailure(e){Promise.resolve().then(()=>this.options.onFailure?.(e)).catch(()=>{})}recordLifecycle(e){try{this.options.recordLifecycle?.(e)}catch{}}}
package/lib/public.d.ts CHANGED
@@ -4,6 +4,7 @@ export { createClient, RequestError } from './client/public.js';
4
4
  export type { Client, ClientOptions, ClientOn, ClientState, ConnectOptions, ConnectSettings, NotificationHandler, RequestContext, RequestHandler, RequestOptions, Unsubscribe, } from './client/types.js';
5
5
  export { createHarness } from './harness/create-harness.js';
6
6
  export type { Harness, HarnessOptions, HarnessTools, HostInfo, ProductConfig, ToolDefinition } from './harness/types.js';
7
+ export type { SandboxCenterOption } from './runtime/sandbox-center.js';
7
8
  export type { TelemetryOptions, LogSink } from './telemetry/public.js';
8
9
  export { createServer } from './server/create-server.js';
9
10
  export type { ServerOptions } from './server/create-server.js';
@@ -0,0 +1,21 @@
1
+ export type SandboxCenterOption = 'managed' | {
2
+ readonly address: string;
3
+ };
4
+ /** One center address per Harness process. The Agent and sandbox-cli daemons consume it through env. */
5
+ export declare class HarnessSandboxCenter {
6
+ readonly address: string;
7
+ readonly managed: boolean;
8
+ private uid;
9
+ private child;
10
+ private client;
11
+ private tail;
12
+ private closing;
13
+ constructor(appHome: string, option?: SandboxCenterOption, inheritedAddress?: string);
14
+ private readonly appHome;
15
+ get environment(): Record<string, string>;
16
+ /** Called before admitting a query; Account fencing has already drained the previous owner. */
17
+ prepare(uid: string | undefined, signal?: AbortSignal): Promise<void>;
18
+ close(): Promise<void>;
19
+ private enqueue;
20
+ private stopOwned;
21
+ }
@@ -0,0 +1 @@
1
+ var u=Object.defineProperty;var r=(s,t)=>u(s,"name",{value:t,configurable:!0});import{buildEpochCenterAddress as f,createSandboxCenterClient as h,getSandboxCenterPath as m,SANDBOX_CENTER_IPC_ADDRESS_ENV as p,SANDBOX_CENTER_LIFECYCLE_COMMANDS as w,SANDBOX_CENTER_START_MODE_ENV as E,SANDBOX_RULES_COMMANDS as C,spawnSandboxCenter as S}from"#agent-harness-components/sandbox-center";const a=3e3;function o(s){return s.exitCode!==null||s.signalCode!==null}r(o,"hasExited");function c(s,t){return o(s)?Promise.resolve(!0):new Promise(e=>{const i=setTimeout(()=>{s.off("exit",n),e(o(s))},t),n=r(()=>{clearTimeout(i),e(!0)},"onExit");s.once("exit",n)})}r(c,"waitForExit");export class HarnessSandboxCenter{static{r(this,"HarnessSandboxCenter")}constructor(t,e,i){this.tail=Promise.resolve(),this.closing=!1;const n=typeof e=="object"?e.address:e===void 0?i:void 0;if(n!==void 0&&!n.trim())throw new TypeError("sandboxCenter.address must be a non-empty IPC address");this.managed=n===void 0,this.address=n??f(t,process.pid),this.appHome=t}get environment(){return{[p]:this.address,[E]:"connect-only"}}prepare(t,e){return t?.trim()?this.enqueue(async()=>{if(e?.throwIfAborted(),this.closing)throw new Error("Harness sandbox-center is closing");const i=t.trim();this.uid&&this.uid!==i&&(this.managed?await this.stopOwned():(this.client?.close(),this.client=void 0,this.uid=void 0));const n=this.managed?m():void 0;if(this.managed&&!n||this.uid===i&&this.client?.isConnected?.()&&(!this.managed||this.child&&!o(this.child)))return;this.client?.close(),this.managed&&(!this.child||o(this.child))&&(this.child=await S({appHome:this.appHome,executablePath:n,socketPath:this.address,uid:i}));const d=h({clientRole:"agent-harness",startMode:"connect-only",resolveRuntimeContext:r(()=>({appHome:this.appHome,socketPath:this.address,uid:i}),"resolveRuntimeContext")});this.client=d;try{await d.request(C.GET_RULES,{},{signal:e}),e?.throwIfAborted(),this.uid=i}catch(l){throw d.close(),this.managed&&await this.stopOwned(i),l}}):Promise.resolve()}close(){return this.closing=!0,this.enqueue(async()=>{this.managed?await this.stopOwned():this.client?.close(),this.client=void 0,this.uid=void 0})}enqueue(t){const e=this.tail.then(t,t);return this.tail=e.catch(()=>{}),e}async stopOwned(t=this.uid){const e=this.child,i=this.client;if(this.child=void 0,this.client=void 0,this.uid=void 0,!e){i?.close();return}try{if(!o(e)&&t){const n=i??h({clientRole:"agent-harness",startMode:"connect-only",resolveRuntimeContext:r(()=>({appHome:this.appHome,socketPath:this.address,uid:t}),"resolveRuntimeContext")});try{if((await n.request(w.SHUTDOWN,{},{signal:AbortSignal.timeout(a),timeoutMs:a}))?.accepted===!0&&await c(e,a))return}catch{}finally{n.close()}}if(!o(e)&&(e.kill("SIGTERM"),!await c(e,a)&&!o(e)&&(e.kill("SIGKILL"),!await c(e,2e3))))throw new Error("Owned sandbox-center did not exit")}finally{i?.close()}}}
@@ -2,6 +2,7 @@ export { tool } from '#agent-harness-components/tool-definition';
2
2
  /** Embedding entry point: importable under Node and Bun, independent of the binary. */
3
3
  export { createHarness } from '../harness/create-harness.js';
4
4
  export type { Harness, HarnessOptions, HarnessTools, HostInfo, ProductConfig, ToolDefinition } from '../harness/types.js';
5
+ export type { SandboxCenterOption } from '../runtime/sandbox-center.js';
5
6
  export { AgentHarnessServer } from './agent-harness-server.js';
6
7
  export { installNoOrphans } from '../runtime/windows-stdio-containment.js';
7
8
  export type { AgentHarnessServerOptions } from './types.js';
@@ -10,6 +10,8 @@ export interface AgentBackendOptions<R = never> {
10
10
  readonly checkpoints?: boolean;
11
11
  /** Assembly seam: resolve admitted Product/settings into Agent execution inputs. */
12
12
  readonly resolveOptions?: (options: SessionOpenOptions) => Effect.Effect<QueryOptions, unknown, R>;
13
+ /** Ensure the process-owned sandbox center is ready for this run's Account. */
14
+ readonly prepareSandboxCenter?: (options: QueryOptions, signal: AbortSignal) => Promise<void>;
13
15
  }
14
16
  export declare function workspaceQueryOptions(open: SessionOpenOptions): Effect.Effect<QueryOptions, Error>;
15
17
  /** Shared Agent service, scoped session instances. No child process or prewarm protocol. */
@@ -1 +1 @@
1
- var ne=Object.defineProperty;var n=(h,f)=>ne(h,"name",{value:f,configurable:!0});import{randomUUID as ie}from"node:crypto";import{isAbsolute as se}from"node:path";import{Effect as d,Layer as oe}from"effect";import{abortReason as re}from"../internal/async.js";import{promptMetadata as ae}from"../protocol/prompt.js";import{AGENT_HARNESS_JSON_RPC_ERROR_CODES as J,AgentHarnessInvalidParamsError as X,AgentHarnessJsonRpcError as K}from"../server/errors.js";import{readSessionTree as ce}from"../subagent/history.js";import{AgentServer as de}from"./agent-server.js";import{SessionConfigStore as le}from"./config-store.js";import{replayCodecs as M,replaySession as ue}from"./replay.js";import{SessionRuntime as V,SessionRuntimeClosedError as F}from"./runtime.js";import{ServerSessionConfig as W}from"./server-config.js";import{ServerSessionEvents as fe}from"./server-events.js";import{serverCanUseTool as ge}from"./server-interactions.js";import{ServerSessionMcp as we}from"./server-mcp.js";import{serverPromptInput as pe}from"./server-prompt.js";export function workspaceQueryOptions(h){return h.workspace?.product?d.succeed({product:h.workspace.product,persistSession:!0,tools:{type:"preset",preset:"default"},freezeToolsDuringRun:!0,settings:{enabledPlugins:{...h.pluginSettings.enabledPlugins}}}):d.fail(new Error("In-process Agent backend requires a resolved workspace Product"))}n(workspaceQueryOptions,"workspaceQueryOptions");const Y={compact:!0,configReload:!0,promptSteer:!0},R={session:{additionalDirectories:{},delete:{},fork:{},mcp:{acp:{},http:{},stdio:{}},prompt:{image:{},embeddedContext:{}}}};export function AgentBackend(h={}){return oe.effect(V,d.gen(function*(){const f=yield*de,q=yield*le,x=yield*d.context();yield*d.tryPromise({try:M,catch:n(r=>r,"catch")});const C=new AbortController;return yield*d.addFinalizer(()=>d.sync(()=>C.abort(new F))),V.of({profile:{capabilities:R,supports:Y,checkpoints:h.checkpoints===!0},prepare:d.void,readCatalog:n((r,a)=>d.gen(function*(){const c=yield*(h.resolveOptions??workspaceQueryOptions)(a).pipe(d.provideContext(x)),v=yield*d.tryPromise({try:n(()=>W.create(c,a.workspace?.sessionModelConfigOption,a.clientCapabilities),"try"),catch:n(S=>S,"catch")}),o=a.cwd??c.cwd??process.cwd();v.restore(yield*q.read({sessionId:r,cwd:o}));const{fs:w,settings:O,product:p,agents:u,agent:m}={...c,...v.queryOptions};return yield*d.tryPromise({try:n(async()=>{const S=AbortSignal.any([C.signal,a.signal]),I=await f.readSessionCatalog({cwd:o,fs:w,settings:O,product:p,agents:u,agent:m,signal:S});return S.throwIfAborted(),(await M()).projectAgentEvent({type:"agent_event",session_id:r,event:{type:"catalog",data:I}})},"try"),catch:n(S=>S,"catch")})}),"readCatalog"),rewind:n((r,a)=>d.tryPromise({try:n(async()=>{const c=await f.readSession(r.sessionId,a);if(!c)throw new X("Session history was not found");const{selectRewindMessage:v}=await M();let o;try{o=v(c,r._meta)}catch(w){throw w instanceof Error&&"code"in w&&["invalid_history","invalid_boundary","cursor_not_found"].includes(String(w.code))?new X(w.message):w}return await f.rewind(r.sessionId,{...a,to:o}),{}},"try"),catch:n(c=>c,"catch")}),"rewind"),open:n(r=>d.acquireRelease(d.gen(function*(){let a=yield*(h.resolveOptions??workspaceQueryOptions)(r).pipe(d.provideContext(x));const c=yield*d.tryPromise({try:n(()=>W.create(a,r.workspace?.sessionModelConfigOption,r.clientCapabilities),"try"),catch:n(e=>e,"catch")}),v=AbortSignal.any([r.signal,C.signal]);v.throwIfAborted();let o,w={},O,p,u,m=-1,S=0,I,k,T,G,D=!1;const U=n((e,t,i)=>d.runPromise(q.write({sessionId:e,cwd:t},i.selections())),"saveConfig"),z=n(e=>{D||T||(D=!0,G=e,k?.abort(e),p?.fail(e),r.onFailure(e))},"fail"),H=new we(r.callbacks,()=>k?.signal??C.signal),y=n(()=>{if(T||C.signal.aborted)throw new F;if(D)throw G},"assertOpen"),E=n(e=>{if(y(),e!==o)throw new Error("Session does not belong to this execution")},"assertSession"),P=n((e,t)=>{if(y(),I)throw new Error("Session is already running");const i=new AbortController;k=i;const s=AbortSignal.any([i.signal,C.signal,...e?.signal?[e.signal]:[]]),l=n(()=>i.abort(re(s)),"abort");s.addEventListener("abort",l,{once:!0}),s.aborted&&l();const A=Promise.resolve().then(()=>(s.throwIfAborted(),t(i))).finally(()=>{s.removeEventListener("abort",l),I=void 0,k=void 0});return I=A,A},"run"),L=n(()=>T??=(async()=>{k?.abort(new F);try{if(!o)return;await f.interrupt(o),await I?.catch(()=>{})}finally{try{o&&await f.close(o)}finally{O?.unsubscribe(),await H.close()}}})(),"dispose"),Z=a.canUseTool??ge(r,()=>({id:o,meta:p?.meta??{}}),(e,t)=>p?.interaction(e,t)??Promise.resolve()),$=n(async({signal:e})=>{e.throwIfAborted(),y();const t=u;if(!t||!r.callbacks.refreshAuthentication)throw new Error("Authentication required");const i=await r.callbacks.refreshAuthentication({accountId:t.account.id,generation:t.generation},{signal:e});if(e.throwIfAborted(),y(),!u||i.account.id!==t.account.id||m>i.generation)throw new Error("Authentication changed during refresh");return u=i,m=i.generation,{accessToken:i.credential.accessToken,method:i.credential.type}},"refreshAuthentication"),N=n(()=>({...a,...w,...c.queryOptions,includePartialMessages:!0,...!r.clientCapabilities.elicitation?.form&&!a.canUseTool?{disallowedTools:[...new Set([...a.disallowedTools??[],"AskUserQuestion"])]}:{},headers:{...h.headers,...u?.credential.domain?{"X-Domain":u.credential.domain}:{},...u?.account.organization?.id?{"X-Tenant-Id":u.account.organization.id}:{},...a.headers},auth:u?{accessToken:u.credential.accessToken,method:u.credential.type,...r.callbacks.refreshAuthentication?{refresh:$}:{}}:m<0?a.auth:void 0,account:u?{uid:u.account.id,...u.account.organization?.id?{enterpriseId:u.account.organization.id}:{}}:m<0?a.account:void 0,canUseTool:Z}),"runOptions"),Q=n((e,t,i)=>{const s=Promise.withResolvers();let l=!1;return P(i,async g=>{const b=f.query(o,e,{...N(),_meta:t,abortController:g});c.lockAgent(),b.catch(()=>{});try{const _=p.begin(b.runId);l=!0,s.resolve({_meta:{"codebuddy.ai/requestId":b.runId}}),await _;const ee=await p.waitForCompletion(b.runId);await b.catch(te=>{if(ee.stopReason!=="error")throw te}),y()}catch(_){throw g.abort(_),await f.interrupt(o),await b.catch(()=>{}),_}}).catch(g=>{l?z(g):s.reject(g)}),s.promise},"acceptQuery"),j=n((e,t,i)=>{if(y(),i?.signal?.throwIfAborted(),o)throw new Error("Execution is already bound to a session");if(!se(t.cwd))throw new Error("Session cwd must be an absolute path");const s=H.configure(t.mcpServers??[],a.mcpServers),l=new fe(e,async g=>{try{await r.callbacks.sessionUpdate(g)}catch(b){throw z(b),b}},c,g=>U(e,t.cwd,g)),A=f.subscribe(e,g=>l.accept(g));o=e,w={cwd:t.cwd,additionalDirectories:t.additionalDirectories?[...t.additionalDirectories]:a.additionalDirectories,mcpServers:s},p=l,O=A,O.closed.then(g=>{g.reason==="failed"&&z(g.error)}).catch(()=>{})},"bindSession"),B=n(e=>P(e,async t=>{const{cwd:i,fs:s,settings:l,product:A,agents:g,agent:b}=N(),_=await f.readSessionCatalog({cwd:i,fs:s,settings:l,product:A,agents:g,agent:b,signal:t.signal});t.signal.throwIfAborted(),y(),await p.accept({type:"agent_event",session_id:o,origin:{},event:{type:"catalog",data:_}})}),"publishCatalog");return{capabilities:{...R,session:{...R.session,mcp:{...R.session.mcp,acp:{}}}},supports:Y,dispose:L,newSession:n(async(e,t)=>{if(y(),o)throw new Error("Execution is already bound to a session");t?.signal?.throwIfAborted(),c.initializeBlank();const i=ie();return await f.createSession(i,{cwd:e.cwd,signal:t?.signal?AbortSignal.any([v,t.signal]):v}),await U(i,e.cwd,c),j(i,e,t),await p.restoreUsage([]),await B(t),{sessionId:o,configOptions:c.snapshot()}},"newSession"),resumeSession:n(async(e,t)=>{if(y(),o){if(E(e.sessionId),w.cwd!==e.cwd)throw new Error("Session cwd cannot change");if(I)throw new Error("Session is already running")}o||c.restore(await d.runPromise(q.read({sessionId:e.sessionId,cwd:e.cwd})));const i=e.replayFrom?await P(t,s=>ue(f.readSession,e,{signal:s.signal,onUpdate:r.callbacks.sessionUpdate,config:c})):{};if(o)w.additionalDirectories=e.additionalDirectories?[...e.additionalDirectories]:w.additionalDirectories;else{const s=await P(t,l=>ce(f.readSession,e,l.signal));j(e.sessionId,e,t),await p.restoreUsage(s.find(l=>l.snapshot.sessionId===e.sessionId)?.snapshot.history??[],s)}return await B(t),c.lockAgent(),{...i,configOptions:c.snapshot()}},"resumeSession"),prompt:n(async(e,t)=>{E(e.sessionId);const i=await pe(e),s=ae(e._meta);if(s?.mode==="steer"){const l=await f.steer(e.sessionId,i,{expectedRunId:s.expectedRequestId,signal:t?.signal});if(!l.steered)throw new K(J.invalidRequest,l.reason==="stale"?"Active query does not match expectedRequestId":"Session has no active query accepting steer");return{_meta:{"codebuddy.ai/requestId":l.runId}}}return Q(i,e._meta,t)},"prompt"),compactSession:n(async(e,t)=>(E(e.sessionId),Q({type:"compact"},e._meta,t)),"compactSession"),cancelSession:n(async e=>{E(e.sessionId),k?.abort(),await f.interrupt(e.sessionId),await I?.catch(()=>{})},"cancelSession"),closeSession:n(async e=>(E(e.sessionId),await L(),{}),"closeSession"),setAuthentication:n(async e=>e.generation<m?{applied:!1}:(u=e,m=e.generation,{applied:!0}),"setAuthentication"),clearAuthentication:n(async e=>e.generation<m?{applied:!1}:(u=void 0,m=e.generation,{applied:!0}),"clearAuthentication"),refreshUserConfig:n(async(e,t)=>{y(),t?.signal?.throwIfAborted();const i=++S,s=await d.runPromise((h.resolveOptions??workspaceQueryOptions)(r).pipe(d.provideContext(x)),{signal:t?.signal});y(),t?.signal?.throwIfAborted(),i===S&&(o&&f.reload(o,{settings:s.settings??{},agents:s.agents??{}}),a={...a,settings:s.settings,agents:s.agents})},"refreshUserConfig"),setSessionConfigOption:n(async(e,t)=>{if(E(e.sessionId),t?.signal?.throwIfAborted(),I)throw new K(J.invalidParams,"Cannot change Agent configuration during a prompt");const i=c.copy();i.set(e),await U(e.sessionId,w.cwd,i),c.replace(i);const s=c.snapshot();return await p.configuration(s),{configOptions:s}},"setSessionConfigOption")}}),a=>d.promise(()=>a.dispose())),"open")})}))}n(AgentBackend,"AgentBackend");
1
+ var se=Object.defineProperty;var n=(p,l)=>se(p,"name",{value:l,configurable:!0});import{randomUUID as ie}from"node:crypto";import{isAbsolute as oe}from"node:path";import{Effect as d,Layer as re}from"effect";import{abortReason as ae}from"../internal/async.js";import{promptMetadata as ce}from"../protocol/prompt.js";import{AGENT_HARNESS_JSON_RPC_ERROR_CODES as X,AgentHarnessInvalidParamsError as K,AgentHarnessJsonRpcError as V}from"../server/errors.js";import{readSessionTree as de}from"../subagent/history.js";import{AgentServer as le}from"./agent-server.js";import{SessionConfigStore as ue}from"./config-store.js";import{replayCodecs as F,replaySession as fe}from"./replay.js";import{SessionRuntime as W,SessionRuntimeClosedError as G}from"./runtime.js";import{ServerSessionConfig as Y}from"./server-config.js";import{ServerSessionEvents as ge}from"./server-events.js";import{serverCanUseTool as we}from"./server-interactions.js";import{ServerSessionMcp as pe}from"./server-mcp.js";import{serverPromptInput as he}from"./server-prompt.js";export function workspaceQueryOptions(p){if(!p.workspace?.product)return d.fail(new Error("In-process Agent backend requires a resolved workspace Product"));const l=p.workspace.product;return d.succeed({product:{...l,skills:l.skills??[],commands:l.commands??[]},persistSession:!0,tools:{type:"preset",preset:"default"},freezeToolsDuringRun:!0,...process.platform==="win32"?{usePty:!1}:{},settings:{enabledPlugins:{...p.pluginSettings.enabledPlugins}}})}n(workspaceQueryOptions,"workspaceQueryOptions");const Z={compact:!0,configReload:!0,promptSteer:!0},q={session:{additionalDirectories:{},delete:{},fork:{},mcp:{acp:{},http:{},stdio:{}},prompt:{image:{},embeddedContext:{}}}};export function AgentBackend(p={}){return re.effect(W,d.gen(function*(){const l=yield*le,x=yield*ue,T=yield*d.context();yield*d.tryPromise({try:F,catch:n(r=>r,"catch")});const k=new AbortController;return yield*d.addFinalizer(()=>d.sync(()=>k.abort(new G))),W.of({profile:{capabilities:q,supports:Z,checkpoints:p.checkpoints===!0},prepare:d.void,readCatalog:n((r,a)=>d.gen(function*(){const c=yield*(p.resolveOptions??workspaceQueryOptions)(a).pipe(d.provideContext(T)),I=yield*d.tryPromise({try:n(()=>Y.create(c,a.workspace?.sessionModelConfigOption,a.clientCapabilities),"try"),catch:n(b=>b,"catch")}),o=a.cwd??c.cwd??process.cwd();I.restore(yield*x.read({sessionId:r,cwd:o}));const{fs:w,settings:_,product:h,agents:f,agent:m}={...c,...I.queryOptions};return yield*d.tryPromise({try:n(async()=>{const b=AbortSignal.any([k.signal,a.signal]),S=await l.readSessionCatalog({cwd:o,fs:w,settings:_,product:h,agents:f,agent:m,signal:b});return b.throwIfAborted(),(await F()).projectAgentEvent({type:"agent_event",session_id:r,event:{type:"catalog",data:S}})},"try"),catch:n(b=>b,"catch")})}),"readCatalog"),rewind:n((r,a)=>d.tryPromise({try:n(async()=>{const c=await l.readSession(r.sessionId,a);if(!c)throw new K("Session history was not found");const{selectRewindMessage:I}=await F();let o;try{o=I(c,r._meta)}catch(w){throw w instanceof Error&&"code"in w&&["invalid_history","invalid_boundary","cursor_not_found"].includes(String(w.code))?new K(w.message):w}return await l.rewind(r.sessionId,{...a,to:o}),{}},"try"),catch:n(c=>c,"catch")}),"rewind"),open:n(r=>d.acquireRelease(d.gen(function*(){let a=yield*(p.resolveOptions??workspaceQueryOptions)(r).pipe(d.provideContext(T));const c=yield*d.tryPromise({try:n(()=>Y.create(a,r.workspace?.sessionModelConfigOption,r.clientCapabilities),"try"),catch:n(e=>e,"catch")}),I=AbortSignal.any([r.signal,k.signal]);I.throwIfAborted();let o,w={},_,h,f,m=-1,b=0,S,E,D,H,U=!1;const z=n((e,t,s)=>d.runPromise(x.write({sessionId:e,cwd:t},s.selections())),"saveConfig"),M=n(e=>{U||D||(U=!0,H=e,E?.abort(e),h?.fail(e),r.onFailure(e))},"fail"),L=new pe(r.callbacks,()=>E?.signal??k.signal),y=n(()=>{if(D||k.signal.aborted)throw new G;if(U)throw H},"assertOpen"),O=n(e=>{if(y(),e!==o)throw new Error("Session does not belong to this execution")},"assertSession"),P=n((e,t)=>{if(y(),S)throw new Error("Session is already running");const s=new AbortController;E=s;const i=AbortSignal.any([s.signal,k.signal,...e?.signal?[e.signal]:[]]),u=n(()=>s.abort(ae(i)),"abort");i.addEventListener("abort",u,{once:!0}),i.aborted&&u();const A=Promise.resolve().then(()=>(i.throwIfAborted(),t(s))).finally(()=>{i.removeEventListener("abort",u),S=void 0,E=void 0});return S=A,A},"run"),N=n(()=>D??=(async()=>{E?.abort(new G);try{if(!o)return;await l.interrupt(o),await S?.catch(()=>{})}finally{try{o&&await l.close(o)}finally{_?.unsubscribe(),await L.close()}}})(),"dispose"),$=a.canUseTool??we(r,()=>({id:o,meta:h?.meta??{}}),(e,t)=>h?.interaction(e,t)??Promise.resolve()),ee=n(async({signal:e})=>{e.throwIfAborted(),y();const t=f;if(!t||!r.callbacks.refreshAuthentication)throw new Error("Authentication required");const s=await r.callbacks.refreshAuthentication({accountId:t.account.id,generation:t.generation},{signal:e});if(e.throwIfAborted(),y(),!f||s.account.id!==t.account.id||m>s.generation)throw new Error("Authentication changed during refresh");return f=s,m=s.generation,{accessToken:s.credential.accessToken,method:s.credential.type}},"refreshAuthentication"),Q=n(()=>({...a,...w,...c.queryOptions,includePartialMessages:!0,...!r.clientCapabilities.elicitation?.form&&!a.canUseTool?{disallowedTools:[...new Set([...a.disallowedTools??[],"AskUserQuestion"])]}:{},headers:{...p.headers,...f?.credential.domain?{"X-Domain":f.credential.domain}:{},...f?.account.organization?.id?{"X-Tenant-Id":f.account.organization.id}:{},...a.headers},auth:f?{accessToken:f.credential.accessToken,method:f.credential.type,...r.callbacks.refreshAuthentication?{refresh:ee}:{}}:m<0?a.auth:void 0,account:f?{uid:f.account.id,...f.account.organization?.id?{enterpriseId:f.account.organization.id}:{}}:m<0?a.account:void 0,canUseTool:$}),"runOptions"),j=n((e,t,s)=>{const i=Promise.withResolvers();let u=!1;return P(s,async g=>{const C=Q();await p.prepareSandboxCenter?.(C,g.signal),g.signal.throwIfAborted();const v=l.query(o,e,{...C,_meta:t,abortController:g});c.lockAgent(),v.catch(()=>{});try{const R=h.begin(v.runId);u=!0,i.resolve({_meta:{"codebuddy.ai/requestId":v.runId}}),await R;const te=await h.waitForCompletion(v.runId);await v.catch(ne=>{if(te.stopReason!=="error")throw ne}),y()}catch(R){throw g.abort(R),await l.interrupt(o),await v.catch(()=>{}),R}}).catch(g=>{u?M(g):i.reject(g)}),i.promise},"acceptQuery"),B=n((e,t,s)=>{if(y(),s?.signal?.throwIfAborted(),o)throw new Error("Execution is already bound to a session");if(!oe(t.cwd))throw new Error("Session cwd must be an absolute path");const i=L.configure(t.mcpServers??[],a.mcpServers),u=new ge(e,async g=>{try{await r.callbacks.sessionUpdate(g)}catch(C){throw M(C),C}},c,g=>z(e,t.cwd,g)),A=l.subscribe(e,g=>u.accept(g));o=e,w={cwd:t.cwd,additionalDirectories:t.additionalDirectories?[...t.additionalDirectories]:a.additionalDirectories,mcpServers:i},h=u,_=A,_.closed.then(g=>{g.reason==="failed"&&M(g.error)}).catch(()=>{})},"bindSession"),J=n(e=>P(e,async t=>{const{cwd:s,fs:i,settings:u,product:A,agents:g,agent:C}=Q(),v=await l.readSessionCatalog({cwd:s,fs:i,settings:u,product:A,agents:g,agent:C,signal:t.signal});t.signal.throwIfAborted(),y(),await h.accept({type:"agent_event",session_id:o,origin:{},event:{type:"catalog",data:v}})}),"publishCatalog");return{capabilities:{...q,session:{...q.session,mcp:{...q.session.mcp,acp:{}}}},supports:Z,dispose:N,newSession:n(async(e,t)=>{if(y(),o)throw new Error("Execution is already bound to a session");t?.signal?.throwIfAborted(),c.initializeBlank();const s=ie();return await l.createSession(s,{cwd:e.cwd,signal:t?.signal?AbortSignal.any([I,t.signal]):I}),await z(s,e.cwd,c),B(s,e,t),await h.restoreUsage([]),await J(t),{sessionId:o,configOptions:c.snapshot()}},"newSession"),resumeSession:n(async(e,t)=>{if(y(),o){if(O(e.sessionId),w.cwd!==e.cwd)throw new Error("Session cwd cannot change");if(S)throw new Error("Session is already running")}o||c.restore(await d.runPromise(x.read({sessionId:e.sessionId,cwd:e.cwd})));const s=e.replayFrom?await P(t,i=>fe(l.readSession,e,{signal:i.signal,onUpdate:r.callbacks.sessionUpdate,config:c})):{};if(o)w.additionalDirectories=e.additionalDirectories?[...e.additionalDirectories]:w.additionalDirectories;else{const i=await P(t,u=>de(l.readSession,e,u.signal));B(e.sessionId,e,t),await h.restoreUsage(i.find(u=>u.snapshot.sessionId===e.sessionId)?.snapshot.history??[],i)}return await J(t),c.lockAgent(),{...s,configOptions:c.snapshot()}},"resumeSession"),prompt:n(async(e,t)=>{O(e.sessionId);const s=await he(e),i=ce(e._meta);if(i?.mode==="steer"){const u=await l.steer(e.sessionId,s,{expectedRunId:i.expectedRequestId,signal:t?.signal});if(!u.steered)throw new V(X.invalidRequest,u.reason==="stale"?"Active query does not match expectedRequestId":"Session has no active query accepting steer");return{_meta:{"codebuddy.ai/requestId":u.runId}}}return j(s,e._meta,t)},"prompt"),compactSession:n(async(e,t)=>(O(e.sessionId),j({type:"compact"},e._meta,t)),"compactSession"),cancelSession:n(async e=>{O(e.sessionId),E?.abort(),await l.interrupt(e.sessionId),await S?.catch(()=>{})},"cancelSession"),closeSession:n(async e=>(O(e.sessionId),await N(),{}),"closeSession"),setAuthentication:n(async e=>e.generation<m?{applied:!1}:(f=e,m=e.generation,{applied:!0}),"setAuthentication"),clearAuthentication:n(async e=>e.generation<m?{applied:!1}:(f=void 0,m=e.generation,{applied:!0}),"clearAuthentication"),refreshUserConfig:n(async(e,t)=>{y(),t?.signal?.throwIfAborted();const s=++b,i=await d.runPromise((p.resolveOptions??workspaceQueryOptions)(r).pipe(d.provideContext(T)),{signal:t?.signal});y(),t?.signal?.throwIfAborted(),s===b&&(o&&l.reload(o,{settings:i.settings??{},agents:i.agents??{}}),a={...a,settings:i.settings,agents:i.agents})},"refreshUserConfig"),setSessionConfigOption:n(async(e,t)=>{if(O(e.sessionId),t?.signal?.throwIfAborted(),S)throw new V(X.invalidParams,"Cannot change Agent configuration during a prompt");const s=c.copy();s.set(e),await z(e.sessionId,w.cwd,s),c.replace(s);const i=c.snapshot();return await h.configuration(i),{configOptions:i}},"setSessionConfigOption")}}),a=>d.promise(()=>a.dispose())),"open")})}))}n(AgentBackend,"AgentBackend");
@@ -1 +1 @@
1
- var c=Object.defineProperty;var r=(e,i)=>c(e,"name",{value:i,configurable:!0});import{access as l,mkdir as m,readdir as a,readFile as s,rename as o,rm as n,stat as d,writeFile as y}from"node:fs/promises";export const localFs={pathStyle:"native",readFile:r(e=>s(e,"utf8"),"readFile"),readFileBuffer:r(e=>s(e),"readFileBuffer"),writeFile:r((e,i)=>y(e,i),"writeFile"),exists:r(async e=>{try{return await l(e),!0}catch(i){const t=i.code;if(t==="ENOENT"||t==="ENOTDIR")return!1;throw i}},"exists"),stat:r(async e=>{const i=await d(e);return{isFile:i.isFile(),isDirectory:i.isDirectory(),isSymbolicLink:i.isSymbolicLink(),size:i.size,mtime:i.mtime}},"stat"),mkdir:r(async(e,i)=>{await m(e,i)},"mkdir"),readdir:r(e=>a(e),"readdir"),readdirWithFileTypes:r(async e=>(await a(e,{withFileTypes:!0})).map(i=>({name:i.name,isFile:i.isFile(),isDirectory:i.isDirectory(),isSymbolicLink:i.isSymbolicLink()})),"readdirWithFileTypes"),rm:r((e,i)=>n(e,i),"rm"),mv:r((e,i)=>o(e,i),"mv")};
1
+ var c=Object.defineProperty;var r=(e,i)=>c(e,"name",{value:i,configurable:!0});import{access as l,lstat as m,mkdir as o,readdir as s,readFile as a,realpath as n,rename as y,rm as F,stat as d,writeFile as u}from"node:fs/promises";export const localFs={pathStyle:"native",readFile:r(e=>a(e,"utf8"),"readFile"),readFileBuffer:r(e=>a(e),"readFileBuffer"),writeFile:r((e,i)=>u(e,i),"writeFile"),exists:r(async e=>{try{return await l(e),!0}catch(i){const t=i.code;if(t==="ENOENT"||t==="ENOTDIR")return!1;throw i}},"exists"),stat:r(async e=>{const i=await d(e);return{isFile:i.isFile(),isDirectory:i.isDirectory(),isSymbolicLink:i.isSymbolicLink(),size:i.size,mtime:i.mtime}},"stat"),lstat:r(async e=>{const i=await m(e);return{isFile:i.isFile(),isDirectory:i.isDirectory(),isSymbolicLink:i.isSymbolicLink(),size:i.size,mtime:i.mtime}},"lstat"),realpath:n,mkdir:r(async(e,i)=>{await o(e,i)},"mkdir"),readdir:r(e=>s(e),"readdir"),readdirWithFileTypes:r(async e=>(await s(e,{withFileTypes:!0})).map(i=>({name:i.name,isFile:i.isFile(),isDirectory:i.isDirectory(),isSymbolicLink:i.isSymbolicLink()})),"readdirWithFileTypes"),rm:r((e,i)=>F(e,i),"rm"),mv:r((e,i)=>y(e,i),"mv")};