@amodalai/runtime 0.1.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/LICENSE +21 -0
- package/dist/.last_build +0 -0
- package/dist/src/agent/agent-runner.d.ts +13 -0
- package/dist/src/agent/agent-runner.js +827 -0
- package/dist/src/agent/agent-runner.js.map +1 -0
- package/dist/src/agent/agent-runner.test.d.ts +6 -0
- package/dist/src/agent/agent-runner.test.js +552 -0
- package/dist/src/agent/agent-runner.test.js.map +1 -0
- package/dist/src/agent/agent-types.d.ts +57 -0
- package/dist/src/agent/agent-types.js +17 -0
- package/dist/src/agent/agent-types.js.map +1 -0
- package/dist/src/agent/agent-types.test.d.ts +6 -0
- package/dist/src/agent/agent-types.test.js +44 -0
- package/dist/src/agent/agent-types.test.js.map +1 -0
- package/dist/src/agent/automation-bridge.d.ts +24 -0
- package/dist/src/agent/automation-bridge.js +24 -0
- package/dist/src/agent/automation-bridge.js.map +1 -0
- package/dist/src/agent/automation-bridge.test.d.ts +6 -0
- package/dist/src/agent/automation-bridge.test.js +67 -0
- package/dist/src/agent/automation-bridge.test.js.map +1 -0
- package/dist/src/agent/config-watcher.d.ts +20 -0
- package/dist/src/agent/config-watcher.js +68 -0
- package/dist/src/agent/config-watcher.js.map +1 -0
- package/dist/src/agent/config-watcher.test.d.ts +6 -0
- package/dist/src/agent/config-watcher.test.js +83 -0
- package/dist/src/agent/config-watcher.test.js.map +1 -0
- package/dist/src/agent/custom-tools-e2e.test.d.ts +6 -0
- package/dist/src/agent/custom-tools-e2e.test.js +566 -0
- package/dist/src/agent/custom-tools-e2e.test.js.map +1 -0
- package/dist/src/agent/local-server.d.ts +15 -0
- package/dist/src/agent/local-server.js +158 -0
- package/dist/src/agent/local-server.js.map +1 -0
- package/dist/src/agent/local-server.test.d.ts +6 -0
- package/dist/src/agent/local-server.test.js +126 -0
- package/dist/src/agent/local-server.test.js.map +1 -0
- package/dist/src/agent/proactive/delivery.d.ts +21 -0
- package/dist/src/agent/proactive/delivery.js +68 -0
- package/dist/src/agent/proactive/delivery.js.map +1 -0
- package/dist/src/agent/proactive/delivery.test.d.ts +6 -0
- package/dist/src/agent/proactive/delivery.test.js +65 -0
- package/dist/src/agent/proactive/delivery.test.js.map +1 -0
- package/dist/src/agent/proactive/proactive-runner.d.ts +76 -0
- package/dist/src/agent/proactive/proactive-runner.js +201 -0
- package/dist/src/agent/proactive/proactive-runner.js.map +1 -0
- package/dist/src/agent/proactive/proactive-runner.test.d.ts +6 -0
- package/dist/src/agent/proactive/proactive-runner.test.js +265 -0
- package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -0
- package/dist/src/agent/request-helper.d.ts +16 -0
- package/dist/src/agent/request-helper.js +87 -0
- package/dist/src/agent/request-helper.js.map +1 -0
- package/dist/src/agent/routes/automations.d.ts +19 -0
- package/dist/src/agent/routes/automations.js +58 -0
- package/dist/src/agent/routes/automations.js.map +1 -0
- package/dist/src/agent/routes/automations.test.d.ts +6 -0
- package/dist/src/agent/routes/automations.test.js +117 -0
- package/dist/src/agent/routes/automations.test.js.map +1 -0
- package/dist/src/agent/routes/chat.d.ts +35 -0
- package/dist/src/agent/routes/chat.js +88 -0
- package/dist/src/agent/routes/chat.js.map +1 -0
- package/dist/src/agent/routes/chat.test.d.ts +6 -0
- package/dist/src/agent/routes/chat.test.js +115 -0
- package/dist/src/agent/routes/chat.test.js.map +1 -0
- package/dist/src/agent/routes/inspect.d.ts +12 -0
- package/dist/src/agent/routes/inspect.js +40 -0
- package/dist/src/agent/routes/inspect.js.map +1 -0
- package/dist/src/agent/routes/inspect.test.d.ts +6 -0
- package/dist/src/agent/routes/inspect.test.js +80 -0
- package/dist/src/agent/routes/inspect.test.js.map +1 -0
- package/dist/src/agent/routes/stores.d.ts +20 -0
- package/dist/src/agent/routes/stores.js +137 -0
- package/dist/src/agent/routes/stores.js.map +1 -0
- package/dist/src/agent/routes/stores.test.d.ts +6 -0
- package/dist/src/agent/routes/stores.test.js +191 -0
- package/dist/src/agent/routes/stores.test.js.map +1 -0
- package/dist/src/agent/routes/task.d.ts +11 -0
- package/dist/src/agent/routes/task.js +116 -0
- package/dist/src/agent/routes/task.js.map +1 -0
- package/dist/src/agent/routes/task.test.d.ts +6 -0
- package/dist/src/agent/routes/task.test.js +91 -0
- package/dist/src/agent/routes/task.test.js.map +1 -0
- package/dist/src/agent/routes/webhooks.d.ts +17 -0
- package/dist/src/agent/routes/webhooks.js +53 -0
- package/dist/src/agent/routes/webhooks.js.map +1 -0
- package/dist/src/agent/routes/webhooks.test.d.ts +6 -0
- package/dist/src/agent/routes/webhooks.test.js +100 -0
- package/dist/src/agent/routes/webhooks.test.js.map +1 -0
- package/dist/src/agent/session-manager.d.ts +72 -0
- package/dist/src/agent/session-manager.js +214 -0
- package/dist/src/agent/session-manager.js.map +1 -0
- package/dist/src/agent/session-manager.test.d.ts +6 -0
- package/dist/src/agent/session-manager.test.js +145 -0
- package/dist/src/agent/session-manager.test.js.map +1 -0
- package/dist/src/agent/shell-executor-local.d.ts +16 -0
- package/dist/src/agent/shell-executor-local.js +51 -0
- package/dist/src/agent/shell-executor-local.js.map +1 -0
- package/dist/src/agent/shell-executor-local.test.d.ts +6 -0
- package/dist/src/agent/shell-executor-local.test.js +46 -0
- package/dist/src/agent/shell-executor-local.test.js.map +1 -0
- package/dist/src/agent/snapshot-server.d.ts +38 -0
- package/dist/src/agent/snapshot-server.js +114 -0
- package/dist/src/agent/snapshot-server.js.map +1 -0
- package/dist/src/agent/stores-e2e.test.d.ts +6 -0
- package/dist/src/agent/stores-e2e.test.js +433 -0
- package/dist/src/agent/stores-e2e.test.js.map +1 -0
- package/dist/src/agent/tool-context-builder.d.ts +11 -0
- package/dist/src/agent/tool-context-builder.js +84 -0
- package/dist/src/agent/tool-context-builder.js.map +1 -0
- package/dist/src/agent/tool-context-builder.test.d.ts +6 -0
- package/dist/src/agent/tool-context-builder.test.js +152 -0
- package/dist/src/agent/tool-context-builder.test.js.map +1 -0
- package/dist/src/agent/tool-executor-local.d.ts +15 -0
- package/dist/src/agent/tool-executor-local.js +74 -0
- package/dist/src/agent/tool-executor-local.js.map +1 -0
- package/dist/src/agent/tool-executor-local.test.d.ts +6 -0
- package/dist/src/agent/tool-executor-local.test.js +116 -0
- package/dist/src/agent/tool-executor-local.test.js.map +1 -0
- package/dist/src/agent/tool-harness-template.d.ts +23 -0
- package/dist/src/agent/tool-harness-template.js +94 -0
- package/dist/src/agent/tool-harness-template.js.map +1 -0
- package/dist/src/agent/user-context-fetcher.d.ts +25 -0
- package/dist/src/agent/user-context-fetcher.js +79 -0
- package/dist/src/agent/user-context-fetcher.js.map +1 -0
- package/dist/src/agent/user-context-fetcher.test.d.ts +6 -0
- package/dist/src/agent/user-context-fetcher.test.js +121 -0
- package/dist/src/agent/user-context-fetcher.test.js.map +1 -0
- package/dist/src/audit/audit-client.d.ts +46 -0
- package/dist/src/audit/audit-client.js +83 -0
- package/dist/src/audit/audit-client.js.map +1 -0
- package/dist/src/cron/heartbeat-runner.d.ts +24 -0
- package/dist/src/cron/heartbeat-runner.js +87 -0
- package/dist/src/cron/heartbeat-runner.js.map +1 -0
- package/dist/src/cron/heartbeat-runner.test.d.ts +6 -0
- package/dist/src/cron/heartbeat-runner.test.js +120 -0
- package/dist/src/cron/heartbeat-runner.test.js.map +1 -0
- package/dist/src/cron/heartbeat-scheduler.d.ts +26 -0
- package/dist/src/cron/heartbeat-scheduler.js +54 -0
- package/dist/src/cron/heartbeat-scheduler.js.map +1 -0
- package/dist/src/cron/heartbeat-scheduler.test.d.ts +6 -0
- package/dist/src/cron/heartbeat-scheduler.test.js +61 -0
- package/dist/src/cron/heartbeat-scheduler.test.js.map +1 -0
- package/dist/src/index.d.ts +24 -0
- package/dist/src/index.js +118 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/middleware/auth.d.ts +40 -0
- package/dist/src/middleware/auth.js +135 -0
- package/dist/src/middleware/auth.js.map +1 -0
- package/dist/src/middleware/auth.test.d.ts +6 -0
- package/dist/src/middleware/auth.test.js +268 -0
- package/dist/src/middleware/auth.test.js.map +1 -0
- package/dist/src/middleware/error-handler.d.ts +20 -0
- package/dist/src/middleware/error-handler.js +48 -0
- package/dist/src/middleware/error-handler.js.map +1 -0
- package/dist/src/middleware/error-handler.test.d.ts +6 -0
- package/dist/src/middleware/error-handler.test.js +68 -0
- package/dist/src/middleware/error-handler.test.js.map +1 -0
- package/dist/src/middleware/request-validation.d.ts +13 -0
- package/dist/src/middleware/request-validation.js +26 -0
- package/dist/src/middleware/request-validation.js.map +1 -0
- package/dist/src/middleware/request-validation.test.d.ts +6 -0
- package/dist/src/middleware/request-validation.test.js +57 -0
- package/dist/src/middleware/request-validation.test.js.map +1 -0
- package/dist/src/output/email-output.d.ts +10 -0
- package/dist/src/output/email-output.js +12 -0
- package/dist/src/output/email-output.js.map +1 -0
- package/dist/src/output/output-router.d.ts +12 -0
- package/dist/src/output/output-router.js +36 -0
- package/dist/src/output/output-router.js.map +1 -0
- package/dist/src/output/output-router.test.d.ts +6 -0
- package/dist/src/output/output-router.test.js +132 -0
- package/dist/src/output/output-router.test.js.map +1 -0
- package/dist/src/output/slack-output.d.ts +10 -0
- package/dist/src/output/slack-output.js +54 -0
- package/dist/src/output/slack-output.js.map +1 -0
- package/dist/src/output/webhook-output.d.ts +10 -0
- package/dist/src/output/webhook-output.js +25 -0
- package/dist/src/output/webhook-output.js.map +1 -0
- package/dist/src/routes/ai-stream.d.ts +159 -0
- package/dist/src/routes/ai-stream.js +309 -0
- package/dist/src/routes/ai-stream.js.map +1 -0
- package/dist/src/routes/ai-stream.test.d.ts +6 -0
- package/dist/src/routes/ai-stream.test.js +586 -0
- package/dist/src/routes/ai-stream.test.js.map +1 -0
- package/dist/src/routes/ask-user-response.d.ts +30 -0
- package/dist/src/routes/ask-user-response.js +61 -0
- package/dist/src/routes/ask-user-response.js.map +1 -0
- package/dist/src/routes/ask-user-response.test.d.ts +6 -0
- package/dist/src/routes/ask-user-response.test.js +88 -0
- package/dist/src/routes/ask-user-response.test.js.map +1 -0
- package/dist/src/routes/chat-stream.d.ts +14 -0
- package/dist/src/routes/chat-stream.js +84 -0
- package/dist/src/routes/chat-stream.js.map +1 -0
- package/dist/src/routes/chat-stream.test.d.ts +6 -0
- package/dist/src/routes/chat-stream.test.js +155 -0
- package/dist/src/routes/chat-stream.test.js.map +1 -0
- package/dist/src/routes/chat.d.ts +13 -0
- package/dist/src/routes/chat.js +55 -0
- package/dist/src/routes/chat.js.map +1 -0
- package/dist/src/routes/chat.test.d.ts +6 -0
- package/dist/src/routes/chat.test.js +99 -0
- package/dist/src/routes/chat.test.js.map +1 -0
- package/dist/src/routes/health.d.ts +13 -0
- package/dist/src/routes/health.js +23 -0
- package/dist/src/routes/health.js.map +1 -0
- package/dist/src/routes/health.test.d.ts +6 -0
- package/dist/src/routes/health.test.js +45 -0
- package/dist/src/routes/health.test.js.map +1 -0
- package/dist/src/routes/sessions.d.ts +14 -0
- package/dist/src/routes/sessions.js +82 -0
- package/dist/src/routes/sessions.js.map +1 -0
- package/dist/src/routes/webhooks.d.ts +13 -0
- package/dist/src/routes/webhooks.js +43 -0
- package/dist/src/routes/webhooks.js.map +1 -0
- package/dist/src/routes/webhooks.test.d.ts +6 -0
- package/dist/src/routes/webhooks.test.js +80 -0
- package/dist/src/routes/webhooks.test.js.map +1 -0
- package/dist/src/routes/widget-actions.d.ts +49 -0
- package/dist/src/routes/widget-actions.js +78 -0
- package/dist/src/routes/widget-actions.js.map +1 -0
- package/dist/src/server.d.ts +31 -0
- package/dist/src/server.js +129 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/server.test.d.ts +6 -0
- package/dist/src/server.test.js +153 -0
- package/dist/src/server.test.js.map +1 -0
- package/dist/src/session/history-converter.d.ts +21 -0
- package/dist/src/session/history-converter.js +59 -0
- package/dist/src/session/history-converter.js.map +1 -0
- package/dist/src/session/history-converter.test.d.ts +6 -0
- package/dist/src/session/history-converter.test.js +130 -0
- package/dist/src/session/history-converter.test.js.map +1 -0
- package/dist/src/session/session-manager.d.ts +117 -0
- package/dist/src/session/session-manager.js +480 -0
- package/dist/src/session/session-manager.js.map +1 -0
- package/dist/src/session/session-manager.test.d.ts +6 -0
- package/dist/src/session/session-manager.test.js +586 -0
- package/dist/src/session/session-manager.test.js.map +1 -0
- package/dist/src/session/session-runner.d.ts +30 -0
- package/dist/src/session/session-runner.js +771 -0
- package/dist/src/session/session-runner.js.map +1 -0
- package/dist/src/session/session-runner.test.d.ts +6 -0
- package/dist/src/session/session-runner.test.js +842 -0
- package/dist/src/session/session-runner.test.js.map +1 -0
- package/dist/src/stores/index.d.ts +8 -0
- package/dist/src/stores/index.js +9 -0
- package/dist/src/stores/index.js.map +1 -0
- package/dist/src/stores/key-resolver.d.ts +21 -0
- package/dist/src/stores/key-resolver.js +30 -0
- package/dist/src/stores/key-resolver.js.map +1 -0
- package/dist/src/stores/key-resolver.test.d.ts +6 -0
- package/dist/src/stores/key-resolver.test.js +31 -0
- package/dist/src/stores/key-resolver.test.js.map +1 -0
- package/dist/src/stores/pglite-store-backend.d.ts +36 -0
- package/dist/src/stores/pglite-store-backend.js +227 -0
- package/dist/src/stores/pglite-store-backend.js.map +1 -0
- package/dist/src/stores/pglite-store-backend.test.d.ts +6 -0
- package/dist/src/stores/pglite-store-backend.test.js +150 -0
- package/dist/src/stores/pglite-store-backend.test.js.map +1 -0
- package/dist/src/stores/ttl-resolver.d.ts +24 -0
- package/dist/src/stores/ttl-resolver.js +64 -0
- package/dist/src/stores/ttl-resolver.js.map +1 -0
- package/dist/src/stores/ttl-resolver.test.d.ts +6 -0
- package/dist/src/stores/ttl-resolver.test.js +68 -0
- package/dist/src/stores/ttl-resolver.test.js.map +1 -0
- package/dist/src/types.d.ts +227 -0
- package/dist/src/types.js +50 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/types.test.d.ts +6 -0
- package/dist/src/types.test.js +68 -0
- package/dist/src/types.test.js.map +1 -0
- package/dist/src/utils/jwt-verify.d.ts +20 -0
- package/dist/src/utils/jwt-verify.js +34 -0
- package/dist/src/utils/jwt-verify.js.map +1 -0
- package/dist/src/utils/jwt-verify.test.d.ts +6 -0
- package/dist/src/utils/jwt-verify.test.js +156 -0
- package/dist/src/utils/jwt-verify.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
/**
|
|
8
|
+
* Creates routes for listing, starting, stopping, and triggering automations.
|
|
9
|
+
*
|
|
10
|
+
* GET /automations — list all registered automations
|
|
11
|
+
* POST /automations/:name/start — start a cron automation
|
|
12
|
+
* POST /automations/:name/stop — stop a running cron automation
|
|
13
|
+
* POST /automations/:name/run — manually trigger an automation
|
|
14
|
+
*/
|
|
15
|
+
export function createAutomationRouter(options) {
|
|
16
|
+
const router = Router();
|
|
17
|
+
router.get('/automations', (_req, res) => {
|
|
18
|
+
const automations = options.runner.listAutomations();
|
|
19
|
+
res.json({ automations });
|
|
20
|
+
});
|
|
21
|
+
router.post('/automations/:name/start', (req, res) => {
|
|
22
|
+
const name = req.params['name'] ?? '';
|
|
23
|
+
const result = options.runner.startAutomation(name);
|
|
24
|
+
if (!result.success) {
|
|
25
|
+
res.status(400).json({ error: result.error });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
res.json({ status: 'started', automation: name });
|
|
29
|
+
});
|
|
30
|
+
router.post('/automations/:name/stop', (req, res) => {
|
|
31
|
+
const name = req.params['name'] ?? '';
|
|
32
|
+
const result = options.runner.stopAutomation(name);
|
|
33
|
+
if (!result.success) {
|
|
34
|
+
res.status(400).json({ error: result.error });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
res.json({ status: 'stopped', automation: name });
|
|
38
|
+
});
|
|
39
|
+
router.post('/automations/:name/run', async (req, res) => {
|
|
40
|
+
const name = req.params['name'] ?? '';
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Express body parsing
|
|
42
|
+
const payload = (req.body ?? {});
|
|
43
|
+
try {
|
|
44
|
+
const result = await options.runner.triggerAutomation(name, payload);
|
|
45
|
+
if (!result.success) {
|
|
46
|
+
res.status(404).json({ error: result.error });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
res.json({ status: 'triggered', automation: name });
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
53
|
+
res.status(500).json({ error: msg });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return router;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=automations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automations.js","sourceRoot":"","sources":["../../../../src/agent/routes/automations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import request from 'supertest';
|
|
9
|
+
import { createAutomationRouter } from './automations.js';
|
|
10
|
+
function makeMockRunner(overrides) {
|
|
11
|
+
return {
|
|
12
|
+
start: vi.fn(),
|
|
13
|
+
stop: vi.fn(),
|
|
14
|
+
startAutomation: vi.fn().mockReturnValue({ success: true }),
|
|
15
|
+
stopAutomation: vi.fn().mockReturnValue({ success: true }),
|
|
16
|
+
listAutomations: vi.fn().mockReturnValue([
|
|
17
|
+
{ name: 'daily-check', title: 'Daily Check', schedule: '0 9 * * *', webhookTriggered: false, running: false },
|
|
18
|
+
{ name: 'alert-handler', title: 'Alert Handler', webhookTriggered: true, running: true },
|
|
19
|
+
]),
|
|
20
|
+
handleWebhook: vi.fn().mockResolvedValue({ matched: true }),
|
|
21
|
+
triggerAutomation: vi.fn().mockResolvedValue({ success: true }),
|
|
22
|
+
...overrides,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createApp(runner) {
|
|
26
|
+
const app = express();
|
|
27
|
+
app.use(express.json());
|
|
28
|
+
app.use(createAutomationRouter({ runner }));
|
|
29
|
+
return app;
|
|
30
|
+
}
|
|
31
|
+
describe('repo-automations routes', () => {
|
|
32
|
+
it('should list automations with running state', async () => {
|
|
33
|
+
const runner = makeMockRunner();
|
|
34
|
+
const app = createApp(runner);
|
|
35
|
+
const res = await request(app).get('/automations');
|
|
36
|
+
expect(res.status).toBe(200);
|
|
37
|
+
expect(res.body.automations).toHaveLength(2);
|
|
38
|
+
expect(res.body.automations[0].name).toBe('daily-check');
|
|
39
|
+
expect(res.body.automations[0].running).toBe(false);
|
|
40
|
+
expect(res.body.automations[1].running).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it('should start an automation', async () => {
|
|
43
|
+
const runner = makeMockRunner();
|
|
44
|
+
const app = createApp(runner);
|
|
45
|
+
const res = await request(app).post('/automations/daily-check/start');
|
|
46
|
+
expect(res.status).toBe(200);
|
|
47
|
+
expect(res.body.status).toBe('started');
|
|
48
|
+
expect(runner.startAutomation).toHaveBeenCalledWith('daily-check');
|
|
49
|
+
});
|
|
50
|
+
it('should return 400 when start fails', async () => {
|
|
51
|
+
const runner = makeMockRunner({
|
|
52
|
+
startAutomation: vi.fn().mockReturnValue({ success: false, error: 'Already running' }),
|
|
53
|
+
});
|
|
54
|
+
const app = createApp(runner);
|
|
55
|
+
const res = await request(app).post('/automations/daily-check/start');
|
|
56
|
+
expect(res.status).toBe(400);
|
|
57
|
+
expect(res.body.error).toBe('Already running');
|
|
58
|
+
});
|
|
59
|
+
it('should stop an automation', async () => {
|
|
60
|
+
const runner = makeMockRunner();
|
|
61
|
+
const app = createApp(runner);
|
|
62
|
+
const res = await request(app).post('/automations/daily-check/stop');
|
|
63
|
+
expect(res.status).toBe(200);
|
|
64
|
+
expect(res.body.status).toBe('stopped');
|
|
65
|
+
expect(runner.stopAutomation).toHaveBeenCalledWith('daily-check');
|
|
66
|
+
});
|
|
67
|
+
it('should return 400 when stop fails', async () => {
|
|
68
|
+
const runner = makeMockRunner({
|
|
69
|
+
stopAutomation: vi.fn().mockReturnValue({ success: false, error: 'Not running' }),
|
|
70
|
+
});
|
|
71
|
+
const app = createApp(runner);
|
|
72
|
+
const res = await request(app).post('/automations/daily-check/stop');
|
|
73
|
+
expect(res.status).toBe(400);
|
|
74
|
+
expect(res.body.error).toBe('Not running');
|
|
75
|
+
});
|
|
76
|
+
it('should trigger automation manually', async () => {
|
|
77
|
+
const runner = makeMockRunner();
|
|
78
|
+
const app = createApp(runner);
|
|
79
|
+
const res = await request(app)
|
|
80
|
+
.post('/automations/daily-check/run')
|
|
81
|
+
.send({});
|
|
82
|
+
expect(res.status).toBe(200);
|
|
83
|
+
expect(res.body.status).toBe('triggered');
|
|
84
|
+
expect(runner.triggerAutomation).toHaveBeenCalledWith('daily-check', {});
|
|
85
|
+
});
|
|
86
|
+
it('should return 404 for unknown automation', async () => {
|
|
87
|
+
const runner = makeMockRunner({
|
|
88
|
+
triggerAutomation: vi.fn().mockResolvedValue({ success: false, error: 'Not found' }),
|
|
89
|
+
});
|
|
90
|
+
const app = createApp(runner);
|
|
91
|
+
const res = await request(app)
|
|
92
|
+
.post('/automations/unknown/run')
|
|
93
|
+
.send({});
|
|
94
|
+
expect(res.status).toBe(404);
|
|
95
|
+
expect(res.body.error).toContain('Not found');
|
|
96
|
+
});
|
|
97
|
+
it('should pass payload to triggerAutomation', async () => {
|
|
98
|
+
const runner = makeMockRunner();
|
|
99
|
+
const app = createApp(runner);
|
|
100
|
+
await request(app)
|
|
101
|
+
.post('/automations/daily-check/run')
|
|
102
|
+
.send({ context: 'manual-trigger' });
|
|
103
|
+
expect(runner.triggerAutomation).toHaveBeenCalledWith('daily-check', { context: 'manual-trigger' });
|
|
104
|
+
});
|
|
105
|
+
it('should handle trigger errors', async () => {
|
|
106
|
+
const runner = makeMockRunner({
|
|
107
|
+
triggerAutomation: vi.fn().mockRejectedValue(new Error('Runtime failure')),
|
|
108
|
+
});
|
|
109
|
+
const app = createApp(runner);
|
|
110
|
+
const res = await request(app)
|
|
111
|
+
.post('/automations/daily-check/run')
|
|
112
|
+
.send({});
|
|
113
|
+
expect(res.status).toBe(500);
|
|
114
|
+
expect(res.body.error).toBe('Runtime failure');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=automations.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automations.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/automations.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import type { Request, Response } from 'express';
|
|
8
|
+
import type { AgentSession } from '../agent-types.js';
|
|
9
|
+
import type { AgentSessionManager } from '../session-manager.js';
|
|
10
|
+
/**
|
|
11
|
+
* Optional hook for customizing session creation.
|
|
12
|
+
* When provided, called instead of sessionManager.create().
|
|
13
|
+
* Receives the Express request and response (for auth context access).
|
|
14
|
+
*/
|
|
15
|
+
export type SessionCreator = (req: Request, res: Response, tenantId: string, tenantToken?: string) => Promise<AgentSession>;
|
|
16
|
+
/**
|
|
17
|
+
* Optional hook for hydrating a session from external storage.
|
|
18
|
+
* Called when session_id is provided but not found in memory.
|
|
19
|
+
*/
|
|
20
|
+
export type SessionHydrator = (req: Request, res: Response, sessionId: string, tenantId: string) => Promise<AgentSession | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Optional hook called after each agent turn completes.
|
|
23
|
+
* Used by hosted runtime to persist conversation history.
|
|
24
|
+
*/
|
|
25
|
+
export type TurnCompleteHandler = (session: AgentSession, req: Request, res: Response) => void;
|
|
26
|
+
export interface ChatRouterOptions {
|
|
27
|
+
sessionManager: AgentSessionManager;
|
|
28
|
+
/** Optional session creator hook — used by hosted runtime to inject tenant config from platform API */
|
|
29
|
+
sessionCreator?: SessionCreator;
|
|
30
|
+
/** Optional session hydrator — called when session_id not found in memory (e.g., load from platform API) */
|
|
31
|
+
sessionHydrator?: SessionHydrator;
|
|
32
|
+
/** Optional callback after each agent turn — used for persisting conversation history */
|
|
33
|
+
onTurnComplete?: TurnCompleteHandler;
|
|
34
|
+
}
|
|
35
|
+
export declare function createChatRouter(options: ChatRouterOptions): Router;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import { AgentChatRequestSchema } from '../agent-types.js';
|
|
8
|
+
import { runAgentTurn } from '../agent-runner.js';
|
|
9
|
+
import { SSEEventType } from '../../types.js';
|
|
10
|
+
export function createChatRouter(options) {
|
|
11
|
+
const router = Router();
|
|
12
|
+
router.post('/chat', async (req, res) => {
|
|
13
|
+
const parsed = AgentChatRequestSchema.safeParse(req.body);
|
|
14
|
+
if (!parsed.success) {
|
|
15
|
+
res.status(400).json({
|
|
16
|
+
error: {
|
|
17
|
+
code: 'VALIDATION_ERROR',
|
|
18
|
+
message: parsed.error.message,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const { message, session_id, tenant_id, tenant_token } = parsed.data;
|
|
24
|
+
// SSE headers
|
|
25
|
+
res.writeHead(200, {
|
|
26
|
+
'Content-Type': 'text/event-stream',
|
|
27
|
+
'Cache-Control': 'no-cache',
|
|
28
|
+
'Connection': 'keep-alive',
|
|
29
|
+
});
|
|
30
|
+
// Get or create session
|
|
31
|
+
let session = session_id ? options.sessionManager.get(session_id) : undefined;
|
|
32
|
+
// Try hydration if session not in memory
|
|
33
|
+
if (!session && session_id && options.sessionHydrator) {
|
|
34
|
+
try {
|
|
35
|
+
session = await options.sessionHydrator(req, res, session_id, tenant_id) ?? undefined;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Hydration failed — fall through to create new session
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!session) {
|
|
42
|
+
try {
|
|
43
|
+
session = options.sessionCreator
|
|
44
|
+
? await options.sessionCreator(req, res, tenant_id, tenant_token)
|
|
45
|
+
: await options.sessionManager.create(tenant_id, tenant_token);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
writeSSE(res, { type: SSEEventType.Error, message: errMsg, timestamp: ts() });
|
|
50
|
+
writeSSE(res, { type: SSEEventType.Done, timestamp: ts() });
|
|
51
|
+
res.end();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Send init event
|
|
56
|
+
writeSSE(res, { type: SSEEventType.Init, session_id: session.id, timestamp: ts() });
|
|
57
|
+
// Abort on client disconnect (use res, not req — req closes when body is consumed)
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
res.on('close', () => controller.abort());
|
|
60
|
+
try {
|
|
61
|
+
for await (const event of runAgentTurn(session, message, controller.signal)) {
|
|
62
|
+
if (controller.signal.aborted)
|
|
63
|
+
break;
|
|
64
|
+
writeSSE(res, event);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
if (!controller.signal.aborted) {
|
|
69
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
70
|
+
writeSSE(res, { type: SSEEventType.Error, message: errMsg, timestamp: ts() });
|
|
71
|
+
writeSSE(res, { type: SSEEventType.Done, timestamp: ts() });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Notify after turn completes (e.g., persist history)
|
|
75
|
+
if (options.onTurnComplete) {
|
|
76
|
+
options.onTurnComplete(session, req, res);
|
|
77
|
+
}
|
|
78
|
+
res.end();
|
|
79
|
+
});
|
|
80
|
+
return router;
|
|
81
|
+
}
|
|
82
|
+
function writeSSE(res, event) {
|
|
83
|
+
res.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
84
|
+
}
|
|
85
|
+
function ts() {
|
|
86
|
+
return new Date().toISOString();
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../../src/agent/routes/chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import request from 'supertest';
|
|
9
|
+
import { createChatRouter } from './chat.js';
|
|
10
|
+
// Mock agent-runner
|
|
11
|
+
vi.mock('../agent-runner.js', () => ({
|
|
12
|
+
runAgentTurn: vi.fn(async function* () {
|
|
13
|
+
yield { type: 'text_delta', content: 'Hello!', timestamp: new Date().toISOString() };
|
|
14
|
+
yield { type: 'done', timestamp: new Date().toISOString() };
|
|
15
|
+
}),
|
|
16
|
+
}));
|
|
17
|
+
function makeSessionManager() {
|
|
18
|
+
const sessions = new Map();
|
|
19
|
+
return {
|
|
20
|
+
size: 0,
|
|
21
|
+
create: vi.fn(async (tenantId) => {
|
|
22
|
+
const session = {
|
|
23
|
+
id: 'session-1',
|
|
24
|
+
tenantId,
|
|
25
|
+
runtime: { compiledContext: { systemPrompt: 'test' } },
|
|
26
|
+
conversationHistory: [],
|
|
27
|
+
createdAt: Date.now(),
|
|
28
|
+
lastAccessedAt: Date.now(),
|
|
29
|
+
planModeManager: {},
|
|
30
|
+
exploreConfig: {},
|
|
31
|
+
};
|
|
32
|
+
sessions.set(session.id, session);
|
|
33
|
+
return session;
|
|
34
|
+
}),
|
|
35
|
+
get: vi.fn((id) => sessions.get(id)),
|
|
36
|
+
destroy: vi.fn(),
|
|
37
|
+
cleanup: vi.fn(),
|
|
38
|
+
updateRepo: vi.fn(),
|
|
39
|
+
shutdown: vi.fn(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createTestApp(sessionManager) {
|
|
43
|
+
const app = express();
|
|
44
|
+
app.use(express.json());
|
|
45
|
+
app.use(createChatRouter({ sessionManager }));
|
|
46
|
+
return app;
|
|
47
|
+
}
|
|
48
|
+
describe('repo-chat route', () => {
|
|
49
|
+
let sessionManager;
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
sessionManager = makeSessionManager();
|
|
52
|
+
});
|
|
53
|
+
it('should reject invalid request body', async () => {
|
|
54
|
+
const app = createTestApp(sessionManager);
|
|
55
|
+
const res = await request(app).post('/chat').send({});
|
|
56
|
+
expect(res.status).toBe(400);
|
|
57
|
+
});
|
|
58
|
+
it('should reject missing tenant_id', async () => {
|
|
59
|
+
const app = createTestApp(sessionManager);
|
|
60
|
+
const res = await request(app).post('/chat').send({ message: 'hello' });
|
|
61
|
+
expect(res.status).toBe(400);
|
|
62
|
+
});
|
|
63
|
+
it('should return SSE events for valid request', async () => {
|
|
64
|
+
const app = createTestApp(sessionManager);
|
|
65
|
+
const res = await request(app)
|
|
66
|
+
.post('/chat')
|
|
67
|
+
.send({ message: 'hello', tenant_id: 'tenant-1' })
|
|
68
|
+
.set('Accept', 'text/event-stream');
|
|
69
|
+
expect(res.status).toBe(200);
|
|
70
|
+
expect(res.headers['content-type']).toContain('text/event-stream');
|
|
71
|
+
expect(res.text).toContain('data:');
|
|
72
|
+
});
|
|
73
|
+
it('should create a new session if no session_id', async () => {
|
|
74
|
+
const app = createTestApp(sessionManager);
|
|
75
|
+
await request(app)
|
|
76
|
+
.post('/chat')
|
|
77
|
+
.send({ message: 'hello', tenant_id: 'tenant-1' });
|
|
78
|
+
expect(sessionManager.create).toHaveBeenCalledWith('tenant-1', undefined);
|
|
79
|
+
});
|
|
80
|
+
it('should reuse existing session if session_id provided', async () => {
|
|
81
|
+
const app = createTestApp(sessionManager);
|
|
82
|
+
// Create a session first
|
|
83
|
+
await request(app)
|
|
84
|
+
.post('/chat')
|
|
85
|
+
.send({ message: 'hello', tenant_id: 'tenant-1' });
|
|
86
|
+
// Reuse it
|
|
87
|
+
await request(app)
|
|
88
|
+
.post('/chat')
|
|
89
|
+
.send({ message: 'follow up', tenant_id: 'tenant-1', session_id: 'session-1' });
|
|
90
|
+
expect(sessionManager.get).toHaveBeenCalledWith('session-1');
|
|
91
|
+
});
|
|
92
|
+
it('should include init event in response', async () => {
|
|
93
|
+
const app = createTestApp(sessionManager);
|
|
94
|
+
const res = await request(app)
|
|
95
|
+
.post('/chat')
|
|
96
|
+
.send({ message: 'hello', tenant_id: 'tenant-1' });
|
|
97
|
+
expect(res.text).toContain('"type":"init"');
|
|
98
|
+
});
|
|
99
|
+
it('should handle session creation failure', async () => {
|
|
100
|
+
sessionManager.create.mockRejectedValue(new Error('Setup failed'));
|
|
101
|
+
const app = createTestApp(sessionManager);
|
|
102
|
+
const res = await request(app)
|
|
103
|
+
.post('/chat')
|
|
104
|
+
.send({ message: 'hello', tenant_id: 'tenant-1' });
|
|
105
|
+
expect(res.text).toContain('"type":"error"');
|
|
106
|
+
});
|
|
107
|
+
it('should pass tenant_token when provided', async () => {
|
|
108
|
+
const app = createTestApp(sessionManager);
|
|
109
|
+
await request(app)
|
|
110
|
+
.post('/chat')
|
|
111
|
+
.send({ message: 'hello', tenant_id: 'tenant-1', tenant_token: 'tok-123' });
|
|
112
|
+
expect(sessionManager.create).toHaveBeenCalledWith('tenant-1', 'tok-123');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=chat.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/chat.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import type { AgentSessionManager } from '../session-manager.js';
|
|
8
|
+
export interface InspectRouterOptions {
|
|
9
|
+
sessionManager: AgentSessionManager;
|
|
10
|
+
repoPath: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function createInspectRouter(options: InspectRouterOptions): Router;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
export function createInspectRouter(options) {
|
|
8
|
+
const router = Router();
|
|
9
|
+
router.get('/inspect/context', async (_req, res) => {
|
|
10
|
+
try {
|
|
11
|
+
// Create a temporary session to inspect the compiled context
|
|
12
|
+
const session = await options.sessionManager.create('__inspect__');
|
|
13
|
+
const runtime = session.runtime;
|
|
14
|
+
const compiled = runtime.compiledContext;
|
|
15
|
+
res.json({
|
|
16
|
+
repo_path: options.repoPath,
|
|
17
|
+
system_prompt_length: compiled.systemPrompt.length,
|
|
18
|
+
token_usage: compiled.tokenUsage,
|
|
19
|
+
sections: compiled.sections.map((s) => ({
|
|
20
|
+
name: s.name,
|
|
21
|
+
tokens: s.tokens,
|
|
22
|
+
priority: s.priority,
|
|
23
|
+
trimmed: s.trimmed,
|
|
24
|
+
})),
|
|
25
|
+
connections: Array.from(runtime.repo.connections.keys()),
|
|
26
|
+
skills: runtime.repo.skills.map((s) => s.name),
|
|
27
|
+
automations: runtime.repo.automations.map((a) => a.name),
|
|
28
|
+
knowledge: runtime.repo.knowledge.map((k) => k.name),
|
|
29
|
+
});
|
|
30
|
+
// Clean up the temporary session
|
|
31
|
+
options.sessionManager.destroy(session.id);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
35
|
+
res.status(500).json({ error: { code: 'INSPECT_FAILED', message: msg } });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return router;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../../../src/agent/routes/inspect.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAS/B,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;QACpE,IAAI,CAAC;YACH,6DAA6D;YAC7D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAEnE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;YAEzC,GAAG,CAAC,IAAI,CAAC;gBACP,SAAS,EAAE,OAAO,CAAC,QAAQ;gBAC3B,oBAAoB,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM;gBAClD,WAAW,EAAE,QAAQ,CAAC,UAAU;gBAChC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACtC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,OAAO,EAAE,CAAC,CAAC,OAAO;iBACnB,CAAC,CAAC;gBACH,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;gBACxD,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC9C,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBACxD,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aACrD,CAAC,CAAC;YAEH,iCAAiC;YACjC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,EAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,EAAC,EAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import request from 'supertest';
|
|
9
|
+
import { createInspectRouter } from './inspect.js';
|
|
10
|
+
function makeSessionManager() {
|
|
11
|
+
return {
|
|
12
|
+
size: 0,
|
|
13
|
+
create: vi.fn(async () => ({
|
|
14
|
+
id: 'inspect-session',
|
|
15
|
+
tenantId: '__inspect__',
|
|
16
|
+
runtime: {
|
|
17
|
+
compiledContext: {
|
|
18
|
+
systemPrompt: 'You are a test agent.',
|
|
19
|
+
tokenUsage: { total: 100000, used: 500, remaining: 99500, sectionBreakdown: { core: 200, skills: 300 } },
|
|
20
|
+
sections: [
|
|
21
|
+
{ name: 'core', content: 'Core instructions', tokens: 200, priority: 10, trimmed: false },
|
|
22
|
+
{ name: 'skills', content: 'Skill definitions', tokens: 300, priority: 5, trimmed: false },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
repo: {
|
|
26
|
+
connections: new Map([['crm', {}]]),
|
|
27
|
+
skills: [{ name: 'triage' }, { name: 'investigate' }],
|
|
28
|
+
automations: [{ name: 'daily-scan' }],
|
|
29
|
+
knowledge: [{ name: 'api-docs' }],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
})),
|
|
33
|
+
destroy: vi.fn(),
|
|
34
|
+
get: vi.fn(),
|
|
35
|
+
cleanup: vi.fn(),
|
|
36
|
+
updateRepo: vi.fn(),
|
|
37
|
+
shutdown: vi.fn(),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createTestApp(sessionManager) {
|
|
41
|
+
const app = express();
|
|
42
|
+
app.use(createInspectRouter({ sessionManager, repoPath: '/test/repo' }));
|
|
43
|
+
return app;
|
|
44
|
+
}
|
|
45
|
+
describe('repo-inspect route', () => {
|
|
46
|
+
let sessionManager;
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
sessionManager = makeSessionManager();
|
|
49
|
+
});
|
|
50
|
+
it('should return compiled context info', async () => {
|
|
51
|
+
const app = createTestApp(sessionManager);
|
|
52
|
+
const res = await request(app).get('/inspect/context');
|
|
53
|
+
expect(res.status).toBe(200);
|
|
54
|
+
expect(res.body).toHaveProperty('repo_path', '/test/repo');
|
|
55
|
+
expect(res.body['token_usage']).toEqual({
|
|
56
|
+
total: 100000,
|
|
57
|
+
used: 500,
|
|
58
|
+
remaining: 99500,
|
|
59
|
+
sectionBreakdown: { core: 200, skills: 300 },
|
|
60
|
+
});
|
|
61
|
+
expect(res.body['sections']).toHaveLength(2);
|
|
62
|
+
expect(res.body['connections']).toEqual(['crm']);
|
|
63
|
+
expect(res.body['skills']).toEqual(['triage', 'investigate']);
|
|
64
|
+
expect(res.body['automations']).toEqual(['daily-scan']);
|
|
65
|
+
expect(res.body['knowledge']).toEqual(['api-docs']);
|
|
66
|
+
});
|
|
67
|
+
it('should destroy temporary session after inspect', async () => {
|
|
68
|
+
const app = createTestApp(sessionManager);
|
|
69
|
+
await request(app).get('/inspect/context');
|
|
70
|
+
expect(sessionManager.destroy).toHaveBeenCalledWith('inspect-session');
|
|
71
|
+
});
|
|
72
|
+
it('should handle session creation errors', async () => {
|
|
73
|
+
sessionManager.create.mockRejectedValue(new Error('Config invalid'));
|
|
74
|
+
const app = createTestApp(sessionManager);
|
|
75
|
+
const res = await request(app).get('/inspect/context');
|
|
76
|
+
expect(res.status).toBe(500);
|
|
77
|
+
expect(res.body['error']['code']).toBe('INSPECT_FAILED');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=inspect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.test.js","sourceRoot":"","sources":["../../../../src/agent/routes/inspect.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Amodal Labs, Inc.
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import type { AmodalRepo, StoreBackend } from '@amodalai/core';
|
|
8
|
+
export interface StoreRouterOptions {
|
|
9
|
+
repo: AmodalRepo;
|
|
10
|
+
storeBackend: StoreBackend;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates routes for reading store data directly (without going through the LLM).
|
|
15
|
+
*
|
|
16
|
+
* GET /api/stores — list store definitions with doc counts
|
|
17
|
+
* GET /api/stores/:name — list documents (filter, sort, limit, offset)
|
|
18
|
+
* GET /api/stores/:name/:key — get single document + version history
|
|
19
|
+
*/
|
|
20
|
+
export declare function createStoresRouter(options: StoreRouterOptions): Router;
|