@nt-ai-lab/deterministic-agent-workflow-engine 0.3.6 → 0.4.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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/platform/domain/base-event.js +3 -2
- package/dist/platform/domain/engine-events.d.ts +24 -24
- package/dist/platform/domain/engine-events.js +41 -40
- package/dist/platform/domain/non-empty-string.d.ts +5 -0
- package/dist/platform/domain/non-empty-string.js +10 -0
- package/dist/platform/domain/reflection-types.js +24 -23
- package/dist/platform/domain/repository-tracking-events.js +5 -4
- package/dist/platform/domain/review-types.js +15 -14
- package/dist/platform/domain/workflow-engine-support.d.ts +1 -1
- package/dist/platform/domain/workflow-engine-support.js +7 -4
- package/dist/platform/domain/workflow-engine-types.d.ts +1 -1
- package/dist/platform/domain/workflow-engine.d.ts +1 -1
- package/dist/platform/domain/workflow-engine.js +8 -5
- package/dist/platform/domain/workflow-engine.spec.js +17 -2
- package/dist/platform/infra/cli/presentation/output-guidance.spec.js +1 -1
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type { BaseWorkflowState } from './platform/domain/workflow-state';
|
|
|
2
2
|
export { WorkflowStateError } from './platform/domain/workflow-state';
|
|
3
3
|
export type { BaseEvent } from './platform/domain/base-event';
|
|
4
4
|
export { baseEventSchema } from './platform/domain/base-event';
|
|
5
|
+
export { nonEmptyStringSchema, requireNonEmptyString, } from './platform/domain/non-empty-string';
|
|
5
6
|
export type { EventEnvelope, StoredEvent, } from './platform/domain/stored-event';
|
|
6
7
|
export { flattenStoredEvent, stripEnvelopeKeys, toPayload, } from './platform/domain/stored-event';
|
|
7
8
|
export { reflectionCategorySchema, reflectionConfidenceSchema, reflectionEvidenceSchema, reflectionFindingSchema, reflectionPayloadSchema, recordReflectionInputSchema, storedReflectionSchema, } from './platform/domain/reflection-types';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { WorkflowStateError } from './platform/domain/workflow-state.js';
|
|
2
2
|
export { baseEventSchema } from './platform/domain/base-event.js';
|
|
3
|
+
export { nonEmptyStringSchema, requireNonEmptyString, } from './platform/domain/non-empty-string.js';
|
|
3
4
|
export { flattenStoredEvent, stripEnvelopeKeys, toPayload, } from './platform/domain/stored-event.js';
|
|
4
5
|
export { reflectionCategorySchema, reflectionConfidenceSchema, reflectionEvidenceSchema, reflectionFindingSchema, reflectionPayloadSchema, recordReflectionInputSchema, storedReflectionSchema, } from './platform/domain/reflection-types.js';
|
|
5
6
|
export { reviewTypeSchema, reviewVerdictSchema, reviewFindingSeveritySchema, reviewFindingStatusSchema, reviewFindingSchema, reviewPayloadSchema, recordReviewInputSchema, storedReviewSchema, listedReviewSchema, reviewFiltersSchema, } from './platform/domain/review-types.js';
|
|
@@ -2,24 +2,24 @@ import { z } from 'zod';
|
|
|
2
2
|
declare const sessionStartedSchema: z.ZodObject<{
|
|
3
3
|
type: z.ZodLiteral<"session-started">;
|
|
4
4
|
at: z.ZodString;
|
|
5
|
-
transcriptPath: z.
|
|
6
|
-
repository: z.
|
|
7
|
-
currentState: z.
|
|
8
|
-
states: z.
|
|
5
|
+
transcriptPath: z.ZodString;
|
|
6
|
+
repository: z.ZodString;
|
|
7
|
+
currentState: z.ZodString;
|
|
8
|
+
states: z.ZodArray<z.ZodString, "many">;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
10
|
type: "session-started";
|
|
11
11
|
at: string;
|
|
12
|
-
repository
|
|
13
|
-
transcriptPath
|
|
14
|
-
currentState
|
|
15
|
-
states
|
|
12
|
+
repository: string;
|
|
13
|
+
transcriptPath: string;
|
|
14
|
+
currentState: string;
|
|
15
|
+
states: string[];
|
|
16
16
|
}, {
|
|
17
17
|
type: "session-started";
|
|
18
18
|
at: string;
|
|
19
|
-
repository
|
|
20
|
-
transcriptPath
|
|
21
|
-
currentState
|
|
22
|
-
states
|
|
19
|
+
repository: string;
|
|
20
|
+
transcriptPath: string;
|
|
21
|
+
currentState: string;
|
|
22
|
+
states: string[];
|
|
23
23
|
}>;
|
|
24
24
|
declare const transitionedSchema: z.ZodObject<{
|
|
25
25
|
type: z.ZodLiteral<"transitioned">;
|
|
@@ -230,24 +230,24 @@ export declare const reviewRecordedEventSchema: z.ZodObject<{
|
|
|
230
230
|
export declare const engineEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
231
231
|
type: z.ZodLiteral<"session-started">;
|
|
232
232
|
at: z.ZodString;
|
|
233
|
-
transcriptPath: z.
|
|
234
|
-
repository: z.
|
|
235
|
-
currentState: z.
|
|
236
|
-
states: z.
|
|
233
|
+
transcriptPath: z.ZodString;
|
|
234
|
+
repository: z.ZodString;
|
|
235
|
+
currentState: z.ZodString;
|
|
236
|
+
states: z.ZodArray<z.ZodString, "many">;
|
|
237
237
|
}, "strip", z.ZodTypeAny, {
|
|
238
238
|
type: "session-started";
|
|
239
239
|
at: string;
|
|
240
|
-
repository
|
|
241
|
-
transcriptPath
|
|
242
|
-
currentState
|
|
243
|
-
states
|
|
240
|
+
repository: string;
|
|
241
|
+
transcriptPath: string;
|
|
242
|
+
currentState: string;
|
|
243
|
+
states: string[];
|
|
244
244
|
}, {
|
|
245
245
|
type: "session-started";
|
|
246
246
|
at: string;
|
|
247
|
-
repository
|
|
248
|
-
transcriptPath
|
|
249
|
-
currentState
|
|
250
|
-
states
|
|
247
|
+
repository: string;
|
|
248
|
+
transcriptPath: string;
|
|
249
|
+
currentState: string;
|
|
250
|
+
states: string[];
|
|
251
251
|
}>, z.ZodObject<{
|
|
252
252
|
type: z.ZodLiteral<"transitioned">;
|
|
253
253
|
at: z.ZodString;
|
|
@@ -1,86 +1,87 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { nonEmptyStringSchema } from './non-empty-string.js';
|
|
2
3
|
const sessionStartedSchema = z.object({
|
|
3
4
|
type: z.literal('session-started'),
|
|
4
|
-
at:
|
|
5
|
-
transcriptPath:
|
|
6
|
-
repository:
|
|
7
|
-
currentState:
|
|
8
|
-
states: z.array(
|
|
5
|
+
at: nonEmptyStringSchema,
|
|
6
|
+
transcriptPath: nonEmptyStringSchema,
|
|
7
|
+
repository: nonEmptyStringSchema,
|
|
8
|
+
currentState: nonEmptyStringSchema,
|
|
9
|
+
states: z.array(nonEmptyStringSchema),
|
|
9
10
|
});
|
|
10
11
|
const transitionedSchema = z.object({
|
|
11
12
|
type: z.literal('transitioned'),
|
|
12
|
-
at:
|
|
13
|
-
from:
|
|
14
|
-
to:
|
|
15
|
-
preBlockedState:
|
|
13
|
+
at: nonEmptyStringSchema,
|
|
14
|
+
from: nonEmptyStringSchema,
|
|
15
|
+
to: nonEmptyStringSchema,
|
|
16
|
+
preBlockedState: nonEmptyStringSchema.optional(),
|
|
16
17
|
iteration: z.number().optional(),
|
|
17
|
-
developingHeadCommit:
|
|
18
|
+
developingHeadCommit: nonEmptyStringSchema.optional(),
|
|
18
19
|
developerDone: z.boolean().optional(),
|
|
19
20
|
});
|
|
20
21
|
const agentRegisteredSchema = z.object({
|
|
21
22
|
type: z.literal('agent-registered'),
|
|
22
|
-
at:
|
|
23
|
-
agentType:
|
|
24
|
-
agentId:
|
|
23
|
+
at: nonEmptyStringSchema,
|
|
24
|
+
agentType: nonEmptyStringSchema,
|
|
25
|
+
agentId: nonEmptyStringSchema,
|
|
25
26
|
});
|
|
26
27
|
const agentShutDownSchema = z.object({
|
|
27
28
|
type: z.literal('agent-shut-down'),
|
|
28
|
-
at:
|
|
29
|
-
agentName:
|
|
29
|
+
at: nonEmptyStringSchema,
|
|
30
|
+
agentName: nonEmptyStringSchema,
|
|
30
31
|
});
|
|
31
32
|
const journalEntrySchema = z.object({
|
|
32
33
|
type: z.literal('journal-entry'),
|
|
33
|
-
at:
|
|
34
|
-
agentName:
|
|
35
|
-
content:
|
|
34
|
+
at: nonEmptyStringSchema,
|
|
35
|
+
agentName: nonEmptyStringSchema,
|
|
36
|
+
content: nonEmptyStringSchema,
|
|
36
37
|
});
|
|
37
38
|
const writeCheckedSchema = z.object({
|
|
38
39
|
type: z.literal('write-checked'),
|
|
39
|
-
at:
|
|
40
|
-
tool:
|
|
41
|
-
filePath:
|
|
40
|
+
at: nonEmptyStringSchema,
|
|
41
|
+
tool: nonEmptyStringSchema,
|
|
42
|
+
filePath: nonEmptyStringSchema,
|
|
42
43
|
allowed: z.boolean(),
|
|
43
|
-
reason:
|
|
44
|
+
reason: nonEmptyStringSchema.optional(),
|
|
44
45
|
});
|
|
45
46
|
const bashCheckedSchema = z.object({
|
|
46
47
|
type: z.literal('bash-checked'),
|
|
47
|
-
at:
|
|
48
|
-
tool:
|
|
49
|
-
command:
|
|
48
|
+
at: nonEmptyStringSchema,
|
|
49
|
+
tool: nonEmptyStringSchema,
|
|
50
|
+
command: nonEmptyStringSchema,
|
|
50
51
|
allowed: z.boolean(),
|
|
51
|
-
reason:
|
|
52
|
+
reason: nonEmptyStringSchema.optional(),
|
|
52
53
|
});
|
|
53
54
|
const pluginReadCheckedSchema = z.object({
|
|
54
55
|
type: z.literal('plugin-read-checked'),
|
|
55
|
-
at:
|
|
56
|
-
tool:
|
|
57
|
-
path:
|
|
56
|
+
at: nonEmptyStringSchema,
|
|
57
|
+
tool: nonEmptyStringSchema,
|
|
58
|
+
path: nonEmptyStringSchema,
|
|
58
59
|
allowed: z.boolean(),
|
|
59
|
-
reason:
|
|
60
|
+
reason: nonEmptyStringSchema.optional(),
|
|
60
61
|
});
|
|
61
62
|
const idleCheckedSchema = z.object({
|
|
62
63
|
type: z.literal('idle-checked'),
|
|
63
|
-
at:
|
|
64
|
-
agentName:
|
|
64
|
+
at: nonEmptyStringSchema,
|
|
65
|
+
agentName: nonEmptyStringSchema,
|
|
65
66
|
allowed: z.boolean(),
|
|
66
|
-
reason:
|
|
67
|
+
reason: nonEmptyStringSchema.optional(),
|
|
67
68
|
});
|
|
68
69
|
const identityVerifiedSchema = z.object({
|
|
69
70
|
type: z.literal('identity-verified'),
|
|
70
|
-
at:
|
|
71
|
-
status:
|
|
72
|
-
transcriptPath:
|
|
71
|
+
at: nonEmptyStringSchema,
|
|
72
|
+
status: nonEmptyStringSchema,
|
|
73
|
+
transcriptPath: nonEmptyStringSchema,
|
|
73
74
|
});
|
|
74
75
|
const contextRequestedSchema = z.object({
|
|
75
76
|
type: z.literal('context-requested'),
|
|
76
|
-
at:
|
|
77
|
-
agentName:
|
|
77
|
+
at: nonEmptyStringSchema,
|
|
78
|
+
agentName: nonEmptyStringSchema,
|
|
78
79
|
});
|
|
79
80
|
export const reviewRecordedEventSchema = z.object({
|
|
80
81
|
type: z.literal('review-recorded'),
|
|
81
|
-
at:
|
|
82
|
+
at: nonEmptyStringSchema,
|
|
82
83
|
reviewId: z.number().int().positive(),
|
|
83
|
-
reviewType:
|
|
84
|
+
reviewType: nonEmptyStringSchema,
|
|
84
85
|
verdict: z.enum(['PASS', 'FAIL']),
|
|
85
86
|
});
|
|
86
87
|
export const engineEventSchema = z.discriminatedUnion('type', [
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** @riviere-role value-object */
|
|
3
|
+
export const nonEmptyStringSchema = z.string().trim().min(1);
|
|
4
|
+
/** @riviere-role domain-service */
|
|
5
|
+
export function requireNonEmptyString(value, name) {
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
if (trimmed.length === 0)
|
|
8
|
+
throw new TypeError(`${name} must be a non-empty string.`);
|
|
9
|
+
return trimmed;
|
|
10
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { nonEmptyStringSchema } from './non-empty-string.js';
|
|
2
3
|
export const reflectionCategorySchema = z.enum([
|
|
3
4
|
'state-efficiency',
|
|
4
5
|
'review-rework',
|
|
@@ -7,13 +8,13 @@ export const reflectionCategorySchema = z.enum([
|
|
|
7
8
|
'workflow-design',
|
|
8
9
|
]);
|
|
9
10
|
export const reflectionConfidenceSchema = z.enum(['low', 'medium', 'high']);
|
|
10
|
-
const evidenceBaseSchema = z.object({ label:
|
|
11
|
+
const evidenceBaseSchema = z.object({ label: nonEmptyStringSchema.optional(), });
|
|
11
12
|
export const reflectionEvidenceSchema = z.discriminatedUnion('kind', [
|
|
12
13
|
evidenceBaseSchema.extend({
|
|
13
14
|
kind: z.literal('state-period'),
|
|
14
|
-
state:
|
|
15
|
-
startedAt:
|
|
16
|
-
endedAt:
|
|
15
|
+
state: nonEmptyStringSchema,
|
|
16
|
+
startedAt: nonEmptyStringSchema.optional(),
|
|
17
|
+
endedAt: nonEmptyStringSchema.optional(),
|
|
17
18
|
}),
|
|
18
19
|
evidenceBaseSchema.extend({
|
|
19
20
|
kind: z.literal('event'),
|
|
@@ -26,8 +27,8 @@ export const reflectionEvidenceSchema = z.discriminatedUnion('kind', [
|
|
|
26
27
|
}),
|
|
27
28
|
evidenceBaseSchema.extend({
|
|
28
29
|
kind: z.literal('journal-entry'),
|
|
29
|
-
at:
|
|
30
|
-
agentName:
|
|
30
|
+
at: nonEmptyStringSchema,
|
|
31
|
+
agentName: nonEmptyStringSchema.optional(),
|
|
31
32
|
}),
|
|
32
33
|
evidenceBaseSchema.extend({
|
|
33
34
|
kind: z.literal('transcript-range'),
|
|
@@ -36,37 +37,37 @@ export const reflectionEvidenceSchema = z.discriminatedUnion('kind', [
|
|
|
36
37
|
}),
|
|
37
38
|
evidenceBaseSchema.extend({
|
|
38
39
|
kind: z.literal('tool-activity'),
|
|
39
|
-
state:
|
|
40
|
-
toolName:
|
|
41
|
-
metric:
|
|
40
|
+
state: nonEmptyStringSchema.optional(),
|
|
41
|
+
toolName: nonEmptyStringSchema.optional(),
|
|
42
|
+
metric: nonEmptyStringSchema.optional(),
|
|
42
43
|
}),
|
|
43
44
|
]);
|
|
44
45
|
export const reflectionFindingSchema = z.object({
|
|
45
|
-
title:
|
|
46
|
+
title: nonEmptyStringSchema,
|
|
46
47
|
category: reflectionCategorySchema,
|
|
47
|
-
opportunity:
|
|
48
|
-
likelyCause:
|
|
49
|
-
suggestedChange:
|
|
50
|
-
expectedImpact:
|
|
48
|
+
opportunity: nonEmptyStringSchema,
|
|
49
|
+
likelyCause: nonEmptyStringSchema,
|
|
50
|
+
suggestedChange: nonEmptyStringSchema,
|
|
51
|
+
expectedImpact: nonEmptyStringSchema,
|
|
51
52
|
confidence: reflectionConfidenceSchema.optional(),
|
|
52
53
|
evidence: z.array(reflectionEvidenceSchema).min(1),
|
|
53
54
|
});
|
|
54
55
|
export const reflectionPayloadSchema = z.object({
|
|
55
|
-
summary:
|
|
56
|
+
summary: nonEmptyStringSchema.optional(),
|
|
56
57
|
findings: z.array(reflectionFindingSchema).max(10),
|
|
57
58
|
}).strict();
|
|
58
59
|
export const recordReflectionInputSchema = z.object({
|
|
59
|
-
label:
|
|
60
|
-
agentName:
|
|
61
|
-
sourceState:
|
|
60
|
+
label: nonEmptyStringSchema.optional(),
|
|
61
|
+
agentName: nonEmptyStringSchema.optional(),
|
|
62
|
+
sourceState: nonEmptyStringSchema.optional(),
|
|
62
63
|
reflection: reflectionPayloadSchema,
|
|
63
64
|
}).strict();
|
|
64
65
|
export const storedReflectionSchema = z.object({
|
|
65
66
|
id: z.number().int().positive(),
|
|
66
|
-
sessionId:
|
|
67
|
-
createdAt:
|
|
68
|
-
label:
|
|
69
|
-
agentName:
|
|
70
|
-
sourceState:
|
|
67
|
+
sessionId: nonEmptyStringSchema,
|
|
68
|
+
createdAt: nonEmptyStringSchema,
|
|
69
|
+
label: nonEmptyStringSchema.optional(),
|
|
70
|
+
agentName: nonEmptyStringSchema.optional(),
|
|
71
|
+
sourceState: nonEmptyStringSchema.optional(),
|
|
71
72
|
reflection: reflectionPayloadSchema,
|
|
72
73
|
}).strict();
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { nonEmptyStringSchema } from './non-empty-string.js';
|
|
2
3
|
const issueRecordedSchema = z.object({
|
|
3
4
|
type: z.literal('issue-recorded'),
|
|
4
|
-
at:
|
|
5
|
+
at: nonEmptyStringSchema,
|
|
5
6
|
issueNumber: z.number(),
|
|
6
7
|
});
|
|
7
8
|
const branchRecordedSchema = z.object({
|
|
8
9
|
type: z.literal('branch-recorded'),
|
|
9
|
-
at:
|
|
10
|
-
branch:
|
|
10
|
+
at: nonEmptyStringSchema,
|
|
11
|
+
branch: nonEmptyStringSchema,
|
|
11
12
|
});
|
|
12
13
|
const prRecordedSchema = z.object({
|
|
13
14
|
type: z.literal('pr-recorded'),
|
|
14
|
-
at:
|
|
15
|
+
at: nonEmptyStringSchema,
|
|
15
16
|
prNumber: z.number(),
|
|
16
17
|
});
|
|
17
18
|
export const repositoryMetadataEventSchema = z.discriminatedUnion('type', [
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
|
|
2
|
+
import { nonEmptyStringSchema } from './non-empty-string.js';
|
|
3
|
+
export const reviewTypeSchema = nonEmptyStringSchema;
|
|
3
4
|
export const reviewVerdictSchema = z.enum(['PASS', 'FAIL']);
|
|
4
5
|
export const reviewFindingSeveritySchema = z.enum(['minor', 'major', 'critical']);
|
|
5
6
|
export const reviewFindingStatusSchema = z.enum(['blocking', 'non-blocking', 'accepted-risk']);
|
|
6
7
|
export const reviewFindingSchema = z.object({
|
|
7
|
-
title:
|
|
8
|
+
title: nonEmptyStringSchema.optional(),
|
|
8
9
|
severity: reviewFindingSeveritySchema.optional(),
|
|
9
10
|
status: reviewFindingStatusSchema.optional(),
|
|
10
|
-
rule:
|
|
11
|
-
file:
|
|
11
|
+
rule: nonEmptyStringSchema.optional(),
|
|
12
|
+
file: nonEmptyStringSchema.optional(),
|
|
12
13
|
startLine: z.number().int().positive().optional(),
|
|
13
14
|
endLine: z.number().int().positive().optional(),
|
|
14
|
-
details:
|
|
15
|
-
recommendation:
|
|
15
|
+
details: nonEmptyStringSchema.optional(),
|
|
16
|
+
recommendation: nonEmptyStringSchema.optional(),
|
|
16
17
|
}).strict().superRefine((finding, context) => {
|
|
17
18
|
if (finding.title === undefined && finding.details === undefined && finding.rule === undefined) {
|
|
18
19
|
context.addIssue({
|
|
@@ -38,24 +39,24 @@ export const reviewFindingSchema = z.object({
|
|
|
38
39
|
});
|
|
39
40
|
export const reviewPayloadSchema = z.object({
|
|
40
41
|
verdict: reviewVerdictSchema,
|
|
41
|
-
summary:
|
|
42
|
-
branch:
|
|
42
|
+
summary: nonEmptyStringSchema.optional(),
|
|
43
|
+
branch: nonEmptyStringSchema.optional(),
|
|
43
44
|
pullRequestNumber: z.number().int().positive().optional(),
|
|
44
45
|
findings: z.array(reviewFindingSchema),
|
|
45
46
|
}).strict();
|
|
46
47
|
export const recordReviewInputSchema = reviewPayloadSchema.extend({
|
|
47
48
|
reviewType: reviewTypeSchema,
|
|
48
|
-
sourceState:
|
|
49
|
+
sourceState: nonEmptyStringSchema.optional(),
|
|
49
50
|
}).strict();
|
|
50
51
|
export const storedReviewSchema = recordReviewInputSchema.extend({
|
|
51
52
|
id: z.number().int().positive(),
|
|
52
|
-
sessionId:
|
|
53
|
-
createdAt:
|
|
53
|
+
sessionId: nonEmptyStringSchema,
|
|
54
|
+
createdAt: nonEmptyStringSchema,
|
|
54
55
|
}).strict();
|
|
55
|
-
export const listedReviewSchema = storedReviewSchema.extend({ repository:
|
|
56
|
+
export const listedReviewSchema = storedReviewSchema.extend({ repository: nonEmptyStringSchema.optional() }).strict();
|
|
56
57
|
export const reviewFiltersSchema = z.object({
|
|
57
|
-
repository:
|
|
58
|
-
branch:
|
|
58
|
+
repository: nonEmptyStringSchema.optional(),
|
|
59
|
+
branch: nonEmptyStringSchema.optional(),
|
|
59
60
|
pullRequestNumber: z.number().int().positive().optional(),
|
|
60
61
|
reviewType: reviewTypeSchema.optional(),
|
|
61
62
|
verdict: reviewVerdictSchema.optional(),
|
|
@@ -10,4 +10,4 @@ export declare function buildProcedurePath<TStateName extends string>(engineDeps
|
|
|
10
10
|
/** @riviere-role domain-service */
|
|
11
11
|
export declare function readProcedure<TStateName extends string>(engineDeps: WorkflowEngineDeps, stateName: TStateName): string;
|
|
12
12
|
/** @riviere-role domain-service */
|
|
13
|
-
export declare function enrichSessionStartedEvents<TStateName extends string>(engineDeps: WorkflowEngineDeps, events: readonly BaseEvent[], transcriptPath: string, repository: string
|
|
13
|
+
export declare function enrichSessionStartedEvents<TStateName extends string>(engineDeps: WorkflowEngineDeps, events: readonly BaseEvent[], transcriptPath: string, repository: string, currentState: TStateName, states: readonly string[]): readonly BaseEvent[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requireNonEmptyString } from './non-empty-string.js';
|
|
1
2
|
/** @riviere-role domain-service */
|
|
2
3
|
export function buildPrefixPattern(registry) {
|
|
3
4
|
const prefixes = [];
|
|
@@ -21,14 +22,16 @@ export function readProcedure(engineDeps, stateName) {
|
|
|
21
22
|
}
|
|
22
23
|
/** @riviere-role domain-service */
|
|
23
24
|
export function enrichSessionStartedEvents(engineDeps, events, transcriptPath, repository, currentState, states) {
|
|
25
|
+
const validRepository = requireNonEmptyString(repository, 'repository');
|
|
26
|
+
const validTranscriptPath = requireNonEmptyString(transcriptPath, 'transcriptPath');
|
|
24
27
|
const enriched = events.map((event) => {
|
|
25
28
|
if (event.type !== 'session-started') {
|
|
26
29
|
return event;
|
|
27
30
|
}
|
|
28
31
|
return {
|
|
29
32
|
...event,
|
|
30
|
-
transcriptPath,
|
|
31
|
-
|
|
33
|
+
transcriptPath: validTranscriptPath,
|
|
34
|
+
repository: validRepository,
|
|
32
35
|
currentState,
|
|
33
36
|
states: [...states],
|
|
34
37
|
};
|
|
@@ -39,8 +42,8 @@ export function enrichSessionStartedEvents(engineDeps, events, transcriptPath, r
|
|
|
39
42
|
return [{
|
|
40
43
|
type: 'session-started',
|
|
41
44
|
at: engineDeps.now(),
|
|
42
|
-
transcriptPath,
|
|
43
|
-
|
|
45
|
+
transcriptPath: validTranscriptPath,
|
|
46
|
+
repository: validRepository,
|
|
44
47
|
currentState,
|
|
45
48
|
states: [...states],
|
|
46
49
|
}, ...enriched];
|
|
@@ -23,7 +23,7 @@ export interface RehydratableWorkflow<TState extends BaseWorkflowState> {
|
|
|
23
23
|
getState(): TState;
|
|
24
24
|
appendEvent(event: BaseEvent): void;
|
|
25
25
|
getPendingEvents(): readonly BaseEvent[];
|
|
26
|
-
startSession(transcriptPath: string, repository: string
|
|
26
|
+
startSession(transcriptPath: string, repository: string): void;
|
|
27
27
|
getTranscriptPath(): string;
|
|
28
28
|
registerAgent(agentType: string, agentId: string): PreconditionResult;
|
|
29
29
|
handleTeammateIdle(agentName: string): PreconditionResult;
|
|
@@ -8,7 +8,7 @@ export declare class WorkflowEngine<TWorkflow extends RehydratableWorkflow<TStat
|
|
|
8
8
|
private readonly engineDeps;
|
|
9
9
|
private readonly workflowDeps;
|
|
10
10
|
constructor(factory: WorkflowDefinition<TWorkflow, TState, TDeps, TStateName, TOperation>, engineDeps: WorkflowEngineDeps, workflowDeps: TDeps);
|
|
11
|
-
startSession(sessionId: string, transcriptPath: string, repository
|
|
11
|
+
startSession(sessionId: string, transcriptPath: string, repository: string): EngineResult;
|
|
12
12
|
transaction(sessionId: string, op: string, fn: (workflow: TWorkflow) => PreconditionResult): EngineResult;
|
|
13
13
|
writeJournal(sessionId: string, agentName: string, content: string): EngineResult;
|
|
14
14
|
transition(sessionId: string, target: TStateName): EngineResult;
|
|
@@ -7,6 +7,7 @@ import { engineEventSchema } from './engine-events.js';
|
|
|
7
7
|
import { WorkflowStateError, } from './workflow-state.js';
|
|
8
8
|
import { reduceWorkflowStateFromStoredEvents } from './workflow-state-reducer.js';
|
|
9
9
|
import { serializeWorkflowState } from './workflow-state-serialization.js';
|
|
10
|
+
import { requireNonEmptyString } from './non-empty-string.js';
|
|
10
11
|
/** @riviere-role domain-service */
|
|
11
12
|
export class WorkflowEngine {
|
|
12
13
|
factory;
|
|
@@ -18,7 +19,10 @@ export class WorkflowEngine {
|
|
|
18
19
|
this.workflowDeps = workflowDeps;
|
|
19
20
|
}
|
|
20
21
|
startSession(sessionId, transcriptPath, repository) {
|
|
21
|
-
|
|
22
|
+
const validSessionId = requireNonEmptyString(sessionId, 'sessionId');
|
|
23
|
+
const validTranscriptPath = requireNonEmptyString(transcriptPath, 'transcriptPath');
|
|
24
|
+
const validRepository = requireNonEmptyString(repository, 'repository');
|
|
25
|
+
if (this.engineDeps.store.hasSessionStarted(validSessionId)) {
|
|
22
26
|
return {
|
|
23
27
|
type: 'success',
|
|
24
28
|
output: ''
|
|
@@ -26,12 +30,11 @@ export class WorkflowEngine {
|
|
|
26
30
|
}
|
|
27
31
|
const initialState = this.factory.initialState();
|
|
28
32
|
const workflow = this.factory.buildWorkflow(initialState, this.workflowDeps);
|
|
29
|
-
|
|
30
|
-
workflow.startSession(transcriptPath, resolvedRepository);
|
|
33
|
+
workflow.startSession(validTranscriptPath, validRepository);
|
|
31
34
|
const registry = this.factory.getRegistry();
|
|
32
35
|
const stateNames = Object.keys(registry);
|
|
33
|
-
const pendingEvents = enrichSessionStartedEvents(this.engineDeps, workflow.getPendingEvents(),
|
|
34
|
-
this.engineDeps.store.appendEvents(
|
|
36
|
+
const pendingEvents = enrichSessionStartedEvents(this.engineDeps, workflow.getPendingEvents(), validTranscriptPath, validRepository, initialState.currentStateMachineState, stateNames);
|
|
37
|
+
this.engineDeps.store.appendEvents(validSessionId, this.wrapEvents(pendingEvents, initialState));
|
|
35
38
|
const procedureContent = this.engineDeps.readFile(buildProcedurePath(this.engineDeps, initialState.currentStateMachineState));
|
|
36
39
|
const expectedPrefix = getExpectedPrefix(initialState.currentStateMachineState, registry);
|
|
37
40
|
return {
|
|
@@ -256,11 +256,26 @@ function createEngine() {
|
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
258
|
describe('WorkflowEngine platform-owned events', () => {
|
|
259
|
+
it.each([
|
|
260
|
+
['repository', ''],
|
|
261
|
+
['repository', ' '],
|
|
262
|
+
['transcriptPath', ''],
|
|
263
|
+
['transcriptPath', ' '],
|
|
264
|
+
['sessionId', ''],
|
|
265
|
+
['sessionId', ' '],
|
|
266
|
+
])('rejects empty %s before persisting a session', (field, value) => {
|
|
267
|
+
const { engine, store, } = createEngine();
|
|
268
|
+
const sessionId = field === 'sessionId' ? value : 'session-1';
|
|
269
|
+
const transcriptPath = field === 'transcriptPath' ? value : '/transcripts/session-1.jsonl';
|
|
270
|
+
const repository = field === 'repository' ? value : 'test/repo';
|
|
271
|
+
expect(() => engine.startSession(sessionId, transcriptPath, repository)).toThrow(`${field} must be a non-empty string.`);
|
|
272
|
+
expect(store.readEvents('session-1')).toStrictEqual([]);
|
|
273
|
+
});
|
|
259
274
|
it('persists journal and write-check events without routing them through the consumer workflow', () => {
|
|
260
275
|
const { engine, store, } = createEngine();
|
|
261
|
-
engine.startSession('session-1', '/transcripts/session-1.jsonl');
|
|
276
|
+
engine.startSession('session-1', '/transcripts/session-1.jsonl', 'test/repo');
|
|
262
277
|
const journalResult = engine.writeJournal('session-1', 'gpt-5.4', 'Captured planning context.');
|
|
263
|
-
const writeCheckResult = engine.checkWrite('session-1', 'Read', '', () => true);
|
|
278
|
+
const writeCheckResult = engine.checkWrite('session-1', 'Read', '/src/example.ts', () => true);
|
|
264
279
|
const stateResult = engine.getState('session-1');
|
|
265
280
|
expect(journalResult.type).toBe('success');
|
|
266
281
|
expect(writeCheckResult).toStrictEqual({
|
|
@@ -181,7 +181,7 @@ const engineDeps = {
|
|
|
181
181
|
it('reinserts the current procedure when identity verification fails', () => {
|
|
182
182
|
const emptyWorkflowDeps = {};
|
|
183
183
|
const engine = new WorkflowEngine(workflowDefinition, engineDeps, emptyWorkflowDeps);
|
|
184
|
-
engine.startSession('session-1', '/transcripts/session-1.jsonl');
|
|
184
|
+
engine.startSession('session-1', '/transcripts/session-1.jsonl', 'test/repo');
|
|
185
185
|
const result = engine.checkWrite('session-1', 'Write', '/workspace/note.md', () => true);
|
|
186
186
|
const expectedOutput = [
|
|
187
187
|
'Cannot write-check',
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nt-ai-lab/deterministic-agent-workflow-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/NTCoding/deterministic-agent-workflows.git",
|
|
9
|
+
"directory": "packages/deterministic-agent-workflows-engine"
|
|
10
|
+
},
|
|
6
11
|
"exports": {
|
|
7
12
|
".": "./dist/index.js"
|
|
8
13
|
},
|