@agenthippo-ai/agenthippo 0.2.3-dataplane → 1.110.9

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 (130) hide show
  1. package/out/analytics/dashboard/provider.js +13 -2
  2. package/out/analytics/dashboard/webview/panel.js +3 -2
  3. package/out/analytics/identity.js +0 -0
  4. package/out/analytics/service.js +23 -25
  5. package/out/analytics/sessionEvents.js +98 -23
  6. package/out/auth/authBaseUrl.js +59 -0
  7. package/out/auth/bootstrapApply.js +9 -10
  8. package/out/auth/brokerClient.js +48 -14
  9. package/out/auth/provider.js +8 -21
  10. package/out/auth/sessionStore.js +3 -40
  11. package/out/auth/signInFlow.js +2 -1
  12. package/out/auth-broker/config.js +50 -5
  13. package/out/auth-broker/server.js +122 -26
  14. package/out/auth-broker/store.js +25 -24
  15. package/out/authority/warrant.js +206 -0
  16. package/out/branding.js +27 -1
  17. package/out/cli/commands/conformance.js +249 -0
  18. package/out/cli/commands/data-plane.js +67 -0
  19. package/out/cli/commands/deploy.js +1 -0
  20. package/out/cli/commands/gateway.js +4 -0
  21. package/out/cli/commands/pack.js +182 -3
  22. package/out/cli/commands/sandbox.js +332 -0
  23. package/out/cli/commands/serve.js +875 -52
  24. package/out/cli/commands/store.js +12 -4
  25. package/out/cli/data-plane/gateway.js +28 -5
  26. package/out/cli/data-plane/index.js +17 -2
  27. package/out/cli/data-plane/registry.js +9 -0
  28. package/out/cli/data-plane/remote.js +106 -0
  29. package/out/cli/data-plane/sidecar.js +161 -0
  30. package/out/cli/deploy/layers/identity.js +85 -4
  31. package/out/cli/deploy-init.js +89 -24
  32. package/out/cli/deps.js +106 -2
  33. package/out/cli/idp-init.js +35 -0
  34. package/out/cli/index.js +155 -16
  35. package/out/cli/pack-install-ref.js +15 -0
  36. package/out/cli/pack-loader.js +8 -1
  37. package/out/cli/pack-runtime.js +61 -0
  38. package/out/cli/runtime.js +35 -1
  39. package/out/cli/serve-hardening.js +80 -3
  40. package/out/cli/utils.js +12 -1
  41. package/out/engines/base.js +32 -3
  42. package/out/engines/claude.js +33 -15
  43. package/out/engines/codex.js +110 -26
  44. package/out/engines/custom.js +8 -0
  45. package/out/evidence/sessionShip.js +610 -0
  46. package/out/extension.js +11 -2
  47. package/out/gateway/bridge.js +40 -2
  48. package/out/gateway/client.js +34 -1
  49. package/out/gateway/installSource.js +68 -0
  50. package/out/gateway/lifecycle.js +185 -51
  51. package/out/gateway/outboundPaths.js +4 -1
  52. package/out/gateway/secretsPreflight.js +90 -0
  53. package/out/gateway/service.js +7 -2
  54. package/out/headless/index.js +17 -1
  55. package/out/live-e2e/mcp-demo/server.mjs +32 -0
  56. package/out/mcp.js +30 -0
  57. package/out/pack/caps.js +271 -0
  58. package/out/pack/governor.js +309 -0
  59. package/out/pack/lease-schema.js +270 -0
  60. package/out/pack/lease.js +640 -0
  61. package/out/pack/reconcile.js +217 -0
  62. package/out/pack/signature.js +839 -0
  63. package/out/remote/handleRemoteChat.js +44 -3
  64. package/out/remote/remoteTrust.js +277 -0
  65. package/out/remote/serveClient.js +52 -5
  66. package/out/runner/host.js +131 -0
  67. package/out/runner/protocol.js +108 -0
  68. package/out/runner/remoteEngine.js +130 -0
  69. package/out/runtime/interfaces/edit-tracker.js +2 -0
  70. package/out/runtime/vscode/vscode-edit-tracker.js +2 -0
  71. package/out/sandbox/containerDriver.js +570 -0
  72. package/out/sandbox/processDriver.js +315 -0
  73. package/out/sandbox/sandboxRunner.js +191 -0
  74. package/out/sandbox/support.js +301 -0
  75. package/out/sandbox/types.js +55 -0
  76. package/out/scripts/agentide-litellm.sh +67 -5
  77. package/out/scripts/agentide_litellm_hooks_v1.py +182 -21
  78. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +94 -132
  79. package/out/scripts/analytics/setup-analytics.ps1 +37 -13
  80. package/out/scripts/analytics/setup-analytics.sh +93 -13
  81. package/out/scripts/analytics/start-analytics.sh +86 -14
  82. package/out/scripts/gateway/setup-gateway.sh +72 -32
  83. package/out/shared/models.js +11 -110
  84. package/out/spotlight/install.js +7 -1
  85. package/out/store/index.js +41 -10
  86. package/out/sync.js +3 -1
  87. package/out/test/analytics.test.js +162 -23
  88. package/out/test/auth-baseurl.test.js +132 -0
  89. package/out/test/auth-bootstrapApply.test.js +27 -6
  90. package/out/test/auth-broker-hardening.test.js +227 -0
  91. package/out/test/auth-broker.test.js +59 -9
  92. package/out/test/branding.test.js +13 -0
  93. package/out/test/caps-governor.test.js +455 -0
  94. package/out/test/codex-new-file-survival.test.js +119 -0
  95. package/out/test/configuration-scopes.test.js +131 -0
  96. package/out/test/data-plane.test.js +67 -0
  97. package/out/test/deploy-init.test.js +40 -0
  98. package/out/test/gateway-client.test.js +28 -0
  99. package/out/test/gateway-install-source.test.js +111 -0
  100. package/out/test/gateway-lifecycle.test.js +1 -1
  101. package/out/test/gateway-outbound.test.js +7 -0
  102. package/out/test/gateway-secrets-preflight.test.js +127 -0
  103. package/out/test/gateway-session-routing.test.js +18 -0
  104. package/out/test/governor-hardening.test.js +217 -0
  105. package/out/test/headless-sync.test.js +22 -0
  106. package/out/test/lease-signature.test.js +357 -0
  107. package/out/test/lease-trust-root.test.js +273 -0
  108. package/out/test/lease-validation.test.js +169 -0
  109. package/out/test/lease.test.js +114 -0
  110. package/out/test/mcp.test.js +27 -1
  111. package/out/test/pack-admission.test.js +216 -0
  112. package/out/test/pack-digest-parity.test.js +140 -0
  113. package/out/test/pack-reconcile.test.js +183 -0
  114. package/out/test/pack-signature-artifact.test.js +103 -0
  115. package/out/test/pack-signature.test.js +176 -0
  116. package/out/test/pack-trust-root.test.js +202 -0
  117. package/out/test/remote-trust.test.js +242 -0
  118. package/out/test/runner-protocol.test.js +249 -0
  119. package/out/test/sandbox-driver.test.js +553 -0
  120. package/out/test/sandbox-hardening.test.js +395 -0
  121. package/out/test/sandbox-runner.test.js +343 -0
  122. package/out/test/serve-hardening.test.js +45 -6
  123. package/out/test/serveClient.test.js +6 -5
  124. package/out/test/sessionShip.test.js +560 -0
  125. package/out/test/spotlightPublish.test.js +28 -0
  126. package/out/test/store-install-safe.test.js +69 -0
  127. package/out/test/tls-bypass.test.js +90 -0
  128. package/out/test/warrant.test.js +138 -0
  129. package/out/utils.js +46 -9
  130. package/package.json +1 -1
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Sandbox runner layer (PLAN/serve-v4-clean.md §3–§4).
4
+ *
5
+ * Covers the three rules the design turns on, each of which is a bug if it regresses:
6
+ * 1. a turn settles on the TERMINAL frame, never on the streamed `done` (engines call done()
7
+ * mid-run — the existing worker protocol separates them for exactly this reason);
8
+ * 2. `question` is one-way — no reverse RPC, so it can never wedge a turn;
9
+ * 3. no model credential crosses into the sandbox (invariant 1).
10
+ *--------------------------------------------------------------------------------------------*/
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ require("mocha");
46
+ const assert = __importStar(require("assert"));
47
+ const node_stream_1 = require("node:stream");
48
+ const protocol_1 = require("../runner/protocol");
49
+ const host_1 = require("../runner/host");
50
+ const remoteEngine_1 = require("../runner/remoteEngine");
51
+ /** Minimal options for tests — the fields under test are baseUrl/modelToken/apiKey only. */
52
+ const WIRE_OPTS = {};
53
+ suite('runner protocol', () => {
54
+ test('round-trips every frame kind', () => {
55
+ const frames = [
56
+ { type: 'ready' },
57
+ { type: 'result', id: 'r1', nativeSessionId: 'nsid-9' },
58
+ { type: 'failed', id: 'r2', message: 'boom' },
59
+ { type: 'text', delta: 'hi' },
60
+ { type: 'toolEnd', toolName: 't', toolCallId: 'c1', isError: true },
61
+ { type: 'question', payload: { questionId: 'q1', prompt: 'pick' } },
62
+ ];
63
+ for (const f of frames) {
64
+ assert.deepStrictEqual((0, protocol_1.parseRunnerFrame)((0, protocol_1.encodeRunnerFrame)(f).trim()), f, `round-trip ${f.type}`);
65
+ }
66
+ const client = { type: 'run', id: 'r1', message: 'go', options: WIRE_OPTS };
67
+ assert.deepStrictEqual((0, protocol_1.parseClientFrame)((0, protocol_1.encodeClientFrame)(client).trim()), client);
68
+ assert.deepStrictEqual((0, protocol_1.parseClientFrame)('{"type":"abort","id":"r1"}'), { type: 'abort', id: 'r1' });
69
+ });
70
+ test('malformed input is dropped, never thrown — the sandbox is untrusted toward serve', () => {
71
+ for (const bad of ['', 'not json', '[]', 'null', '{"type":"nope"}', '{"type":"result"}', '{"type":"run"}']) {
72
+ assert.strictEqual((0, protocol_1.parseRunnerFrame)(bad), undefined, `runner frame: ${bad}`);
73
+ assert.strictEqual((0, protocol_1.parseClientFrame)(bad), undefined, `client frame: ${bad}`);
74
+ }
75
+ });
76
+ test('terminal frames are exactly result/failed — done and error are NOT terminal', () => {
77
+ assert.ok((0, protocol_1.isTerminalFrame)({ type: 'result', id: 'r1' }));
78
+ assert.ok((0, protocol_1.isTerminalFrame)({ type: 'failed', id: 'r1', message: 'x' }));
79
+ assert.ok(!(0, protocol_1.isTerminalFrame)({ type: 'done' }), 'streamed done must not end a turn');
80
+ assert.ok(!(0, protocol_1.isTerminalFrame)({ type: 'error', message: 'x' }), 'streamed error must not end a turn');
81
+ });
82
+ test('splitFrames keeps partial lines for the next chunk', () => {
83
+ const a = (0, protocol_1.splitFrames)('{"type":"ready"}\n{"type":"do');
84
+ assert.deepStrictEqual(a.lines, ['{"type":"ready"}']);
85
+ assert.strictEqual(a.rest, '{"type":"do');
86
+ const b = (0, protocol_1.splitFrames)(a.rest + 'ne"}\n');
87
+ assert.deepStrictEqual(b.lines, ['{"type":"done"}']);
88
+ assert.strictEqual(b.rest, '');
89
+ });
90
+ test('toWireOptions drops apiKey and attaches the sandbox-scoped model token (invariant 1)', () => {
91
+ const wire = (0, protocol_1.toWireOptions)({ apiKey: 'sk-secret', model: 'gpt-5.5', workspace: '/w' }, { baseUrl: 'http://127.0.0.1:9099/v1', modelToken: 'sandbox-scoped' });
92
+ assert.ok(!('apiKey' in wire), 'apiKey must never cross the sandbox boundary');
93
+ assert.ok(!JSON.stringify(wire).includes('sk-secret'), 'no provider key anywhere in the frame');
94
+ assert.strictEqual(wire.baseUrl, 'http://127.0.0.1:9099/v1');
95
+ assert.strictEqual(wire.modelToken, 'sandbox-scoped');
96
+ assert.strictEqual(wire.model, 'gpt-5.5', 'non-secret options survive');
97
+ });
98
+ });
99
+ /** Wire a RemoteEngine to a runner host over two in-memory pipes — the `process` driver shape. */
100
+ function pair(engine) {
101
+ const toRunner = new node_stream_1.PassThrough();
102
+ const toServe = new node_stream_1.PassThrough();
103
+ const host = (0, host_1.startRunnerHost)({
104
+ engine,
105
+ runtime: { logger: { info() { }, warn() { }, error() { }, debug() { } } },
106
+ input: toRunner,
107
+ output: { write: (c) => toServe.write(c) },
108
+ maintenanceIntervalMs: 60_000,
109
+ });
110
+ const remote = new remoteEngine_1.RemoteEngine({
111
+ id: 'test', displayName: 'Test',
112
+ channel: { input: toServe, output: { write: (c) => toRunner.write(c) } },
113
+ });
114
+ return { host, remote };
115
+ }
116
+ function recorder() {
117
+ const events = [];
118
+ const emitter = {
119
+ async thinking(d) { events.push(`thinking:${d}`); },
120
+ async text(d) { events.push(`text:${d}`); },
121
+ async toolStart(n) { events.push(`toolStart:${n}`); },
122
+ async toolEnd(n) { events.push(`toolEnd:${n}`); },
123
+ async progress(m) { events.push(`progress:${m}`); },
124
+ async question(p) { events.push(`question:${p.questionId}`); return { selected: [], freeText: null, declined: true }; },
125
+ async error(m) { events.push(`error:${m}`); },
126
+ async done() { events.push('done'); },
127
+ };
128
+ return { events, emitter };
129
+ }
130
+ const RUNTIME = { logger: { info() { }, warn() { }, error() { }, debug() { } } };
131
+ suite('runner host ⇄ RemoteEngine', () => {
132
+ test('streams events through and settles on the terminal frame, not the mid-run done()', async () => {
133
+ let resolveEngine;
134
+ const engine = {
135
+ id: 'e', displayName: 'E',
136
+ async stream(_m, _o, emitter) {
137
+ await emitter.text('hello');
138
+ await emitter.done(); // engines call done() MID-RUN...
139
+ await new Promise((r) => { resolveEngine = r; }); // ...then keep working
140
+ await emitter.text('after-done');
141
+ },
142
+ onMaintenance() { }, dispose() { },
143
+ };
144
+ const { remote } = pair(engine);
145
+ const { events, emitter } = recorder();
146
+ let settled = false;
147
+ const turn = remote.stream('go', {}, emitter, RUNTIME).then(() => { settled = true; });
148
+ await waitFor(() => events.includes('done'));
149
+ assert.strictEqual(settled, false, 'streamed done must NOT settle the turn');
150
+ resolveEngine?.();
151
+ await turn;
152
+ assert.strictEqual(settled, true, 'turn settles once the engine returns (result frame)');
153
+ assert.deepStrictEqual(events, ['text:hello', 'done', 'text:after-done']);
154
+ });
155
+ test('engine failure rejects the turn with the runner message', async () => {
156
+ const engine = {
157
+ id: 'e', displayName: 'E',
158
+ async stream() { throw new Error('engine exploded'); },
159
+ onMaintenance() { }, dispose() { },
160
+ };
161
+ const { remote } = pair(engine);
162
+ const { emitter } = recorder();
163
+ await assert.rejects(remote.stream('go', {}, emitter, RUNTIME), /engine exploded/);
164
+ });
165
+ test('question is one-way: the runner answers declined locally and the turn never blocks', async () => {
166
+ let answer;
167
+ const engine = {
168
+ id: 'e', displayName: 'E',
169
+ async stream(_m, _o, emitter) {
170
+ // If this awaited a reverse RPC that never comes, the turn would hang — the
171
+ // deadlock class the design removes by construction.
172
+ answer = await emitter.question({ questionId: 'q1', prompt: 'pick one' });
173
+ await emitter.text('continued');
174
+ },
175
+ onMaintenance() { }, dispose() { },
176
+ };
177
+ const { remote } = pair(engine);
178
+ const { events, emitter } = recorder();
179
+ await remote.stream('go', {}, emitter, RUNTIME);
180
+ assert.deepStrictEqual(answer, { selected: [], freeText: null, declined: true }, 'runner answers declined in-sandbox, mirroring serve.ts and headless');
181
+ assert.ok(events.includes('question:q1'), 'question still forwarded to serve for visibility');
182
+ assert.ok(events.includes('text:continued'), 'the run continues past the question');
183
+ });
184
+ test('abort reaches the in-sandbox engine and settles the turn', async () => {
185
+ const engine = {
186
+ id: 'e', displayName: 'E',
187
+ async stream(_m, _o, _emitter, _rt, signal) {
188
+ await new Promise((_resolve, reject) => {
189
+ if (signal?.aborted) {
190
+ return reject(new Error('aborted'));
191
+ }
192
+ signal?.addEventListener('abort', () => reject(new Error('aborted')), { once: true });
193
+ });
194
+ },
195
+ onMaintenance() { }, dispose() { },
196
+ };
197
+ const { remote } = pair(engine);
198
+ const { emitter } = recorder();
199
+ const controller = new AbortController();
200
+ const turn = remote.stream('go', {}, emitter, RUNTIME, controller.signal);
201
+ setTimeout(() => controller.abort(), 20);
202
+ await assert.rejects(turn, /aborted/);
203
+ });
204
+ test('nativeSessionId rides the terminal frame — session resume across sandbox death', async () => {
205
+ const engine = {
206
+ id: 'e', displayName: 'E',
207
+ async stream(_m, _o, emitter) { await emitter.text('x'); },
208
+ onMaintenance() { }, dispose() { },
209
+ };
210
+ const frames = [];
211
+ const toRunner = new node_stream_1.PassThrough();
212
+ (0, host_1.startRunnerHost)({
213
+ engine, runtime: RUNTIME, input: toRunner,
214
+ output: { write: (c) => { frames.push(c.trim()); return true; } },
215
+ maintenanceIntervalMs: 60_000,
216
+ });
217
+ const runFrame = { type: 'run', id: 'r1', message: 'go', options: WIRE_OPTS };
218
+ toRunner.write((0, protocol_1.encodeClientFrame)(runFrame));
219
+ await waitFor(() => frames.some((f) => f.includes('"result"')));
220
+ assert.ok(frames[0].includes('"ready"'), 'runner announces ready before serving turns');
221
+ const terminal = frames.find((f) => f.includes('"result"'));
222
+ assert.ok(terminal.includes('"id":"r1"'), 'terminal carries the run id');
223
+ });
224
+ test('a dead channel fails in-flight turns instead of hanging them', async () => {
225
+ const toServe = new node_stream_1.PassThrough();
226
+ let closeChannel;
227
+ const remote = new remoteEngine_1.RemoteEngine({
228
+ id: 't', displayName: 'T',
229
+ channel: {
230
+ input: toServe,
231
+ output: { write: () => true },
232
+ closed: new Promise((resolve) => { closeChannel = resolve; }),
233
+ },
234
+ });
235
+ const { emitter } = recorder();
236
+ const turn = remote.stream('go', {}, emitter, RUNTIME);
237
+ setTimeout(() => closeChannel?.(), 20);
238
+ await assert.rejects(turn, /sandbox channel closed/);
239
+ });
240
+ });
241
+ async function waitFor(cond, timeoutMs = 2000) {
242
+ const start = Date.now();
243
+ while (!cond()) {
244
+ if (Date.now() - start > timeoutMs) {
245
+ throw new Error('timed out waiting for condition');
246
+ }
247
+ await new Promise((r) => setTimeout(r, 5));
248
+ }
249
+ }