@longzai-intelligence-workflow/core 0.0.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +14 -0
  3. package/coverage/.lcov.info.0d8fc8c4f6acaa77.tmp +159 -0
  4. package/coverage/.lcov.info.1ca0aee1c681607a.tmp +61 -0
  5. package/coverage/.lcov.info.5a9690152fb62c73.tmp +159 -0
  6. package/coverage/.lcov.info.984d9ad89a4b1598.tmp +12 -0
  7. package/coverage/.lcov.info.a607374a9831c63e.tmp +61 -0
  8. package/coverage/.lcov.info.b58246c9a6df7fc5.tmp +167 -0
  9. package/coverage/.lcov.info.b5f068b7c1d63f36.tmp +12 -0
  10. package/coverage/.lcov.info.bbac83a4ec8a1294.tmp +159 -0
  11. package/coverage/.lcov.info.bf3e6cf9d98abfc0.tmp +159 -0
  12. package/coverage/.lcov.info.fb2d882b78dc47d4.tmp +169 -0
  13. package/coverage/lcov.info +169 -0
  14. package/dist/index.d.ts +577 -0
  15. package/dist/index.js +8 -0
  16. package/dist/schemas-D0Zuq8_5.js +1 -0
  17. package/dist/schemas.d.ts +684 -0
  18. package/dist/schemas.js +1 -0
  19. package/docs/overview.md +17 -0
  20. package/lzi-builder.config.ts +13 -0
  21. package/lzi-dev.config.ts +7 -0
  22. package/oxlint.config.ts +6 -0
  23. package/package.json +38 -0
  24. package/src/__tests__/helpers/setup.ts +9 -0
  25. package/src/__tests__/unit/constants.test.ts +129 -0
  26. package/src/__tests__/unit/utils.test.ts +156 -0
  27. package/src/__tests__/work-item-rules.test.ts +90 -0
  28. package/src/constants/index.ts +1 -0
  29. package/src/constants/workflow.ts +114 -0
  30. package/src/index.ts +16 -0
  31. package/src/ports/action-executor.port.ts +73 -0
  32. package/src/ports/feed-event.port.ts +74 -0
  33. package/src/ports/index.ts +9 -0
  34. package/src/schemas/action-executor.schema.ts +209 -0
  35. package/src/schemas/api.schema.ts +11 -0
  36. package/src/schemas/definition.schema.ts +53 -0
  37. package/src/schemas/feed-event-trigger.schema.ts +102 -0
  38. package/src/schemas/index.ts +8 -0
  39. package/src/schemas/instance.schema.ts +47 -0
  40. package/src/schemas/monitoring.schema.ts +53 -0
  41. package/src/schemas/trigger.schema.ts +26 -0
  42. package/src/schemas/workflow-doc.schema.ts +365 -0
  43. package/src/types/action-executor.ts +64 -0
  44. package/src/types/api.ts +10 -0
  45. package/src/types/definition.ts +49 -0
  46. package/src/types/feed-event-trigger.ts +38 -0
  47. package/src/types/index.ts +6 -0
  48. package/src/types/instance.ts +49 -0
  49. package/src/types/monitoring.ts +54 -0
  50. package/src/types/trigger.ts +39 -0
  51. package/src/utils/dag.utils.ts +95 -0
  52. package/src/utils/declaration-frontmatter.utils.ts +138 -0
  53. package/src/utils/index.ts +19 -0
  54. package/src/utils/work-item-rules.utils.ts +194 -0
  55. package/tsconfig/.cache/build.tsbuildinfo +1 -0
  56. package/tsconfig/.cache/node.tsbuildinfo +1 -0
  57. package/tsconfig/.cache/test.tsbuildinfo +1 -0
  58. package/tsconfig/app.json +12 -0
  59. package/tsconfig/build.json +15 -0
  60. package/tsconfig/node.json +12 -0
  61. package/tsconfig/test.json +15 -0
  62. package/tsconfig.json +15 -0
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from '@longzai-intelligence-builder/esm';
2
+
3
+ /**
4
+ * 核心包 tsdown 配置
5
+ *
6
+ * 包含核心类型定义、常量和 Zod schemas
7
+ */
8
+ export default defineConfig({
9
+ entry: {
10
+ index: 'src/index.ts',
11
+ schemas: 'src/schemas/index.ts',
12
+ },
13
+ });
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from '@longzai-intelligence-dev-tools/config';
2
+
3
+ export default defineConfig({
4
+ clean: {
5
+ plugins: ['turbo', 'tsgo'],
6
+ },
7
+ });
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from '@longzai-intelligence-oxlint/presets/library';
2
+
3
+ /**
4
+ * oxlint 代码检查配置
5
+ */
6
+ export default defineConfig();
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@longzai-intelligence-workflow/core",
3
+ "version": "0.0.1",
4
+ "license": "UNLICENSED",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./schemas": {
14
+ "types": "./dist/schemas.d.ts",
15
+ "import": "./dist/schemas.js"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "lzi-builder",
20
+ "build:prod": "NODE_ENV=production bun run build",
21
+ "prepublishOnly": "bun run build:prod",
22
+ "typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
23
+ "typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
24
+ "typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
25
+ "typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
26
+ "lint": "oxlint src && oxfmt --check src",
27
+ "lint:fix": "oxlint --fix src && oxfmt src",
28
+ "test": "bun test",
29
+ "test:watch": "bun test --watch",
30
+ "test:coverage": "bun test --coverage",
31
+ "clean": "lzi-dev-cli clean"
32
+ },
33
+ "dependencies": {
34
+ "@longzai-intelligence-shared-kernel/core": "^0.1.4",
35
+ "zod": "^4.4.3"
36
+ },
37
+ "devDependencies": {}
38
+ }
@@ -0,0 +1,9 @@
1
+ import { afterAll, afterEach, beforeAll } from 'bun:test';
2
+
3
+ process.env.NODE_ENV ??= 'test';
4
+
5
+ beforeAll(() => {});
6
+
7
+ afterAll(() => {});
8
+
9
+ afterEach(() => {});
@@ -0,0 +1,129 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import {
4
+ ALERT_TYPES,
5
+ DEFAULT_PAGE_SIZE,
6
+ INSTANCE_STATUSES,
7
+ MAX_PAGE_SIZE,
8
+ METRIC_TYPES,
9
+ NODE_EXECUTION_STATUSES,
10
+ NODE_TYPES,
11
+ TRIGGER_TYPES,
12
+ } from '../../constants/workflow';
13
+
14
+ describe('DEFAULT_PAGE_SIZE', () => {
15
+ it('默认分页大小为 20', () => {
16
+ // Arrange & Act & Assert
17
+ expect(DEFAULT_PAGE_SIZE).toBe(20);
18
+ });
19
+ });
20
+
21
+ describe('MAX_PAGE_SIZE', () => {
22
+ it('最大分页大小为 100', () => {
23
+ // Arrange & Act & Assert
24
+ expect(MAX_PAGE_SIZE).toBe(100);
25
+ });
26
+ });
27
+
28
+ describe('NODE_TYPES', () => {
29
+ it('包含预期的节点类型', () => {
30
+ // Arrange
31
+ const expectedTypes = [
32
+ 'StartEvent',
33
+ 'EndEvent',
34
+ 'UserTask',
35
+ 'ServiceTask',
36
+ 'ExclusiveGateway',
37
+ 'ParallelGateway',
38
+ 'InclusiveGateway',
39
+ 'SubProcess',
40
+ 'TimerEvent',
41
+ 'ErrorEvent',
42
+ 'SignalEvent',
43
+ ];
44
+
45
+ // Act & Assert
46
+ expect(NODE_TYPES).toEqual(expectedTypes);
47
+ });
48
+
49
+ it('包含 StartEvent', () => {
50
+ // Arrange & Act & Assert
51
+ expect(NODE_TYPES).toContain('StartEvent');
52
+ });
53
+
54
+ it('包含 EndEvent', () => {
55
+ // Arrange & Act & Assert
56
+ expect(NODE_TYPES).toContain('EndEvent');
57
+ });
58
+
59
+ it('为只读数组', () => {
60
+ // Arrange & Act & Assert
61
+ expect(Array.isArray(NODE_TYPES)).toBe(true);
62
+ });
63
+ });
64
+
65
+ describe('INSTANCE_STATUSES', () => {
66
+ it('包含预期的实例状态', () => {
67
+ // Arrange
68
+ const expectedStatuses = ['pending', 'running', 'paused', 'completed', 'cancelled', 'failed'];
69
+
70
+ // Act & Assert
71
+ expect(INSTANCE_STATUSES).toEqual(expectedStatuses);
72
+ });
73
+
74
+ it('包含 pending 状态', () => {
75
+ // Arrange & Act & Assert
76
+ expect(INSTANCE_STATUSES).toContain('pending');
77
+ });
78
+
79
+ it('包含 failed 状态', () => {
80
+ // Arrange & Act & Assert
81
+ expect(INSTANCE_STATUSES).toContain('failed');
82
+ });
83
+ });
84
+
85
+ describe('NODE_EXECUTION_STATUSES', () => {
86
+ it('包含预期的节点执行状态', () => {
87
+ // Arrange
88
+ const expectedStatuses = ['pending', 'running', 'completed', 'failed', 'skipped'];
89
+
90
+ // Act & Assert
91
+ expect(NODE_EXECUTION_STATUSES).toEqual(expectedStatuses);
92
+ });
93
+ });
94
+
95
+ describe('TRIGGER_TYPES', () => {
96
+ it('包含预期的触发器类型', () => {
97
+ // Arrange
98
+ const expectedTypes = ['timer', 'webhook', 'event'];
99
+
100
+ // Act & Assert
101
+ expect(TRIGGER_TYPES).toEqual(expectedTypes);
102
+ });
103
+ });
104
+
105
+ describe('ALERT_TYPES', () => {
106
+ it('包含预期的告警类型', () => {
107
+ // Arrange
108
+ const expectedTypes = ['timeout', 'failure_rate', 'slow_execution'];
109
+
110
+ // Act & Assert
111
+ expect(ALERT_TYPES).toEqual(expectedTypes);
112
+ });
113
+ });
114
+
115
+ describe('METRIC_TYPES', () => {
116
+ it('包含预期的指标类型', () => {
117
+ // Arrange
118
+ const expectedTypes = [
119
+ 'avg_duration',
120
+ 'success_rate',
121
+ 'failure_rate',
122
+ 'timeout_rate',
123
+ 'instance_count',
124
+ ];
125
+
126
+ // Act & Assert
127
+ expect(METRIC_TYPES).toEqual(expectedTypes);
128
+ });
129
+ });
@@ -0,0 +1,156 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../constants/workflow';
4
+ import { formatDate, getPagination, getTotalPages } from '../../utils/index';
5
+
6
+ describe('getPagination', () => {
7
+ it('默认参数返回 offset=0, limit=DEFAULT_PAGE_SIZE', () => {
8
+ // Arrange & Act
9
+ const result = getPagination();
10
+
11
+ // Assert
12
+ expect(result.offset).toBe(0);
13
+ expect(result.limit).toBe(DEFAULT_PAGE_SIZE);
14
+ });
15
+
16
+ it('page=2, pageSize=10 返回 offset=10, limit=10', () => {
17
+ // Arrange & Act
18
+ const result = getPagination(2, 10);
19
+
20
+ // Assert
21
+ expect(result.offset).toBe(10);
22
+ expect(result.limit).toBe(10);
23
+ });
24
+
25
+ it('pageSize 超过 MAX_PAGE_SIZE 时限制为 MAX_PAGE_SIZE', () => {
26
+ // Arrange
27
+ const oversizedPageSize = MAX_PAGE_SIZE + 50;
28
+
29
+ // Act
30
+ const result = getPagination(1, oversizedPageSize);
31
+
32
+ // Assert
33
+ expect(result.limit).toBe(MAX_PAGE_SIZE);
34
+ });
35
+
36
+ it('page=0 时默认为 page=1', () => {
37
+ // Arrange & Act
38
+ const result = getPagination(0, 10);
39
+
40
+ // Assert
41
+ expect(result.offset).toBe(0);
42
+ expect(result.limit).toBe(10);
43
+ });
44
+
45
+ it('page 为负数时默认为 page=1', () => {
46
+ // Arrange & Act
47
+ const result = getPagination(-1, 10);
48
+
49
+ // Assert
50
+ expect(result.offset).toBe(0);
51
+ });
52
+
53
+ it('仅传入 page 时 pageSize 使用默认值', () => {
54
+ // Arrange & Act
55
+ const result = getPagination(3);
56
+
57
+ // Assert
58
+ expect(result.offset).toBe((3 - 1) * DEFAULT_PAGE_SIZE);
59
+ expect(result.limit).toBe(DEFAULT_PAGE_SIZE);
60
+ });
61
+
62
+ it('仅传入 pageSize 时 page 默认为 1', () => {
63
+ // Arrange & Act
64
+ const result = getPagination(undefined, 15);
65
+
66
+ // Assert
67
+ expect(result.offset).toBe(0);
68
+ expect(result.limit).toBe(15);
69
+ });
70
+ });
71
+
72
+ describe('getTotalPages', () => {
73
+ it('正确计算总页数', () => {
74
+ // Arrange
75
+ const total = 45;
76
+ const pageSize = 10;
77
+
78
+ // Act
79
+ const result = getTotalPages(total, pageSize);
80
+
81
+ // Assert
82
+ expect(result).toBe(5);
83
+ });
84
+
85
+ it('总数恰好整除时返回精确页数', () => {
86
+ // Arrange
87
+ const total = 40;
88
+ const pageSize = 10;
89
+
90
+ // Act
91
+ const result = getTotalPages(total, pageSize);
92
+
93
+ // Assert
94
+ expect(result).toBe(4);
95
+ });
96
+
97
+ it('总数为 0 时返回 0', () => {
98
+ // Arrange
99
+ const total = 0;
100
+ const pageSize = 10;
101
+
102
+ // Act
103
+ const result = getTotalPages(total, pageSize);
104
+
105
+ // Assert
106
+ expect(result).toBe(0);
107
+ });
108
+
109
+ it('总数为 1 时返回 1', () => {
110
+ // Arrange
111
+ const total = 1;
112
+ const pageSize = 10;
113
+
114
+ // Act
115
+ const result = getTotalPages(total, pageSize);
116
+
117
+ // Assert
118
+ expect(result).toBe(1);
119
+ });
120
+ });
121
+
122
+ describe('formatDate', () => {
123
+ it('将 Date 对象转换为 ISO 字符串', () => {
124
+ // Arrange
125
+ const date = new Date('2025-01-15T10:30:00.000Z');
126
+
127
+ // Act
128
+ const result = formatDate(date);
129
+
130
+ // Assert
131
+ expect(result).toBe('2025-01-15T10:30:00.000Z');
132
+ });
133
+
134
+ it('将日期字符串转换为 ISO 字符串', () => {
135
+ // Arrange
136
+ const dateStr = '2025-06-01';
137
+
138
+ // Act
139
+ const result = formatDate(dateStr);
140
+
141
+ // Assert
142
+ expect(result).toContain('2025-06-01');
143
+ expect(typeof result).toBe('string');
144
+ });
145
+
146
+ it('返回值为有效的 ISO 格式', () => {
147
+ // Arrange
148
+ const date = new Date();
149
+
150
+ // Act
151
+ const result = formatDate(date);
152
+
153
+ // Assert
154
+ expect(new Date(result).toISOString()).toBe(result);
155
+ });
156
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * 工作项判定核测试:四段制解析 + 转移表执法 + 视图派生
3
+ */
4
+ import { describe, expect, test } from 'bun:test';
5
+
6
+ import { parseGateLine, parseItemLine, type WorkflowEdge, type WorkflowGate, type WorkflowItem } from '../schemas/workflow-doc.schema';
7
+ import { checkStatusTransition, deriveWorkflowView } from '../utils/work-item-rules.utils';
8
+
9
+ describe('声明方言四段制解析', () => {
10
+ test('工作项行:状态段执法', () => {
11
+ expect(parseItemLine('t-011 | 生成器补全 | ref:demo/docs/tasks/a.md | todo')).toEqual({
12
+ id: 't-011',
13
+ title: '生成器补全',
14
+ ref: 'ref:demo/docs/tasks/a.md',
15
+ status: 'todo',
16
+ });
17
+ expect(parseItemLine('t-011 | 生成器补全 | ref:demo/docs/tasks/a.md')).toBeNull();
18
+ expect(parseItemLine('t-011 | 生成器补全 | ref:demo/docs/tasks/a.md | invalid')).toBeNull();
19
+ });
20
+
21
+ test('裁定门行:裁定段四形态执法', () => {
22
+ expect(parseGateLine('t-013 | ruling | 载体指示待裁 | pending')?.ruling).toEqual({ status: 'pending' });
23
+ expect(parseGateLine('workflow | ruling | TE 悬置 | pending')?.at).toBe('workflow');
24
+ expect(parseGateLine('t-013 | ruling | 载体指示待裁 | approved:user:decisions/019.md')?.ruling).toEqual({
25
+ status: 'approved',
26
+ decidedBy: 'user',
27
+ evidence: 'decisions/019.md',
28
+ });
29
+ expect(parseGateLine('t-013 | ruling | 载体指示待裁 | rejected:user')?.ruling).toEqual({
30
+ status: 'rejected',
31
+ decidedBy: 'user',
32
+ });
33
+ expect(parseGateLine('t-013 | ruling | 载体指示待裁 | approved')).toBeNull();
34
+ });
35
+ });
36
+
37
+ describe('状态转移表执法', () => {
38
+ test('合法/非法转移判定', () => {
39
+ expect(checkStatusTransition('todo', 'doing')).toBeNull();
40
+ expect(checkStatusTransition('doing', 'blocked')).toBeNull();
41
+ expect(checkStatusTransition('done', 'todo')).toBeNull();
42
+ const error = checkStatusTransition('todo', 'done');
43
+ expect(error?.code).toBe('INVALID_TRANSITION');
44
+ expect(error?.message).toContain('todo → done');
45
+ });
46
+ });
47
+
48
+ describe('视图派生(依赖门控与未决裁定)', () => {
49
+ /**
50
+ * 拓扑:a -> b(b 挂门);c 独立;workflow 级门一枚
51
+ */
52
+ const items: readonly WorkflowItem[] = [
53
+ { id: 'a', title: '甲', ref: 'ref:demo/a.md', status: 'todo' },
54
+ { id: 'b', title: '乙', ref: 'ref:demo/b.md', status: 'todo' },
55
+ { id: 'c', title: '丙', ref: 'task:demo/c-item', status: 'doing' },
56
+ ];
57
+ const edges: readonly WorkflowEdge[] = [{ from: 'a', to: 'b' }];
58
+ const gates: readonly WorkflowGate[] = [
59
+ { at: 'b', kind: 'ruling', note: '乙项须裁定', ruling: { status: 'pending' } },
60
+ { at: 'workflow', kind: 'ruling', note: '工作流级悬置', ruling: { status: 'pending' } },
61
+ ];
62
+
63
+ test('依赖未满足派生阻塞;门未批不可启动;未决裁定含工作流级', () => {
64
+ const view = deriveWorkflowView(items, edges, gates);
65
+ const byId = new Map(view.items.map((entry) => [entry.id, entry]));
66
+
67
+ expect(byId.get('a')?.canStart).toBe(true);
68
+ expect(byId.get('b')?.blockedOnPrerequisite).toBe(true);
69
+ expect(byId.get('b')?.canStart).toBe(false);
70
+ expect(byId.get('c')?.canStart).toBe(false);
71
+ expect(view.pendingRulings.map((ruling) => ruling.key)).toEqual(['b:ruling', 'workflow:ruling']);
72
+ });
73
+
74
+ test('前置闭环解除阻塞;门批准解除门控;escalated 仍属未决', () => {
75
+ const settledItems: readonly WorkflowItem[] = [
76
+ { id: 'a', title: '甲', ref: 'ref:demo/a.md', status: 'done' },
77
+ { id: 'b', title: '乙', ref: 'ref:demo/b.md', status: 'todo' },
78
+ ];
79
+ const approvedGates: readonly WorkflowGate[] = [
80
+ { at: 'b', kind: 'ruling', note: '已裁', ruling: { status: 'approved', decidedBy: 'user' } },
81
+ { at: 'workflow', kind: 'ruling', note: '升级待裁', ruling: { status: 'escalated' } },
82
+ ];
83
+ const view = deriveWorkflowView(settledItems, edges, approvedGates);
84
+ const byId = new Map(view.items.map((entry) => [entry.id, entry]));
85
+
86
+ expect(byId.get('b')?.blockedOnPrerequisite).toBe(false);
87
+ expect(byId.get('b')?.canStart).toBe(true);
88
+ expect(view.pendingRulings.map((ruling) => ruling.rulingStatus)).toEqual(['escalated']);
89
+ });
90
+ });
@@ -0,0 +1 @@
1
+ export * from './workflow';
@@ -0,0 +1,114 @@
1
+ /**
2
+ * 工作流节点类型枚举
3
+ */
4
+ export const NODE_TYPES = [
5
+ 'StartEvent',
6
+ 'EndEvent',
7
+ 'UserTask',
8
+ 'ServiceTask',
9
+ 'ExclusiveGateway',
10
+ 'ParallelGateway',
11
+ 'InclusiveGateway',
12
+ 'SubProcess',
13
+ 'TimerEvent',
14
+ 'ErrorEvent',
15
+ 'SignalEvent',
16
+ ] as const;
17
+
18
+ /**
19
+ * 工作流实例状态枚举
20
+ */
21
+ export const INSTANCE_STATUSES = [
22
+ 'pending',
23
+ 'running',
24
+ 'paused',
25
+ 'completed',
26
+ 'cancelled',
27
+ 'failed',
28
+ ] as const;
29
+
30
+ /**
31
+ * 节点执行状态枚举
32
+ */
33
+ export const NODE_EXECUTION_STATUSES = [
34
+ 'pending',
35
+ 'running',
36
+ 'completed',
37
+ 'failed',
38
+ 'skipped',
39
+ ] as const;
40
+
41
+ /**
42
+ * 触发器类型枚举
43
+ */
44
+ export const TRIGGER_TYPES = ['timer', 'webhook', 'event', 'feed.event'] as const;
45
+
46
+ /**
47
+ * feed 事件名称枚举(W-2,Phase 2)
48
+ *
49
+ * 用于 feed.event 触发器订阅 feed 项目暴露的事件总线。
50
+ */
51
+ export const FEED_EVENT_NAMES = [
52
+ /**
53
+ * 新条目入库事件
54
+ */
55
+ 'item.ingested',
56
+
57
+ /**
58
+ * 信息源抓取完成事件
59
+ */
60
+ 'source.fetched',
61
+
62
+ /**
63
+ * 条目过滤事件
64
+ */
65
+ 'item.filtered',
66
+
67
+ /**
68
+ * 行业识别事件
69
+ */
70
+ 'industry.detected',
71
+ ] as const;
72
+
73
+ /**
74
+ * 告警类型枚举
75
+ */
76
+ export const ALERT_TYPES = ['timeout', 'failure_rate', 'slow_execution'] as const;
77
+
78
+ /**
79
+ * 工作流内置 action 类型枚举(W-3,Phase 2)
80
+ *
81
+ * - feed.applyTags:调用 feed F-2 applyTags 为条目打标签
82
+ * - feed.summarize:调用 feed F-3 summarize 生成摘要
83
+ * - llm.complete:调用 agent LlmCompletePort 完成文本
84
+ * - webhook.send:调用 webhook 项目发送 webhook
85
+ *
86
+ * D-08 决策:不暴露 DSL 编辑 UI,action 通过自然语言编译的 DSL 执行。
87
+ */
88
+ export const ACTION_TYPES = [
89
+ 'feed.applyTags',
90
+ 'feed.summarize',
91
+ 'llm.complete',
92
+ 'webhook.send',
93
+ ] as const;
94
+
95
+ /**
96
+ * 监控指标类型枚举
97
+ */
98
+ export const METRIC_TYPES = [
99
+ 'avg_duration',
100
+ 'success_rate',
101
+ 'failure_rate',
102
+ 'timeout_rate',
103
+ 'instance_count',
104
+ ] as const;
105
+
106
+ /**
107
+ * 分页查询默认每页条数
108
+ */
109
+ export const DEFAULT_PAGE_SIZE = 20;
110
+
111
+ /**
112
+ * 分页查询每页最大条数上限
113
+ */
114
+ export const MAX_PAGE_SIZE = 100;
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 工作流核心包
3
+ *
4
+ * 提供共享基础类型、Schema、常量和工具函数。
5
+ * 不依赖任何 domain 包。
6
+ */
7
+ // 类型导出
8
+ export * from './types/index';
9
+ // 常量导出
10
+ export * from './constants/index';
11
+ // 工具函数导出
12
+ export * from './utils/index';
13
+ // zod schema 导出
14
+ export * from './schemas/index';
15
+ // 端口契约导出(C1 合规,零框架依赖)
16
+ export * from './ports/index';
@@ -0,0 +1,73 @@
1
+ /**
2
+ * action 执行器端口契约(W-3,Phase 2)
3
+ *
4
+ * 定义工作流内置 action 执行器的端口契约。
5
+ * execution 子插件通过此端口注册与调度 action handler,
6
+ * 当工作流执行到 action 节点时,根据 action.type 调用对应 handler。
7
+ *
8
+ * 支持的 action 类型:
9
+ * - feed.applyTags:调用 feed F-2 applyTags(Phase 2)
10
+ * - feed.summarize:调用 feed F-3 summarize(Phase 2)
11
+ * - llm.complete:调用 agent LlmCompletePort
12
+ * - webhook.send:调用 webhook 项目
13
+ *
14
+ * D-08 决策:不暴露 DSL 编辑 UI,action 通过自然语言编译的 DSL 执行。
15
+ *
16
+ * C1 合规:本端口为零框架依赖的纯类型契约,由具体适配器层提供实现。
17
+ */
18
+
19
+ import type { Action, ActionContext, ActionResult, ActionType } from '../types';
20
+
21
+ /**
22
+ * 单个 action handler 函数签名
23
+ *
24
+ * 注册到 ActionExecutorPort 中,按 action.type 路由调用。
25
+ *
26
+ * @param action - 待执行的 action(具体子类型由注册时的 actionType 决定)
27
+ * @param context - action 执行上下文
28
+ * @returns 执行结果
29
+ */
30
+ export type ActionHandler = (action: Action, context: ActionContext) => Promise<ActionResult>;
31
+
32
+ /**
33
+ * action 执行器端口
34
+ *
35
+ * 工作流引擎通过此端口调度内置 action。
36
+ * execution 子插件在初始化时注册各 actionType 的 handler,
37
+ * 工作流执行到 action 节点时调用 execute 方法。
38
+ */
39
+ export type ActionExecutorPort = {
40
+ /**
41
+ * 执行指定 action
42
+ *
43
+ * 根据 action.type 路由到注册的 handler 执行。
44
+ * 未注册的 actionType 返回失败结果。
45
+ *
46
+ * @param action - 待执行的 action
47
+ * @param context - action 执行上下文
48
+ * @returns 执行结果
49
+ */
50
+ execute: (action: Action, context: ActionContext) => Promise<ActionResult>;
51
+
52
+ /**
53
+ * 注册 action handler
54
+ *
55
+ * 为指定 actionType 注册 handler,重复注册将覆盖旧 handler。
56
+ *
57
+ * @param actionType - action 类型
58
+ * @param handler - action 处理器
59
+ */
60
+ registerHandler: (actionType: ActionType, handler: ActionHandler) => void;
61
+
62
+ /**
63
+ * 检查 action 执行器是否可用
64
+ *
65
+ * @returns 端口是否可用
66
+ */
67
+ isAvailable: () => Promise<boolean>;
68
+ };
69
+
70
+ /**
71
+ * action 执行器端口 DI 令牌
72
+ */
73
+ export const ACTION_EXECUTOR_PORT_TOKEN = Symbol('ACTION_EXECUTOR_PORT_TOKEN');