@nt-ai-lab/deterministic-agent-workflow-engine 0.1.2 → 0.1.4

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 CHANGED
@@ -15,3 +15,5 @@ export type { EngineResult, RehydratableWorkflow, WorkflowDefinition, WorkflowEv
15
15
  export type { TranscriptMessage, TranscriptReader } from './platform/infra/external-clients/transcript/transcript-reader';
16
16
  export type { IdentityCheckResult } from './platform/domain/identity-verification';
17
17
  export { checkIdentity } from './platform/domain/identity-verification';
18
+ export { workflowSpec, WorkflowSpecError, } from './platform/domain/testing/workflow-spec';
19
+ export type { GivenPhase, OperationResult, SpecConfig, ThrowResult, WorkflowSpecification, } from './platform/domain/testing/workflow-spec';
package/dist/index.js CHANGED
@@ -6,3 +6,4 @@ export { checkBashCommand } from './platform/domain/bash-enforcement.js';
6
6
  export { pass, fail } from './platform/domain/precondition-result.js';
7
7
  export { WorkflowEngine } from './platform/domain/workflow-engine.js';
8
8
  export { checkIdentity } from './platform/domain/identity-verification.js';
9
+ export { workflowSpec, WorkflowSpecError, } from './platform/domain/testing/workflow-spec.js';
@@ -0,0 +1,35 @@
1
+ /** @riviere-role value-object */
2
+ export type SpecConfig<TEvent, TState, TDeps, TWorkflow> = {
3
+ readonly fold: (events: readonly TEvent[]) => TState;
4
+ readonly rehydrate: (state: TState, deps: TDeps) => TWorkflow;
5
+ readonly defaultDeps: () => TDeps;
6
+ readonly getPendingEvents: (wf: TWorkflow) => readonly TEvent[];
7
+ readonly getState: (wf: TWorkflow) => TState;
8
+ readonly mergeDeps: (defaults: TDeps, overrides: Partial<TDeps>) => TDeps;
9
+ };
10
+ /** @riviere-role value-object */
11
+ export type OperationResult<TEvent, TState, TResult> = {
12
+ readonly result: TResult;
13
+ readonly events: readonly TEvent[];
14
+ readonly state: TState;
15
+ };
16
+ /** @riviere-role value-object */
17
+ export type ThrowResult = {
18
+ readonly error: unknown;
19
+ };
20
+ /** @riviere-role value-object */
21
+ export type GivenPhase<TEvent, TState, TDeps, TWorkflow> = {
22
+ readonly withDeps: (overrides: Partial<TDeps>) => GivenPhase<TEvent, TState, TDeps, TWorkflow>;
23
+ readonly when: <TResult>(op: (wf: TWorkflow) => TResult) => OperationResult<TEvent, TState, TResult>;
24
+ readonly whenThrows: (op: (wf: TWorkflow) => unknown) => ThrowResult;
25
+ };
26
+ /** @riviere-role value-object */
27
+ export type WorkflowSpecification<TEvent, TState, TDeps, TWorkflow> = {
28
+ readonly given: (...events: readonly TEvent[]) => GivenPhase<TEvent, TState, TDeps, TWorkflow>;
29
+ };
30
+ /** @riviere-role domain-error */
31
+ export declare class WorkflowSpecError extends Error {
32
+ constructor(message: string);
33
+ }
34
+ /** @riviere-role domain-service */
35
+ export declare function workflowSpec<TEvent, TState, TDeps, TWorkflow>(config: SpecConfig<TEvent, TState, TDeps, TWorkflow>): WorkflowSpecification<TEvent, TState, TDeps, TWorkflow>;
@@ -0,0 +1,44 @@
1
+ /** @riviere-role domain-error */
2
+ export class WorkflowSpecError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = 'WorkflowSpecError';
6
+ }
7
+ }
8
+ const EMPTY_OVERRIDES = Object.freeze({});
9
+ /** @riviere-role domain-service */
10
+ export function workflowSpec(config) {
11
+ function buildGiven(events, depOverrides) {
12
+ const resolveDeps = () => config.mergeDeps(config.defaultDeps(), depOverrides);
13
+ const rehydrate = () => {
14
+ const state = config.fold(events);
15
+ return config.rehydrate(state, resolveDeps());
16
+ };
17
+ return {
18
+ withDeps: (overrides) => buildGiven(events, {
19
+ ...depOverrides,
20
+ ...overrides,
21
+ }),
22
+ when: (op) => {
23
+ const wf = rehydrate();
24
+ const result = op(wf);
25
+ return {
26
+ result,
27
+ events: config.getPendingEvents(wf),
28
+ state: config.getState(wf),
29
+ };
30
+ },
31
+ whenThrows: (op) => {
32
+ const wf = rehydrate();
33
+ try {
34
+ op(wf);
35
+ }
36
+ catch (error) {
37
+ return { error };
38
+ }
39
+ throw new WorkflowSpecError('Expected operation to throw, but it did not');
40
+ },
41
+ };
42
+ }
43
+ return { given: (...events) => buildGiven(events, EMPTY_OVERRIDES) };
44
+ }
@@ -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, currentState: TStateName, states: readonly string[]): readonly BaseEvent[];
13
+ export declare function enrichSessionStartedEvents<TStateName extends string>(engineDeps: WorkflowEngineDeps, events: readonly BaseEvent[], transcriptPath: string, repository: string | undefined, currentState: TStateName, states: readonly string[]): readonly BaseEvent[];
@@ -28,7 +28,7 @@ export function enrichSessionStartedEvents(engineDeps, events, transcriptPath, r
28
28
  return {
29
29
  ...event,
30
30
  transcriptPath,
31
- repository,
31
+ ...(repository === undefined ? {} : { repository }),
32
32
  currentState,
33
33
  states: [...states],
34
34
  };
@@ -40,7 +40,7 @@ export function enrichSessionStartedEvents(engineDeps, events, transcriptPath, r
40
40
  type: 'session-started',
41
41
  at: engineDeps.now(),
42
42
  transcriptPath,
43
- repository,
43
+ ...(repository === undefined ? {} : { repository }),
44
44
  currentState,
45
45
  states: [...states],
46
46
  }, ...enriched];
@@ -23,12 +23,6 @@ export class WorkflowEngine {
23
23
  const initialState = this.factory.initialState();
24
24
  const workflow = this.factory.buildWorkflow(initialState, this.workflowDeps);
25
25
  const resolvedRepository = repository ?? this.engineDeps.getRepositoryName?.();
26
- if (resolvedRepository === undefined || resolvedRepository === '') {
27
- return {
28
- type: 'error',
29
- output: 'Could not determine repository name for session-started event.'
30
- };
31
- }
32
26
  workflow.startSession(transcriptPath, resolvedRepository);
33
27
  const registry = this.factory.getRegistry();
34
28
  const stateNames = Object.keys(registry);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nt-ai-lab/deterministic-agent-workflow-engine",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {