@anteros/core 0.0.41 → 0.0.42
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/database/audit.ts +9 -59
- package/database/collection.ts +3 -1
- package/database/deleteLog.ts +67 -3
- package/database/file.ts +4 -3
- package/database/mongodbadapter.ts +103 -42
- package/database/replication.ts +110 -32
- package/database/ttl.ts +68 -0
- package/database/workflow.ts +466 -240
- package/index.ts +6 -0
- package/lib/agent.ts +1327 -0
- package/lib/agentMemory.ts +586 -0
- package/lib/agents.ts +157 -0
- package/lib/ai.ts +0 -0
- package/lib/api.ts +246 -0
- package/lib/attachment.ts +351 -0
- package/lib/auditResult.ts +13 -0
- package/lib/define.ts +43 -1
- package/lib/endpoints.ts +80 -0
- package/lib/files.ts +2 -1
- package/lib/jsonSchema.ts +183 -0
- package/lib/lifecycle.ts +7 -1
- package/lib/load.ts +17 -0
- package/lib/mcp.ts +3 -2
- package/lib/messages.ts +299 -0
- package/lib/providers.ts +867 -0
- package/lib/routes.ts +14 -1
- package/lib/scriptWorker.ts +4 -1
- package/lib/scripts.ts +6 -1
- package/lib/sockets.ts +3 -1
- package/lib/workflow.ts +209 -37
- package/lib/zip.ts +109 -0
- package/package.json +1 -1
- package/server/access.ts +96 -0
- package/server/agents.ts +451 -0
- package/server/api.ts +14 -72
- package/server/boot.ts +11 -0
- package/server/hono.ts +8 -3
- package/server/mcp.ts +17 -63
- package/server/routes.ts +19 -24
- package/tests/agent-memory.test.ts +617 -0
- package/tests/agent-working-memory.test.ts +402 -0
- package/tests/agent.test.ts +1239 -0
- package/tests/agents-api.test.ts +593 -0
- package/tests/api.test.ts +51 -0
- package/tests/attachment.test.ts +241 -0
- package/tests/audit-operations.test.ts +1 -1
- package/tests/audit-redact.test.ts +29 -3
- package/tests/audit-run-action.test.ts +1 -1
- package/tests/endpoints.test.ts +80 -0
- package/tests/fixtures/agent-tenant/agents/support.agent.ts +9 -0
- package/tests/fixtures/agent-tenant/agents/weather.agent.ts +21 -0
- package/tests/fixtures/agents-api/agents/assistant.agent.ts +46 -0
- package/tests/fixtures/agents-api/agents/plain.agent.ts +23 -0
- package/tests/fixtures/agents-api/agents/private.agent.ts +15 -0
- package/tests/fixtures/agents-api/collections/notes.model.ts +26 -0
- package/tests/fixtures/agents-api/routes/probe.route.ts +21 -0
- package/tests/fixtures/agents-api/services/probe.service.ts +19 -0
- package/tests/fixtures/attachment/data.csv +2 -0
- package/tests/fixtures/fake-provider.ts +128 -0
- package/tests/fixtures/replication-meta/agents/chat.agent.ts +16 -0
- package/tests/fixtures/replication-meta/collections/counters.model.ts +13 -0
- package/tests/fixtures/replication-meta/collections/orders.model.ts +9 -0
- package/tests/fixtures/replication-meta/workflows/run.workflow.ts +8 -0
- package/tests/fixtures/vars-tenant/vars/private.var.ts +4 -1
- package/tests/fixtures/workflow-engine/workflows/failing.workflow.ts +34 -0
- package/tests/fixtures/workflow-engine/workflows/flaky.workflow.ts +23 -0
- package/tests/fixtures/workflow-engine/workflows/hang.workflow.ts +17 -0
- package/tests/fixtures/workflow-engine/workflows/simple.workflow.ts +19 -0
- package/tests/fixtures/workflow-engine/workflows/slow.workflow.ts +23 -0
- package/tests/fixtures/workflow-engine/workflows/versioned.workflow.ts +19 -0
- package/tests/fixtures/workflow-tenant/workflows/broken.workflow.ts +3 -0
- package/tests/fixtures/workflow-tenant/workflows/disabled.workflow.ts +8 -0
- package/tests/fixtures/workflow-tenant/workflows/invoice.workflow.ts +21 -0
- package/tests/fixtures/workflow-tenant/workflows/no-id.workflow.ts +7 -0
- package/tests/fixtures/workflow-tenant/workflows/order-duplicate.workflow.ts +13 -0
- package/tests/fixtures/workflow-tenant/workflows/order.workflow.ts +17 -0
- package/tests/hono.test.ts +6 -3
- package/tests/locks.test.ts +120 -0
- package/tests/mcp.test.ts +11 -11
- package/tests/messages.test.ts +258 -0
- package/tests/replication-control.test.ts +2 -2
- package/tests/replication-meta.test.ts +243 -0
- package/tests/upload.test.ts +44 -12
- package/tests/vars-api.test.ts +1 -1
- package/tests/vars-replication.test.ts +3 -2
- package/tests/workflow-engine.test.ts +340 -0
- package/tests/workflow-retention.test.ts +103 -0
- package/tests/workflow.test.ts +186 -0
- package/types/agent.d.ts +837 -0
- package/types/config.d.ts +16 -0
- package/types/file.d.ts +7 -7
- package/types/hook.d.ts +6 -0
- package/types/lifecycle.d.ts +6 -0
- package/types/mcp.d.ts +11 -1
- package/types/replication.d.ts +29 -0
- package/types/route.d.ts +7 -1
- package/types/scripts.d.ts +6 -0
- package/types/service.d.ts +7 -1
- package/types/tenant.d.ts +13 -0
- package/types/vars.d.ts +2 -2
- package/types/websocket.d.ts +6 -0
- package/types/workflow.d.ts +50 -3
package/server/mcp.ts
CHANGED
|
@@ -10,72 +10,18 @@ import {
|
|
|
10
10
|
ErrorCode,
|
|
11
11
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
12
12
|
import { StreamableHTTPTransport } from "@hono/mcp";
|
|
13
|
-
import type Joi from "joi";
|
|
14
13
|
import { cfg } from "./config";
|
|
15
14
|
import { useRest } from "../database/rest";
|
|
15
|
+
import { createAgents } from "../lib/agents";
|
|
16
|
+
import { createApi } from "../lib/api";
|
|
16
17
|
import { logger } from "../utils/logger";
|
|
17
18
|
import type { McpTool, McpResource } from "../types/mcp";
|
|
18
19
|
import type { HonoVariables } from "./env";
|
|
20
|
+
import { joiToJsonSchema } from "../lib/jsonSchema";
|
|
21
|
+
import { patterns } from "../lib/endpoints";
|
|
19
22
|
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
function joiTypeToJson(type: string): string {
|
|
23
|
-
switch (type) {
|
|
24
|
-
case 'number': return 'number';
|
|
25
|
-
case 'integer': return 'integer';
|
|
26
|
-
case 'boolean': return 'boolean';
|
|
27
|
-
case 'date': return 'string';
|
|
28
|
-
default: return 'string';
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Minimal Joi → JSON Schema converter (covers the common field types). */
|
|
33
|
-
function joiToJsonSchema(schema: Joi.Schema, describe = schema.describe() as any): any {
|
|
34
|
-
const node: any = {};
|
|
35
|
-
const type = describe?.type;
|
|
36
|
-
|
|
37
|
-
switch (type) {
|
|
38
|
-
case 'object': {
|
|
39
|
-
node.type = 'object';
|
|
40
|
-
const properties: Record<string, any> = {};
|
|
41
|
-
const required: string[] = [];
|
|
42
|
-
for (const [key, child] of Object.entries(describe.keys ?? {})) {
|
|
43
|
-
properties[key] = joiToJsonSchema(child as any, child);
|
|
44
|
-
if ((child as any)?.flags?.presence === 'required') required.push(key);
|
|
45
|
-
}
|
|
46
|
-
node.properties = properties;
|
|
47
|
-
if (required.length) node.required = required;
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
case 'array': {
|
|
51
|
-
node.type = 'array';
|
|
52
|
-
if (describe.items?.length) node.items = joiToJsonSchema(describe.items[0], describe.items[0]);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
default: {
|
|
56
|
-
node.type = joiTypeToJson(type);
|
|
57
|
-
if (type === 'date') node.format = 'date-time';
|
|
58
|
-
if (type === 'string') {
|
|
59
|
-
for (const rule of describe.rules ?? []) {
|
|
60
|
-
if (['email', 'uri', 'uuid', 'isoDate', 'ip'].includes(rule.name)) {
|
|
61
|
-
node.format = rule.name;
|
|
62
|
-
}
|
|
63
|
-
if (rule.name === 'pattern' && rule.args?.regex) {
|
|
64
|
-
node.pattern = String(rule.args.regex).replace(/^\/|\/[gimsuy]*$/g, '');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (describe.valids?.length && describe.valids.length <= 50) {
|
|
69
|
-
node.enum = describe.valids;
|
|
70
|
-
}
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (describe?.flags?.presence === 'required') node.description = node.description ?? 'required';
|
|
76
|
-
if (describe?.flags?.description) node.description = describe.flags.description;
|
|
77
|
-
return node;
|
|
78
|
-
}
|
|
23
|
+
// The Joi → JSON Schema converter is shared with the agent runtime — a tool
|
|
24
|
+
// must look identical whether it is exposed over MCP or to a model.
|
|
79
25
|
|
|
80
26
|
// ─── URI template matching (users://{id} → params) ───────────────────────
|
|
81
27
|
|
|
@@ -148,7 +94,13 @@ function buildServer(tenantId: string, tools: McpTool[], resources: McpResource[
|
|
|
148
94
|
|
|
149
95
|
const rest = new useRest({ tenant_id: tenantId });
|
|
150
96
|
try {
|
|
151
|
-
const result = await tool.exec({
|
|
97
|
+
const result = await tool.exec({
|
|
98
|
+
c: undefined as any,
|
|
99
|
+
rest,
|
|
100
|
+
args: value,
|
|
101
|
+
agents: createAgents(tenantId, rest),
|
|
102
|
+
api: createApi(rest),
|
|
103
|
+
});
|
|
152
104
|
const isError = !!(result as any)?.isError;
|
|
153
105
|
logger[isError ? 'warn' : 'info']('MCP tools/call', { method: 'tools/call', tenant: tenantId, tool: req.params.name, args: value, isError, duration: ms(start) });
|
|
154
106
|
if (result && Array.isArray(result.content)) return result;
|
|
@@ -205,6 +157,8 @@ function buildServer(tenantId: string, tools: McpTool[], resources: McpResource[
|
|
|
205
157
|
const result = await matched.resource.read({
|
|
206
158
|
c: undefined as any,
|
|
207
159
|
rest,
|
|
160
|
+
agents: createAgents(tenantId, rest),
|
|
161
|
+
api: createApi(rest),
|
|
208
162
|
params: matched.params,
|
|
209
163
|
uri,
|
|
210
164
|
});
|
|
@@ -221,7 +175,7 @@ function buildServer(tenantId: string, tools: McpTool[], resources: McpResource[
|
|
|
221
175
|
|
|
222
176
|
/**
|
|
223
177
|
* Expose each tenant's MCP tools & resources over the Model Context Protocol
|
|
224
|
-
* at `GET/POST /
|
|
178
|
+
* at `GET/POST /api/:tenant_id/mcp` (Streamable HTTP transport — works with
|
|
225
179
|
* Claude, Cursor, VS Code, and any MCP client).
|
|
226
180
|
*/
|
|
227
181
|
export function initializeMcp(app: Hono<{ Variables: HonoVariables }>) {
|
|
@@ -238,7 +192,7 @@ export function initializeMcp(app: Hono<{ Variables: HonoVariables }>) {
|
|
|
238
192
|
resourcesByTenant.set(resource._tenant_ ?? '', list);
|
|
239
193
|
}
|
|
240
194
|
|
|
241
|
-
app.all(
|
|
195
|
+
app.all(patterns.mcp, async (c: Context<{ Variables: HonoVariables }>) => {
|
|
242
196
|
const tenantId = c.req.param('tenant_id') ?? '';
|
|
243
197
|
const tools = toolsByTenant.get(tenantId) ?? [];
|
|
244
198
|
const resources = resourcesByTenant.get(tenantId) ?? [];
|
package/server/routes.ts
CHANGED
|
@@ -3,10 +3,26 @@ import { cfg } from "./config";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { jwt } from "../utils/func";
|
|
5
5
|
import { useRest } from "../database/rest";
|
|
6
|
+
import { createAgents } from "../lib/agents";
|
|
7
|
+
import { createApi } from "../lib/api";
|
|
6
8
|
import { io } from "./io";
|
|
7
9
|
import { requestCtxStorage } from "../lib/asyncContextStorage";
|
|
8
10
|
import type { HonoVariables } from "./env";
|
|
9
11
|
|
|
12
|
+
/** The context of a route handler — `rest` and `agents` share the same tenant. */
|
|
13
|
+
function routeContext(c: any, tenantId: string) {
|
|
14
|
+
const rest = new useRest({ tenant_id: tenantId });
|
|
15
|
+
return {
|
|
16
|
+
c,
|
|
17
|
+
rest,
|
|
18
|
+
// Tenant-scoped LLM registry, bound to this request's `rest`
|
|
19
|
+
agents: createAgents(tenantId, rest),
|
|
20
|
+
api: createApi(rest),
|
|
21
|
+
jwt: jwt,
|
|
22
|
+
io: io,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
function initializeRoutes(app: Hono<{ Variables: HonoVariables }>) {
|
|
11
27
|
for (let route of cfg.routes ?? []) {
|
|
12
28
|
if (route._prefix_) {
|
|
@@ -24,42 +40,21 @@ function initializeRoutes(app: Hono<{ Variables: HonoVariables }>) {
|
|
|
24
40
|
if (route.method == "GET") {
|
|
25
41
|
app.get(routePath, async (c) => { //
|
|
26
42
|
resolveTenant();
|
|
27
|
-
return route.handler(
|
|
28
|
-
c,
|
|
29
|
-
rest: new useRest({
|
|
30
|
-
tenant_id: route._tenant_,
|
|
31
|
-
}),
|
|
32
|
-
jwt: jwt,
|
|
33
|
-
io: io,
|
|
34
|
-
});
|
|
43
|
+
return route.handler(routeContext(c, route._tenant_!));
|
|
35
44
|
});
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
if (route.method == 'POST') {
|
|
39
48
|
app.post(routePath, async (c) => {
|
|
40
49
|
resolveTenant();
|
|
41
|
-
return route.handler(
|
|
42
|
-
c,
|
|
43
|
-
rest: new useRest({
|
|
44
|
-
tenant_id: route._tenant_,
|
|
45
|
-
}),
|
|
46
|
-
jwt: jwt,
|
|
47
|
-
io: io,
|
|
48
|
-
});
|
|
50
|
+
return route.handler(routeContext(c, route._tenant_!));
|
|
49
51
|
});
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
if (route.method == "PUT") {
|
|
53
55
|
app.put(routePath, async (c) => { //
|
|
54
56
|
resolveTenant();
|
|
55
|
-
return route.handler(
|
|
56
|
-
c,
|
|
57
|
-
rest: new useRest({
|
|
58
|
-
tenant_id: route._tenant_,
|
|
59
|
-
}),
|
|
60
|
-
jwt: jwt,
|
|
61
|
-
io: io,
|
|
62
|
-
});
|
|
57
|
+
return route.handler(routeContext(c, route._tenant_!));
|
|
63
58
|
});
|
|
64
59
|
}
|
|
65
60
|
}
|