@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/types/config.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { Script } from "./scripts";
|
|
|
8
8
|
import type { FileCollection } from "./file";
|
|
9
9
|
import type { McpTool, McpResource } from "./mcp";
|
|
10
10
|
import type { VarDefinition } from "./vars";
|
|
11
|
+
import type { AgentDefinition } from "./agent";
|
|
11
12
|
import type { AuditFileConfig } from "../lib/audit";
|
|
12
13
|
export type ServerConfig = {
|
|
13
14
|
debug?: boolean;
|
|
@@ -67,6 +68,18 @@ export type ServerConfig = {
|
|
|
67
68
|
*/
|
|
68
69
|
results?: 'none' | 'summary' | 'full';
|
|
69
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Workflow defaults for every tenant — a tenant declaring its own
|
|
73
|
+
* `tenant.workflows` always wins.
|
|
74
|
+
*/
|
|
75
|
+
workflows?: {
|
|
76
|
+
/**
|
|
77
|
+
* How long **finished** workflow runs are kept (MongoDB TTL on
|
|
78
|
+
* `completedAt`). Duration string: `'30d'`, `'90d'`.
|
|
79
|
+
* `false` → explicitly disabled. Omitted → untouched.
|
|
80
|
+
*/
|
|
81
|
+
retention?: string | false;
|
|
82
|
+
};
|
|
70
83
|
body?: {
|
|
71
84
|
maxSize?: number;
|
|
72
85
|
};
|
|
@@ -187,4 +200,7 @@ export type Config = ServerConfig & {
|
|
|
187
200
|
mcpTools?: McpTool[]
|
|
188
201
|
mcpResources?: McpResource[]
|
|
189
202
|
vars?: VarDefinition[]
|
|
203
|
+
agents?: AgentDefinition[]
|
|
204
|
+
/** Mongo collections used as agent memory — published by `syncAgents()` (see the Memory page). */
|
|
205
|
+
agentMemories?: Array<{ _tenant_: string; collection: string }>
|
|
190
206
|
}
|
package/types/file.d.ts
CHANGED
|
@@ -16,11 +16,11 @@ type FileAccessHandler = (ctx: {
|
|
|
16
16
|
type FileApiAccess = {
|
|
17
17
|
/** Default access rule applied when no per-operation rule is set */
|
|
18
18
|
'*'?: boolean | FileAccessHandler;
|
|
19
|
-
/** Access control for POST /
|
|
19
|
+
/** Access control for POST /api/:tenant_id/upload/:slug */
|
|
20
20
|
upload?: boolean | FileAccessHandler;
|
|
21
|
-
/** Access control for GET /
|
|
21
|
+
/** Access control for GET /api/:tenant_id/files/:slug/:file */
|
|
22
22
|
read?: boolean | FileAccessHandler;
|
|
23
|
-
/** Access control for DELETE /
|
|
23
|
+
/** Access control for DELETE /api/:tenant_id/files/:slug/:file */
|
|
24
24
|
delete?: boolean | FileAccessHandler;
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -31,11 +31,11 @@ type FileApiAccess = {
|
|
|
31
31
|
* for handling file uploads, storage, and serving.
|
|
32
32
|
*
|
|
33
33
|
* Each file collection generates:
|
|
34
|
-
* POST /
|
|
35
|
-
* GET /
|
|
34
|
+
* POST /api/:tenant_id/upload/:slug — upload a file
|
|
35
|
+
* GET /api/:tenant_id/files/:slug/:file — serve/download a file
|
|
36
36
|
*/
|
|
37
37
|
export type FileCollection = {
|
|
38
|
-
/** Unique identifier used in routes: `/
|
|
38
|
+
/** Unique identifier used in routes: `/api/:tenant_id/upload/:slug` */
|
|
39
39
|
slug: string;
|
|
40
40
|
hooks?: {
|
|
41
41
|
beforeOperation?: HooksCollection['beforeOperation'];
|
|
@@ -54,7 +54,7 @@ export type FileCollection = {
|
|
|
54
54
|
maxSize?: number;
|
|
55
55
|
/**
|
|
56
56
|
* Image transformations (resize, format, etc.).
|
|
57
|
-
* Applied on-the-fly when serving via GET /
|
|
57
|
+
* Applied on-the-fly when serving via GET /api/:tenant_id/files/:slug/:file
|
|
58
58
|
*/
|
|
59
59
|
transformations?: {
|
|
60
60
|
/** Resize to max width in pixels */
|
package/types/hook.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { MongoRest } from "../database/mongodbadapter";
|
|
2
2
|
import type { Server as SocketIO } from "socket.io";
|
|
3
3
|
import type { ActionsApiList } from "./api";
|
|
4
|
+
import type { TenantAgents } from "./agent";
|
|
5
|
+
import type { Api } from "../lib/api";
|
|
4
6
|
|
|
5
7
|
export type HookMeta = {
|
|
6
8
|
action: ActionsApiList;
|
|
@@ -19,6 +21,10 @@ export type HookMeta = {
|
|
|
19
21
|
/** Context passed to a collection hook (`define.Hook`). */
|
|
20
22
|
export type HookContext = {
|
|
21
23
|
rest: MongoRest;
|
|
24
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
25
|
+
agents: TenantAgents;
|
|
26
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
27
|
+
api: Api;
|
|
22
28
|
action: ActionsApiList;
|
|
23
29
|
meta: HookMeta;
|
|
24
30
|
io: SocketIO;
|
package/types/lifecycle.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { Config } from "./config";
|
|
|
4
4
|
import type { logger } from "../utils/logger";
|
|
5
5
|
import type { Server as SocketIO } from "socket.io";
|
|
6
6
|
import type { TenantReplicationApi } from "./replication";
|
|
7
|
+
import type { TenantAgents } from "./agent";
|
|
8
|
+
import type { Api } from "../lib/api";
|
|
7
9
|
|
|
8
10
|
/** Signal that triggered the shutdown. */
|
|
9
11
|
export type LifecycleReason = "SIGINT" | "SIGTERM";
|
|
@@ -12,6 +14,10 @@ export type LifecycleReason = "SIGINT" | "SIGTERM";
|
|
|
12
14
|
export type LifecycleContext = {
|
|
13
15
|
tenant: Tenant;
|
|
14
16
|
rest: InstanceType<typeof useRest>;
|
|
17
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
18
|
+
agents: TenantAgents;
|
|
19
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
20
|
+
api: Api;
|
|
15
21
|
logger: typeof logger;
|
|
16
22
|
cfg: Config;
|
|
17
23
|
/** Tenant-scoped replication API — `reset()`, `seed()`, `now()`, `state()` (no tenant id needed). */
|
package/types/mcp.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type Joi from "joi";
|
|
|
2
2
|
import type { ContentBlock } from "@modelcontextprotocol/sdk/types.js";
|
|
3
3
|
import type { Context } from "hono";
|
|
4
4
|
import type { useRest } from "../database/rest";
|
|
5
|
+
import type { TenantAgents } from "./agent";
|
|
6
|
+
import type { Api } from "../lib/api";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* MCP tool result — the Model Context Protocol `CallToolResult` shape.
|
|
@@ -15,7 +17,7 @@ export type McpToolResult = {
|
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* MCP tool definition — auto-loaded from `{tenant.dir}/mcp/tools/**\/*.tool.ts`.
|
|
18
|
-
* Served over the MCP protocol at `GET/POST /
|
|
20
|
+
* Served over the MCP protocol at `GET/POST /api/:tenant_id/mcp` (Streamable HTTP).
|
|
19
21
|
*/
|
|
20
22
|
export type McpTool = {
|
|
21
23
|
_isMcpTool_?: boolean;
|
|
@@ -32,6 +34,10 @@ export type McpTool = {
|
|
|
32
34
|
exec: (ctx: {
|
|
33
35
|
c: Context;
|
|
34
36
|
rest: InstanceType<typeof useRest>;
|
|
37
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
38
|
+
agents: TenantAgents;
|
|
39
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
40
|
+
api: Api;
|
|
35
41
|
/** Parsed & validated arguments */
|
|
36
42
|
args: Record<string, any>;
|
|
37
43
|
}) => McpToolResult | Promise<McpToolResult>;
|
|
@@ -73,6 +79,10 @@ export type McpResource = {
|
|
|
73
79
|
read: (ctx: {
|
|
74
80
|
c: Context;
|
|
75
81
|
rest: InstanceType<typeof useRest>;
|
|
82
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
83
|
+
agents: TenantAgents;
|
|
84
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
85
|
+
api: Api;
|
|
76
86
|
/** Params extracted from the URI template (e.g. `{ id: '123' }`) */
|
|
77
87
|
params: Record<string, string>;
|
|
78
88
|
/** The exact URI the client requested */
|
package/types/replication.d.ts
CHANGED
|
@@ -31,6 +31,17 @@ export type ReplicationDestination = {
|
|
|
31
31
|
enabled?: boolean;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Framework (internal) collections that replication covers **by default**.
|
|
36
|
+
*
|
|
37
|
+
* The name is the collection name without its underscores: `_audit_` → `'audit'`,
|
|
38
|
+
* `_workflows_` → `'workflows'`, `_locks_` → `'locks'`, `_replication_` →
|
|
39
|
+
* `'replication'`, `_vars_` → `'vars'`, `_memories_` → `'memory'`.
|
|
40
|
+
*
|
|
41
|
+
* Every one of them is left out with `replication.exclude: ['audit', …]`.
|
|
42
|
+
*/
|
|
43
|
+
export type ReplicationMetaName = 'audit' | 'workflows' | 'locks' | 'replication' | 'vars' | 'memory';
|
|
44
|
+
|
|
34
45
|
/** Per-tenant replication configuration (source → destination, one-way). */
|
|
35
46
|
export type ReplicationConfig = {
|
|
36
47
|
/** Enable/disable replication for this scope (default: true when `destinations` is non-empty). */
|
|
@@ -54,6 +65,20 @@ export type ReplicationConfig = {
|
|
|
54
65
|
* backfill when the destination is already pre-loaded (e.g. via `mongorestore`).
|
|
55
66
|
*/
|
|
56
67
|
initialSync?: ReplicationInitialSync;
|
|
68
|
+
/**
|
|
69
|
+
* Framework collections to **leave out** of replication. All of them are
|
|
70
|
+
* replicated by default (`audit`, `workflows`, `locks`, `replication`,
|
|
71
|
+
* `vars`) — excluding one is what you opt out of.
|
|
72
|
+
*
|
|
73
|
+
* ```ts
|
|
74
|
+
* replication: { exclude: ['locks', 'replication'] }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* ⚠️ `vars` covers *every* namespace of `_vars_`, including the ones that
|
|
78
|
+
* never declared `replication: { enabled: true }`; a namespace can still opt
|
|
79
|
+
* out with `replication: { enabled: false }`, but this list wins over it.
|
|
80
|
+
*/
|
|
81
|
+
exclude?: ReplicationMetaName[];
|
|
57
82
|
/** Destination databases (required). */
|
|
58
83
|
destinations: ReplicationDestination[];
|
|
59
84
|
};
|
|
@@ -98,6 +123,10 @@ export type ReplicationState = {
|
|
|
98
123
|
lastRunAt: Date | null;
|
|
99
124
|
lastError: string | null;
|
|
100
125
|
stats: ReplicationStats;
|
|
126
|
+
/** PID of the process that ran this replication (`reusePort` / forked workers) */
|
|
127
|
+
pid?: number;
|
|
128
|
+
/** Hostname of that process — a PID is only meaningful on its own host */
|
|
129
|
+
hostname?: string;
|
|
101
130
|
createdAt?: Date;
|
|
102
131
|
updatedAt: Date;
|
|
103
132
|
};
|
package/types/route.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { Context } from "hono";
|
|
2
2
|
import type { useRest } from "../database/rest";
|
|
3
|
+
import type { TenantAgents } from "./agent";
|
|
4
|
+
import type { Api } from "../lib/api";
|
|
3
5
|
|
|
4
6
|
type routeContext = {
|
|
5
7
|
rest: InstanceType<typeof useRest>;
|
|
8
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
9
|
+
agents: TenantAgents;
|
|
10
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
11
|
+
api: Api;
|
|
6
12
|
jwt: typeof jwt;
|
|
7
|
-
io: InstanceType<
|
|
13
|
+
io: InstanceType<IO>;
|
|
8
14
|
c: Context
|
|
9
15
|
}
|
|
10
16
|
|
package/types/scripts.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useRest } from "../database/rest"
|
|
2
2
|
import type { Tenant } from "./tenant"
|
|
3
|
+
import type { TenantAgents } from "./agent"
|
|
4
|
+
import type { Api } from "../lib/api"
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
export type Script = {
|
|
@@ -15,6 +17,10 @@ export type Script = {
|
|
|
15
17
|
timeout?: number;
|
|
16
18
|
exec: (ctx: {
|
|
17
19
|
rest: InstanceType<typeof useRest>
|
|
20
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
21
|
+
agents: TenantAgents;
|
|
22
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
23
|
+
api: Api;
|
|
18
24
|
/** Report progress — only wired for heavy scripts (sent via IPC to the parent) */
|
|
19
25
|
progress?: (percent: number, info?: any) => void;
|
|
20
26
|
/** Tenant this script runs for */
|
package/types/service.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { Server as SocketIO } from "socket.io";
|
|
|
2
2
|
import type { useRest } from "../database/rest";
|
|
3
3
|
import type { fn } from "../lib/error";
|
|
4
4
|
import type { jwt } from "../utils/func";
|
|
5
|
+
import type { TenantAgents } from "./agent";
|
|
6
|
+
import type { Api } from "../lib/api";
|
|
5
7
|
|
|
6
8
|
export type Service = {
|
|
7
9
|
_isService_?: boolean;
|
|
@@ -31,7 +33,11 @@ export type Service = {
|
|
|
31
33
|
jwt: typeof jwt;
|
|
32
34
|
error: typeof fn.error;
|
|
33
35
|
io: SocketIO;
|
|
34
|
-
rest: InstanceType<typeof useRest
|
|
36
|
+
rest: InstanceType<typeof useRest>;
|
|
37
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
38
|
+
agents: TenantAgents;
|
|
39
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
40
|
+
api: Api;
|
|
35
41
|
}) => Promise<any>
|
|
36
42
|
}
|
|
37
43
|
}
|
package/types/tenant.d.ts
CHANGED
|
@@ -27,6 +27,19 @@ export type Tenant = {
|
|
|
27
27
|
*/
|
|
28
28
|
file?: AuditFileConfig;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Workflow runs (`_workflows_`). Indexes are always ensured in the
|
|
32
|
+
* background; retention is opt-in and only prunes **finished** runs.
|
|
33
|
+
*/
|
|
34
|
+
workflows?: {
|
|
35
|
+
/**
|
|
36
|
+
* How long finished runs are kept, as a MongoDB TTL index on `completedAt`
|
|
37
|
+
* (runs still running, paused or failed keep no `completedAt` and are never
|
|
38
|
+
* pruned). Duration string: `'30d'`, `'90d'`.
|
|
39
|
+
* `false` → explicitly disabled. Omitted → untouched.
|
|
40
|
+
*/
|
|
41
|
+
retention?: string | false;
|
|
42
|
+
};
|
|
30
43
|
routes?: {
|
|
31
44
|
prefix?: string;
|
|
32
45
|
},
|
package/types/vars.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { useRest } from "../database/rest";
|
|
|
3
3
|
import type { fn } from "../lib/error";
|
|
4
4
|
import type { jwt } from "../utils/func";
|
|
5
5
|
|
|
6
|
-
/** Actions exposed by the variables HTTP API (`POST /
|
|
6
|
+
/** Actions exposed by the variables HTTP API (`POST /api/:tenant_id/vars/:action`). */
|
|
7
7
|
export type VarsActions =
|
|
8
8
|
| "set"
|
|
9
9
|
| "setMany"
|
|
@@ -82,7 +82,7 @@ export type VarDefinition = {
|
|
|
82
82
|
meta?: Field[];
|
|
83
83
|
/** Variables — a raw default value, or a `VarSpec`. */
|
|
84
84
|
vars: Record<string, any>;
|
|
85
|
-
/** HTTP API access rules — required to expose this namespace over `POST /
|
|
85
|
+
/** HTTP API access rules — required to expose this namespace over `POST /api/:tenant_id/vars/:action`. */
|
|
86
86
|
api?: VarsApi;
|
|
87
87
|
/** Opt this namespace into replication — like a collection, but scoped to this namespace. */
|
|
88
88
|
replication?: VarsReplicationConfig;
|
package/types/websocket.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Server as SocketIO, Socket as SocketClient } from "socket.io";
|
|
2
2
|
import type { useRest } from "../database/rest";
|
|
3
|
+
import type { TenantAgents } from "./agent";
|
|
4
|
+
import type { Api } from "../lib/api";
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
|
|
@@ -11,5 +13,9 @@ export type WebSocketHandler = {
|
|
|
11
13
|
io: SocketIO;
|
|
12
14
|
socket: SocketClient;
|
|
13
15
|
rest: InstanceType<typeof useRest>;
|
|
16
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
17
|
+
agents: TenantAgents;
|
|
18
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
19
|
+
api: Api;
|
|
14
20
|
}) => void | Promise<void>;
|
|
15
21
|
};
|
package/types/workflow.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
import type { useRest } from "../database/rest";
|
|
2
|
+
import type { TenantAgents } from "./agent";
|
|
3
|
+
import type { Api } from "../lib/api";
|
|
4
|
+
|
|
1
5
|
export type WorkflowStepHandler<TData = any> = (ctx: {
|
|
2
6
|
data: TData;
|
|
3
7
|
prevOutput: any;
|
|
4
8
|
input?: any;
|
|
5
|
-
rest
|
|
9
|
+
/** Tenant-scoped client — `rest.find`, `rest.insertOne`, `rest.workflow`, `rest.vars`… */
|
|
10
|
+
rest: InstanceType<typeof useRest>;
|
|
11
|
+
/** Tenant-scoped LLM registry — `agents.get('support')`, bound to `rest`. */
|
|
12
|
+
agents: TenantAgents;
|
|
13
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
14
|
+
api: Api;
|
|
6
15
|
error: any;
|
|
7
16
|
jwt: any;
|
|
17
|
+
/** Aborted when the step exceeds its `timeout` — forward it to your own IO */
|
|
18
|
+
signal?: AbortSignal;
|
|
8
19
|
}) => Promise<any>;
|
|
9
20
|
|
|
10
21
|
export type WorkflowCompensationHandler<TData = any> = (ctx: {
|
|
@@ -13,9 +24,13 @@ export type WorkflowCompensationHandler<TData = any> = (ctx: {
|
|
|
13
24
|
stepOutput: any;
|
|
14
25
|
/** The error that caused the failure */
|
|
15
26
|
stepError: { message: string; code?: string };
|
|
16
|
-
rest:
|
|
27
|
+
rest: InstanceType<typeof useRest>;
|
|
28
|
+
agents: TenantAgents;
|
|
29
|
+
/** The in-process facade — `api.collection("orders")`, `api.service("analytics")`, `api.vars`, `api.files`, `api.agent(id)`. */
|
|
30
|
+
api: Api;
|
|
17
31
|
error: any;
|
|
18
32
|
jwt: any;
|
|
33
|
+
signal?: AbortSignal;
|
|
19
34
|
}) => Promise<void>;
|
|
20
35
|
|
|
21
36
|
export type WorkflowStep<TData = any> = {
|
|
@@ -27,6 +42,12 @@ export type WorkflowStep<TData = any> = {
|
|
|
27
42
|
compensate?: WorkflowCompensationHandler<TData>;
|
|
28
43
|
/** List of step IDs this compensation depends on / targets */
|
|
29
44
|
depend?: string[];
|
|
45
|
+
/** Attempts after the first failure (default: 0 — no retry) */
|
|
46
|
+
retries?: number;
|
|
47
|
+
/** Base delay before a retry, doubled on each attempt (default: 250ms, capped at 5s) */
|
|
48
|
+
backoffMs?: number;
|
|
49
|
+
/** Abort the step after this duration (`'5s'`, `'2m'`, or ms) — the ctx receives an aborted `signal` */
|
|
50
|
+
timeout?: string | number;
|
|
30
51
|
condition?: (ctx: {
|
|
31
52
|
data: TData;
|
|
32
53
|
prevOutput: any;
|
|
@@ -42,12 +63,32 @@ export type WorkflowContextField = {
|
|
|
42
63
|
|
|
43
64
|
export type WorkflowContextFields = Record<string, WorkflowContextField>;
|
|
44
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Index created on `_workflows_` for this workflow. Dotted paths are allowed
|
|
68
|
+
* (`context.companyId`, `status`, …), so compound indexes can be declared:
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* indexes: [{ key: { 'context.companyId': 1, status: 1 } }]
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export type WorkflowIndex = {
|
|
75
|
+
key: Record<string, 1 | -1>;
|
|
76
|
+
/** Explicit index name — defaults to MongoDB's `field_1_field_-1` */
|
|
77
|
+
name?: string;
|
|
78
|
+
unique?: boolean;
|
|
79
|
+
sparse?: boolean;
|
|
80
|
+
};
|
|
81
|
+
|
|
45
82
|
export type WorkflowDefinition<TData = any> = {
|
|
46
83
|
id: string;
|
|
47
84
|
name: string;
|
|
48
85
|
description?: string;
|
|
49
86
|
version?: number;
|
|
87
|
+
/** Set to `false` to keep the definition in the codebase without registering it. Default: `true`. */
|
|
88
|
+
enabled?: boolean;
|
|
50
89
|
context?: WorkflowContextFields;
|
|
90
|
+
/** Indexes to create on `_workflows_` (compound, unique, sparse — beyond `context.index`) */
|
|
91
|
+
indexes?: WorkflowIndex[];
|
|
51
92
|
exec?: WorkflowStepHandler<TData>;
|
|
52
93
|
steps: WorkflowStep<TData>[];
|
|
53
94
|
/** Global compensation handlers executed when any step fails (reverse order) */
|
|
@@ -56,7 +97,7 @@ export type WorkflowDefinition<TData = any> = {
|
|
|
56
97
|
_isWorkflow_?: boolean;
|
|
57
98
|
};
|
|
58
99
|
|
|
59
|
-
export type WorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'paused' | 'cancelled' | 'skipped';
|
|
100
|
+
export type WorkflowRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'compensated' | 'paused' | 'cancelled' | 'skipped';
|
|
60
101
|
|
|
61
102
|
export type WorkflowRunStep = {
|
|
62
103
|
stepId: string;
|
|
@@ -84,6 +125,12 @@ export type WorkflowRun = {
|
|
|
84
125
|
steps: WorkflowRunStep[];
|
|
85
126
|
/** Compensation steps that were executed */
|
|
86
127
|
compensations?: WorkflowRunStep[];
|
|
128
|
+
/** PID of the process executing this run (`reusePort` / forked deployments) */
|
|
129
|
+
pid?: number;
|
|
130
|
+
/** Hostname of that process — a PID is only meaningful on its own host */
|
|
131
|
+
hostname?: string;
|
|
132
|
+
/** The store this run was last claimed by (distributed lock holder) */
|
|
133
|
+
lockedAt?: Date;
|
|
87
134
|
error?: { message: string; code?: string; stepId?: string };
|
|
88
135
|
createdAt: Date;
|
|
89
136
|
updatedAt: Date;
|