@wopr-network/defcon 0.2.0 → 0.2.1
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/execution/cli.js +0 -0
- package/package.json +3 -2
- package/dist/api/router.d.ts +0 -24
- package/dist/api/router.js +0 -44
- package/dist/api/server.d.ts +0 -13
- package/dist/api/server.js +0 -280
- package/dist/api/wire-types.d.ts +0 -46
- package/dist/api/wire-types.js +0 -5
- package/dist/config/db-path.d.ts +0 -1
- package/dist/config/db-path.js +0 -1
- package/dist/config/exporter.d.ts +0 -3
- package/dist/config/exporter.js +0 -87
- package/dist/config/index.d.ts +0 -4
- package/dist/config/index.js +0 -4
- package/dist/config/seed-loader.d.ts +0 -10
- package/dist/config/seed-loader.js +0 -108
- package/dist/config/zod-schemas.d.ts +0 -165
- package/dist/config/zod-schemas.js +0 -283
- package/dist/cors.d.ts +0 -8
- package/dist/cors.js +0 -21
- package/dist/engine/constants.d.ts +0 -1
- package/dist/engine/constants.js +0 -1
- package/dist/engine/engine.d.ts +0 -69
- package/dist/engine/engine.js +0 -485
- package/dist/engine/event-emitter.d.ts +0 -9
- package/dist/engine/event-emitter.js +0 -19
- package/dist/engine/event-types.d.ts +0 -105
- package/dist/engine/event-types.js +0 -1
- package/dist/engine/flow-spawner.d.ts +0 -8
- package/dist/engine/flow-spawner.js +0 -28
- package/dist/engine/gate-command-validator.d.ts +0 -6
- package/dist/engine/gate-command-validator.js +0 -46
- package/dist/engine/gate-evaluator.d.ts +0 -12
- package/dist/engine/gate-evaluator.js +0 -233
- package/dist/engine/handlebars.d.ts +0 -9
- package/dist/engine/handlebars.js +0 -51
- package/dist/engine/index.d.ts +0 -12
- package/dist/engine/index.js +0 -7
- package/dist/engine/invocation-builder.d.ts +0 -18
- package/dist/engine/invocation-builder.js +0 -58
- package/dist/engine/on-enter.d.ts +0 -8
- package/dist/engine/on-enter.js +0 -102
- package/dist/engine/ssrf-guard.d.ts +0 -22
- package/dist/engine/ssrf-guard.js +0 -159
- package/dist/engine/state-machine.d.ts +0 -12
- package/dist/engine/state-machine.js +0 -74
- package/dist/execution/active-runner.d.ts +0 -45
- package/dist/execution/active-runner.js +0 -165
- package/dist/execution/admin-schemas.d.ts +0 -116
- package/dist/execution/admin-schemas.js +0 -125
- package/dist/execution/cli.d.ts +0 -57
- package/dist/execution/cli.js +0 -498
- package/dist/execution/handlers/admin.d.ts +0 -67
- package/dist/execution/handlers/admin.js +0 -200
- package/dist/execution/handlers/flow.d.ts +0 -25
- package/dist/execution/handlers/flow.js +0 -289
- package/dist/execution/handlers/query.d.ts +0 -31
- package/dist/execution/handlers/query.js +0 -64
- package/dist/execution/index.d.ts +0 -4
- package/dist/execution/index.js +0 -3
- package/dist/execution/mcp-helpers.d.ts +0 -42
- package/dist/execution/mcp-helpers.js +0 -23
- package/dist/execution/mcp-server.d.ts +0 -33
- package/dist/execution/mcp-server.js +0 -1020
- package/dist/execution/provision-worktree.d.ts +0 -16
- package/dist/execution/provision-worktree.js +0 -123
- package/dist/execution/tool-schemas.d.ts +0 -40
- package/dist/execution/tool-schemas.js +0 -44
- package/dist/logger.d.ts +0 -8
- package/dist/logger.js +0 -12
- package/dist/main.d.ts +0 -14
- package/dist/main.js +0 -28
- package/dist/repositories/drizzle/entity.repo.d.ts +0 -27
- package/dist/repositories/drizzle/entity.repo.js +0 -190
- package/dist/repositories/drizzle/event.repo.d.ts +0 -12
- package/dist/repositories/drizzle/event.repo.js +0 -24
- package/dist/repositories/drizzle/flow.repo.d.ts +0 -22
- package/dist/repositories/drizzle/flow.repo.js +0 -364
- package/dist/repositories/drizzle/gate.repo.d.ts +0 -16
- package/dist/repositories/drizzle/gate.repo.js +0 -98
- package/dist/repositories/drizzle/index.d.ts +0 -6
- package/dist/repositories/drizzle/index.js +0 -7
- package/dist/repositories/drizzle/invocation.repo.d.ts +0 -23
- package/dist/repositories/drizzle/invocation.repo.js +0 -199
- package/dist/repositories/drizzle/schema.d.ts +0 -1932
- package/dist/repositories/drizzle/schema.js +0 -155
- package/dist/repositories/drizzle/transition-log.repo.d.ts +0 -11
- package/dist/repositories/drizzle/transition-log.repo.js +0 -42
- package/dist/repositories/interfaces.d.ts +0 -321
- package/dist/repositories/interfaces.js +0 -2
- package/dist/utils/redact.d.ts +0 -2
- package/dist/utils/redact.js +0 -62
- package/gates/blocking-graph.d.ts +0 -26
- package/gates/blocking-graph.js +0 -102
- package/gates/test/bad-return-gate.d.ts +0 -1
- package/gates/test/bad-return-gate.js +0 -4
- package/gates/test/passing-gate.d.ts +0 -2
- package/gates/test/passing-gate.js +0 -3
- package/gates/test/slow-gate.d.ts +0 -2
- package/gates/test/slow-gate.js +0 -5
- package/gates/test/throwing-gate.d.ts +0 -1
- package/gates/test/throwing-gate.js +0 -3
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v4";
|
|
2
|
-
export declare const FlowDefinitionSchema: z.ZodObject<{
|
|
3
|
-
name: z.ZodString;
|
|
4
|
-
description: z.ZodOptional<z.ZodString>;
|
|
5
|
-
entitySchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
6
|
-
initialState: z.ZodString;
|
|
7
|
-
maxConcurrent: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
8
|
-
maxConcurrentPerRepo: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
9
|
-
affinityWindowMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
10
|
-
gateTimeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
11
|
-
version: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
12
|
-
createdBy: z.ZodOptional<z.ZodString>;
|
|
13
|
-
discipline: z.ZodString;
|
|
14
|
-
defaultModelTier: z.ZodOptional<z.ZodString>;
|
|
15
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
16
|
-
}, z.core.$strip>;
|
|
17
|
-
export declare const OnEnterSchema: z.ZodObject<{
|
|
18
|
-
command: z.ZodString;
|
|
19
|
-
artifacts: z.ZodArray<z.ZodString>;
|
|
20
|
-
timeout_ms: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
21
|
-
}, z.core.$strip>;
|
|
22
|
-
export declare const StateDefinitionSchema: z.ZodObject<{
|
|
23
|
-
name: z.ZodString;
|
|
24
|
-
flowName: z.ZodString;
|
|
25
|
-
modelTier: z.ZodOptional<z.ZodString>;
|
|
26
|
-
mode: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
27
|
-
passive: "passive";
|
|
28
|
-
active: "active";
|
|
29
|
-
}>>>;
|
|
30
|
-
promptTemplate: z.ZodOptional<z.ZodString>;
|
|
31
|
-
constraints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
32
|
-
onEnter: z.ZodOptional<z.ZodObject<{
|
|
33
|
-
command: z.ZodString;
|
|
34
|
-
artifacts: z.ZodArray<z.ZodString>;
|
|
35
|
-
timeout_ms: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
36
|
-
}, z.core.$strip>>;
|
|
37
|
-
}, z.core.$strip>;
|
|
38
|
-
export declare const CommandGateSchema: z.ZodObject<{
|
|
39
|
-
name: z.ZodString;
|
|
40
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
41
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
42
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
43
|
-
type: z.ZodLiteral<"command">;
|
|
44
|
-
command: z.ZodString;
|
|
45
|
-
}, z.core.$strip>;
|
|
46
|
-
export declare const FunctionGateSchema: z.ZodObject<{
|
|
47
|
-
name: z.ZodString;
|
|
48
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
49
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
50
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
51
|
-
type: z.ZodLiteral<"function">;
|
|
52
|
-
functionRef: z.ZodString;
|
|
53
|
-
}, z.core.$strip>;
|
|
54
|
-
export declare const ApiGateSchema: z.ZodObject<{
|
|
55
|
-
name: z.ZodString;
|
|
56
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
57
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
58
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
59
|
-
type: z.ZodLiteral<"api">;
|
|
60
|
-
apiConfig: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
61
|
-
}, z.core.$strip>;
|
|
62
|
-
export declare const GateDefinitionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
63
|
-
name: z.ZodString;
|
|
64
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
65
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
66
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
67
|
-
type: z.ZodLiteral<"command">;
|
|
68
|
-
command: z.ZodString;
|
|
69
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
70
|
-
name: z.ZodString;
|
|
71
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
72
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
73
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
74
|
-
type: z.ZodLiteral<"function">;
|
|
75
|
-
functionRef: z.ZodString;
|
|
76
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
77
|
-
name: z.ZodString;
|
|
78
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
79
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
80
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
81
|
-
type: z.ZodLiteral<"api">;
|
|
82
|
-
apiConfig: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
83
|
-
}, z.core.$strip>], "type">;
|
|
84
|
-
export declare const TransitionRuleSchema: z.ZodObject<{
|
|
85
|
-
flowName: z.ZodString;
|
|
86
|
-
fromState: z.ZodString;
|
|
87
|
-
toState: z.ZodString;
|
|
88
|
-
trigger: z.ZodString;
|
|
89
|
-
gateName: z.ZodOptional<z.ZodString>;
|
|
90
|
-
condition: z.ZodOptional<z.ZodString>;
|
|
91
|
-
priority: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
92
|
-
spawnFlow: z.ZodOptional<z.ZodString>;
|
|
93
|
-
spawnTemplate: z.ZodOptional<z.ZodString>;
|
|
94
|
-
}, z.core.$strip>;
|
|
95
|
-
export declare const SeedFileSchema: z.ZodObject<{
|
|
96
|
-
flows: z.ZodArray<z.ZodObject<{
|
|
97
|
-
name: z.ZodString;
|
|
98
|
-
description: z.ZodOptional<z.ZodString>;
|
|
99
|
-
entitySchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
100
|
-
initialState: z.ZodString;
|
|
101
|
-
maxConcurrent: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
102
|
-
maxConcurrentPerRepo: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
103
|
-
affinityWindowMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
104
|
-
gateTimeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
105
|
-
version: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
106
|
-
createdBy: z.ZodOptional<z.ZodString>;
|
|
107
|
-
discipline: z.ZodString;
|
|
108
|
-
defaultModelTier: z.ZodOptional<z.ZodString>;
|
|
109
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
110
|
-
}, z.core.$strip>>;
|
|
111
|
-
states: z.ZodArray<z.ZodObject<{
|
|
112
|
-
name: z.ZodString;
|
|
113
|
-
flowName: z.ZodString;
|
|
114
|
-
modelTier: z.ZodOptional<z.ZodString>;
|
|
115
|
-
mode: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
116
|
-
passive: "passive";
|
|
117
|
-
active: "active";
|
|
118
|
-
}>>>;
|
|
119
|
-
promptTemplate: z.ZodOptional<z.ZodString>;
|
|
120
|
-
constraints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
121
|
-
onEnter: z.ZodOptional<z.ZodObject<{
|
|
122
|
-
command: z.ZodString;
|
|
123
|
-
artifacts: z.ZodArray<z.ZodString>;
|
|
124
|
-
timeout_ms: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
125
|
-
}, z.core.$strip>>;
|
|
126
|
-
}, z.core.$strip>>;
|
|
127
|
-
gates: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
128
|
-
name: z.ZodString;
|
|
129
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
130
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
131
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
132
|
-
type: z.ZodLiteral<"command">;
|
|
133
|
-
command: z.ZodString;
|
|
134
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
135
|
-
name: z.ZodString;
|
|
136
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
137
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
138
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
139
|
-
type: z.ZodLiteral<"function">;
|
|
140
|
-
functionRef: z.ZodString;
|
|
141
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
142
|
-
name: z.ZodString;
|
|
143
|
-
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
144
|
-
failurePrompt: z.ZodOptional<z.ZodString>;
|
|
145
|
-
timeoutPrompt: z.ZodOptional<z.ZodString>;
|
|
146
|
-
type: z.ZodLiteral<"api">;
|
|
147
|
-
apiConfig: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
148
|
-
}, z.core.$strip>], "type">>>>;
|
|
149
|
-
transitions: z.ZodArray<z.ZodObject<{
|
|
150
|
-
flowName: z.ZodString;
|
|
151
|
-
fromState: z.ZodString;
|
|
152
|
-
toState: z.ZodString;
|
|
153
|
-
trigger: z.ZodString;
|
|
154
|
-
gateName: z.ZodOptional<z.ZodString>;
|
|
155
|
-
condition: z.ZodOptional<z.ZodString>;
|
|
156
|
-
priority: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
157
|
-
spawnFlow: z.ZodOptional<z.ZodString>;
|
|
158
|
-
spawnTemplate: z.ZodOptional<z.ZodString>;
|
|
159
|
-
}, z.core.$strip>>;
|
|
160
|
-
}, z.core.$strict>;
|
|
161
|
-
export type FlowDefinition = z.infer<typeof FlowDefinitionSchema>;
|
|
162
|
-
export type StateDefinition = z.infer<typeof StateDefinitionSchema>;
|
|
163
|
-
export type GateDefinition = z.infer<typeof GateDefinitionSchema>;
|
|
164
|
-
export type TransitionRule = z.infer<typeof TransitionRuleSchema>;
|
|
165
|
-
export type SeedFile = z.infer<typeof SeedFileSchema>;
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v4";
|
|
2
|
-
import { validateGateCommand } from "../engine/gate-command-validator.js";
|
|
3
|
-
import { validateTemplate } from "../engine/handlebars.js";
|
|
4
|
-
// ─── Leaf Schemas ───
|
|
5
|
-
export const FlowDefinitionSchema = z.object({
|
|
6
|
-
name: z.string().min(1),
|
|
7
|
-
description: z.string().optional(),
|
|
8
|
-
entitySchema: z.record(z.string(), z.unknown()).optional(),
|
|
9
|
-
initialState: z.string().min(1),
|
|
10
|
-
maxConcurrent: z.number().int().min(0).optional().default(0),
|
|
11
|
-
maxConcurrentPerRepo: z.number().int().min(0).optional().default(0),
|
|
12
|
-
affinityWindowMs: z.number().int().min(0).optional().default(300000),
|
|
13
|
-
gateTimeoutMs: z.number().int().min(1).optional(),
|
|
14
|
-
version: z.number().int().min(1).optional().default(1),
|
|
15
|
-
createdBy: z.string().optional(),
|
|
16
|
-
discipline: z.string().min(1),
|
|
17
|
-
defaultModelTier: z.string().min(1).optional(),
|
|
18
|
-
timeoutPrompt: z
|
|
19
|
-
.string()
|
|
20
|
-
.min(1)
|
|
21
|
-
.refine((val) => validateTemplate(val), {
|
|
22
|
-
message: "timeoutPrompt contains disallowed Handlebars expressions",
|
|
23
|
-
})
|
|
24
|
-
.optional(),
|
|
25
|
-
});
|
|
26
|
-
export const OnEnterSchema = z.object({
|
|
27
|
-
command: z
|
|
28
|
-
.string()
|
|
29
|
-
.min(1)
|
|
30
|
-
.refine((val) => validateTemplate(val), {
|
|
31
|
-
message: "onEnter command contains disallowed Handlebars expressions",
|
|
32
|
-
}),
|
|
33
|
-
artifacts: z.array(z.string().min(1)).min(1),
|
|
34
|
-
timeout_ms: z.number().int().min(0).optional().default(30000),
|
|
35
|
-
});
|
|
36
|
-
export const StateDefinitionSchema = z.object({
|
|
37
|
-
name: z.string().min(1),
|
|
38
|
-
flowName: z.string().min(1),
|
|
39
|
-
modelTier: z.string().optional(),
|
|
40
|
-
mode: z.enum(["passive", "active"]).optional().default("passive"),
|
|
41
|
-
promptTemplate: z
|
|
42
|
-
.string()
|
|
43
|
-
.min(1)
|
|
44
|
-
.refine((val) => validateTemplate(val), {
|
|
45
|
-
message: "promptTemplate contains disallowed Handlebars expressions",
|
|
46
|
-
})
|
|
47
|
-
.optional(),
|
|
48
|
-
constraints: z.record(z.string(), z.unknown()).optional(),
|
|
49
|
-
onEnter: OnEnterSchema.optional(),
|
|
50
|
-
});
|
|
51
|
-
// Gate: discriminated union on `type`
|
|
52
|
-
const BaseGateSchema = z.object({
|
|
53
|
-
name: z.string().min(1),
|
|
54
|
-
timeoutMs: z.number().int().min(1).optional(),
|
|
55
|
-
failurePrompt: z.string().optional(),
|
|
56
|
-
timeoutPrompt: z.string().min(1).optional(),
|
|
57
|
-
});
|
|
58
|
-
export const CommandGateSchema = BaseGateSchema.extend({
|
|
59
|
-
type: z.literal("command"),
|
|
60
|
-
command: z
|
|
61
|
-
.string()
|
|
62
|
-
.min(1)
|
|
63
|
-
.superRefine((cmd, ctx) => {
|
|
64
|
-
const result = validateGateCommand(cmd);
|
|
65
|
-
if (!result.valid) {
|
|
66
|
-
ctx.addIssue({ code: "custom", message: result.error ?? "Gate command not allowed" });
|
|
67
|
-
}
|
|
68
|
-
}),
|
|
69
|
-
});
|
|
70
|
-
export const FunctionGateSchema = BaseGateSchema.extend({
|
|
71
|
-
type: z.literal("function"),
|
|
72
|
-
functionRef: z.string().regex(/^[^:]+:[^:]+$/, "functionRef must be in 'path:exportName' format"),
|
|
73
|
-
});
|
|
74
|
-
export const ApiGateSchema = BaseGateSchema.extend({
|
|
75
|
-
type: z.literal("api"),
|
|
76
|
-
apiConfig: z.record(z.string(), z.unknown()),
|
|
77
|
-
});
|
|
78
|
-
export const GateDefinitionSchema = z.discriminatedUnion("type", [
|
|
79
|
-
CommandGateSchema,
|
|
80
|
-
FunctionGateSchema,
|
|
81
|
-
ApiGateSchema,
|
|
82
|
-
]);
|
|
83
|
-
export const TransitionRuleSchema = z.object({
|
|
84
|
-
flowName: z.string().min(1),
|
|
85
|
-
fromState: z.string().min(1),
|
|
86
|
-
toState: z.string().min(1),
|
|
87
|
-
trigger: z.string().min(1),
|
|
88
|
-
gateName: z.string().optional(),
|
|
89
|
-
condition: z
|
|
90
|
-
.string()
|
|
91
|
-
.refine((val) => validateTemplate(val), {
|
|
92
|
-
message: "condition contains disallowed Handlebars expressions",
|
|
93
|
-
})
|
|
94
|
-
.optional(),
|
|
95
|
-
priority: z.number().int().min(0).optional().default(0),
|
|
96
|
-
spawnFlow: z.string().optional(),
|
|
97
|
-
spawnTemplate: z
|
|
98
|
-
.string()
|
|
99
|
-
.refine((val) => validateTemplate(val), {
|
|
100
|
-
message: "spawnTemplate contains disallowed Handlebars expressions",
|
|
101
|
-
})
|
|
102
|
-
.optional(),
|
|
103
|
-
});
|
|
104
|
-
// ─── Seed File Schema (with cross-reference validation) ───
|
|
105
|
-
export const SeedFileSchema = z
|
|
106
|
-
.object({
|
|
107
|
-
flows: z.array(FlowDefinitionSchema).min(1),
|
|
108
|
-
states: z.array(StateDefinitionSchema).min(1),
|
|
109
|
-
gates: z.array(GateDefinitionSchema).optional().default([]),
|
|
110
|
-
transitions: z.array(TransitionRuleSchema).min(1),
|
|
111
|
-
})
|
|
112
|
-
.strict()
|
|
113
|
-
.superRefine((seed, ctx) => {
|
|
114
|
-
// Bug 2 fix: detect duplicate flow names explicitly before building the Set
|
|
115
|
-
const flowNames = new Set();
|
|
116
|
-
for (let i = 0; i < seed.flows.length; i++) {
|
|
117
|
-
const name = seed.flows[i].name;
|
|
118
|
-
if (flowNames.has(name)) {
|
|
119
|
-
ctx.addIssue({
|
|
120
|
-
code: "custom",
|
|
121
|
-
message: `Duplicate flow name "${name}"`,
|
|
122
|
-
path: ["flows", i, "name"],
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
flowNames.add(name);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
// Bug 2 fix: detect duplicate gate names explicitly before building the Set
|
|
130
|
-
const gateNames = new Set();
|
|
131
|
-
for (let i = 0; i < seed.gates.length; i++) {
|
|
132
|
-
const name = seed.gates[i].name;
|
|
133
|
-
if (gateNames.has(name)) {
|
|
134
|
-
ctx.addIssue({
|
|
135
|
-
code: "custom",
|
|
136
|
-
message: `Duplicate gate name "${name}"`,
|
|
137
|
-
path: ["gates", i, "name"],
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
gateNames.add(name);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Detect duplicate state names within a flow
|
|
145
|
-
const stateNamesByFlow = new Map();
|
|
146
|
-
for (let i = 0; i < seed.states.length; i++) {
|
|
147
|
-
const s = seed.states[i];
|
|
148
|
-
if (!stateNamesByFlow.has(s.flowName)) {
|
|
149
|
-
stateNamesByFlow.set(s.flowName, new Set());
|
|
150
|
-
}
|
|
151
|
-
const seen = stateNamesByFlow.get(s.flowName);
|
|
152
|
-
if (seen?.has(s.name)) {
|
|
153
|
-
ctx.addIssue({
|
|
154
|
-
code: "custom",
|
|
155
|
-
message: `Duplicate state name '${s.name}' in flow '${s.flowName}'`,
|
|
156
|
-
path: ["states", i, "name"],
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
seen?.add(s.name);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// Bug 1 fix: only populate statesByFlow for flows that actually exist,
|
|
164
|
-
// so that transitions referencing unknown flows don't find stale state data.
|
|
165
|
-
const statesByFlow = new Map();
|
|
166
|
-
for (const s of seed.states) {
|
|
167
|
-
if (!flowNames.has(s.flowName))
|
|
168
|
-
continue;
|
|
169
|
-
if (!statesByFlow.has(s.flowName)) {
|
|
170
|
-
statesByFlow.set(s.flowName, new Set());
|
|
171
|
-
}
|
|
172
|
-
statesByFlow.get(s.flowName)?.add(s.name);
|
|
173
|
-
}
|
|
174
|
-
// Validate states reference existing flows
|
|
175
|
-
for (let i = 0; i < seed.states.length; i++) {
|
|
176
|
-
const s = seed.states[i];
|
|
177
|
-
if (!flowNames.has(s.flowName)) {
|
|
178
|
-
ctx.addIssue({
|
|
179
|
-
code: "custom",
|
|
180
|
-
message: `State "${s.name}" references unknown flow "${s.flowName}"`,
|
|
181
|
-
path: ["states", i, "flowName"],
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// Validate each flow's initialState is a defined state
|
|
186
|
-
for (let i = 0; i < seed.flows.length; i++) {
|
|
187
|
-
const f = seed.flows[i];
|
|
188
|
-
const flowStates = statesByFlow.get(f.name);
|
|
189
|
-
if (!flowStates || !flowStates.has(f.initialState)) {
|
|
190
|
-
ctx.addIssue({
|
|
191
|
-
code: "custom",
|
|
192
|
-
message: `Flow "${f.name}" has initialState "${f.initialState}" which is not a defined state`,
|
|
193
|
-
path: ["flows", i, "initialState"],
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
// Validate transitions
|
|
198
|
-
for (let i = 0; i < seed.transitions.length; i++) {
|
|
199
|
-
const t = seed.transitions[i];
|
|
200
|
-
if (!flowNames.has(t.flowName)) {
|
|
201
|
-
ctx.addIssue({
|
|
202
|
-
code: "custom",
|
|
203
|
-
message: `Transition references unknown flow "${t.flowName}"`,
|
|
204
|
-
path: ["transitions", i, "flowName"],
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
// Bug 3 fix: flow exists — check fromState/toState even if the flow has
|
|
209
|
-
// zero states (statesByFlow entry will be missing or empty in that case).
|
|
210
|
-
const flowStates = statesByFlow.get(t.flowName) ?? new Set();
|
|
211
|
-
if (!flowStates.has(t.fromState)) {
|
|
212
|
-
ctx.addIssue({
|
|
213
|
-
code: "custom",
|
|
214
|
-
message: `Transition fromState "${t.fromState}" not defined in flow "${t.flowName}"`,
|
|
215
|
-
path: ["transitions", i, "fromState"],
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
if (!flowStates.has(t.toState)) {
|
|
219
|
-
ctx.addIssue({
|
|
220
|
-
code: "custom",
|
|
221
|
-
message: `Transition toState "${t.toState}" not defined in flow "${t.flowName}"`,
|
|
222
|
-
path: ["transitions", i, "toState"],
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
if (t.gateName && !gateNames.has(t.gateName)) {
|
|
227
|
-
ctx.addIssue({
|
|
228
|
-
code: "custom",
|
|
229
|
-
message: `Transition references unknown gate "${t.gateName}"`,
|
|
230
|
-
path: ["transitions", i, "gateName"],
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
if (t.spawnFlow && !flowNames.has(t.spawnFlow)) {
|
|
234
|
-
ctx.addIssue({
|
|
235
|
-
code: "custom",
|
|
236
|
-
message: `Transition spawnFlow "${t.spawnFlow}" references unknown flow`,
|
|
237
|
-
path: ["transitions", i, "spawnFlow"],
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Detect circular spawnFlow chains via DFS
|
|
242
|
-
const spawnAdj = new Map();
|
|
243
|
-
for (const t of seed.transitions) {
|
|
244
|
-
if (t.spawnFlow && flowNames.has(t.flowName) && flowNames.has(t.spawnFlow)) {
|
|
245
|
-
if (!spawnAdj.has(t.flowName))
|
|
246
|
-
spawnAdj.set(t.flowName, new Set());
|
|
247
|
-
spawnAdj.get(t.flowName)?.add(t.spawnFlow);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
const visited = new Set();
|
|
251
|
-
const inStack = new Set();
|
|
252
|
-
function dfs(node, path) {
|
|
253
|
-
if (inStack.has(node))
|
|
254
|
-
return [...path, node];
|
|
255
|
-
if (visited.has(node))
|
|
256
|
-
return null;
|
|
257
|
-
visited.add(node);
|
|
258
|
-
inStack.add(node);
|
|
259
|
-
for (const neighbor of spawnAdj.get(node) ?? []) {
|
|
260
|
-
const cycle = dfs(neighbor, [...path, node]);
|
|
261
|
-
if (cycle)
|
|
262
|
-
return cycle;
|
|
263
|
-
}
|
|
264
|
-
inStack.delete(node);
|
|
265
|
-
return null;
|
|
266
|
-
}
|
|
267
|
-
for (const flowName of spawnAdj.keys()) {
|
|
268
|
-
if (visited.has(flowName))
|
|
269
|
-
continue;
|
|
270
|
-
const cycle = dfs(flowName, []);
|
|
271
|
-
if (cycle) {
|
|
272
|
-
const cycleStart = cycle[cycle.length - 1];
|
|
273
|
-
const cycleStartIdx = cycle.indexOf(cycleStart);
|
|
274
|
-
const cyclePath = cycle.slice(cycleStartIdx);
|
|
275
|
-
ctx.addIssue({
|
|
276
|
-
code: "custom",
|
|
277
|
-
message: `Circular spawnFlow chain detected: ${cyclePath.join(" -> ")}`,
|
|
278
|
-
path: ["transitions"],
|
|
279
|
-
});
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
});
|
package/dist/cors.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface CorsOriginResult {
|
|
2
|
-
/** Explicit allowed origin, or null meaning "loopback-only default pattern" */
|
|
3
|
-
origin: string | null;
|
|
4
|
-
}
|
|
5
|
-
export declare function resolveCorsOrigin(opts: {
|
|
6
|
-
host: string;
|
|
7
|
-
corsEnv: string | undefined;
|
|
8
|
-
}): CorsOriginResult;
|
package/dist/cors.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1"]);
|
|
2
|
-
export function resolveCorsOrigin(opts) {
|
|
3
|
-
const corsValue = opts.corsEnv?.trim() || undefined;
|
|
4
|
-
const isLoopback = LOOPBACK_HOSTS.has(opts.host);
|
|
5
|
-
// If explicit origin provided, validate and use it
|
|
6
|
-
if (corsValue) {
|
|
7
|
-
if (!/^https?:\/\/[^/]+$/.test(corsValue)) {
|
|
8
|
-
throw new Error(`DEFCON_CORS_ORIGIN must be a bare origin like https://app.example.com, not ${corsValue}. ` +
|
|
9
|
-
"Remove any path component or trailing slash.");
|
|
10
|
-
}
|
|
11
|
-
return { origin: corsValue };
|
|
12
|
-
}
|
|
13
|
-
// Non-loopback without explicit origin — refuse to start
|
|
14
|
-
if (!isLoopback) {
|
|
15
|
-
throw new Error(`DEFCON_CORS_ORIGIN must be set when binding to non-loopback address "${opts.host}". ` +
|
|
16
|
-
"Without an explicit CORS origin, any website on the network can make cross-origin requests to this server. " +
|
|
17
|
-
'Set DEFCON_CORS_ORIGIN to the allowed origin (e.g. "https://my-app.example.com") or use a loopback address.');
|
|
18
|
-
}
|
|
19
|
-
// Loopback without explicit origin — use default pattern
|
|
20
|
-
return { origin: null };
|
|
21
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const DEFAULT_TIMEOUT_PROMPT = "Your report was received. The gate is still evaluating \u2014 this is not an error. Call flow.claim to reclaim the entity, then call flow.report again with the same arguments after a short wait.";
|
package/dist/engine/constants.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_TIMEOUT_PROMPT = "Your report was received. The gate is still evaluating — this is not an error. Call flow.claim to reclaim the entity, then call flow.report again with the same arguments after a short wait.";
|
package/dist/engine/engine.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { Logger } from "../logger.js";
|
|
2
|
-
import type { Artifacts, Entity, IEntityRepository, IFlowRepository, IGateRepository, IInvocationRepository, ITransitionLogRepository } from "../repositories/interfaces.js";
|
|
3
|
-
import type { IEventBusAdapter } from "./event-types.js";
|
|
4
|
-
export interface ProcessSignalResult {
|
|
5
|
-
newState?: string;
|
|
6
|
-
/** Names (not IDs) of gates that evaluated and passed during this transition. */
|
|
7
|
-
gatesPassed: string[];
|
|
8
|
-
gated: boolean;
|
|
9
|
-
gateTimedOut?: boolean;
|
|
10
|
-
gateOutput?: string;
|
|
11
|
-
gateName?: string;
|
|
12
|
-
failurePrompt?: string;
|
|
13
|
-
timeoutPrompt?: string;
|
|
14
|
-
onEnterFailed?: boolean;
|
|
15
|
-
invocationId?: string;
|
|
16
|
-
spawned?: string[];
|
|
17
|
-
terminal: boolean;
|
|
18
|
-
}
|
|
19
|
-
export interface ClaimWorkResult {
|
|
20
|
-
entityId: string;
|
|
21
|
-
invocationId: string;
|
|
22
|
-
prompt: string;
|
|
23
|
-
context: Record<string, unknown> | null;
|
|
24
|
-
}
|
|
25
|
-
export interface EngineStatus {
|
|
26
|
-
flows: Record<string, Record<string, number>>;
|
|
27
|
-
activeInvocations: number;
|
|
28
|
-
pendingClaims: number;
|
|
29
|
-
}
|
|
30
|
-
export interface EngineDeps {
|
|
31
|
-
entityRepo: IEntityRepository;
|
|
32
|
-
flowRepo: IFlowRepository;
|
|
33
|
-
invocationRepo: IInvocationRepository;
|
|
34
|
-
gateRepo: IGateRepository;
|
|
35
|
-
transitionLogRepo: ITransitionLogRepository;
|
|
36
|
-
adapters: Map<string, unknown>;
|
|
37
|
-
eventEmitter: IEventBusAdapter;
|
|
38
|
-
logger?: Logger;
|
|
39
|
-
}
|
|
40
|
-
export declare class Engine {
|
|
41
|
-
private entityRepo;
|
|
42
|
-
private flowRepo;
|
|
43
|
-
private invocationRepo;
|
|
44
|
-
private gateRepo;
|
|
45
|
-
private transitionLogRepo;
|
|
46
|
-
readonly adapters: Map<string, unknown>;
|
|
47
|
-
private eventEmitter;
|
|
48
|
-
private readonly logger;
|
|
49
|
-
constructor(deps: EngineDeps);
|
|
50
|
-
processSignal(entityId: string, signal: string, artifacts?: Artifacts, triggeringInvocationId?: string): Promise<ProcessSignalResult>;
|
|
51
|
-
createEntity(flowName: string, refs?: Record<string, {
|
|
52
|
-
adapter: string;
|
|
53
|
-
id: string;
|
|
54
|
-
[key: string]: unknown;
|
|
55
|
-
}>): Promise<Entity>;
|
|
56
|
-
claimWork(role: string, flowName?: string, worker_id?: string): Promise<ClaimWorkResult | null>;
|
|
57
|
-
/**
|
|
58
|
-
* Try to claim an existing unclaimed invocation for an already-claimed entity.
|
|
59
|
-
* Handles the race condition where another worker claims the invocation first
|
|
60
|
-
* (releases the entity claim and returns null so the caller can try the next candidate).
|
|
61
|
-
*/
|
|
62
|
-
private tryClaimInvocation;
|
|
63
|
-
private setAffinityIfNeeded;
|
|
64
|
-
private buildPrompt;
|
|
65
|
-
private emitAndReturn;
|
|
66
|
-
getStatus(): Promise<EngineStatus>;
|
|
67
|
-
startReaper(intervalMs: number, entityTtlMs?: number): () => Promise<void>;
|
|
68
|
-
private checkConcurrency;
|
|
69
|
-
}
|