@renseiai/agentfactory 0.8.6 → 0.8.8
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/README.md +2 -2
- package/dist/src/config/repository-config.d.ts +14 -0
- package/dist/src/config/repository-config.d.ts.map +1 -1
- package/dist/src/config/repository-config.js +20 -0
- package/dist/src/governor/decision-engine.d.ts +7 -0
- package/dist/src/governor/decision-engine.d.ts.map +1 -1
- package/dist/src/governor/decision-engine.js +59 -1
- package/dist/src/governor/event-types.d.ts +18 -1
- package/dist/src/governor/event-types.d.ts.map +1 -1
- package/dist/src/governor/event-types.js +4 -0
- package/dist/src/governor/governor.d.ts +5 -1
- package/dist/src/governor/governor.d.ts.map +1 -1
- package/dist/src/governor/governor.js +6 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts +22 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -0
- package/dist/src/merge-queue/adapters/github-native.js +243 -0
- package/dist/src/merge-queue/adapters/github-native.test.d.ts +2 -0
- package/dist/src/merge-queue/adapters/github-native.test.d.ts.map +1 -0
- package/dist/src/merge-queue/adapters/github-native.test.js +384 -0
- package/dist/src/merge-queue/index.d.ts +18 -0
- package/dist/src/merge-queue/index.d.ts.map +1 -0
- package/dist/src/merge-queue/index.js +28 -0
- package/dist/src/merge-queue/merge-queue.integration.test.d.ts +2 -0
- package/dist/src/merge-queue/merge-queue.integration.test.d.ts.map +1 -0
- package/dist/src/merge-queue/merge-queue.integration.test.js +128 -0
- package/dist/src/merge-queue/types.d.ts +48 -0
- package/dist/src/merge-queue/types.d.ts.map +1 -0
- package/dist/src/merge-queue/types.js +8 -0
- package/dist/src/orchestrator/activity-emitter.d.ts +3 -3
- package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -1
- package/dist/src/orchestrator/activity-emitter.js +1 -1
- package/dist/src/orchestrator/artifact-tracker.d.ts +93 -0
- package/dist/src/orchestrator/artifact-tracker.d.ts.map +1 -0
- package/dist/src/orchestrator/artifact-tracker.js +235 -0
- package/dist/src/orchestrator/artifact-tracker.test.d.ts +2 -0
- package/dist/src/orchestrator/artifact-tracker.test.d.ts.map +1 -0
- package/dist/src/orchestrator/artifact-tracker.test.js +189 -0
- package/dist/src/orchestrator/context-manager.d.ts +72 -0
- package/dist/src/orchestrator/context-manager.d.ts.map +1 -0
- package/dist/src/orchestrator/context-manager.js +120 -0
- package/dist/src/orchestrator/context-manager.test.d.ts +2 -0
- package/dist/src/orchestrator/context-manager.test.d.ts.map +1 -0
- package/dist/src/orchestrator/context-manager.test.js +137 -0
- package/dist/src/orchestrator/detect-work-type.test.js +25 -16
- package/dist/src/orchestrator/index.d.ts +12 -2
- package/dist/src/orchestrator/index.d.ts.map +1 -1
- package/dist/src/orchestrator/index.js +9 -1
- package/dist/src/orchestrator/issue-tracker-client.d.ts +103 -0
- package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -0
- package/dist/src/orchestrator/issue-tracker-client.js +8 -0
- package/dist/src/orchestrator/log-analyzer.d.ts +19 -4
- package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -1
- package/dist/src/orchestrator/log-analyzer.js +26 -50
- package/dist/src/orchestrator/orchestrator-utils.test.js +3 -0
- package/dist/src/orchestrator/orchestrator.d.ts +16 -2
- package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.js +449 -115
- package/dist/src/orchestrator/parse-work-result.d.ts +1 -1
- package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
- package/dist/src/orchestrator/parse-work-result.js +1 -1
- package/dist/src/orchestrator/session-logger.d.ts +1 -1
- package/dist/src/orchestrator/session-logger.d.ts.map +1 -1
- package/dist/src/orchestrator/state-recovery.d.ts +22 -3
- package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
- package/dist/src/orchestrator/state-recovery.js +55 -2
- package/dist/src/orchestrator/state-recovery.test.js +106 -2
- package/dist/src/orchestrator/state-types.d.ts +63 -1
- package/dist/src/orchestrator/state-types.d.ts.map +1 -1
- package/dist/src/orchestrator/state-types.js +5 -1
- package/dist/src/orchestrator/summary-builder.d.ts +47 -0
- package/dist/src/orchestrator/summary-builder.d.ts.map +1 -0
- package/dist/src/orchestrator/summary-builder.js +240 -0
- package/dist/src/orchestrator/summary-builder.test.d.ts +2 -0
- package/dist/src/orchestrator/summary-builder.test.d.ts.map +1 -0
- package/dist/src/orchestrator/summary-builder.test.js +236 -0
- package/dist/src/orchestrator/types.d.ts +24 -2
- package/dist/src/orchestrator/types.d.ts.map +1 -1
- package/dist/src/orchestrator/work-types.d.ts +50 -0
- package/dist/src/orchestrator/work-types.d.ts.map +1 -0
- package/dist/src/orchestrator/work-types.js +20 -0
- package/dist/src/templates/registry.d.ts +1 -1
- package/dist/src/templates/registry.test.js +2 -2
- package/dist/src/templates/renderer.d.ts +1 -1
- package/dist/src/templates/types.d.ts +6 -2
- package/dist/src/templates/types.d.ts.map +1 -1
- package/dist/src/templates/types.js +2 -0
- package/dist/src/templates/types.test.js +4 -3
- package/dist/src/tools/index.d.ts +0 -3
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +0 -2
- package/dist/src/workflow/branching-router.d.ts +38 -0
- package/dist/src/workflow/branching-router.d.ts.map +1 -0
- package/dist/src/workflow/branching-router.js +52 -0
- package/dist/src/workflow/branching-router.test.d.ts +2 -0
- package/dist/src/workflow/branching-router.test.d.ts.map +1 -0
- package/dist/src/workflow/branching-router.test.js +209 -0
- package/dist/src/workflow/duration.d.ts +28 -0
- package/dist/src/workflow/duration.d.ts.map +1 -0
- package/dist/src/workflow/duration.js +57 -0
- package/dist/src/workflow/duration.test.d.ts +2 -0
- package/dist/src/workflow/duration.test.d.ts.map +1 -0
- package/dist/src/workflow/duration.test.js +74 -0
- package/dist/src/workflow/expression/ast.d.ts +53 -0
- package/dist/src/workflow/expression/ast.d.ts.map +1 -0
- package/dist/src/workflow/expression/ast.js +8 -0
- package/dist/src/workflow/expression/context.d.ts +40 -0
- package/dist/src/workflow/expression/context.d.ts.map +1 -0
- package/dist/src/workflow/expression/context.js +37 -0
- package/dist/src/workflow/expression/evaluator.d.ts +28 -0
- package/dist/src/workflow/expression/evaluator.d.ts.map +1 -0
- package/dist/src/workflow/expression/evaluator.js +165 -0
- package/dist/src/workflow/expression/evaluator.test.d.ts +2 -0
- package/dist/src/workflow/expression/evaluator.test.d.ts.map +1 -0
- package/dist/src/workflow/expression/evaluator.test.js +792 -0
- package/dist/src/workflow/expression/expression.test.d.ts +2 -0
- package/dist/src/workflow/expression/expression.test.d.ts.map +1 -0
- package/dist/src/workflow/expression/expression.test.js +516 -0
- package/dist/src/workflow/expression/helpers.d.ts +21 -0
- package/dist/src/workflow/expression/helpers.d.ts.map +1 -0
- package/dist/src/workflow/expression/helpers.js +56 -0
- package/dist/src/workflow/expression/index.d.ts +55 -0
- package/dist/src/workflow/expression/index.d.ts.map +1 -0
- package/dist/src/workflow/expression/index.js +71 -0
- package/dist/src/workflow/expression/lexer.d.ts +37 -0
- package/dist/src/workflow/expression/lexer.d.ts.map +1 -0
- package/dist/src/workflow/expression/lexer.js +166 -0
- package/dist/src/workflow/expression/parser.d.ts +23 -0
- package/dist/src/workflow/expression/parser.d.ts.map +1 -0
- package/dist/src/workflow/expression/parser.js +181 -0
- package/dist/src/workflow/index.d.ts +21 -0
- package/dist/src/workflow/index.d.ts.map +1 -0
- package/dist/src/workflow/index.js +15 -0
- package/dist/src/workflow/retry-resolver.d.ts +51 -0
- package/dist/src/workflow/retry-resolver.d.ts.map +1 -0
- package/dist/src/workflow/retry-resolver.js +70 -0
- package/dist/src/workflow/retry-resolver.test.d.ts +2 -0
- package/dist/src/workflow/retry-resolver.test.d.ts.map +1 -0
- package/dist/src/workflow/retry-resolver.test.js +149 -0
- package/dist/src/workflow/transition-engine.d.ts +46 -0
- package/dist/src/workflow/transition-engine.d.ts.map +1 -0
- package/dist/src/workflow/transition-engine.js +113 -0
- package/dist/src/workflow/transition-engine.test.d.ts +2 -0
- package/dist/src/workflow/transition-engine.test.d.ts.map +1 -0
- package/dist/src/workflow/transition-engine.test.js +425 -0
- package/dist/src/workflow/workflow-loader.d.ts +21 -0
- package/dist/src/workflow/workflow-loader.d.ts.map +1 -0
- package/dist/src/workflow/workflow-loader.js +40 -0
- package/dist/src/workflow/workflow-loader.test.d.ts +2 -0
- package/dist/src/workflow/workflow-loader.test.d.ts.map +1 -0
- package/dist/src/workflow/workflow-loader.test.js +134 -0
- package/dist/src/workflow/workflow-registry.d.ts +97 -0
- package/dist/src/workflow/workflow-registry.d.ts.map +1 -0
- package/dist/src/workflow/workflow-registry.js +173 -0
- package/dist/src/workflow/workflow-registry.test.d.ts +2 -0
- package/dist/src/workflow/workflow-registry.test.d.ts.map +1 -0
- package/dist/src/workflow/workflow-registry.test.js +201 -0
- package/dist/src/workflow/workflow-types.d.ts +442 -0
- package/dist/src/workflow/workflow-types.d.ts.map +1 -0
- package/dist/src/workflow/workflow-types.js +113 -0
- package/dist/src/workflow/workflow-types.test.d.ts +2 -0
- package/dist/src/workflow/workflow-types.test.d.ts.map +1 -0
- package/dist/src/workflow/workflow-types.test.js +440 -0
- package/package.json +3 -4
- package/dist/src/linear-cli.d.ts +0 -38
- package/dist/src/linear-cli.d.ts.map +0 -1
- package/dist/src/linear-cli.js +0 -674
- package/dist/src/tools/linear-runner.d.ts +0 -34
- package/dist/src/tools/linear-runner.d.ts.map +0 -1
- package/dist/src/tools/linear-runner.js +0 -700
- package/dist/src/tools/plugins/linear.d.ts +0 -9
- package/dist/src/tools/plugins/linear.d.ts.map +0 -1
- package/dist/src/tools/plugins/linear.js +0 -138
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluation Context
|
|
3
|
+
*
|
|
4
|
+
* Defines the sandboxed context in which expression ASTs are evaluated.
|
|
5
|
+
* The context provides variable bindings and registered helper functions,
|
|
6
|
+
* with no access to globals, prototypes, or dynamic code execution.
|
|
7
|
+
*/
|
|
8
|
+
import type { GovernorIssue } from '../../governor/governor-types.js';
|
|
9
|
+
/**
|
|
10
|
+
* The sandboxed evaluation context passed to the expression evaluator.
|
|
11
|
+
*
|
|
12
|
+
* - `variables` holds named values that `VariableRef` nodes resolve against.
|
|
13
|
+
* - `functions` holds callable helpers that `FunctionCall` nodes invoke.
|
|
14
|
+
*/
|
|
15
|
+
export interface EvaluationContext {
|
|
16
|
+
/** Variable bindings — e.g., { isParentIssue: true, priority: 3 } */
|
|
17
|
+
readonly variables: Record<string, unknown>;
|
|
18
|
+
/** Registered helper functions */
|
|
19
|
+
readonly functions: Record<string, (...args: unknown[]) => unknown>;
|
|
20
|
+
}
|
|
21
|
+
export interface BuildContextOptions {
|
|
22
|
+
/** Whether the issue has sub-issues (i.e., it is a parent issue) */
|
|
23
|
+
hasSubIssues?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build an EvaluationContext from a GovernorIssue and optional phase state.
|
|
27
|
+
*
|
|
28
|
+
* This is the primary way to create contexts for condition evaluation
|
|
29
|
+
* during workflow transitions. It:
|
|
30
|
+
* 1. Extracts well-known variables from the issue (status, labels, etc.)
|
|
31
|
+
* 2. Merges in phase-state booleans (researchCompleted, etc.)
|
|
32
|
+
* 3. Registers all built-in helper functions
|
|
33
|
+
*
|
|
34
|
+
* @param issue - The issue being evaluated.
|
|
35
|
+
* @param phaseState - Optional map of phase completion flags.
|
|
36
|
+
* @param opts - Additional context not on the issue itself.
|
|
37
|
+
* @returns A fully populated EvaluationContext.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildEvaluationContext(issue: GovernorIssue, phaseState?: Record<string, boolean>, opts?: BuildContextOptions): EvaluationContext;
|
|
40
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAOrE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;CACpE;AAMD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,CAAC,EAAE,mBAAmB,GACzB,iBAAiB,CAkBnB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluation Context
|
|
3
|
+
*
|
|
4
|
+
* Defines the sandboxed context in which expression ASTs are evaluated.
|
|
5
|
+
* The context provides variable bindings and registered helper functions,
|
|
6
|
+
* with no access to globals, prototypes, or dynamic code execution.
|
|
7
|
+
*/
|
|
8
|
+
import { createBuiltinHelpers } from './helpers.js';
|
|
9
|
+
/**
|
|
10
|
+
* Build an EvaluationContext from a GovernorIssue and optional phase state.
|
|
11
|
+
*
|
|
12
|
+
* This is the primary way to create contexts for condition evaluation
|
|
13
|
+
* during workflow transitions. It:
|
|
14
|
+
* 1. Extracts well-known variables from the issue (status, labels, etc.)
|
|
15
|
+
* 2. Merges in phase-state booleans (researchCompleted, etc.)
|
|
16
|
+
* 3. Registers all built-in helper functions
|
|
17
|
+
*
|
|
18
|
+
* @param issue - The issue being evaluated.
|
|
19
|
+
* @param phaseState - Optional map of phase completion flags.
|
|
20
|
+
* @param opts - Additional context not on the issue itself.
|
|
21
|
+
* @returns A fully populated EvaluationContext.
|
|
22
|
+
*/
|
|
23
|
+
export function buildEvaluationContext(issue, phaseState, opts) {
|
|
24
|
+
const hasSubIssues = opts?.hasSubIssues ?? false;
|
|
25
|
+
const variables = {
|
|
26
|
+
// Issue-derived variables
|
|
27
|
+
isParentIssue: hasSubIssues,
|
|
28
|
+
labels: issue.labels,
|
|
29
|
+
status: issue.status,
|
|
30
|
+
priority: 0, // GovernorIssue doesn't carry priority; default to 0
|
|
31
|
+
// Spread phase-state booleans so expressions like
|
|
32
|
+
// `researchCompleted and not backlogCreationCompleted` work directly.
|
|
33
|
+
...phaseState,
|
|
34
|
+
};
|
|
35
|
+
const functions = createBuiltinHelpers(issue, { hasSubIssues });
|
|
36
|
+
return { variables, functions };
|
|
37
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression Evaluator (Tree-Walking)
|
|
3
|
+
*
|
|
4
|
+
* Walks a parsed AST and produces a result value within a sandboxed
|
|
5
|
+
* EvaluationContext. No `eval()`, `new Function()`, or dynamic code
|
|
6
|
+
* execution is used — evaluation is a pure recursive descent over the
|
|
7
|
+
* typed AST nodes.
|
|
8
|
+
*/
|
|
9
|
+
import type { ASTNode } from './ast.js';
|
|
10
|
+
import type { EvaluationContext } from './context.js';
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when expression evaluation fails at runtime.
|
|
13
|
+
*
|
|
14
|
+
* Examples: unknown function name, type mismatch in numeric comparison.
|
|
15
|
+
*/
|
|
16
|
+
export declare class EvaluationError extends Error {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Evaluate an AST node within the given context.
|
|
21
|
+
*
|
|
22
|
+
* @param ast - The AST node to evaluate.
|
|
23
|
+
* @param context - The sandboxed evaluation context.
|
|
24
|
+
* @returns The result of evaluating the node.
|
|
25
|
+
* @throws {EvaluationError} on unknown functions or type mismatches.
|
|
26
|
+
*/
|
|
27
|
+
export declare function evaluate(ast: ASTNode, context: EvaluationContext): unknown;
|
|
28
|
+
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAMrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAiBD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CA6D1E"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression Evaluator (Tree-Walking)
|
|
3
|
+
*
|
|
4
|
+
* Walks a parsed AST and produces a result value within a sandboxed
|
|
5
|
+
* EvaluationContext. No `eval()`, `new Function()`, or dynamic code
|
|
6
|
+
* execution is used — evaluation is a pure recursive descent over the
|
|
7
|
+
* typed AST nodes.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// EvaluationError
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown when expression evaluation fails at runtime.
|
|
14
|
+
*
|
|
15
|
+
* Examples: unknown function name, type mismatch in numeric comparison.
|
|
16
|
+
*/
|
|
17
|
+
export class EvaluationError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'EvaluationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Helpers
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Coerce an arbitrary value to a boolean using JavaScript truthiness rules.
|
|
28
|
+
*/
|
|
29
|
+
function toBool(value) {
|
|
30
|
+
return Boolean(value);
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Evaluator
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Evaluate an AST node within the given context.
|
|
37
|
+
*
|
|
38
|
+
* @param ast - The AST node to evaluate.
|
|
39
|
+
* @param context - The sandboxed evaluation context.
|
|
40
|
+
* @returns The result of evaluating the node.
|
|
41
|
+
* @throws {EvaluationError} on unknown functions or type mismatches.
|
|
42
|
+
*/
|
|
43
|
+
export function evaluate(ast, context) {
|
|
44
|
+
switch (ast.type) {
|
|
45
|
+
// -------------------------------------------------------------------
|
|
46
|
+
// Literals — return value directly
|
|
47
|
+
// -------------------------------------------------------------------
|
|
48
|
+
case 'BooleanLiteral':
|
|
49
|
+
return ast.value;
|
|
50
|
+
case 'StringLiteral':
|
|
51
|
+
return ast.value;
|
|
52
|
+
case 'NumberLiteral':
|
|
53
|
+
return ast.value;
|
|
54
|
+
// -------------------------------------------------------------------
|
|
55
|
+
// Variable reference — look up in context, default to false
|
|
56
|
+
// -------------------------------------------------------------------
|
|
57
|
+
case 'VariableRef': {
|
|
58
|
+
const value = context.variables[ast.name];
|
|
59
|
+
// Undefined variables resolve to `false` (no crash)
|
|
60
|
+
if (value === undefined) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
// -------------------------------------------------------------------
|
|
66
|
+
// Unary operator
|
|
67
|
+
// -------------------------------------------------------------------
|
|
68
|
+
case 'UnaryOp': {
|
|
69
|
+
// Currently only 'not' is supported
|
|
70
|
+
const operand = evaluate(ast.operand, context);
|
|
71
|
+
return !toBool(operand);
|
|
72
|
+
}
|
|
73
|
+
// -------------------------------------------------------------------
|
|
74
|
+
// Binary operator
|
|
75
|
+
// -------------------------------------------------------------------
|
|
76
|
+
case 'BinaryOp':
|
|
77
|
+
return evaluateBinaryOp(ast.operator, ast.left, ast.right, context);
|
|
78
|
+
// -------------------------------------------------------------------
|
|
79
|
+
// Function call
|
|
80
|
+
// -------------------------------------------------------------------
|
|
81
|
+
case 'FunctionCall': {
|
|
82
|
+
const fn = context.functions[ast.name];
|
|
83
|
+
if (!fn) {
|
|
84
|
+
throw new EvaluationError(`Unknown function '${ast.name}'. Available functions: ${Object.keys(context.functions).join(', ') || '(none)'}`);
|
|
85
|
+
}
|
|
86
|
+
const args = ast.args.map((arg) => evaluate(arg, context));
|
|
87
|
+
return fn(...args);
|
|
88
|
+
}
|
|
89
|
+
default: {
|
|
90
|
+
// Exhaustive check — should never reach here with a well-typed AST
|
|
91
|
+
const _exhaustive = ast;
|
|
92
|
+
throw new EvaluationError(`Unknown AST node type: ${_exhaustive.type}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Binary operator evaluation
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
function evaluateBinaryOp(operator, left, right, context) {
|
|
100
|
+
switch (operator) {
|
|
101
|
+
// Short-circuit logical operators
|
|
102
|
+
case 'and': {
|
|
103
|
+
const leftVal = evaluate(left, context);
|
|
104
|
+
if (!toBool(leftVal))
|
|
105
|
+
return leftVal;
|
|
106
|
+
return evaluate(right, context);
|
|
107
|
+
}
|
|
108
|
+
case 'or': {
|
|
109
|
+
const leftVal = evaluate(left, context);
|
|
110
|
+
if (toBool(leftVal))
|
|
111
|
+
return leftVal;
|
|
112
|
+
return evaluate(right, context);
|
|
113
|
+
}
|
|
114
|
+
// Equality — works across all types
|
|
115
|
+
case 'eq': {
|
|
116
|
+
const leftVal = evaluate(left, context);
|
|
117
|
+
const rightVal = evaluate(right, context);
|
|
118
|
+
return leftVal === rightVal;
|
|
119
|
+
}
|
|
120
|
+
case 'neq': {
|
|
121
|
+
const leftVal = evaluate(left, context);
|
|
122
|
+
const rightVal = evaluate(right, context);
|
|
123
|
+
return leftVal !== rightVal;
|
|
124
|
+
}
|
|
125
|
+
// Ordering comparisons — require matching numeric types
|
|
126
|
+
case 'gt':
|
|
127
|
+
case 'lt':
|
|
128
|
+
case 'gte':
|
|
129
|
+
case 'lte': {
|
|
130
|
+
const leftVal = evaluate(left, context);
|
|
131
|
+
const rightVal = evaluate(right, context);
|
|
132
|
+
return evaluateOrdering(operator, leftVal, rightVal);
|
|
133
|
+
}
|
|
134
|
+
default:
|
|
135
|
+
throw new EvaluationError(`Unknown operator '${operator}'`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function evaluateOrdering(operator, left, right) {
|
|
139
|
+
// Both must be numbers or both must be strings for ordering comparisons
|
|
140
|
+
if (typeof left === 'number' && typeof right === 'number') {
|
|
141
|
+
switch (operator) {
|
|
142
|
+
case 'gt': return left > right;
|
|
143
|
+
case 'lt': return left < right;
|
|
144
|
+
case 'gte': return left >= right;
|
|
145
|
+
case 'lte': return left <= right;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (typeof left === 'string' && typeof right === 'string') {
|
|
149
|
+
switch (operator) {
|
|
150
|
+
case 'gt': return left > right;
|
|
151
|
+
case 'lt': return left < right;
|
|
152
|
+
case 'gte': return left >= right;
|
|
153
|
+
case 'lte': return left <= right;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
throw new EvaluationError(`Cannot compare ${typeLabel(left)} and ${typeLabel(right)} with '${operator}'. ` +
|
|
157
|
+
`Both operands must be numbers or both must be strings.`);
|
|
158
|
+
}
|
|
159
|
+
function typeLabel(value) {
|
|
160
|
+
if (value === null)
|
|
161
|
+
return 'null';
|
|
162
|
+
if (Array.isArray(value))
|
|
163
|
+
return 'array';
|
|
164
|
+
return typeof value;
|
|
165
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.test.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.test.ts"],"names":[],"mappings":""}
|