@agenthippo-ai/agenthippo 0.2.3-dataplane → 1.110.11

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 (139) hide show
  1. package/out/agentpack/index.js +3 -1
  2. package/out/agentpack/paths.js +25 -2
  3. package/out/analytics/dashboard/localFleetAdapter.js +82 -2
  4. package/out/analytics/dashboard/provider.js +13 -2
  5. package/out/analytics/dashboard/webview/panel.js +3 -2
  6. package/out/analytics/identity.js +0 -0
  7. package/out/analytics/service.js +29 -25
  8. package/out/analytics/sessionEvents.js +100 -24
  9. package/out/auth/authBaseUrl.js +59 -0
  10. package/out/auth/bootstrapApply.js +9 -10
  11. package/out/auth/brokerClient.js +48 -14
  12. package/out/auth/provider.js +8 -21
  13. package/out/auth/sessionStore.js +3 -40
  14. package/out/auth/signInFlow.js +2 -1
  15. package/out/auth-broker/config.js +50 -5
  16. package/out/auth-broker/server.js +126 -26
  17. package/out/auth-broker/store.js +25 -24
  18. package/out/authority/warrant.js +206 -0
  19. package/out/branding.js +27 -1
  20. package/out/cli/commands/conformance.js +249 -0
  21. package/out/cli/commands/data-plane.js +151 -0
  22. package/out/cli/commands/deploy.js +1 -0
  23. package/out/cli/commands/gateway.js +4 -0
  24. package/out/cli/commands/pack.js +182 -3
  25. package/out/cli/commands/sandbox.js +351 -0
  26. package/out/cli/commands/serve.js +1145 -130
  27. package/out/cli/commands/store.js +12 -4
  28. package/out/cli/credential-context.js +17 -0
  29. package/out/cli/data-plane/gateway.js +28 -5
  30. package/out/cli/data-plane/index.js +18 -2
  31. package/out/cli/data-plane/registry.js +9 -0
  32. package/out/cli/data-plane/remote.js +106 -0
  33. package/out/cli/data-plane/sidecar.js +225 -0
  34. package/out/cli/deploy/layers/identity.js +88 -4
  35. package/out/cli/deploy-init.js +89 -24
  36. package/out/cli/deps.js +106 -2
  37. package/out/cli/idp-init.js +35 -0
  38. package/out/cli/index.js +171 -17
  39. package/out/cli/pack-install-ref.js +15 -0
  40. package/out/cli/pack-loader.js +8 -1
  41. package/out/cli/pack-runtime.js +61 -0
  42. package/out/cli/runtime.js +35 -1
  43. package/out/cli/serve-hardening.js +260 -14
  44. package/out/cli/utils.js +12 -1
  45. package/out/engines/base.js +32 -3
  46. package/out/engines/claude.js +33 -15
  47. package/out/engines/codex.js +111 -27
  48. package/out/engines/custom.js +15 -1
  49. package/out/evidence/sessionShip.js +643 -0
  50. package/out/extension.js +11 -2
  51. package/out/gateway/bridge.js +40 -2
  52. package/out/gateway/client.js +34 -1
  53. package/out/gateway/installSource.js +68 -0
  54. package/out/gateway/lifecycle.js +185 -51
  55. package/out/gateway/outboundPaths.js +4 -1
  56. package/out/gateway/secretsPreflight.js +90 -0
  57. package/out/gateway/service.js +7 -2
  58. package/out/headless/index.js +25 -2
  59. package/out/live-e2e/mcp-demo/server.mjs +32 -0
  60. package/out/mcp.js +30 -0
  61. package/out/pack/caps.js +271 -0
  62. package/out/pack/governor.js +326 -0
  63. package/out/pack/lease-schema.js +273 -0
  64. package/out/pack/lease.js +682 -0
  65. package/out/pack/reconcile.js +217 -0
  66. package/out/pack/signature.js +839 -0
  67. package/out/remote/handleRemoteChat.js +44 -3
  68. package/out/remote/remoteTrust.js +277 -0
  69. package/out/remote/serveClient.js +52 -5
  70. package/out/runner/host.js +141 -0
  71. package/out/runner/protocol.js +128 -0
  72. package/out/runner/remoteEngine.js +166 -0
  73. package/out/runtime/interfaces/edit-tracker.js +2 -0
  74. package/out/runtime/vscode/vscode-edit-tracker.js +2 -0
  75. package/out/sandbox/containerDriver.js +572 -0
  76. package/out/sandbox/processDriver.js +318 -0
  77. package/out/sandbox/sandboxRunner.js +303 -0
  78. package/out/sandbox/support.js +301 -0
  79. package/out/sandbox/types.js +55 -0
  80. package/out/scripts/agentide-litellm.sh +67 -5
  81. package/out/scripts/agentide_litellm_hooks_v1.py +266 -21
  82. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +98 -132
  83. package/out/scripts/analytics/setup-analytics.ps1 +45 -14
  84. package/out/scripts/analytics/setup-analytics.sh +106 -15
  85. package/out/scripts/analytics/start-analytics.sh +86 -14
  86. package/out/scripts/gateway/setup-gateway.sh +72 -32
  87. package/out/shared/models.js +11 -110
  88. package/out/spotlight/install.js +7 -1
  89. package/out/store/index.js +41 -10
  90. package/out/sync.js +3 -1
  91. package/out/test/analytics.test.js +162 -23
  92. package/out/test/auth-baseurl.test.js +132 -0
  93. package/out/test/auth-bootstrapApply.test.js +27 -6
  94. package/out/test/auth-broker-hardening.test.js +227 -0
  95. package/out/test/auth-broker.test.js +59 -9
  96. package/out/test/branding.test.js +13 -0
  97. package/out/test/caps-governor.test.js +460 -0
  98. package/out/test/codex-new-file-survival.test.js +119 -0
  99. package/out/test/configuration-scopes.test.js +131 -0
  100. package/out/test/data-plane-engine-wiring.test.js +32 -0
  101. package/out/test/data-plane.test.js +380 -0
  102. package/out/test/deploy-init.test.js +47 -1
  103. package/out/test/gateway-client.test.js +28 -0
  104. package/out/test/gateway-install-source.test.js +111 -0
  105. package/out/test/gateway-lifecycle.test.js +1 -1
  106. package/out/test/gateway-outbound.test.js +7 -0
  107. package/out/test/gateway-secrets-preflight.test.js +127 -0
  108. package/out/test/gateway-session-routing.test.js +18 -0
  109. package/out/test/governor-hardening.test.js +222 -0
  110. package/out/test/headless-sync.test.js +22 -0
  111. package/out/test/lease-signature.test.js +357 -0
  112. package/out/test/lease-trust-root.test.js +273 -0
  113. package/out/test/lease-validation.test.js +224 -0
  114. package/out/test/lease.test.js +114 -0
  115. package/out/test/localFleetAdapter.test.js +91 -0
  116. package/out/test/mcp.test.js +27 -1
  117. package/out/test/pack-admission.test.js +216 -0
  118. package/out/test/pack-digest-parity.test.js +140 -0
  119. package/out/test/pack-reconcile.test.js +183 -0
  120. package/out/test/pack-signature-artifact.test.js +103 -0
  121. package/out/test/pack-signature.test.js +176 -0
  122. package/out/test/pack-trust-root.test.js +202 -0
  123. package/out/test/remote-trust.test.js +242 -0
  124. package/out/test/runner-protocol.test.js +249 -0
  125. package/out/test/sandbox-driver.test.js +553 -0
  126. package/out/test/sandbox-hardening.test.js +406 -0
  127. package/out/test/sandbox-runner.test.js +343 -0
  128. package/out/test/sandbox-scope.test.js +449 -0
  129. package/out/test/serve-cron-acceptance.test.js +370 -0
  130. package/out/test/serve-gateway-turn.test.js +122 -0
  131. package/out/test/serve-hardening.test.js +227 -15
  132. package/out/test/serveClient.test.js +6 -5
  133. package/out/test/sessionShip.test.js +618 -0
  134. package/out/test/spotlightPublish.test.js +28 -0
  135. package/out/test/store-install-safe.test.js +69 -0
  136. package/out/test/tls-bypass.test.js +90 -0
  137. package/out/test/warrant.test.js +138 -0
  138. package/out/utils.js +46 -9
  139. package/package.json +1 -1
@@ -37,6 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.CodexEngine = void 0;
40
+ exports.registerNewFilesWithTracker = registerNewFilesWithTracker;
40
41
  const fs_1 = require("fs");
41
42
  const path = __importStar(require("path"));
42
43
  const mcp_1 = require("../mcp");
@@ -47,8 +48,8 @@ const permissions_1 = require("../permissions");
47
48
  const session_1 = require("../session");
48
49
  const agentpack_1 = require("../agentpack");
49
50
  const credential_context_1 = require("../cli/credential-context");
50
- const data_plane_1 = require("../cli/data-plane");
51
51
  const runtime_1 = require("../cli/runtime");
52
+ const types_1 = require("../sandbox/types");
52
53
  // Note: HTTP edit server removed - file changes are now handled directly via file_change events
53
54
  // -----------------------------------------------------------------------------
54
55
  // Constants
@@ -65,11 +66,56 @@ const AGENTIDE_CODEX_AGENT_VERSION_ENV_VAR = 'AGENTIDE_ANALYTICS_AGENT_VERSION';
65
66
  const AGENTIDE_CODEX_SOURCE_ENV_VAR = 'AGENTIDE_ANALYTICS_SOURCE';
66
67
  const AGENTIDE_CODEX_ENGINE_ENV_VAR = 'AGENTIDE_ANALYTICS_ENGINE';
67
68
  const AGENTIDE_CODEX_REQUEST_ID_ENV_VAR = 'AGENTIDE_ANALYTICS_REQUEST_ID';
69
+ const AGENTIDE_CODEX_POLICY_VERSION_ENV_VAR = 'AGENTIDE_ANALYTICS_POLICY_VERSION';
70
+ const AGENTIDE_CODEX_PACK_DIGEST_ENV_VAR = 'AGENTIDE_ANALYTICS_PACK_DIGEST';
71
+ const AGENTIDE_CODEX_ENGINE_VERSION_ENV_VAR = 'AGENTIDE_ANALYTICS_ENGINE_VERSION';
72
+ const AGENTIDE_CODEX_TIER_ENV_VAR = 'AGENTIDE_ANALYTICS_TIER';
73
+ const AGENTIDE_CODEX_INSTANCE_ID_ENV_VAR = 'AGENTIDE_ANALYTICS_INSTANCE_ID';
68
74
  // Bump when we change generated config semantics so long-lived sessions regenerate config.toml.
69
- const AGENTIDE_CODEX_CONFIG_VERSION = 20; // v20: default_tools_approval_mode "auto"→"approve" ("auto" is invalid on codex ≥0.131 and cancels every headless MCP tool call)
75
+ const AGENTIDE_CODEX_CONFIG_VERSION = 21; // v21: sandbox_mode "danger-full-access" now requires tier 2, not merely being inside a sandbox — a tier-0 home written by v20 must be rewritten
70
76
  // Per-process runtime context for agents (not analytics): lets the agent locate its per-session context export.
71
77
  const AGENTIDE_CONTEXT_EXPORT_PATH_ENV_VAR = 'AGENTIDE_CONTEXT_EXPORT_PATH';
72
78
  const AGENTIDE_TERMINAL_LOG_PATH_ENV_VAR = 'AGENTIDE_TERMINAL_LOG_PATH';
79
+ /**
80
+ * Hand files codex just CREATED to the edit tracker so the IDE can render them against an empty
81
+ * original — without ever risking the agent's work.
82
+ *
83
+ * The IDE trick is read → delete → `applyEdit`. That delete caused live data loss: headless
84
+ * (`serve`/`ask`/`chat` and every sandbox) gets `NoOpEditTracker`, whose `applyEdit` does nothing, so
85
+ * every new file codex created was silently destroyed. The command exited 0, the file was there
86
+ * during the command, and it was gone by the next one — while standalone `codex exec` wrote it
87
+ * fine. Two guards now: skip trackers that do not write back, and restore the file if it is
88
+ * missing when we are done, whatever the tracker did or threw.
89
+ *
90
+ * Exported so the invariant "a file the agent created still exists after the turn" is testable.
91
+ */
92
+ async function registerNewFilesWithTracker(files, editTracker, sessionId) {
93
+ // A tracker that does not write the file back must never see a delete.
94
+ if (editTracker.appliesEdits === false) {
95
+ return;
96
+ }
97
+ for (const f of files) {
98
+ try {
99
+ if ((0, utils_1.isBinaryFile)(f)) {
100
+ continue; // Binary would be corrupted by the UTF-8 read/write round trip.
101
+ }
102
+ if (!(await (0, utils_1.pathExists)(f))) {
103
+ continue;
104
+ }
105
+ const code = await fs_1.promises.readFile(f, 'utf-8');
106
+ try {
107
+ await fs_1.promises.unlink(f);
108
+ await editTracker.applyEdit(sessionId, f, code, true);
109
+ }
110
+ finally {
111
+ if (!(await (0, utils_1.pathExists)(f))) {
112
+ await fs_1.promises.writeFile(f, code, 'utf-8');
113
+ }
114
+ }
115
+ }
116
+ catch { /* ignore — never fail a turn over edit-diff bookkeeping */ }
117
+ }
118
+ }
73
119
  function isCodexItemEvent(event) {
74
120
  return event.type === 'item.started' || event.type === 'item.updated' || event.type === 'item.completed';
75
121
  }
@@ -130,13 +176,17 @@ class CodexEngine {
130
176
  ...(runtime.cliEnvPatch ?? {}),
131
177
  OPENAI_LOG: 'debug',
132
178
  };
133
- // When serve runs the egress broker, the OpenClaw gateway token must never enter the
134
- // agent's trust domain (secure-obo-design §7.6 / §7.4 gap 1). Scrub it from the child env
135
- // at the spawn boundary — belt-and-suspenders with serve's boot-time process.env strip,
136
- // so a token in process.env (e.g. captured before the strip) still cannot reach the model.
137
- if (codexEnv[data_plane_1.EGRESS_URL_ENV]) {
138
- delete codexEnv[runtime_1.OPENCLAW_GATEWAY_TOKEN_ENV];
139
- }
179
+ // The OpenClaw gateway token must never enter the agent's trust domain (secure-obo-design
180
+ // §7.6 / §7.4 gap 1). UNCONDITIONALLY (serve-v4 §10 hole 2): the scrub used to depend on
181
+ // the egress broker being up, so a deployment without --gateway-bridge re-inherited the
182
+ // token — and buildCliEnvPatch can bake it in from the host's ~/.openclaw config, not just
183
+ // process.env. This engine never needs it: outbound goes through the broker's turn nonce,
184
+ // and the openclaw CLI reads its own config file on single-tenant hosts.
185
+ delete codexEnv[runtime_1.OPENCLAW_GATEWAY_TOKEN_ENV];
186
+ // Data-plane sidecar control token: the engine only needs the gateway URL + its per-turn
187
+ // nonce, never the register token — scrub it so a compromised agent can't forge a turn as
188
+ // another user (secure-obo-design §7.6). Harmless when absent (in-process/no data plane).
189
+ delete codexEnv['AGENTHIPPO_DATA_PLANE_TOKEN'];
140
190
  // Always expose the VS Code chat session id to the agent process so it can locate:
141
191
  // .agentide/sessions/<sessionId>/context.md
142
192
  const rawChatSessionId = sessionId?.trim();
@@ -157,7 +207,7 @@ class CodexEngine {
157
207
  // and a shared per-agent home lets concurrent turns of different users race it
158
208
  // (secure-obo-design §1 defect 1 / §8 Phase 0). No credential frame (IDE,
159
209
  // single-tenant CLI) ⇒ unchanged per-agent path.
160
- const codexHome = (0, agentpack_1.userScopedEngineHome)(runtimePaths.codexHome, (0, credential_context_1.currentCredential)()?.userId);
210
+ const codexHome = (0, agentpack_1.userScopedEngineHomeFromKey)(runtimePaths.codexHome, (0, credential_context_1.resolveEngineHomeUserKey)(options.engineHomeUserKey));
161
211
  codexEnv['CODEX_HOME'] = codexHome;
162
212
  await fs_1.promises.mkdir(codexHome, { recursive: true });
163
213
  // Always set AGENT_ID for agent to know its identity
@@ -179,7 +229,15 @@ class CodexEngine {
179
229
  agentId, // Pass agent ID for correct skills path
180
230
  runtime.permissionHandler instanceof interfaces_1.AutoApprovePermissionHandler);
181
231
  // LiteLLM analytics metadata (enriched - see PLAN/analytics-design.md)
182
- if (useLiteLLM && this.config.codexHome) {
232
+ //
233
+ // Gate on the codexHome actually in use (resolved above), NOT `this.config.codexHome`:
234
+ // headless/index.ts passes `codexHome: undefined`, so under serve/ask/chat and inside
235
+ // every sandbox this block was skipped and codex sent NO metadata headers at all — no
236
+ // session-id, user-id, agent-id, source, request-id, or engine. Spotlight lost codex
237
+ // attribution outside the IDE, and the gateway could not see `x-litellm-metadata-engine`,
238
+ // so engine-conditional ah-auto routing never fired. config.toml was written correctly
239
+ // the whole time (it uses this same resolved home) — only the env vars it reads were missing.
240
+ if (useLiteLLM && codexHome) {
183
241
  if (analyticsUserId?.trim()) {
184
242
  codexEnv[AGENTIDE_CODEX_USER_ENV_VAR] = analyticsUserId.trim();
185
243
  }
@@ -197,6 +255,21 @@ class CodexEngine {
197
255
  if (options.requestId) {
198
256
  codexEnv[AGENTIDE_CODEX_REQUEST_ID_ENV_VAR] = options.requestId;
199
257
  }
258
+ if (options.policyVersion?.trim()) {
259
+ codexEnv[AGENTIDE_CODEX_POLICY_VERSION_ENV_VAR] = options.policyVersion.trim();
260
+ }
261
+ if (options.packDigest?.trim()) {
262
+ codexEnv[AGENTIDE_CODEX_PACK_DIGEST_ENV_VAR] = options.packDigest.trim();
263
+ }
264
+ if (options.engineVersion?.trim()) {
265
+ codexEnv[AGENTIDE_CODEX_ENGINE_VERSION_ENV_VAR] = options.engineVersion.trim();
266
+ }
267
+ if (options.tier !== undefined) {
268
+ codexEnv[AGENTIDE_CODEX_TIER_ENV_VAR] = String(options.tier);
269
+ }
270
+ if (options.instanceId?.trim()) {
271
+ codexEnv[AGENTIDE_CODEX_INSTANCE_ID_ENV_VAR] = options.instanceId.trim();
272
+ }
200
273
  }
201
274
  // For custom providers (OpenRouter, LiteLLM), set API key in CODEX_API_KEY.
202
275
  // The config.toml's `env_key = "CODEX_API_KEY"` tells the CLI to read from this variable.
@@ -225,6 +298,16 @@ class CodexEngine {
225
298
  ];
226
299
  // Map unified permissions to Codex SDK options
227
300
  const codexPermOpts = (0, permissions_1.toCodexOptions)(effectivePerms, workspaceFolders);
301
+ // One boundary, not two — but only when the OTHER boundary is real. Inside a tier-2
302
+ // container Codex's own bubblewrap sandbox cannot start (it needs a user namespace
303
+ // `--cap-drop ALL` + `no-new-privileges` deny), so standing it down is the difference
304
+ // between working shell commands and silent failures. The tier-0 process driver
305
+ // provides NO boundary — same uid, same filesystem as serve — so there Codex's own
306
+ // sandbox is the only thing between the agent and the host and must stay on.
307
+ // The SDK's ThreadOptions.sandboxMode overrides config.toml, so force it here too.
308
+ if ((0, types_1.isContainerSandbox)()) {
309
+ codexPermOpts.sandboxMode = 'danger-full-access';
310
+ }
228
311
  logger.info(`[AgentIDE] Codex mapped: sandboxMode=${codexPermOpts.sandboxMode}, approvalPolicy=${codexPermOpts.approvalPolicy}`);
229
312
  // Build thread options
230
313
  // workingDirectory is ALWAYS workspaceRoot - pack content is synced to workspace's .codex/
@@ -411,21 +494,7 @@ class CodexEngine {
411
494
  catch { /* ignore */ }
412
495
  pendingOperations.delete(item.id);
413
496
  }
414
- // New files: read, delete, apply (so VS Code sees original=empty)
415
- // Skip binary files - they would be corrupted by UTF-8 read/write
416
- for (const f of pendingNewFiles.get(item.id) ?? []) {
417
- try {
418
- if ((0, utils_1.isBinaryFile)(f)) {
419
- continue; // Don't track binary files for edit diffs
420
- }
421
- if (await (0, utils_1.pathExists)(f)) {
422
- const code = await fs_1.promises.readFile(f, 'utf-8');
423
- await fs_1.promises.unlink(f);
424
- await editTracker.applyEdit(rawChatSessionId, f, code, true);
425
- }
426
- }
427
- catch { /* ignore */ }
428
- }
497
+ await registerNewFilesWithTracker(pendingNewFiles.get(item.id) ?? [], editTracker, rawChatSessionId);
429
498
  pendingNewFiles.delete(item.id);
430
499
  }
431
500
  }
@@ -637,6 +706,16 @@ class CodexEngine {
637
706
  // Codex CLI loads a single "model instructions" file that acts like a system/developer prompt overlay.
638
707
  // Note: experimental_instructions_file is deprecated and ignored by newer Codex CLI versions.
639
708
  codexInstructionsFile ? `model_instructions_file = ${JSON.stringify(codexInstructionsFile)}` : undefined,
709
+ // Inside a TIER-2 sandbox the container is the boundary, so Codex's own sandbox is not
710
+ // just redundant — it cannot start. It shells out to bubblewrap, which needs to create
711
+ // a user namespace and scratch space under /tmp; a container drops those capabilities by
712
+ // design (`--cap-drop ALL`, `no-new-privileges`), so every shell command and file
713
+ // write failed while still reporting exit 0. One boundary, not two — but the tier-0
714
+ // process driver is not a boundary at all, so it never earns this. Keyed on the tier
715
+ // the driver reports, not on merely being inside a sandbox.
716
+ ...((0, types_1.isContainerSandbox)()
717
+ ? ['sandbox_mode = "danger-full-access"']
718
+ : []),
640
719
  ];
641
720
  // Add custom provider section for LiteLLM or custom providers (e.g., OpenRouter)
642
721
  if (customBaseUrl) {
@@ -655,7 +734,12 @@ class CodexEngine {
655
734
  `"x-litellm-metadata-agent-version" = "${AGENTIDE_CODEX_AGENT_VERSION_ENV_VAR}", ` +
656
735
  `"x-litellm-metadata-source" = "${AGENTIDE_CODEX_SOURCE_ENV_VAR}", ` +
657
736
  `"x-litellm-metadata-engine" = "${AGENTIDE_CODEX_ENGINE_ENV_VAR}", ` +
658
- `"x-litellm-metadata-request-id" = "${AGENTIDE_CODEX_REQUEST_ID_ENV_VAR}" }`);
737
+ `"x-litellm-metadata-request-id" = "${AGENTIDE_CODEX_REQUEST_ID_ENV_VAR}", ` +
738
+ `"x-litellm-metadata-policy-version" = "${AGENTIDE_CODEX_POLICY_VERSION_ENV_VAR}", ` +
739
+ `"x-litellm-metadata-pack-digest" = "${AGENTIDE_CODEX_PACK_DIGEST_ENV_VAR}", ` +
740
+ `"x-litellm-metadata-engine-version" = "${AGENTIDE_CODEX_ENGINE_VERSION_ENV_VAR}", ` +
741
+ `"x-litellm-metadata-tier" = "${AGENTIDE_CODEX_TIER_ENV_VAR}", ` +
742
+ `"x-litellm-metadata-instance-id" = "${AGENTIDE_CODEX_INSTANCE_ID_ENV_VAR}" }`);
659
743
  }
660
744
  }
661
745
  // Add MCP servers section (pack-aware)
@@ -47,8 +47,10 @@ const fs_1 = require("fs");
47
47
  const path = __importStar(require("path"));
48
48
  const url_1 = require("url");
49
49
  const base_1 = require("./base");
50
+ const runtime_1 = require("../cli/runtime");
50
51
  const customRegistry_1 = require("./customRegistry");
51
52
  const paths_1 = require("../agentpack/paths");
53
+ const credential_context_1 = require("../cli/credential-context");
52
54
  const utils_1 = require("../utils");
53
55
  const resolveNodeBinary_1 = require("../utils/resolveNodeBinary");
54
56
  const customEngineIpc_1 = require("./customEngineIpc");
@@ -493,7 +495,12 @@ class CustomEngine {
493
495
  const customBaseDir = this.config.customEnginesStoragePath
494
496
  ?? path.join(this.config.storagePath, paths_1.AGENT_CONSTANTS.AGENTS_DIR, agentId, 'custom');
495
497
  const engineBaseDir = path.join(customBaseDir, manifest.id);
496
- const engineHomeDir = path.join(engineBaseDir, 'home');
498
+ // Per-user, on the same rule claude and codex use. This engine had NO user scoping at all
499
+ // — in serve or in a sandbox — so on a multi-user deployment every custom engine's home
500
+ // (its config, caches, and whatever the engine chooses to persist) was one shared
501
+ // directory. `home` is the one that needed it: engineSessionDir is already per session.
502
+ // No verified user ⇒ unchanged path, so the IDE and single-tenant CLI are unaffected.
503
+ const engineHomeDir = (0, paths_1.userScopedEngineHomeFromKey)(path.join(engineBaseDir, 'home'), (0, credential_context_1.resolveEngineHomeUserKey)(options.engineHomeUserKey));
497
504
  const engineSessionDir = path.join(engineBaseDir, paths_1.AGENT_CONSTANTS.SESSIONS_DIR, sessionDirName);
498
505
  await fs_1.promises.mkdir(engineHomeDir, { recursive: true });
499
506
  await fs_1.promises.mkdir(engineSessionDir, { recursive: true });
@@ -534,6 +541,8 @@ class CustomEngine {
534
541
  AGENTHIPPO_MODEL_ID: modelId,
535
542
  AGENTHIPPO_USE_LITELLM: routing.useLiteLLM ? 'true' : 'false',
536
543
  };
544
+ delete env[runtime_1.OPENCLAW_GATEWAY_TOKEN_ENV];
545
+ delete env['AGENTHIPPO_DATA_PLANE_TOKEN'];
537
546
  prependNodePath(env, manifest.manifestDir);
538
547
  if (routingApiKey) {
539
548
  env.AGENTHIPPO_API_KEY = routingApiKey;
@@ -560,6 +569,11 @@ class CustomEngine {
560
569
  source: 'agenthippo',
561
570
  engine: `custom:${manifest.id}`,
562
571
  requestId: options.requestId,
572
+ policyVersion: options.policyVersion,
573
+ packDigest: options.packDigest,
574
+ instanceId: options.instanceId,
575
+ engineVersion: options.engineVersion,
576
+ tier: options.tier,
563
577
  });
564
578
  if (litellmMetadataHeaders.length > 0) {
565
579
  env.AGENTHIPPO_LITELLM_METADATA_HEADERS = litellmMetadataHeaders.join('\n');