@coralai/sps-cli 0.49.15 → 0.50.0

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 (175) hide show
  1. package/dist/commands/cardAdd.d.ts.map +1 -1
  2. package/dist/commands/cardAdd.js +47 -67
  3. package/dist/commands/cardAdd.js.map +1 -1
  4. package/dist/commands/cardMarkComplete.js +1 -1
  5. package/dist/commands/cardMarkComplete.js.map +1 -1
  6. package/dist/commands/cardMarkStarted.js +1 -1
  7. package/dist/commands/cardMarkStarted.js.map +1 -1
  8. package/dist/commands/consoleCommand.js +3 -3
  9. package/dist/commands/consoleCommand.js.map +1 -1
  10. package/dist/commands/hookCommand.d.ts +25 -0
  11. package/dist/commands/hookCommand.d.ts.map +1 -1
  12. package/dist/commands/hookCommand.js +2 -2
  13. package/dist/commands/hookCommand.js.map +1 -1
  14. package/dist/console/index.d.ts +15 -0
  15. package/dist/console/index.d.ts.map +1 -0
  16. package/dist/console/index.js +177 -0
  17. package/dist/console/index.js.map +1 -0
  18. package/dist/console/lib/lockFile.d.ts +17 -0
  19. package/dist/console/lib/lockFile.d.ts.map +1 -0
  20. package/dist/console/lib/lockFile.js +61 -0
  21. package/dist/console/lib/lockFile.js.map +1 -0
  22. package/dist/console/lib/portPicker.d.ts +3 -0
  23. package/dist/console/lib/portPicker.d.ts.map +1 -0
  24. package/dist/console/lib/portPicker.js +25 -0
  25. package/dist/console/lib/portPicker.js.map +1 -0
  26. package/dist/console/lib/resultToJson.d.ts +18 -0
  27. package/dist/console/lib/resultToJson.d.ts.map +1 -0
  28. package/dist/console/lib/resultToJson.js +19 -0
  29. package/dist/console/lib/resultToJson.js.map +1 -0
  30. package/dist/console/routes/cards.d.ts +26 -0
  31. package/dist/console/routes/cards.d.ts.map +1 -0
  32. package/dist/console/routes/cards.js +85 -0
  33. package/dist/console/routes/cards.js.map +1 -0
  34. package/dist/console/routes/chat.d.ts +36 -0
  35. package/dist/console/routes/chat.d.ts.map +1 -0
  36. package/dist/console/routes/chat.js +458 -0
  37. package/dist/console/routes/chat.js.map +1 -0
  38. package/dist/console/routes/logs.d.ts +17 -0
  39. package/dist/console/routes/logs.d.ts.map +1 -0
  40. package/dist/console/routes/logs.js +159 -0
  41. package/dist/console/routes/logs.js.map +1 -0
  42. package/dist/console/routes/pipeline.d.ts +10 -0
  43. package/dist/console/routes/pipeline.d.ts.map +1 -0
  44. package/dist/console/routes/pipeline.js +39 -0
  45. package/dist/console/routes/pipeline.js.map +1 -0
  46. package/dist/console/routes/projects.d.ts +15 -0
  47. package/dist/console/routes/projects.d.ts.map +1 -0
  48. package/dist/console/routes/projects.js +132 -0
  49. package/dist/console/routes/projects.js.map +1 -0
  50. package/dist/console/routes/skills.d.ts +4 -0
  51. package/dist/console/routes/skills.d.ts.map +1 -0
  52. package/dist/console/routes/skills.js +91 -0
  53. package/dist/console/routes/skills.js.map +1 -0
  54. package/dist/console/routes/system.d.ts +7 -0
  55. package/dist/console/routes/system.d.ts.map +1 -0
  56. package/dist/console/routes/system.js +288 -0
  57. package/dist/console/routes/system.js.map +1 -0
  58. package/dist/console/routes/workers.d.ts +5 -0
  59. package/dist/console/routes/workers.d.ts.map +1 -0
  60. package/dist/console/routes/workers.js +149 -0
  61. package/dist/console/routes/workers.js.map +1 -0
  62. package/dist/console/sse/eventBus.d.ts +25 -0
  63. package/dist/console/sse/eventBus.d.ts.map +1 -0
  64. package/dist/console/sse/eventBus.js +32 -0
  65. package/dist/console/sse/eventBus.js.map +1 -0
  66. package/dist/console/sse/projectStream.d.ts +13 -0
  67. package/dist/console/sse/projectStream.d.ts.map +1 -0
  68. package/dist/console/sse/projectStream.js +84 -0
  69. package/dist/console/sse/projectStream.js.map +1 -0
  70. package/dist/console-server/routes/projects.d.ts.map +1 -1
  71. package/dist/console-server/routes/projects.js +2 -1
  72. package/dist/console-server/routes/projects.js.map +1 -1
  73. package/dist/console-server/routes/system.js +1 -1
  74. package/dist/console-server/routes/system.js.map +1 -1
  75. package/dist/console-server/routes/workers.d.ts.map +1 -1
  76. package/dist/console-server/routes/workers.js +14 -5
  77. package/dist/console-server/routes/workers.js.map +1 -1
  78. package/dist/console-server/watchers/markerWatcher.d.ts.map +1 -1
  79. package/dist/console-server/watchers/markerWatcher.js +4 -2
  80. package/dist/console-server/watchers/markerWatcher.js.map +1 -1
  81. package/dist/infra/chokidarWatchers.d.ts +38 -0
  82. package/dist/infra/chokidarWatchers.d.ts.map +1 -0
  83. package/dist/infra/chokidarWatchers.js +213 -0
  84. package/dist/infra/chokidarWatchers.js.map +1 -0
  85. package/dist/infra/clock.d.ts +35 -0
  86. package/dist/infra/clock.d.ts.map +1 -0
  87. package/dist/infra/clock.js +45 -0
  88. package/dist/infra/clock.js.map +1 -0
  89. package/dist/infra/filesystem.d.ts +89 -0
  90. package/dist/infra/filesystem.d.ts.map +1 -0
  91. package/dist/infra/filesystem.js +247 -0
  92. package/dist/infra/filesystem.js.map +1 -0
  93. package/dist/infra/spawn.d.ts +67 -0
  94. package/dist/infra/spawn.d.ts.map +1 -0
  95. package/dist/infra/spawn.js +116 -0
  96. package/dist/infra/spawn.js.map +1 -0
  97. package/dist/infra/sseBus.d.ts +36 -0
  98. package/dist/infra/sseBus.d.ts.map +1 -0
  99. package/dist/infra/sseBus.js +72 -0
  100. package/dist/infra/sseBus.js.map +1 -0
  101. package/dist/interfaces/ACPClient.d.ts +1 -1
  102. package/dist/interfaces/ACPClient.d.ts.map +1 -1
  103. package/dist/main.js +1 -1
  104. package/dist/main.js.map +1 -1
  105. package/dist/providers/LocalACPClient.d.ts +1 -1
  106. package/dist/providers/LocalACPClient.d.ts.map +1 -1
  107. package/dist/services/CardService.d.ts +86 -0
  108. package/dist/services/CardService.d.ts.map +1 -0
  109. package/dist/services/CardService.js +313 -0
  110. package/dist/services/CardService.js.map +1 -0
  111. package/dist/services/ChatService.d.ts +62 -0
  112. package/dist/services/ChatService.d.ts.map +1 -0
  113. package/dist/services/ChatService.js +157 -0
  114. package/dist/services/ChatService.js.map +1 -0
  115. package/dist/services/LogService.d.ts +46 -0
  116. package/dist/services/LogService.d.ts.map +1 -0
  117. package/dist/services/LogService.js +185 -0
  118. package/dist/services/LogService.js.map +1 -0
  119. package/dist/services/PipelineService.d.ts +71 -0
  120. package/dist/services/PipelineService.d.ts.map +1 -0
  121. package/dist/services/PipelineService.js +349 -0
  122. package/dist/services/PipelineService.js.map +1 -0
  123. package/dist/services/ProjectService.d.ts +105 -0
  124. package/dist/services/ProjectService.d.ts.map +1 -0
  125. package/dist/services/ProjectService.js +346 -0
  126. package/dist/services/ProjectService.js.map +1 -0
  127. package/dist/services/SkillService.d.ts +38 -0
  128. package/dist/services/SkillService.d.ts.map +1 -0
  129. package/dist/services/SkillService.js +301 -0
  130. package/dist/services/SkillService.js.map +1 -0
  131. package/dist/services/WorkerService.d.ts +83 -0
  132. package/dist/services/WorkerService.d.ts.map +1 -0
  133. package/dist/services/WorkerService.js +262 -0
  134. package/dist/services/WorkerService.js.map +1 -0
  135. package/dist/services/container.d.ts +47 -0
  136. package/dist/services/container.d.ts.map +1 -0
  137. package/dist/services/container.js +77 -0
  138. package/dist/services/container.js.map +1 -0
  139. package/dist/services/defaults.d.ts +15 -0
  140. package/dist/services/defaults.d.ts.map +1 -0
  141. package/dist/services/defaults.js +11 -0
  142. package/dist/services/defaults.js.map +1 -0
  143. package/dist/services/executors.d.ts +38 -0
  144. package/dist/services/executors.d.ts.map +1 -0
  145. package/dist/services/executors.js +157 -0
  146. package/dist/services/executors.js.map +1 -0
  147. package/dist/services/ports.d.ts +17 -0
  148. package/dist/services/ports.d.ts.map +1 -0
  149. package/dist/services/ports.js +2 -0
  150. package/dist/services/ports.js.map +1 -0
  151. package/dist/shared/domainEvents.d.ts +118 -0
  152. package/dist/shared/domainEvents.d.ts.map +1 -0
  153. package/dist/shared/domainEvents.js +40 -0
  154. package/dist/shared/domainEvents.js.map +1 -0
  155. package/dist/shared/errors.d.ts +59 -0
  156. package/dist/shared/errors.d.ts.map +1 -0
  157. package/dist/shared/errors.js +79 -0
  158. package/dist/shared/errors.js.map +1 -0
  159. package/dist/shared/result.d.ts +51 -0
  160. package/dist/shared/result.d.ts.map +1 -0
  161. package/dist/shared/result.js +48 -0
  162. package/dist/shared/result.js.map +1 -0
  163. package/dist/shared/runtimePaths.d.ts +78 -0
  164. package/dist/shared/runtimePaths.d.ts.map +1 -0
  165. package/dist/shared/runtimePaths.js +179 -0
  166. package/dist/shared/runtimePaths.js.map +1 -0
  167. package/dist/shared/runtimeSchemas.d.ts +324 -0
  168. package/dist/shared/runtimeSchemas.d.ts.map +1 -0
  169. package/dist/shared/runtimeSchemas.js +124 -0
  170. package/dist/shared/runtimeSchemas.js.map +1 -0
  171. package/dist/shared/types.d.ts +12 -0
  172. package/dist/shared/types.d.ts.map +1 -0
  173. package/dist/shared/types.js +2 -0
  174. package/dist/shared/types.js.map +1 -0
  175. package/package.json +1 -1
@@ -0,0 +1,185 @@
1
+ /**
2
+ * @module services/LogService
3
+ * @description 日志 tail + 聚合 service
4
+ *
5
+ * @layer services
6
+ *
7
+ * 职责:
8
+ * - 单项目 tail(可选 worker 过滤、since 过滤、limit 截断)
9
+ * - 跨项目聚合 tail
10
+ * - 解析 log 行 → 结构化 LogLine(ts / level / worker / msg)
11
+ *
12
+ * 注意:SSE 流式 tail 是 Delivery 层职责(route 用 fs.watch),Service 只做一次性查询。
13
+ */
14
+ import { createReadStream, statSync } from 'node:fs';
15
+ import { resolve } from 'node:path';
16
+ import { createInterface } from 'node:readline';
17
+ import { domainError } from '../shared/errors.js';
18
+ import { err, ok } from '../shared/result.js';
19
+ import { home, logsDir, projectsDir, workerLogLineTag } from '../shared/runtimePaths.js';
20
+ const MAX_SCAN_BYTES = 4 * 1024 * 1024;
21
+ export class LogService {
22
+ deps;
23
+ constructor(deps) {
24
+ this.deps = deps;
25
+ }
26
+ /** 单项目 tail。 */
27
+ async tail(opts) {
28
+ const limit = clampLimit(opts.limit);
29
+ const files = this.findLogFiles(opts.project, opts.worker);
30
+ if (files.length === 0) {
31
+ return ok({ data: [], file: null, files: [] });
32
+ }
33
+ const file = files[0];
34
+ try {
35
+ const lines = await readTailLines(file, limit);
36
+ const filtered = opts.since ? filterSince(lines, opts.since) : lines;
37
+ return ok({
38
+ data: filtered,
39
+ file: rel(file),
40
+ files: files.map(rel),
41
+ });
42
+ }
43
+ catch (cause) {
44
+ return err(domainError('internal', 'LOG_READ_FAIL', '日志读取失败', { cause }));
45
+ }
46
+ }
47
+ /** 跨项目聚合 tail。 */
48
+ async aggregate(opts = {}) {
49
+ const limit = clampLimit(opts.limit);
50
+ const root = projectsDir();
51
+ if (!this.deps.fs.exists(root)) {
52
+ return ok({ data: [], files: [] });
53
+ }
54
+ let projects;
55
+ try {
56
+ projects = this.deps.fs.readDir(root).filter((e) => e.isDirectory).map((e) => e.name);
57
+ }
58
+ catch (cause) {
59
+ return err(domainError('internal', 'PROJECTS_READ_FAIL', '项目目录读取失败', { cause }));
60
+ }
61
+ // 每项目最新 log
62
+ const picked = [];
63
+ for (const p of projects) {
64
+ const files = this.findLogFiles(p, opts.worker);
65
+ if (files.length > 0)
66
+ picked.push({ project: p, file: files[0] });
67
+ }
68
+ const perLimit = Math.max(50, Math.floor(limit / Math.max(picked.length, 1)) * 2);
69
+ const merged = [];
70
+ for (const { project, file } of picked) {
71
+ try {
72
+ const lines = await readTailLines(file, perLimit);
73
+ for (const l of lines)
74
+ merged.push({ ...l, project });
75
+ }
76
+ catch {
77
+ /* 跳过读不了的,不一票否决 */
78
+ }
79
+ }
80
+ // 按 ts 升序(老的在前,新的在末),取末尾 limit
81
+ merged.sort((a, b) => {
82
+ const at = a.ts ? Date.parse(a.ts) : 0;
83
+ const bt = b.ts ? Date.parse(b.ts) : 0;
84
+ return at - bt;
85
+ });
86
+ const filtered = opts.since ? filterSince(merged, opts.since) : merged;
87
+ return ok({
88
+ data: filtered.slice(-limit),
89
+ files: picked.map((p) => rel(p.file)),
90
+ });
91
+ }
92
+ // ─── 内部 ─────────────────────────────────────────────────────────
93
+ findLogFiles(project, worker) {
94
+ const dir = logsDir(project);
95
+ if (!this.deps.fs.exists(dir))
96
+ return [];
97
+ let entries;
98
+ try {
99
+ entries = this.deps.fs.readDir(dir);
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ const workerTag = worker !== undefined ? workerLogLineTag(worker) : null;
105
+ const files = entries
106
+ .filter((e) => e.isFile && e.name.endsWith('.log'))
107
+ .filter((e) => {
108
+ if (!workerTag)
109
+ return true;
110
+ return e.name.includes(workerTag) || e.name.includes(`-${worker}-`);
111
+ })
112
+ .map((e) => resolve(dir, e.name))
113
+ .sort((a, b) => {
114
+ const sa = this.deps.fs.stat(a);
115
+ const sb = this.deps.fs.stat(b);
116
+ return (sb?.mtimeMs ?? 0) - (sa?.mtimeMs ?? 0);
117
+ });
118
+ return files;
119
+ }
120
+ }
121
+ // ─── helpers ──────────────────────────────────────────────────────
122
+ function clampLimit(input) {
123
+ const n = input ?? 500;
124
+ if (!Number.isFinite(n) || n <= 0)
125
+ return 500;
126
+ return Math.min(n, 2000);
127
+ }
128
+ function filterSince(lines, since) {
129
+ const parsed = Date.parse(since);
130
+ if (Number.isNaN(parsed))
131
+ return lines;
132
+ return lines.filter((l) => {
133
+ if (!l.ts)
134
+ return true;
135
+ const lt = Date.parse(l.ts);
136
+ return Number.isNaN(lt) || lt >= parsed;
137
+ });
138
+ }
139
+ function rel(path) {
140
+ try {
141
+ return path.replace(home(), '~');
142
+ }
143
+ catch {
144
+ return path;
145
+ }
146
+ }
147
+ export function parseLogLine(raw) {
148
+ const cleaned = raw.replace(/\[[0-9;]*m/g, '');
149
+ const m = cleaned.match(/(\d{4}-\d{2}-\d{2}[T ][\d:.]+Z?)\s*(?:\[)?(DEBUG|INFO|WARN|WARNING|ERROR|TRACE)\]?\s*(?:\[?(worker-\d+|acp|claude|supervisor|event-handler|skill|console)\]?\s*)?(.*)$/i);
150
+ if (m) {
151
+ const tsRaw = m[1] ?? '';
152
+ const lvl = (m[2] ?? 'info').toLowerCase().replace('warning', 'warn');
153
+ const src = m[3] ?? '';
154
+ const msg = m[4] ?? cleaned;
155
+ let worker = null;
156
+ const wm = src.match(/worker-(\d+)/);
157
+ if (wm)
158
+ worker = Number.parseInt(wm[1] ?? '', 10);
159
+ return {
160
+ ts: tsRaw.includes('T') ? tsRaw : `${tsRaw.replace(' ', 'T')}Z`,
161
+ worker,
162
+ level: lvl,
163
+ msg: src && !src.startsWith('worker-') ? `[${src}] ${msg}` : msg,
164
+ raw: cleaned,
165
+ };
166
+ }
167
+ return { ts: null, worker: null, level: 'info', msg: cleaned, raw: cleaned };
168
+ }
169
+ async function readTailLines(filePath, limit) {
170
+ const stat = statSync(filePath);
171
+ const start = Math.max(0, stat.size - MAX_SCAN_BYTES);
172
+ const lines = [];
173
+ await new Promise((resolveP) => {
174
+ const stream = createReadStream(filePath, { start, encoding: 'utf-8' });
175
+ const rl = createInterface({ input: stream });
176
+ rl.on('line', (l) => {
177
+ lines.push(parseLogLine(l));
178
+ if (lines.length > limit * 3)
179
+ lines.splice(0, lines.length - limit * 3);
180
+ });
181
+ rl.on('close', () => resolveP());
182
+ });
183
+ return lines.slice(-limit);
184
+ }
185
+ //# sourceMappingURL=LogService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogService.js","sourceRoot":"","sources":["../../src/services/LogService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import type { Clock } from '../infra/clock.js';
2
+ import type { FileSystem } from '../infra/filesystem.js';
3
+ import type { ProcessSpawner } from '../infra/spawn.js';
4
+ import type { DomainEventBus } from '../shared/domainEvents.js';
5
+ import { type DomainError } from '../shared/errors.js';
6
+ import { type Result } from '../shared/result.js';
7
+ export type PipelineStatus = 'idle' | 'running';
8
+ export interface PipelineStatusInfo {
9
+ readonly status: PipelineStatus;
10
+ readonly pid: number | null;
11
+ }
12
+ export interface PipelineSummary {
13
+ readonly active: string | null;
14
+ readonly available: Array<{
15
+ name: string;
16
+ isActive: boolean;
17
+ }>;
18
+ }
19
+ export interface PipelineFileContent {
20
+ readonly content: string;
21
+ readonly etag: string;
22
+ readonly parsed: unknown;
23
+ readonly parseError: string | null;
24
+ readonly isActive: boolean;
25
+ }
26
+ export interface CreatePipelineInput {
27
+ name: string;
28
+ template?: 'blank' | 'sample' | 'active';
29
+ }
30
+ export interface ResetPipelineOpts {
31
+ all?: boolean;
32
+ cards?: number[];
33
+ }
34
+ /** CLI 命令层注入的钩子(Phase 3) */
35
+ export interface PipelineExecutor {
36
+ stop(project: string): Promise<void>;
37
+ reset(project: string, opts: ResetPipelineOpts): Promise<void>;
38
+ }
39
+ export interface PipelineServiceDeps {
40
+ readonly fs: FileSystem;
41
+ readonly clock: Clock;
42
+ readonly events: DomainEventBus;
43
+ readonly spawner: ProcessSpawner;
44
+ readonly executor?: PipelineExecutor;
45
+ }
46
+ export declare class PipelineService {
47
+ private readonly deps;
48
+ constructor(deps: PipelineServiceDeps);
49
+ /** 启动 pipeline —— 已在跑直接返当前 pid。 */
50
+ start(project: string): Promise<Result<PipelineStatusInfo, DomainError>>;
51
+ stop(project: string): Promise<Result<void, DomainError>>;
52
+ reset(project: string, opts?: ResetPipelineOpts): Promise<Result<void, DomainError>>;
53
+ status(project: string): Promise<Result<PipelineStatusInfo, DomainError>>;
54
+ listPipelines(project: string): Promise<Result<PipelineSummary>>;
55
+ readPipeline(project: string, filename: string): Promise<Result<PipelineFileContent, DomainError>>;
56
+ writePipeline(project: string, filename: string, content: string, etag: string): Promise<Result<{
57
+ etag: string;
58
+ }, DomainError>>;
59
+ createPipeline(project: string, input: CreatePipelineInput): Promise<Result<{
60
+ name: string;
61
+ content: string;
62
+ etag: string;
63
+ }, DomainError>>;
64
+ deletePipeline(project: string, filename: string): Promise<Result<void, DomainError>>;
65
+ /** 切换 active pipeline —— 复制指定文件到 project.yaml。 */
66
+ switchActive(project: string, filename: string): Promise<Result<{
67
+ activePipeline: string;
68
+ }, DomainError>>;
69
+ private readSupervisorPid;
70
+ }
71
+ //# sourceMappingURL=PipelineService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineService.d.ts","sourceRoot":"","sources":["../../src/services/PipelineService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,349 @@
1
+ /**
2
+ * @module services/PipelineService
3
+ * @description Pipeline 控制 + yaml CRUD service
4
+ *
5
+ * @layer services
6
+ *
7
+ * 职责:
8
+ * - start:spawn 后台 supervisor(唯一允许用 ProcessSpawner 的 service)
9
+ * - stop:注入 PipelineExecutor.stop 调 CLI 停止(Phase 3 会接到 Domain 内部实现)
10
+ * - reset:注入 PipelineExecutor.reset
11
+ * - status:读 supervisor.pid 判进程活
12
+ * - pipelines yaml CRUD:list / get / write / create / delete / switch active
13
+ */
14
+ import { createHash } from 'node:crypto';
15
+ import { resolve } from 'node:path';
16
+ import YAML from 'yaml';
17
+ import { domainError } from '../shared/errors.js';
18
+ import { err, ok } from '../shared/result.js';
19
+ import { activePipelineFile, logsDir, PipelineFilenameRe, pipelineFile, pipelinesDir, projectDir, supervisorPidFile, } from '../shared/runtimePaths.js';
20
+ export class PipelineService {
21
+ deps;
22
+ constructor(deps) {
23
+ this.deps = deps;
24
+ }
25
+ /** 启动 pipeline —— 已在跑直接返当前 pid。 */
26
+ async start(project) {
27
+ if (!isValidProject(project))
28
+ return err(invalidProject());
29
+ if (!this.deps.fs.exists(projectDir(project))) {
30
+ return err(projectNotFound(project));
31
+ }
32
+ const existing = this.readSupervisorPid(project);
33
+ if (existing) {
34
+ return ok({ status: 'running', pid: existing });
35
+ }
36
+ if (!this.deps.fs.exists(logsDir(project))) {
37
+ this.deps.fs.mkdir(logsDir(project), { recursive: true });
38
+ }
39
+ const date = this.deps.clock.nowIso().slice(0, 10);
40
+ const logPath = resolve(logsDir(project), `console-tick-${date}.log`);
41
+ try {
42
+ const child = this.deps.spawner.spawnSupervisor({
43
+ args: ['tick', project],
44
+ logPath,
45
+ });
46
+ const pid = child.pid ?? null;
47
+ this.deps.events.emit({
48
+ type: 'pipeline.started',
49
+ project,
50
+ pid: pid ?? 0,
51
+ ts: this.deps.clock.now(),
52
+ });
53
+ return ok({ status: 'running', pid });
54
+ }
55
+ catch (cause) {
56
+ return err(domainError('external', 'PIPELINE_SPAWN_FAIL', '启动 pipeline 失败', {
57
+ cause,
58
+ details: { message: cause instanceof Error ? cause.message : String(cause) },
59
+ }));
60
+ }
61
+ }
62
+ async stop(project) {
63
+ if (!isValidProject(project))
64
+ return err(invalidProject());
65
+ if (!this.deps.executor) {
66
+ return err(domainError('internal', 'EXECUTOR_MISSING', 'PipelineExecutor 未注入'));
67
+ }
68
+ try {
69
+ await this.deps.executor.stop(project);
70
+ }
71
+ catch (cause) {
72
+ return err(domainError('external', 'PIPELINE_STOP_FAIL', 'stop pipeline 失败', {
73
+ cause,
74
+ details: { message: cause instanceof Error ? cause.message : String(cause) },
75
+ }));
76
+ }
77
+ this.deps.events.emit({
78
+ type: 'pipeline.stopped',
79
+ project,
80
+ ts: this.deps.clock.now(),
81
+ });
82
+ return ok(undefined);
83
+ }
84
+ async reset(project, opts = {}) {
85
+ if (!isValidProject(project))
86
+ return err(invalidProject());
87
+ if (!this.deps.executor) {
88
+ return err(domainError('internal', 'EXECUTOR_MISSING', 'PipelineExecutor 未注入'));
89
+ }
90
+ try {
91
+ await this.deps.executor.reset(project, opts);
92
+ }
93
+ catch (cause) {
94
+ return err(domainError('external', 'PIPELINE_RESET_FAIL', 'reset pipeline 失败', {
95
+ cause,
96
+ }));
97
+ }
98
+ return ok(undefined);
99
+ }
100
+ async status(project) {
101
+ if (!isValidProject(project))
102
+ return err(invalidProject());
103
+ const pid = this.readSupervisorPid(project);
104
+ return ok({ status: pid ? 'running' : 'idle', pid });
105
+ }
106
+ // ─── Pipeline yaml CRUD ──────────────────────────────────────────
107
+ async listPipelines(project) {
108
+ if (!isValidProject(project))
109
+ return err(invalidProject());
110
+ const dir = pipelinesDir(project);
111
+ if (!this.deps.fs.exists(dir)) {
112
+ return ok({ active: null, available: [] });
113
+ }
114
+ let files;
115
+ try {
116
+ files = this.deps.fs
117
+ .readDir(dir)
118
+ .filter((e) => e.isFile && e.name.endsWith('.yaml'))
119
+ .map((e) => e.name)
120
+ .sort();
121
+ }
122
+ catch (cause) {
123
+ return err(domainError('internal', 'PIPELINES_READ_FAIL', 'pipelines 目录读取失败', { cause }));
124
+ }
125
+ const activePath = activePipelineFile(project);
126
+ let activeHash = null;
127
+ if (this.deps.fs.exists(activePath)) {
128
+ try {
129
+ const content = this.deps.fs.readFile(activePath);
130
+ activeHash = createHash('sha256').update(content).digest('hex');
131
+ }
132
+ catch {
133
+ /* ignore */
134
+ }
135
+ }
136
+ const available = files
137
+ .filter((f) => f !== 'project.yaml')
138
+ .map((name) => {
139
+ const full = resolve(dir, name);
140
+ let isActive = false;
141
+ try {
142
+ const content = this.deps.fs.readFile(full);
143
+ isActive = activeHash !== null && createHash('sha256').update(content).digest('hex') === activeHash;
144
+ }
145
+ catch {
146
+ /* ignore */
147
+ }
148
+ return { name, isActive };
149
+ });
150
+ return ok({ active: activeHash ? 'project.yaml' : null, available });
151
+ }
152
+ async readPipeline(project, filename) {
153
+ if (!isValidProject(project))
154
+ return err(invalidProject());
155
+ if (!PipelineFilenameRe.test(filename)) {
156
+ return err(domainError('validation', 'INVALID_FILENAME', 'pipeline 文件名非法'));
157
+ }
158
+ const path = pipelineFile(project, filename);
159
+ if (!this.deps.fs.exists(path)) {
160
+ return err(domainError('not-found', 'PIPELINE_NOT_FOUND', 'pipeline 文件不存在'));
161
+ }
162
+ let content;
163
+ try {
164
+ content = this.deps.fs.readFile(path);
165
+ }
166
+ catch (cause) {
167
+ return err(domainError('internal', 'PIPELINE_READ_FAIL', '读取失败', { cause }));
168
+ }
169
+ const etag = hashEtag(content);
170
+ let parsed = null;
171
+ let parseError = null;
172
+ try {
173
+ parsed = YAML.parse(content);
174
+ }
175
+ catch (e) {
176
+ parseError = e instanceof Error ? e.message : String(e);
177
+ }
178
+ return ok({
179
+ content,
180
+ etag,
181
+ parsed,
182
+ parseError,
183
+ isActive: filename === 'project.yaml',
184
+ });
185
+ }
186
+ async writePipeline(project, filename, content, etag) {
187
+ if (!isValidProject(project))
188
+ return err(invalidProject());
189
+ if (!PipelineFilenameRe.test(filename)) {
190
+ return err(domainError('validation', 'INVALID_FILENAME', 'pipeline 文件名非法'));
191
+ }
192
+ if (!etag) {
193
+ return err(domainError('validation', 'ETAG_REQUIRED', 'etag 必填'));
194
+ }
195
+ const path = pipelineFile(project, filename);
196
+ if (!this.deps.fs.exists(path)) {
197
+ return err(domainError('not-found', 'PIPELINE_NOT_FOUND', 'pipeline 文件不存在'));
198
+ }
199
+ let current;
200
+ try {
201
+ current = this.deps.fs.readFile(path);
202
+ }
203
+ catch (cause) {
204
+ return err(domainError('internal', 'PIPELINE_READ_FAIL', '读取失败', { cause }));
205
+ }
206
+ if (hashEtag(current) !== etag) {
207
+ return err(domainError('conflict', 'PIPELINE_ETAG_MISMATCH', 'pipeline 被其它人修改,请重新加载'));
208
+ }
209
+ try {
210
+ YAML.parse(content);
211
+ }
212
+ catch (e) {
213
+ return err(domainError('validation', 'YAML_INVALID', 'YAML 语法错误', {
214
+ details: { message: e instanceof Error ? e.message : String(e) },
215
+ }));
216
+ }
217
+ try {
218
+ this.deps.fs.writeFileAtomic(path, content);
219
+ }
220
+ catch (cause) {
221
+ return err(domainError('internal', 'PIPELINE_WRITE_FAIL', '写入失败', { cause }));
222
+ }
223
+ return ok({ etag: hashEtag(content) });
224
+ }
225
+ async createPipeline(project, input) {
226
+ if (!isValidProject(project))
227
+ return err(invalidProject());
228
+ if (!PipelineFilenameRe.test(input.name)) {
229
+ return err(domainError('validation', 'INVALID_FILENAME', '文件名非法'));
230
+ }
231
+ const dir = pipelinesDir(project);
232
+ if (!this.deps.fs.exists(dir)) {
233
+ return err(domainError('not-found', 'PIPELINES_DIR_NOT_FOUND', 'pipelines 目录不存在'));
234
+ }
235
+ const path = pipelineFile(project, input.name);
236
+ if (this.deps.fs.exists(path)) {
237
+ return err(domainError('conflict', 'PIPELINE_EXISTS', 'pipeline 已存在'));
238
+ }
239
+ const template = input.template ?? 'blank';
240
+ let content;
241
+ if (template === 'sample') {
242
+ const src = resolve(dir, 'sample.yaml.example');
243
+ if (!this.deps.fs.exists(src)) {
244
+ return err(domainError('not-found', 'SAMPLE_NOT_FOUND', 'sample 模板不存在'));
245
+ }
246
+ content = this.deps.fs.readFile(src);
247
+ }
248
+ else if (template === 'active') {
249
+ const src = activePipelineFile(project);
250
+ if (!this.deps.fs.exists(src)) {
251
+ return err(domainError('not-found', 'ACTIVE_NOT_FOUND', '当前 active pipeline 不存在'));
252
+ }
253
+ content = this.deps.fs.readFile(src);
254
+ }
255
+ else {
256
+ content = `mode: project\n\nstages:\n - name: develop\n on_complete: "move_card Done"\n on_fail:\n action: "label NEEDS-FIX"\n halt: true\n`;
257
+ }
258
+ try {
259
+ this.deps.fs.writeFileAtomic(path, content);
260
+ }
261
+ catch (cause) {
262
+ return err(domainError('internal', 'PIPELINE_WRITE_FAIL', '写入失败', { cause }));
263
+ }
264
+ return ok({ name: input.name, content, etag: hashEtag(content) });
265
+ }
266
+ async deletePipeline(project, filename) {
267
+ if (!isValidProject(project))
268
+ return err(invalidProject());
269
+ if (!PipelineFilenameRe.test(filename)) {
270
+ return err(domainError('validation', 'INVALID_FILENAME', '文件名非法'));
271
+ }
272
+ if (filename === 'project.yaml') {
273
+ return err(domainError('conflict', 'CANNOT_DELETE_ACTIVE', '当前 active pipeline 不能删,先切换再删'));
274
+ }
275
+ if (filename === 'sample.yaml.example') {
276
+ return err(domainError('conflict', 'CANNOT_DELETE_SAMPLE', 'sample 模板不能删'));
277
+ }
278
+ const path = pipelineFile(project, filename);
279
+ if (!this.deps.fs.exists(path)) {
280
+ return err(domainError('not-found', 'PIPELINE_NOT_FOUND', 'pipeline 不存在'));
281
+ }
282
+ try {
283
+ this.deps.fs.unlink(path);
284
+ }
285
+ catch (cause) {
286
+ return err(domainError('internal', 'PIPELINE_DELETE_FAIL', '删除失败', { cause }));
287
+ }
288
+ return ok(undefined);
289
+ }
290
+ /** 切换 active pipeline —— 复制指定文件到 project.yaml。 */
291
+ async switchActive(project, filename) {
292
+ if (!isValidProject(project))
293
+ return err(invalidProject());
294
+ if (!PipelineFilenameRe.test(filename) || filename === 'project.yaml') {
295
+ return err(domainError('validation', 'INVALID_FILENAME', 'pipeline 文件名非法或不能是 project.yaml'));
296
+ }
297
+ if (this.readSupervisorPid(project)) {
298
+ return err(domainError('conflict', 'PIPELINE_RUNNING', 'pipeline 正在跑,先停止再切换'));
299
+ }
300
+ const src = pipelineFile(project, filename);
301
+ if (!this.deps.fs.exists(src)) {
302
+ return err(domainError('not-found', 'PIPELINE_NOT_FOUND', '源 pipeline 不存在'));
303
+ }
304
+ try {
305
+ const content = this.deps.fs.readFile(src);
306
+ this.deps.fs.writeFileAtomic(activePipelineFile(project), content);
307
+ }
308
+ catch (cause) {
309
+ return err(domainError('internal', 'PIPELINE_SWITCH_FAIL', '切换失败', { cause }));
310
+ }
311
+ return ok({ activePipeline: filename });
312
+ }
313
+ // ─── 内部 ─────────────────────────────────────────────────────────
314
+ readSupervisorPid(project) {
315
+ const path = supervisorPidFile(project);
316
+ if (!this.deps.fs.exists(path))
317
+ return null;
318
+ try {
319
+ const raw = this.deps.fs.readFile(path);
320
+ const pid = Number.parseInt(raw.trim(), 10);
321
+ if (!Number.isFinite(pid) || pid <= 0)
322
+ return null;
323
+ try {
324
+ process.kill(pid, 0);
325
+ return pid;
326
+ }
327
+ catch {
328
+ return null;
329
+ }
330
+ }
331
+ catch {
332
+ return null;
333
+ }
334
+ }
335
+ }
336
+ // ─── helpers ──────────────────────────────────────────────────────
337
+ function hashEtag(content) {
338
+ return createHash('sha256').update(content).digest('hex').slice(0, 16);
339
+ }
340
+ function isValidProject(project) {
341
+ return typeof project === 'string' && /^[a-zA-Z0-9_-]+$/.test(project);
342
+ }
343
+ function invalidProject() {
344
+ return domainError('validation', 'INVALID_PROJECT_NAME', '项目名非法');
345
+ }
346
+ function projectNotFound(name) {
347
+ return domainError('not-found', 'PROJECT_NOT_FOUND', `项目 ${name} 不存在`);
348
+ }
349
+ //# sourceMappingURL=PipelineService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineService.js","sourceRoot":"","sources":["../../src/services/PipelineService.ts"],"names":[],"mappings":"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"}