@amodalai/runtime 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/__fixtures__/e2e.test.js +2 -2
- package/dist/src/__fixtures__/e2e.test.js.map +1 -1
- package/dist/src/__fixtures__/smoke.test.js +0 -88
- package/dist/src/__fixtures__/smoke.test.js.map +1 -1
- package/dist/src/__tests__/studio-integration.test.js +298 -0
- package/dist/src/__tests__/studio-integration.test.js.map +1 -0
- package/dist/src/agent/agent-types.d.ts +4 -0
- package/dist/src/agent/feedback-store.d.ts +11 -10
- package/dist/src/agent/feedback-store.js +147 -75
- package/dist/src/agent/feedback-store.js.map +1 -1
- package/dist/src/agent/local-server.js +30 -111
- package/dist/src/agent/local-server.js.map +1 -1
- package/dist/src/agent/local-server.test.js +17 -1
- package/dist/src/agent/local-server.test.js.map +1 -1
- package/dist/src/agent/routes/context.d.ts +24 -0
- package/dist/src/agent/routes/context.js +30 -0
- package/dist/src/agent/routes/context.js.map +1 -0
- package/dist/src/agent/routes/feedback.js +28 -56
- package/dist/src/agent/routes/feedback.js.map +1 -1
- package/dist/src/api/create-agent.js +8 -4
- package/dist/src/api/create-agent.js.map +1 -1
- package/dist/src/api/types.d.ts +1 -1
- package/dist/src/channels/channel-session-mapper.js +1 -1
- package/dist/src/channels/channel-session-mapper.js.map +1 -1
- package/dist/src/config.d.ts +2 -2
- package/dist/src/config.js +2 -1
- package/dist/src/config.js.map +1 -1
- package/dist/src/config.test.js +1 -1
- package/dist/src/config.test.js.map +1 -1
- package/dist/src/errors.d.ts +2 -2
- package/dist/src/errors.js +2 -2
- package/dist/src/index.d.ts +0 -3
- package/dist/src/index.js +0 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.js +1 -0
- package/dist/src/server.js.map +1 -1
- package/dist/src/session/drizzle-session-store.d.ts +4 -6
- package/dist/src/session/drizzle-session-store.js +15 -5
- package/dist/src/session/drizzle-session-store.js.map +1 -1
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/manager.test.js +7 -5
- package/dist/src/session/manager.test.js.map +1 -1
- package/dist/src/session/postgres-session-store.d.ts +3 -24
- package/dist/src/session/postgres-session-store.js +9 -128
- package/dist/src/session/postgres-session-store.js.map +1 -1
- package/dist/src/session/session-builder.d.ts +0 -4
- package/dist/src/session/session-builder.js +2 -9
- package/dist/src/session/session-builder.js.map +1 -1
- package/dist/src/session/session-builder.test.js +0 -25
- package/dist/src/session/session-builder.test.js.map +1 -1
- package/dist/src/session/session-store-selector.d.ts +11 -26
- package/dist/src/session/session-store-selector.js +3 -48
- package/dist/src/session/session-store-selector.js.map +1 -1
- package/dist/src/session/session-store-selector.test.js +5 -57
- package/dist/src/session/session-store-selector.test.js.map +1 -1
- package/dist/src/session/store.d.ts +8 -14
- package/dist/src/session/store.js +8 -10
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/store.test.js +6 -126
- package/dist/src/session/store.test.js.map +1 -1
- package/dist/src/session/tool-context-factory.js +1 -1
- package/dist/src/session/tool-context-factory.js.map +1 -1
- package/dist/src/stores/drizzle-store-backend.d.ts +5 -0
- package/dist/src/stores/drizzle-store-backend.js +23 -3
- package/dist/src/stores/drizzle-store-backend.js.map +1 -1
- package/dist/src/stores/drizzle-store-backend.test.js +10 -58
- package/dist/src/stores/drizzle-store-backend.test.js.map +1 -1
- package/dist/src/stores/index.d.ts +0 -2
- package/dist/src/stores/index.js +0 -1
- package/dist/src/stores/index.js.map +1 -1
- package/dist/src/stores/postgres-store-backend.d.ts +5 -15
- package/dist/src/stores/postgres-store-backend.js +14 -72
- package/dist/src/stores/postgres-store-backend.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -6
- package/dist/src/agent/automation-bridge.d.ts +0 -33
- package/dist/src/agent/automation-bridge.js +0 -50
- package/dist/src/agent/automation-bridge.js.map +0 -1
- package/dist/src/agent/automation-bridge.test.d.ts +0 -6
- package/dist/src/agent/automation-bridge.test.js +0 -130
- package/dist/src/agent/automation-bridge.test.js.map +0 -1
- package/dist/src/agent/eval-store.d.ts +0 -50
- package/dist/src/agent/eval-store.js +0 -137
- package/dist/src/agent/eval-store.js.map +0 -1
- package/dist/src/agent/proactive/delivery-router.d.ts +0 -68
- package/dist/src/agent/proactive/delivery-router.js +0 -337
- package/dist/src/agent/proactive/delivery-router.js.map +0 -1
- package/dist/src/agent/proactive/delivery-router.test.js +0 -455
- package/dist/src/agent/proactive/delivery-router.test.js.map +0 -1
- package/dist/src/agent/proactive/delivery.d.ts +0 -21
- package/dist/src/agent/proactive/delivery.js +0 -68
- package/dist/src/agent/proactive/delivery.js.map +0 -1
- package/dist/src/agent/proactive/delivery.test.d.ts +0 -6
- package/dist/src/agent/proactive/delivery.test.js +0 -65
- package/dist/src/agent/proactive/delivery.test.js.map +0 -1
- package/dist/src/agent/proactive/proactive-runner.d.ts +0 -129
- package/dist/src/agent/proactive/proactive-runner.js +0 -301
- package/dist/src/agent/proactive/proactive-runner.js.map +0 -1
- package/dist/src/agent/proactive/proactive-runner.test.d.ts +0 -6
- package/dist/src/agent/proactive/proactive-runner.test.js +0 -250
- package/dist/src/agent/proactive/proactive-runner.test.js.map +0 -1
- package/dist/src/agent/routes/admin-chat-abort.test.d.ts +0 -6
- package/dist/src/agent/routes/admin-chat-abort.test.js +0 -207
- package/dist/src/agent/routes/admin-chat-abort.test.js.map +0 -1
- package/dist/src/agent/routes/admin-chat.d.ts +0 -28
- package/dist/src/agent/routes/admin-chat.js +0 -110
- package/dist/src/agent/routes/admin-chat.js.map +0 -1
- package/dist/src/agent/routes/automations.d.ts +0 -19
- package/dist/src/agent/routes/automations.js +0 -86
- package/dist/src/agent/routes/automations.js.map +0 -1
- package/dist/src/agent/routes/automations.test.d.ts +0 -6
- package/dist/src/agent/routes/automations.test.js +0 -117
- package/dist/src/agent/routes/automations.test.js.map +0 -1
- package/dist/src/agent/routes/evals.d.ts +0 -17
- package/dist/src/agent/routes/evals.js +0 -389
- package/dist/src/agent/routes/evals.js.map +0 -1
- package/dist/src/agent/routes/webhooks.d.ts +0 -17
- package/dist/src/agent/routes/webhooks.js +0 -63
- package/dist/src/agent/routes/webhooks.js.map +0 -1
- package/dist/src/agent/routes/webhooks.test.d.ts +0 -6
- package/dist/src/agent/routes/webhooks.test.js +0 -100
- package/dist/src/agent/routes/webhooks.test.js.map +0 -1
- package/dist/src/session/pglite-session-store.d.ts +0 -23
- package/dist/src/session/pglite-session-store.js +0 -92
- package/dist/src/session/pglite-session-store.js.map +0 -1
- package/dist/src/stores/pglite-store-backend.d.ts +0 -39
- package/dist/src/stores/pglite-store-backend.js +0 -128
- package/dist/src/stores/pglite-store-backend.js.map +0 -1
- package/dist/src/stores/pglite-store-backend.test.d.ts +0 -6
- package/dist/src/stores/pglite-store-backend.test.js +0 -150
- package/dist/src/stores/pglite-store-backend.test.js.map +0 -1
- package/dist/src/stores/schema.d.ts +0 -593
- package/dist/src/stores/schema.js +0 -75
- package/dist/src/stores/schema.js.map +0 -1
- package/dist/src/tools/admin-file-tools.d.ts +0 -42
- package/dist/src/tools/admin-file-tools.js +0 -714
- package/dist/src/tools/admin-file-tools.js.map +0 -1
- package/dist/src/tools/admin-file-tools.test.d.ts +0 -6
- package/dist/src/tools/admin-file-tools.test.js +0 -523
- package/dist/src/tools/admin-file-tools.test.js.map +0 -1
- /package/dist/src/{agent/proactive/delivery-router.test.d.ts → __tests__/studio-integration.test.d.ts} +0 -0
|
@@ -1,455 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Amodal Labs, Inc.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
*/
|
|
6
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
-
import { DeliveryRouter } from './delivery-router.js';
|
|
8
|
-
function makeLogger() {
|
|
9
|
-
return {
|
|
10
|
-
trace: vi.fn(),
|
|
11
|
-
debug: vi.fn(),
|
|
12
|
-
info: vi.fn(),
|
|
13
|
-
warn: vi.fn(),
|
|
14
|
-
error: vi.fn(),
|
|
15
|
-
fatal: vi.fn(),
|
|
16
|
-
child: vi.fn().mockReturnThis(),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
describe('DeliveryRouter', () => {
|
|
20
|
-
const originalFetch = globalThis.fetch;
|
|
21
|
-
const calls = [];
|
|
22
|
-
let mockImpl = null;
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
calls.length = 0;
|
|
25
|
-
mockImpl = null;
|
|
26
|
-
globalThis.fetch = ((input, init) => {
|
|
27
|
-
const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : String(input);
|
|
28
|
-
calls.push({
|
|
29
|
-
url,
|
|
30
|
-
body: init?.body ? JSON.parse(String(init.body)) : undefined,
|
|
31
|
-
headers: init?.headers ?? {},
|
|
32
|
-
});
|
|
33
|
-
if (mockImpl)
|
|
34
|
-
return mockImpl(url, init);
|
|
35
|
-
return Promise.resolve(new Response(null, { status: 200 }));
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
afterEach(() => {
|
|
39
|
-
globalThis.fetch = originalFetch;
|
|
40
|
-
});
|
|
41
|
-
describe('onSuccess', () => {
|
|
42
|
-
it('dispatches a webhook target with result', async () => {
|
|
43
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
44
|
-
const delivery = {
|
|
45
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
46
|
-
};
|
|
47
|
-
await router.onSuccess('scan', 'found 5 items', delivery);
|
|
48
|
-
expect(calls).toHaveLength(1);
|
|
49
|
-
expect(calls[0]?.url).toBe('http://example.test/hook');
|
|
50
|
-
const body = calls[0]?.body;
|
|
51
|
-
expect(body['automation']).toBe('scan');
|
|
52
|
-
expect(body['status']).toBe('success');
|
|
53
|
-
expect(body['result']).toBe('found 5 items');
|
|
54
|
-
});
|
|
55
|
-
it('omits result when includeResult=false', async () => {
|
|
56
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
57
|
-
const delivery = {
|
|
58
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
59
|
-
includeResult: false,
|
|
60
|
-
};
|
|
61
|
-
await router.onSuccess('scan', 'secret data', delivery);
|
|
62
|
-
const body = calls[0]?.body;
|
|
63
|
-
expect(body['result']).toBeUndefined();
|
|
64
|
-
});
|
|
65
|
-
it('parses JSON output into data field', async () => {
|
|
66
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
67
|
-
const delivery = {
|
|
68
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
69
|
-
};
|
|
70
|
-
await router.onSuccess('scan', '{"count": 5, "top_title": "AI news"}', delivery);
|
|
71
|
-
const body = calls[0]?.body;
|
|
72
|
-
expect(body['data']).toEqual({ count: 5, top_title: 'AI news' });
|
|
73
|
-
});
|
|
74
|
-
it('renders template with JSON result variables', async () => {
|
|
75
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
76
|
-
const delivery = {
|
|
77
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
78
|
-
template: 'Found {{count}} new trending articles. Top: {{top_title}}',
|
|
79
|
-
};
|
|
80
|
-
await router.onSuccess('scan', '{"count": 5, "top_title": "AI news"}', delivery);
|
|
81
|
-
const body = calls[0]?.body;
|
|
82
|
-
expect(body['message']).toBe('Found 5 new trending articles. Top: AI news');
|
|
83
|
-
});
|
|
84
|
-
it('renders template with built-in variables', async () => {
|
|
85
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
86
|
-
const delivery = {
|
|
87
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
88
|
-
template: '{{automation}} completed at {{timestamp}}',
|
|
89
|
-
};
|
|
90
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
91
|
-
const body = calls[0]?.body;
|
|
92
|
-
expect(body['message']).toMatch(/^scan completed at \d{4}-\d{2}-\d{2}/);
|
|
93
|
-
});
|
|
94
|
-
it('leaves missing template variables as literal tokens', async () => {
|
|
95
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
96
|
-
const delivery = {
|
|
97
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
98
|
-
template: '{{count}} items, {{missing}} unknown',
|
|
99
|
-
};
|
|
100
|
-
await router.onSuccess('scan', '{"count": 3}', delivery);
|
|
101
|
-
const body = calls[0]?.body;
|
|
102
|
-
expect(body['message']).toBe('3 items, {{missing}} unknown');
|
|
103
|
-
});
|
|
104
|
-
it('parses fenced JSON code blocks', async () => {
|
|
105
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
106
|
-
const delivery = {
|
|
107
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
108
|
-
};
|
|
109
|
-
await router.onSuccess('scan', '```json\n{"count": 7}\n```', delivery);
|
|
110
|
-
const body = calls[0]?.body;
|
|
111
|
-
expect(body['data']).toEqual({ count: 7 });
|
|
112
|
-
});
|
|
113
|
-
it('fires multiple targets in parallel', async () => {
|
|
114
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
115
|
-
const delivery = {
|
|
116
|
-
targets: [
|
|
117
|
-
{ type: 'webhook', url: 'http://a.test/hook' },
|
|
118
|
-
{ type: 'webhook', url: 'http://b.test/hook' },
|
|
119
|
-
],
|
|
120
|
-
};
|
|
121
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
122
|
-
expect(calls.map((c) => c.url).sort()).toEqual(['http://a.test/hook', 'http://b.test/hook']);
|
|
123
|
-
});
|
|
124
|
-
it('fires ISV callback target with target metadata', async () => {
|
|
125
|
-
const onResult = vi.fn();
|
|
126
|
-
const router = new DeliveryRouter({ logger: makeLogger(), onResult });
|
|
127
|
-
const delivery = {
|
|
128
|
-
targets: [{ type: 'callback', name: 'primary-handler' }],
|
|
129
|
-
};
|
|
130
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
131
|
-
expect(onResult).toHaveBeenCalledTimes(1);
|
|
132
|
-
expect(onResult.mock.calls[0]?.[0]).toMatchObject({
|
|
133
|
-
automation: 'scan',
|
|
134
|
-
status: 'success',
|
|
135
|
-
result: 'done',
|
|
136
|
-
});
|
|
137
|
-
// Second arg carries target metadata so multi-target setups can
|
|
138
|
-
// distinguish which callback is firing.
|
|
139
|
-
expect(onResult.mock.calls[0]?.[1]).toEqual({ name: 'primary-handler' });
|
|
140
|
-
});
|
|
141
|
-
it('passes undefined target name when not specified', async () => {
|
|
142
|
-
const onResult = vi.fn();
|
|
143
|
-
const router = new DeliveryRouter({ logger: makeLogger(), onResult });
|
|
144
|
-
const delivery = { targets: [{ type: 'callback' }] };
|
|
145
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
146
|
-
expect(onResult.mock.calls[0]?.[1]).toEqual({ name: undefined });
|
|
147
|
-
});
|
|
148
|
-
it('distinguishes multiple callback targets by name', async () => {
|
|
149
|
-
const calls_ = [];
|
|
150
|
-
const onResult = (_, target) => {
|
|
151
|
-
calls_.push(target);
|
|
152
|
-
};
|
|
153
|
-
const router = new DeliveryRouter({ logger: makeLogger(), onResult });
|
|
154
|
-
const delivery = {
|
|
155
|
-
targets: [
|
|
156
|
-
{ type: 'callback', name: 'analytics' },
|
|
157
|
-
{ type: 'callback', name: 'audit-log' },
|
|
158
|
-
],
|
|
159
|
-
};
|
|
160
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
161
|
-
expect(calls_.map((c) => c.name).sort()).toEqual(['analytics', 'audit-log']);
|
|
162
|
-
});
|
|
163
|
-
it('warns and skips callback target when onResult is not configured', async () => {
|
|
164
|
-
const logger = makeLogger();
|
|
165
|
-
const router = new DeliveryRouter({ logger });
|
|
166
|
-
const delivery = {
|
|
167
|
-
targets: [{ type: 'callback' }],
|
|
168
|
-
};
|
|
169
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
170
|
-
expect(logger.warn).toHaveBeenCalledWith('delivery_callback_not_configured', expect.objectContaining({ automation: 'scan' }));
|
|
171
|
-
});
|
|
172
|
-
it('signs webhook with HMAC when webhookSecret is set', async () => {
|
|
173
|
-
const router = new DeliveryRouter({ logger: makeLogger(), webhookSecret: 'topsecret' });
|
|
174
|
-
const delivery = {
|
|
175
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
176
|
-
};
|
|
177
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
178
|
-
expect(calls[0]?.headers['X-Amodal-Signature']).toMatch(/^sha256=[0-9a-f]{64}$/);
|
|
179
|
-
});
|
|
180
|
-
it('does not throw when a webhook returns 500 (and retries once)', async () => {
|
|
181
|
-
mockImpl = () => Promise.resolve(new Response(null, { status: 500 }));
|
|
182
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
183
|
-
const delivery = {
|
|
184
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
185
|
-
};
|
|
186
|
-
await expect(router.onSuccess('scan', 'done', delivery)).resolves.toBeUndefined();
|
|
187
|
-
// 5xx is retryable: should have fired twice (initial + 1 retry)
|
|
188
|
-
expect(calls).toHaveLength(2);
|
|
189
|
-
});
|
|
190
|
-
it('retries on 5xx and succeeds on second attempt', async () => {
|
|
191
|
-
let attempt = 0;
|
|
192
|
-
mockImpl = () => {
|
|
193
|
-
attempt++;
|
|
194
|
-
return Promise.resolve(new Response(null, { status: attempt === 1 ? 503 : 200 }));
|
|
195
|
-
};
|
|
196
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
197
|
-
const delivery = {
|
|
198
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
199
|
-
};
|
|
200
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
201
|
-
expect(attempt).toBe(2);
|
|
202
|
-
});
|
|
203
|
-
it('does NOT retry on 4xx client errors', async () => {
|
|
204
|
-
mockImpl = () => Promise.resolve(new Response(null, { status: 400 }));
|
|
205
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
206
|
-
const delivery = {
|
|
207
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
208
|
-
};
|
|
209
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
210
|
-
// 400 is not retryable: single attempt
|
|
211
|
-
expect(calls).toHaveLength(1);
|
|
212
|
-
});
|
|
213
|
-
it('retries on network error and throws WebhookFailure after second attempt', async () => {
|
|
214
|
-
mockImpl = () => Promise.reject(new TypeError('fetch failed'));
|
|
215
|
-
const logger = makeLogger();
|
|
216
|
-
const router = new DeliveryRouter({ logger });
|
|
217
|
-
const delivery = {
|
|
218
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
219
|
-
};
|
|
220
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
221
|
-
// attempts=2 logged on failure
|
|
222
|
-
expect(logger.warn).toHaveBeenCalledWith('delivery_failed', expect.objectContaining({ attempts: 2, error: expect.stringContaining('fetch failed') }));
|
|
223
|
-
});
|
|
224
|
-
it('does nothing when delivery is undefined', async () => {
|
|
225
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
226
|
-
await router.onSuccess('scan', 'done', undefined);
|
|
227
|
-
expect(calls).toHaveLength(0);
|
|
228
|
-
});
|
|
229
|
-
it('resets failure counter on success', async () => {
|
|
230
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
231
|
-
await router.onFailure('scan', 'boom', undefined);
|
|
232
|
-
await router.onFailure('scan', 'boom', undefined);
|
|
233
|
-
expect(router.getFailureCount('scan')).toBe(2);
|
|
234
|
-
await router.onSuccess('scan', 'ok', undefined);
|
|
235
|
-
expect(router.getFailureCount('scan')).toBe(0);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
describe('template missing-var warning', () => {
|
|
239
|
-
it('warns once per automation+template+missing-keys combo', async () => {
|
|
240
|
-
const logger = makeLogger();
|
|
241
|
-
const router = new DeliveryRouter({ logger });
|
|
242
|
-
const delivery = {
|
|
243
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
244
|
-
template: 'Found {{count}} items matching {{query}}',
|
|
245
|
-
};
|
|
246
|
-
// Only `count` present; `query` missing. Warn fires once.
|
|
247
|
-
await router.onSuccess('scan', '{"count": 5}', delivery);
|
|
248
|
-
await router.onSuccess('scan', '{"count": 5}', delivery);
|
|
249
|
-
await router.onSuccess('scan', '{"count": 5}', delivery);
|
|
250
|
-
const warnCalls = logger.warn.mock.calls.filter((c) => c[0] === 'delivery_template_missing_var');
|
|
251
|
-
expect(warnCalls).toHaveLength(1);
|
|
252
|
-
expect(warnCalls[0]?.[1]).toMatchObject({
|
|
253
|
-
automation: 'scan',
|
|
254
|
-
missing: ['query'],
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
it('warns again if a different variable goes missing', async () => {
|
|
258
|
-
const logger = makeLogger();
|
|
259
|
-
const router = new DeliveryRouter({ logger });
|
|
260
|
-
const delivery = {
|
|
261
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
262
|
-
template: '{{count}} / {{total}}',
|
|
263
|
-
};
|
|
264
|
-
await router.onSuccess('scan', '{"count": 5}', delivery); // missing total
|
|
265
|
-
await router.onSuccess('scan', '{"total": 10}', delivery); // missing count
|
|
266
|
-
const warnCalls = logger.warn.mock.calls.filter((c) => c[0] === 'delivery_template_missing_var');
|
|
267
|
-
expect(warnCalls).toHaveLength(2);
|
|
268
|
-
});
|
|
269
|
-
it('does not warn when all variables resolve', async () => {
|
|
270
|
-
const logger = makeLogger();
|
|
271
|
-
const router = new DeliveryRouter({ logger });
|
|
272
|
-
const delivery = {
|
|
273
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
274
|
-
template: '{{count}} items',
|
|
275
|
-
};
|
|
276
|
-
await router.onSuccess('scan', '{"count": 5}', delivery);
|
|
277
|
-
const warnCalls = logger.warn.mock.calls.filter((c) => c[0] === 'delivery_template_missing_var');
|
|
278
|
-
expect(warnCalls).toHaveLength(0);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
describe('truncation', () => {
|
|
282
|
-
it('truncates result over 16KB with truncated:true flag', async () => {
|
|
283
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
284
|
-
const delivery = {
|
|
285
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
286
|
-
};
|
|
287
|
-
const huge = 'A'.repeat(20_000);
|
|
288
|
-
await router.onSuccess('scan', huge, delivery);
|
|
289
|
-
const body = calls[0]?.body;
|
|
290
|
-
expect(body['truncated']).toBe(true);
|
|
291
|
-
const result = body['result'];
|
|
292
|
-
expect(result.length).toBeLessThan(17_000);
|
|
293
|
-
expect(result).toContain('truncated');
|
|
294
|
-
});
|
|
295
|
-
it('does not truncate result under 16KB and omits the flag', async () => {
|
|
296
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
297
|
-
const delivery = {
|
|
298
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
299
|
-
};
|
|
300
|
-
await router.onSuccess('scan', 'short output', delivery);
|
|
301
|
-
const body = calls[0]?.body;
|
|
302
|
-
expect(body['truncated']).toBeUndefined();
|
|
303
|
-
expect(body['result']).toBe('short output');
|
|
304
|
-
});
|
|
305
|
-
it('template still receives full untruncated result via {{result}}', async () => {
|
|
306
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
307
|
-
const huge = 'X'.repeat(20_000);
|
|
308
|
-
const delivery = {
|
|
309
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
310
|
-
template: 'Length: {{result.length}}',
|
|
311
|
-
includeResult: false,
|
|
312
|
-
};
|
|
313
|
-
// includeResult=false means no `result` in payload but {{result}}
|
|
314
|
-
// in template still works (uses the raw pre-truncation text).
|
|
315
|
-
await router.onSuccess('scan', huge, delivery);
|
|
316
|
-
const body = calls[0]?.body;
|
|
317
|
-
expect(body['result']).toBeUndefined();
|
|
318
|
-
expect(body['message']).toBeDefined();
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
describe('event bus emission', () => {
|
|
322
|
-
it('emits delivery_succeeded on successful webhook', async () => {
|
|
323
|
-
const emitted = [];
|
|
324
|
-
const eventBus = { emit: (e) => { emitted.push(e); } };
|
|
325
|
-
const router = new DeliveryRouter({ logger: makeLogger(), eventBus });
|
|
326
|
-
const delivery = {
|
|
327
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
328
|
-
};
|
|
329
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
330
|
-
expect(emitted).toHaveLength(1);
|
|
331
|
-
expect(emitted[0]).toMatchObject({
|
|
332
|
-
type: 'delivery_succeeded',
|
|
333
|
-
automation: 'scan',
|
|
334
|
-
targetType: 'webhook',
|
|
335
|
-
targetUrl: 'http://example.test/hook',
|
|
336
|
-
httpStatus: 200,
|
|
337
|
-
});
|
|
338
|
-
expect(typeof emitted[0]?.['durationMs']).toBe('number');
|
|
339
|
-
});
|
|
340
|
-
it('emits delivery_succeeded on successful callback', async () => {
|
|
341
|
-
const emitted = [];
|
|
342
|
-
const eventBus = { emit: (e) => { emitted.push(e); } };
|
|
343
|
-
const router = new DeliveryRouter({ logger: makeLogger(), onResult: vi.fn(), eventBus });
|
|
344
|
-
const delivery = { targets: [{ type: 'callback' }] };
|
|
345
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
346
|
-
expect(emitted[0]).toMatchObject({
|
|
347
|
-
type: 'delivery_succeeded',
|
|
348
|
-
automation: 'scan',
|
|
349
|
-
targetType: 'callback',
|
|
350
|
-
});
|
|
351
|
-
expect(emitted[0]?.['targetUrl']).toBeUndefined();
|
|
352
|
-
});
|
|
353
|
-
it('emits delivery_failed with attempt count and status', async () => {
|
|
354
|
-
mockImpl = () => Promise.resolve(new Response(null, { status: 500 }));
|
|
355
|
-
const emitted = [];
|
|
356
|
-
const eventBus = { emit: (e) => { emitted.push(e); } };
|
|
357
|
-
const router = new DeliveryRouter({ logger: makeLogger(), eventBus });
|
|
358
|
-
const delivery = {
|
|
359
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
360
|
-
};
|
|
361
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
362
|
-
expect(emitted).toHaveLength(1);
|
|
363
|
-
expect(emitted[0]).toMatchObject({
|
|
364
|
-
type: 'delivery_failed',
|
|
365
|
-
automation: 'scan',
|
|
366
|
-
targetType: 'webhook',
|
|
367
|
-
targetUrl: 'http://example.test/hook',
|
|
368
|
-
httpStatus: 500,
|
|
369
|
-
attempts: 2,
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
it('emits delivery_failed with attempts=1 for 4xx (no retry)', async () => {
|
|
373
|
-
mockImpl = () => Promise.resolve(new Response(null, { status: 404 }));
|
|
374
|
-
const emitted = [];
|
|
375
|
-
const eventBus = { emit: (e) => { emitted.push(e); } };
|
|
376
|
-
const router = new DeliveryRouter({ logger: makeLogger(), eventBus });
|
|
377
|
-
const delivery = {
|
|
378
|
-
targets: [{ type: 'webhook', url: 'http://example.test/hook' }],
|
|
379
|
-
};
|
|
380
|
-
await router.onSuccess('scan', 'done', delivery);
|
|
381
|
-
expect(emitted[0]).toMatchObject({ attempts: 1, httpStatus: 404 });
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
describe('onFailure', () => {
|
|
385
|
-
it('increments consecutive failure counter', async () => {
|
|
386
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
387
|
-
await router.onFailure('scan', 'err1', undefined);
|
|
388
|
-
await router.onFailure('scan', 'err2', undefined);
|
|
389
|
-
await router.onFailure('scan', 'err3', undefined);
|
|
390
|
-
expect(router.getFailureCount('scan')).toBe(3);
|
|
391
|
-
});
|
|
392
|
-
it('does not fire alert below threshold', async () => {
|
|
393
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
394
|
-
const alert = {
|
|
395
|
-
after: 3,
|
|
396
|
-
targets: [{ type: 'webhook', url: 'http://example.test/alert' }],
|
|
397
|
-
};
|
|
398
|
-
await router.onFailure('scan', 'err1', alert);
|
|
399
|
-
await router.onFailure('scan', 'err2', alert);
|
|
400
|
-
expect(calls).toHaveLength(0);
|
|
401
|
-
await router.onFailure('scan', 'err3', alert);
|
|
402
|
-
expect(calls).toHaveLength(1);
|
|
403
|
-
const body = calls[0]?.body;
|
|
404
|
-
expect(body['status']).toBe('failure');
|
|
405
|
-
expect(body['error']).toBe('err3');
|
|
406
|
-
});
|
|
407
|
-
it('fires on first failure when after=1 (default)', async () => {
|
|
408
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
409
|
-
const alert = {
|
|
410
|
-
targets: [{ type: 'webhook', url: 'http://example.test/alert' }],
|
|
411
|
-
};
|
|
412
|
-
await router.onFailure('scan', 'boom', alert);
|
|
413
|
-
expect(calls).toHaveLength(1);
|
|
414
|
-
});
|
|
415
|
-
it('respects cooldown window between alerts', async () => {
|
|
416
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
417
|
-
const alert = {
|
|
418
|
-
after: 1,
|
|
419
|
-
cooldownMinutes: 60,
|
|
420
|
-
targets: [{ type: 'webhook', url: 'http://example.test/alert' }],
|
|
421
|
-
};
|
|
422
|
-
await router.onFailure('scan', 'err1', alert);
|
|
423
|
-
expect(calls).toHaveLength(1);
|
|
424
|
-
await router.onFailure('scan', 'err2', alert);
|
|
425
|
-
expect(calls).toHaveLength(1);
|
|
426
|
-
await router.onFailure('scan', 'err3', alert);
|
|
427
|
-
expect(calls).toHaveLength(1);
|
|
428
|
-
});
|
|
429
|
-
it('fires again after cooldown expires', async () => {
|
|
430
|
-
vi.useFakeTimers();
|
|
431
|
-
try {
|
|
432
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
433
|
-
const alert = {
|
|
434
|
-
after: 1,
|
|
435
|
-
cooldownMinutes: 1,
|
|
436
|
-
targets: [{ type: 'webhook', url: 'http://example.test/alert' }],
|
|
437
|
-
};
|
|
438
|
-
await router.onFailure('scan', 'err1', alert);
|
|
439
|
-
expect(calls).toHaveLength(1);
|
|
440
|
-
vi.advanceTimersByTime(61_000);
|
|
441
|
-
await router.onFailure('scan', 'err2', alert);
|
|
442
|
-
expect(calls).toHaveLength(2);
|
|
443
|
-
}
|
|
444
|
-
finally {
|
|
445
|
-
vi.useRealTimers();
|
|
446
|
-
}
|
|
447
|
-
});
|
|
448
|
-
it('does nothing when failureAlert is undefined', async () => {
|
|
449
|
-
const router = new DeliveryRouter({ logger: makeLogger() });
|
|
450
|
-
await router.onFailure('scan', 'boom', undefined);
|
|
451
|
-
expect(calls).toHaveLength(0);
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
//# sourceMappingURL=delivery-router.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-router.test.js","sourceRoot":"","sources":["../../../../src/agent/proactive/delivery-router.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
*/
|
|
6
|
-
export interface DeliveryPayload {
|
|
7
|
-
automation: string;
|
|
8
|
-
response: string;
|
|
9
|
-
timestamp: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Deliver automation results to stdout (default) or a proactive webhook.
|
|
13
|
-
*
|
|
14
|
-
* The agent itself handles delivery to Slack/email/etc. via connections.
|
|
15
|
-
* This function only handles the system-level output of the automation run.
|
|
16
|
-
*/
|
|
17
|
-
export declare function deliverResult(payload: DeliveryPayload, webhookUrl?: string, webhookSecret?: string): Promise<boolean>;
|
|
18
|
-
/**
|
|
19
|
-
* Verify an incoming webhook request's HMAC signature.
|
|
20
|
-
*/
|
|
21
|
-
export declare function verifyHmacSignature(body: string, signature: string, secret: string): boolean;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
*/
|
|
6
|
-
import { createHmac } from 'node:crypto';
|
|
7
|
-
/**
|
|
8
|
-
* Deliver automation results to stdout (default) or a proactive webhook.
|
|
9
|
-
*
|
|
10
|
-
* The agent itself handles delivery to Slack/email/etc. via connections.
|
|
11
|
-
* This function only handles the system-level output of the automation run.
|
|
12
|
-
*/
|
|
13
|
-
export async function deliverResult(payload, webhookUrl, webhookSecret) {
|
|
14
|
-
if (webhookUrl) {
|
|
15
|
-
return deliverWebhook(webhookUrl, payload, webhookSecret);
|
|
16
|
-
}
|
|
17
|
-
return deliverStdout(payload);
|
|
18
|
-
}
|
|
19
|
-
async function deliverWebhook(url, payload, webhookSecret) {
|
|
20
|
-
const body = JSON.stringify(payload);
|
|
21
|
-
const headers = {
|
|
22
|
-
'Content-Type': 'application/json',
|
|
23
|
-
};
|
|
24
|
-
if (webhookSecret) {
|
|
25
|
-
const signature = createHmac('sha256', webhookSecret)
|
|
26
|
-
.update(body)
|
|
27
|
-
.digest('hex');
|
|
28
|
-
headers['X-Amodal-Signature'] = `sha256=${signature}`;
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
const response = await fetch(url, { method: 'POST', headers, body });
|
|
32
|
-
return response.ok;
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function deliverStdout(payload) {
|
|
39
|
-
try {
|
|
40
|
-
process.stdout.write(JSON.stringify(payload) + '\n');
|
|
41
|
-
return Promise.resolve(true);
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return Promise.resolve(false);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Verify an incoming webhook request's HMAC signature.
|
|
49
|
-
*/
|
|
50
|
-
export function verifyHmacSignature(body, signature, secret) {
|
|
51
|
-
const expected = createHmac('sha256', secret)
|
|
52
|
-
.update(body)
|
|
53
|
-
.digest('hex');
|
|
54
|
-
const expectedFull = `sha256=${expected}`;
|
|
55
|
-
if (signature.length !== expectedFull.length) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const sigBuffer = Buffer.from(signature);
|
|
59
|
-
const expectedBuffer = Buffer.from(expectedFull);
|
|
60
|
-
return sigBuffer.length === expectedBuffer.length &&
|
|
61
|
-
createHmac('sha256', 'compare')
|
|
62
|
-
.update(sigBuffer)
|
|
63
|
-
.digest()
|
|
64
|
-
.equals(createHmac('sha256', 'compare')
|
|
65
|
-
.update(expectedBuffer)
|
|
66
|
-
.digest());
|
|
67
|
-
}
|
|
68
|
-
//# sourceMappingURL=delivery.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../../src/agent/proactive/delivery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAQvC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAwB,EACxB,UAAmB,EACnB,aAAsB;IAEtB,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,GAAW,EACX,OAAwB,EACxB,aAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,aAAa,CAAC;aAClD,MAAM,CAAC,IAAI,CAAC;aACZ,MAAM,CAAC,KAAK,CAAC,CAAC;QACjB,OAAO,CAAC,oBAAoB,CAAC,GAAG,UAAU,SAAS,EAAE,CAAC;IACxD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC;QACnE,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAAwB;IAC7C,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,SAAiB,EACjB,MAAc;IAEd,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC1C,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,MAAM,YAAY,GAAG,UAAU,QAAQ,EAAE,CAAC;IAE1C,IAAI,SAAS,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM;QAC/C,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC;aAC5B,MAAM,CAAC,SAAS,CAAC;aACjB,MAAM,EAAE;aACR,MAAM,CACL,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC;aAC5B,MAAM,CAAC,cAAc,CAAC;aACtB,MAAM,EAAE,CACZ,CAAC;AACR,CAAC"}
|