@coralai/sps-cli 0.6.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.
- package/dist/commands/cardAdd.d.ts +2 -0
- package/dist/commands/cardAdd.d.ts.map +1 -0
- package/dist/commands/cardAdd.js +65 -0
- package/dist/commands/cardAdd.js.map +1 -0
- package/dist/commands/doctor.d.ts +9 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +264 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/monitorTick.d.ts +2 -0
- package/dist/commands/monitorTick.d.ts.map +1 -0
- package/dist/commands/monitorTick.js +47 -0
- package/dist/commands/monitorTick.js.map +1 -0
- package/dist/commands/pipelineTick.d.ts +2 -0
- package/dist/commands/pipelineTick.d.ts.map +1 -0
- package/dist/commands/pipelineTick.js +44 -0
- package/dist/commands/pipelineTick.js.map +1 -0
- package/dist/commands/pmCommand.d.ts +2 -0
- package/dist/commands/pmCommand.d.ts.map +1 -0
- package/dist/commands/pmCommand.js +159 -0
- package/dist/commands/pmCommand.js.map +1 -0
- package/dist/commands/projectInit.d.ts +2 -0
- package/dist/commands/projectInit.d.ts.map +1 -0
- package/dist/commands/projectInit.js +75 -0
- package/dist/commands/projectInit.js.map +1 -0
- package/dist/commands/qaTick.d.ts +2 -0
- package/dist/commands/qaTick.d.ts.map +1 -0
- package/dist/commands/qaTick.js +43 -0
- package/dist/commands/qaTick.js.map +1 -0
- package/dist/commands/schedulerTick.d.ts +2 -0
- package/dist/commands/schedulerTick.d.ts.map +1 -0
- package/dist/commands/schedulerTick.js +45 -0
- package/dist/commands/schedulerTick.js.map +1 -0
- package/dist/commands/tick.d.ts +14 -0
- package/dist/commands/tick.d.ts.map +1 -0
- package/dist/commands/tick.js +251 -0
- package/dist/commands/tick.js.map +1 -0
- package/dist/commands/workerLaunch.d.ts +2 -0
- package/dist/commands/workerLaunch.d.ts.map +1 -0
- package/dist/commands/workerLaunch.js +56 -0
- package/dist/commands/workerLaunch.js.map +1 -0
- package/dist/core/config.d.ts +38 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +131 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +23 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +28 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/lock.d.ts +14 -0
- package/dist/core/lock.d.ts.map +1 -0
- package/dist/core/lock.js +65 -0
- package/dist/core/lock.js.map +1 -0
- package/dist/core/logger.d.ts +24 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +62 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paths.d.ts +27 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +29 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/queue.d.ts +14 -0
- package/dist/core/queue.d.ts.map +1 -0
- package/dist/core/queue.js +38 -0
- package/dist/core/queue.js.map +1 -0
- package/dist/core/state.d.ts +32 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +52 -0
- package/dist/core/state.js.map +1 -0
- package/dist/engines/CloseoutEngine.d.ts +60 -0
- package/dist/engines/CloseoutEngine.d.ts.map +1 -0
- package/dist/engines/CloseoutEngine.js +596 -0
- package/dist/engines/CloseoutEngine.js.map +1 -0
- package/dist/engines/ExecutionEngine.d.ts +65 -0
- package/dist/engines/ExecutionEngine.d.ts.map +1 -0
- package/dist/engines/ExecutionEngine.js +603 -0
- package/dist/engines/ExecutionEngine.js.map +1 -0
- package/dist/engines/MonitorEngine.d.ts +39 -0
- package/dist/engines/MonitorEngine.d.ts.map +1 -0
- package/dist/engines/MonitorEngine.js +473 -0
- package/dist/engines/MonitorEngine.js.map +1 -0
- package/dist/engines/SchedulerEngine.d.ts +24 -0
- package/dist/engines/SchedulerEngine.d.ts.map +1 -0
- package/dist/engines/SchedulerEngine.js +195 -0
- package/dist/engines/SchedulerEngine.js.map +1 -0
- package/dist/interfaces/HookProvider.d.ts +9 -0
- package/dist/interfaces/HookProvider.d.ts.map +1 -0
- package/dist/interfaces/HookProvider.js +2 -0
- package/dist/interfaces/HookProvider.js.map +1 -0
- package/dist/interfaces/Notifier.d.ts +11 -0
- package/dist/interfaces/Notifier.d.ts.map +1 -0
- package/dist/interfaces/Notifier.js +2 -0
- package/dist/interfaces/Notifier.js.map +1 -0
- package/dist/interfaces/RepoBackend.d.ts +23 -0
- package/dist/interfaces/RepoBackend.d.ts.map +1 -0
- package/dist/interfaces/RepoBackend.js +2 -0
- package/dist/interfaces/RepoBackend.js.map +1 -0
- package/dist/interfaces/TaskBackend.d.ts +24 -0
- package/dist/interfaces/TaskBackend.d.ts.map +1 -0
- package/dist/interfaces/TaskBackend.js +2 -0
- package/dist/interfaces/TaskBackend.js.map +1 -0
- package/dist/interfaces/WorkerProvider.d.ts +23 -0
- package/dist/interfaces/WorkerProvider.d.ts.map +1 -0
- package/dist/interfaces/WorkerProvider.js +2 -0
- package/dist/interfaces/WorkerProvider.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +226 -0
- package/dist/main.js.map +1 -0
- package/dist/models/types.d.ts +68 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +2 -0
- package/dist/models/types.js.map +1 -0
- package/dist/providers/ClaudeWorkerProvider.d.ts +84 -0
- package/dist/providers/ClaudeWorkerProvider.d.ts.map +1 -0
- package/dist/providers/ClaudeWorkerProvider.js +293 -0
- package/dist/providers/ClaudeWorkerProvider.js.map +1 -0
- package/dist/providers/CodexWorkerProvider.d.ts +50 -0
- package/dist/providers/CodexWorkerProvider.d.ts.map +1 -0
- package/dist/providers/CodexWorkerProvider.js +275 -0
- package/dist/providers/CodexWorkerProvider.js.map +1 -0
- package/dist/providers/GitLabRepoBackend.d.ts +42 -0
- package/dist/providers/GitLabRepoBackend.d.ts.map +1 -0
- package/dist/providers/GitLabRepoBackend.js +280 -0
- package/dist/providers/GitLabRepoBackend.js.map +1 -0
- package/dist/providers/MarkdownTaskBackend.d.ts +88 -0
- package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -0
- package/dist/providers/MarkdownTaskBackend.js +414 -0
- package/dist/providers/MarkdownTaskBackend.js.map +1 -0
- package/dist/providers/MatrixNotifier.d.ts +30 -0
- package/dist/providers/MatrixNotifier.d.ts.map +1 -0
- package/dist/providers/MatrixNotifier.js +82 -0
- package/dist/providers/MatrixNotifier.js.map +1 -0
- package/dist/providers/PlaneTaskBackend.d.ts +86 -0
- package/dist/providers/PlaneTaskBackend.d.ts.map +1 -0
- package/dist/providers/PlaneTaskBackend.js +409 -0
- package/dist/providers/PlaneTaskBackend.js.map +1 -0
- package/dist/providers/TrelloTaskBackend.d.ts +53 -0
- package/dist/providers/TrelloTaskBackend.d.ts.map +1 -0
- package/dist/providers/TrelloTaskBackend.js +300 -0
- package/dist/providers/TrelloTaskBackend.js.map +1 -0
- package/dist/providers/registry.d.ts +10 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +29 -0
- package/dist/providers/registry.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** Unified card representation across PM backends */
|
|
2
|
+
export interface Card {
|
|
3
|
+
id: string;
|
|
4
|
+
seq: string;
|
|
5
|
+
name: string;
|
|
6
|
+
desc: string;
|
|
7
|
+
state: CardState;
|
|
8
|
+
labels: string[];
|
|
9
|
+
meta: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export type CardState = 'Planning' | 'Backlog' | 'Todo' | 'Inprogress' | 'QA' | 'Done';
|
|
12
|
+
export type AuxiliaryState = 'BLOCKED' | 'NEEDS-FIX' | 'WAITING-CONFIRMATION' | 'CONFLICT' | 'STALE-RUNTIME';
|
|
13
|
+
/** Worker detection result */
|
|
14
|
+
export type WorkerStatus = 'ALIVE' | 'COMPLETED' | 'NEEDS_INPUT' | 'AUTO_CONFIRM' | 'BLOCKED' | 'DEAD' | 'DEAD_EXCEEDED';
|
|
15
|
+
/** MR status from repo backend */
|
|
16
|
+
export interface MrStatus {
|
|
17
|
+
exists: boolean;
|
|
18
|
+
state: 'opened' | 'merged' | 'closed' | 'not_found';
|
|
19
|
+
ciStatus: 'success' | 'failed' | 'running' | 'pending' | 'created' | 'unknown';
|
|
20
|
+
mergeStatus: 'can_be_merged' | 'cannot_be_merged' | 'checking' | 'unknown';
|
|
21
|
+
url: string | null;
|
|
22
|
+
iid: number | null;
|
|
23
|
+
}
|
|
24
|
+
/** Result from a tick step or command */
|
|
25
|
+
export interface CommandResult {
|
|
26
|
+
project: string;
|
|
27
|
+
component: string;
|
|
28
|
+
status: 'ok' | 'fail' | 'degraded' | 'skipped';
|
|
29
|
+
exitCode: number;
|
|
30
|
+
actions: ActionRecord[];
|
|
31
|
+
recommendedActions: RecommendedAction[];
|
|
32
|
+
details: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
export interface ActionRecord {
|
|
35
|
+
action: string;
|
|
36
|
+
entity: string;
|
|
37
|
+
result: 'ok' | 'fail' | 'skip';
|
|
38
|
+
message?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Tick aggregated result */
|
|
41
|
+
export interface TickResult extends CommandResult {
|
|
42
|
+
steps: StepResult[];
|
|
43
|
+
}
|
|
44
|
+
export interface StepResult {
|
|
45
|
+
step: string;
|
|
46
|
+
status: 'ok' | 'fail' | 'degraded' | 'skipped';
|
|
47
|
+
exitCode: number;
|
|
48
|
+
error?: string;
|
|
49
|
+
note?: string;
|
|
50
|
+
actions?: ActionRecord[];
|
|
51
|
+
checks?: CheckResult[];
|
|
52
|
+
}
|
|
53
|
+
/** recommendedActions protocol (03 §8.4) */
|
|
54
|
+
export interface RecommendedAction {
|
|
55
|
+
action: string;
|
|
56
|
+
reason: string;
|
|
57
|
+
severity: 'info' | 'warning' | 'critical';
|
|
58
|
+
autoExecutable: boolean;
|
|
59
|
+
requiresConfirmation: boolean;
|
|
60
|
+
safeToRetry: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** Doctor check result */
|
|
63
|
+
export interface CheckResult {
|
|
64
|
+
name: string;
|
|
65
|
+
status: 'pass' | 'fail' | 'warn' | 'skip';
|
|
66
|
+
message: string;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvF,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,sBAAsB,GAAG,UAAU,GAAG,eAAe,CAAC;AAE7G,8BAA8B;AAC9B,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,WAAW,GACX,aAAa,GACb,cAAc,GACd,SAAS,GACT,MAAM,GACN,eAAe,CAAC;AAEpB,kCAAkC;AAClC,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IACpD,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC/E,WAAW,EAAE,eAAe,GAAG,kBAAkB,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3E,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6BAA6B;AAC7B,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAC1C,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,0BAA0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ProjectConfig } from '../core/config.js';
|
|
2
|
+
import type { WorkerProvider } from '../interfaces/WorkerProvider.js';
|
|
3
|
+
import type { WorkerStatus } from '../models/types.js';
|
|
4
|
+
export declare class ClaudeWorkerProvider implements WorkerProvider {
|
|
5
|
+
private readonly config;
|
|
6
|
+
constructor(config: ProjectConfig);
|
|
7
|
+
/**
|
|
8
|
+
* Ensure worktree directory exists and is clean.
|
|
9
|
+
* This is largely a no-op when the worktree is already prepared.
|
|
10
|
+
*/
|
|
11
|
+
prepareEnv(worktree: string, _seq: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Launch a Claude Code worker inside a tmux session.
|
|
14
|
+
*
|
|
15
|
+
* Session reuse strategy (WORKER_SESSION_REUSE=true):
|
|
16
|
+
* 1. Session exists + Claude running → reuse: /clear + cd worktree (keep context hot)
|
|
17
|
+
* 2. Session exists + Claude not running → reuse session: cd + start claude
|
|
18
|
+
* 3. No session → create new session + start claude
|
|
19
|
+
*/
|
|
20
|
+
launch(session: string, worktree: string): Promise<void>;
|
|
21
|
+
private log;
|
|
22
|
+
/**
|
|
23
|
+
* Poll tmux pane text until Claude's ready prompt appears.
|
|
24
|
+
* Default timeout: 30 seconds, poll interval: 2 seconds.
|
|
25
|
+
*/
|
|
26
|
+
waitReady(session: string, timeoutMs?: number): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Send a task prompt file to the Claude session.
|
|
29
|
+
*/
|
|
30
|
+
sendTask(session: string, promptFile: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Inspect a tmux session: check if alive and capture pane text.
|
|
33
|
+
*/
|
|
34
|
+
inspect(session: string): Promise<{
|
|
35
|
+
alive: boolean;
|
|
36
|
+
paneText: string;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Multi-layer completion detection chain.
|
|
40
|
+
*
|
|
41
|
+
* Priority order:
|
|
42
|
+
* 1. task_completed marker file in logDir
|
|
43
|
+
* 2. Waiting for confirmation prompts (delegates to detectWaiting)
|
|
44
|
+
* 3. Completion keywords in pane text
|
|
45
|
+
* 4. MR exists on GitLab (skipped — returns ALIVE)
|
|
46
|
+
* 5. tmux session alive → ALIVE
|
|
47
|
+
* 6. Session dead + restart limit exceeded → DEAD_EXCEEDED
|
|
48
|
+
*/
|
|
49
|
+
detectCompleted(session: string, logDir: string, _branch: string): Promise<WorkerStatus>;
|
|
50
|
+
/**
|
|
51
|
+
* Detect whether the worker is waiting for user confirmation.
|
|
52
|
+
* Returns whether the prompt is destructive (delete/remove/drop etc.).
|
|
53
|
+
*/
|
|
54
|
+
detectWaiting(session: string): Promise<{
|
|
55
|
+
waiting: boolean;
|
|
56
|
+
destructive: boolean;
|
|
57
|
+
prompt: string;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Check pane text for blocked indicators (errors, stuck states).
|
|
61
|
+
*/
|
|
62
|
+
detectBlocked(session: string): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Send a fix prompt to the Claude session (e.g. after CI failure).
|
|
65
|
+
*/
|
|
66
|
+
sendFix(session: string, fixPrompt: string): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Send conflict resolution instructions to the Claude session.
|
|
69
|
+
*/
|
|
70
|
+
resolveConflict(session: string, worktree: string, branch: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Stop the worker session.
|
|
73
|
+
* If WORKER_SESSION_REUSE is enabled, keep the session alive (just exit Claude).
|
|
74
|
+
* Otherwise, kill the entire tmux session.
|
|
75
|
+
*/
|
|
76
|
+
stop(session: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Capture the last 100 lines of pane text as a summary.
|
|
79
|
+
*/
|
|
80
|
+
collectSummary(session: string): Promise<string>;
|
|
81
|
+
/** Helper: sleep for the given milliseconds. */
|
|
82
|
+
private sleep;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=ClaudeWorkerProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeWorkerProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ClaudeWorkerProvider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA6DvD,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,MAAM,EAAE,aAAa;IAIjC;;;OAGG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/D;;;;;;;OAOG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkC9D,OAAO,CAAC,GAAG,CAAwE;IAEnF;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BtE;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlE;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAM7E;;;;;;;;;;OAUG;IACG,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC;IAkCxB;;;OAGG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAiBtE;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKtD;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAchB;;;;OAIG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1C;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItD,gDAAgD;IAChD,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
/** Completion keywords detected in pane text (priority 3). */
|
|
4
|
+
const COMPLETION_KEYWORDS = /\b(done|完成|全部完成|MR created|merge request|已提交|已推送)\b|🎉/i;
|
|
5
|
+
/** Confirmation prompt patterns (priority 2 / detectWaiting). */
|
|
6
|
+
const CONFIRMATION_PROMPT = /(Do you want to proceed|y\/n|press enter|confirm|approve)/i;
|
|
7
|
+
/** Destructive operation indicators. */
|
|
8
|
+
const DESTRUCTIVE_PATTERN = /(delete|remove|drop|rm -rf|truncate|destroy)/i;
|
|
9
|
+
/** Blocked indicators in pane text. */
|
|
10
|
+
const BLOCKED_PATTERN = /(error|fatal|panic|BLOCKED|stuck|cannot proceed|timed out|rate.?limit)/i;
|
|
11
|
+
/**
|
|
12
|
+
* Run a tmux command via execFileSync and return stdout.
|
|
13
|
+
* Returns null when the command fails (e.g. session does not exist).
|
|
14
|
+
* On "server exited unexpectedly", auto-cleans stale socket and retries once.
|
|
15
|
+
*/
|
|
16
|
+
function tmux(args) {
|
|
17
|
+
try {
|
|
18
|
+
return execFileSync('tmux', args, {
|
|
19
|
+
encoding: 'utf-8',
|
|
20
|
+
timeout: 10_000,
|
|
21
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const stderr = err.stderr ?? '';
|
|
26
|
+
if (stderr.includes('server exited unexpectedly') || stderr.includes('no server running')) {
|
|
27
|
+
// Stale tmux socket — clean up and retry
|
|
28
|
+
try {
|
|
29
|
+
const uid = process.getuid?.() ?? 1000;
|
|
30
|
+
const { rmSync } = require('node:fs');
|
|
31
|
+
rmSync(`/tmp/tmux-${uid}`, { recursive: true, force: true });
|
|
32
|
+
process.stderr.write('[worker] Cleaned stale tmux socket, retrying\n');
|
|
33
|
+
return execFileSync('tmux', args, {
|
|
34
|
+
encoding: 'utf-8',
|
|
35
|
+
timeout: 10_000,
|
|
36
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Check whether a tmux session exists. */
|
|
47
|
+
function sessionExists(session) {
|
|
48
|
+
return tmux(['has-session', '-t', session]) !== null;
|
|
49
|
+
}
|
|
50
|
+
/** Capture recent pane text from a tmux session. */
|
|
51
|
+
function capturePaneText(session, lines) {
|
|
52
|
+
return tmux(['capture-pane', '-t', session, '-p', '-S', `-${lines}`]) ?? '';
|
|
53
|
+
}
|
|
54
|
+
export class ClaudeWorkerProvider {
|
|
55
|
+
config;
|
|
56
|
+
constructor(config) {
|
|
57
|
+
this.config = config;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Ensure worktree directory exists and is clean.
|
|
61
|
+
* This is largely a no-op when the worktree is already prepared.
|
|
62
|
+
*/
|
|
63
|
+
async prepareEnv(worktree, _seq) {
|
|
64
|
+
if (!existsSync(worktree)) {
|
|
65
|
+
throw new Error(`Worktree directory does not exist: ${worktree}`);
|
|
66
|
+
}
|
|
67
|
+
// Verify the directory is a git worktree / repo
|
|
68
|
+
try {
|
|
69
|
+
execFileSync('git', ['-C', worktree, 'rev-parse', '--is-inside-work-tree'], {
|
|
70
|
+
encoding: 'utf-8',
|
|
71
|
+
timeout: 5_000,
|
|
72
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
throw new Error(`Directory is not a git worktree: ${worktree}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Launch a Claude Code worker inside a tmux session.
|
|
81
|
+
*
|
|
82
|
+
* Session reuse strategy (WORKER_SESSION_REUSE=true):
|
|
83
|
+
* 1. Session exists + Claude running → reuse: /clear + cd worktree (keep context hot)
|
|
84
|
+
* 2. Session exists + Claude not running → reuse session: cd + start claude
|
|
85
|
+
* 3. No session → create new session + start claude
|
|
86
|
+
*/
|
|
87
|
+
async launch(session, worktree) {
|
|
88
|
+
const claudeCmd = 'claude --dangerously-skip-permissions';
|
|
89
|
+
if (sessionExists(session)) {
|
|
90
|
+
const pane = capturePaneText(session, 10);
|
|
91
|
+
const claudeAlive = /❯\s*$/m.test(pane) || /bypass permissions/i.test(pane) || /shortcuts/i.test(pane);
|
|
92
|
+
if (claudeAlive) {
|
|
93
|
+
// Claude is running — reuse instance: clear conversation + switch worktree
|
|
94
|
+
this.log.info(`Reusing live Claude session ${session}`);
|
|
95
|
+
tmux(['send-keys', '-t', session, '/clear', 'Enter']);
|
|
96
|
+
await this.sleep(1_000);
|
|
97
|
+
tmux(['send-keys', '-t', session, `cd ${worktree}`, 'Enter']);
|
|
98
|
+
await this.sleep(500);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Session exists but Claude not running — cd and start claude
|
|
102
|
+
this.log.info(`Reusing tmux session ${session} (Claude not running)`);
|
|
103
|
+
tmux(['send-keys', '-t', session, `cd ${worktree}`, 'Enter']);
|
|
104
|
+
await this.sleep(500);
|
|
105
|
+
tmux(['send-keys', '-t', session, claudeCmd, 'Enter']);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// No session — create new
|
|
109
|
+
const result = tmux(['new-session', '-d', '-s', session, '-c', worktree]);
|
|
110
|
+
if (result === null && !sessionExists(session)) {
|
|
111
|
+
throw new Error(`Failed to create tmux session: ${session}`);
|
|
112
|
+
}
|
|
113
|
+
tmux(['send-keys', '-t', session, claudeCmd, 'Enter']);
|
|
114
|
+
}
|
|
115
|
+
log = { info: (msg) => process.stderr.write(`[worker] ${msg}\n`) };
|
|
116
|
+
/**
|
|
117
|
+
* Poll tmux pane text until Claude's ready prompt appears.
|
|
118
|
+
* Default timeout: 30 seconds, poll interval: 2 seconds.
|
|
119
|
+
*/
|
|
120
|
+
async waitReady(session, timeoutMs = 30_000) {
|
|
121
|
+
const pollInterval = 2_000;
|
|
122
|
+
const deadline = Date.now() + timeoutMs;
|
|
123
|
+
// Wait at least 3s for Claude to start loading before polling
|
|
124
|
+
await this.sleep(3_000);
|
|
125
|
+
while (Date.now() < deadline) {
|
|
126
|
+
const text = capturePaneText(session, 15);
|
|
127
|
+
// Match Claude Code's actual ready state:
|
|
128
|
+
// - The ❯ prompt on its own line (Claude's input prompt)
|
|
129
|
+
// - "bypass permissions" indicator (only appears after Claude is fully loaded)
|
|
130
|
+
// - "? for shortcuts" (appears at bottom when ready)
|
|
131
|
+
if (/bypass permissions/i.test(text) ||
|
|
132
|
+
/\? for shortcuts/i.test(text) ||
|
|
133
|
+
/tips for shortcuts/i.test(text)) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// Also match the ❯ prompt but only if Claude banner has appeared
|
|
137
|
+
if (/Claude Code/i.test(text) && /❯\s*$/m.test(text)) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
await this.sleep(pollInterval);
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Send a task prompt file to the Claude session.
|
|
146
|
+
*/
|
|
147
|
+
async sendTask(session, promptFile) {
|
|
148
|
+
if (!existsSync(promptFile)) {
|
|
149
|
+
throw new Error(`Prompt file does not exist: ${promptFile}`);
|
|
150
|
+
}
|
|
151
|
+
// Write prompt content to a temp file, load into tmux buffer, paste, then Enter.
|
|
152
|
+
const content = readFileSync(promptFile, 'utf-8').trim();
|
|
153
|
+
const bufferFile = `/tmp/sps-task-${Date.now()}.txt`;
|
|
154
|
+
const { writeFileSync: writeTmp, unlinkSync } = await import('node:fs');
|
|
155
|
+
writeTmp(bufferFile, content);
|
|
156
|
+
tmux(['load-buffer', bufferFile]);
|
|
157
|
+
tmux(['paste-buffer', '-t', session]);
|
|
158
|
+
try {
|
|
159
|
+
unlinkSync(bufferFile);
|
|
160
|
+
}
|
|
161
|
+
catch { /* cleanup */ }
|
|
162
|
+
// Small delay to let paste complete before sending Enter
|
|
163
|
+
await this.sleep(500);
|
|
164
|
+
tmux(['send-keys', '-t', session, 'Enter']);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Inspect a tmux session: check if alive and capture pane text.
|
|
168
|
+
*/
|
|
169
|
+
async inspect(session) {
|
|
170
|
+
const alive = sessionExists(session);
|
|
171
|
+
const paneText = alive ? capturePaneText(session, 50) : '';
|
|
172
|
+
return { alive, paneText };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Multi-layer completion detection chain.
|
|
176
|
+
*
|
|
177
|
+
* Priority order:
|
|
178
|
+
* 1. task_completed marker file in logDir
|
|
179
|
+
* 2. Waiting for confirmation prompts (delegates to detectWaiting)
|
|
180
|
+
* 3. Completion keywords in pane text
|
|
181
|
+
* 4. MR exists on GitLab (skipped — returns ALIVE)
|
|
182
|
+
* 5. tmux session alive → ALIVE
|
|
183
|
+
* 6. Session dead + restart limit exceeded → DEAD_EXCEEDED
|
|
184
|
+
*/
|
|
185
|
+
async detectCompleted(session, logDir, _branch) {
|
|
186
|
+
// Priority 1: task_completed marker file
|
|
187
|
+
const markerPath = `${logDir}/task_completed`;
|
|
188
|
+
if (existsSync(markerPath)) {
|
|
189
|
+
return 'COMPLETED';
|
|
190
|
+
}
|
|
191
|
+
// Priority 2: waiting for confirmation
|
|
192
|
+
const waitState = await this.detectWaiting(session);
|
|
193
|
+
if (waitState.waiting) {
|
|
194
|
+
return waitState.destructive ? 'NEEDS_INPUT' : 'AUTO_CONFIRM';
|
|
195
|
+
}
|
|
196
|
+
// Priority 3: completion keywords in pane text
|
|
197
|
+
const paneText = capturePaneText(session, 50);
|
|
198
|
+
if (COMPLETION_KEYWORDS.test(paneText)) {
|
|
199
|
+
return 'COMPLETED';
|
|
200
|
+
}
|
|
201
|
+
// Priority 4: MR exists (skipped for now)
|
|
202
|
+
// Priority 5: session alive
|
|
203
|
+
if (sessionExists(session)) {
|
|
204
|
+
return 'ALIVE';
|
|
205
|
+
}
|
|
206
|
+
// Priority 6: session dead — check restart limit
|
|
207
|
+
// The restart count is tracked externally by the engine via state.json.
|
|
208
|
+
// Here we simply report DEAD_EXCEEDED vs DEAD so the engine can decide.
|
|
209
|
+
// Without access to the restart counter, report DEAD and let the caller
|
|
210
|
+
// escalate to DEAD_EXCEEDED if the limit is reached.
|
|
211
|
+
return 'DEAD';
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Detect whether the worker is waiting for user confirmation.
|
|
215
|
+
* Returns whether the prompt is destructive (delete/remove/drop etc.).
|
|
216
|
+
*/
|
|
217
|
+
async detectWaiting(session) {
|
|
218
|
+
const paneText = capturePaneText(session, 30);
|
|
219
|
+
const match = paneText.match(CONFIRMATION_PROMPT);
|
|
220
|
+
if (!match) {
|
|
221
|
+
return { waiting: false, destructive: false, prompt: '' };
|
|
222
|
+
}
|
|
223
|
+
// Extract the line containing the prompt for context
|
|
224
|
+
const lines = paneText.split('\n');
|
|
225
|
+
const promptLine = lines.find((l) => CONFIRMATION_PROMPT.test(l))?.trim() ?? match[0];
|
|
226
|
+
const destructive = DESTRUCTIVE_PATTERN.test(paneText);
|
|
227
|
+
return { waiting: true, destructive, prompt: promptLine };
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Check pane text for blocked indicators (errors, stuck states).
|
|
231
|
+
*/
|
|
232
|
+
async detectBlocked(session) {
|
|
233
|
+
const paneText = capturePaneText(session, 30);
|
|
234
|
+
return BLOCKED_PATTERN.test(paneText);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Send a fix prompt to the Claude session (e.g. after CI failure).
|
|
238
|
+
*/
|
|
239
|
+
async sendFix(session, fixPrompt) {
|
|
240
|
+
// Escape any single quotes in the prompt for safe tmux transmission
|
|
241
|
+
const escaped = fixPrompt.replace(/'/g, "'\\''");
|
|
242
|
+
tmux(['send-keys', '-t', session, escaped, 'Enter']);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Send conflict resolution instructions to the Claude session.
|
|
246
|
+
*/
|
|
247
|
+
async resolveConflict(session, worktree, branch) {
|
|
248
|
+
const instruction = [
|
|
249
|
+
`There is a merge conflict on branch ${branch}.`,
|
|
250
|
+
`Working directory: ${worktree}`,
|
|
251
|
+
'Please resolve the conflict:',
|
|
252
|
+
`1. Run: git fetch origin && git rebase origin/${this.config.GITLAB_MERGE_BRANCH}`,
|
|
253
|
+
'2. Resolve any conflicts in the affected files',
|
|
254
|
+
'3. Run: git add . && git rebase --continue',
|
|
255
|
+
'4. Run: git push --force-with-lease',
|
|
256
|
+
].join('\n');
|
|
257
|
+
tmux(['send-keys', '-t', session, instruction, 'Enter']);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Stop the worker session.
|
|
261
|
+
* If WORKER_SESSION_REUSE is enabled, keep the session alive (just exit Claude).
|
|
262
|
+
* Otherwise, kill the entire tmux session.
|
|
263
|
+
*/
|
|
264
|
+
async stop(session) {
|
|
265
|
+
if (!sessionExists(session))
|
|
266
|
+
return;
|
|
267
|
+
if (this.config.WORKER_SESSION_REUSE) {
|
|
268
|
+
// Keep session alive — just exit Claude, leave tmux running
|
|
269
|
+
tmux(['send-keys', '-t', session, '/exit', 'Enter']);
|
|
270
|
+
// Don't force kill — session will be reused
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
// Full stop: exit Claude then kill session
|
|
274
|
+
tmux(['send-keys', '-t', session, '/exit', 'Enter']);
|
|
275
|
+
for (let i = 0; i < 5; i++) {
|
|
276
|
+
await this.sleep(1_000);
|
|
277
|
+
if (!sessionExists(session))
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
tmux(['kill-session', '-t', session]);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Capture the last 100 lines of pane text as a summary.
|
|
284
|
+
*/
|
|
285
|
+
async collectSummary(session) {
|
|
286
|
+
return capturePaneText(session, 100);
|
|
287
|
+
}
|
|
288
|
+
/** Helper: sleep for the given milliseconds. */
|
|
289
|
+
sleep(ms) {
|
|
290
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=ClaudeWorkerProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeWorkerProvider.js","sourceRoot":"","sources":["../../src/providers/ClaudeWorkerProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ProjectConfig } from '../core/config.js';
|
|
2
|
+
import type { WorkerProvider } from '../interfaces/WorkerProvider.js';
|
|
3
|
+
import type { WorkerStatus } from '../models/types.js';
|
|
4
|
+
export declare class CodexWorkerProvider implements WorkerProvider {
|
|
5
|
+
private readonly config;
|
|
6
|
+
constructor(config: ProjectConfig);
|
|
7
|
+
prepareEnv(worktree: string, _seq: string): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Launch Codex in a tmux session (interactive mode).
|
|
10
|
+
* Handles session reuse and update prompt auto-skip.
|
|
11
|
+
*/
|
|
12
|
+
launch(session: string, worktree: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Wait for Codex to be ready.
|
|
15
|
+
* Must handle the update prompt blocker (auto-skip).
|
|
16
|
+
*/
|
|
17
|
+
waitReady(session: string, timeoutMs?: number): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Send task prompt to Codex via tmux paste-buffer.
|
|
20
|
+
*/
|
|
21
|
+
sendTask(session: string, promptFile: string): Promise<void>;
|
|
22
|
+
inspect(session: string): Promise<{
|
|
23
|
+
alive: boolean;
|
|
24
|
+
paneText: string;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Codex with --dangerously-bypass-approvals-and-sandbox doesn't need confirmation.
|
|
28
|
+
* But if run without that flag, it may show approval prompts.
|
|
29
|
+
* For now, always return not waiting since we use bypass mode.
|
|
30
|
+
*/
|
|
31
|
+
detectWaiting(session: string): Promise<{
|
|
32
|
+
waiting: boolean;
|
|
33
|
+
destructive: boolean;
|
|
34
|
+
prompt: string;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Detect completion by checking if Codex returned to › prompt after working.
|
|
38
|
+
*/
|
|
39
|
+
detectCompleted(session: string, logDir: string, _branch: string): Promise<WorkerStatus>;
|
|
40
|
+
detectBlocked(session: string): Promise<boolean>;
|
|
41
|
+
sendFix(session: string, fixPrompt: string): Promise<void>;
|
|
42
|
+
resolveConflict(session: string, worktree: string, branch: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Stop Codex. Uses /quit (Codex's exit command, not /exit like Claude).
|
|
45
|
+
*/
|
|
46
|
+
stop(session: string): Promise<void>;
|
|
47
|
+
collectSummary(session: string): Promise<string>;
|
|
48
|
+
private sleep;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=CodexWorkerProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodexWorkerProvider.d.ts","sourceRoot":"","sources":["../../src/providers/CodexWorkerProvider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAuEvD,qBAAa,mBAAoB,YAAW,cAAc;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,MAAM,EAAE,aAAa;IAI3B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa/D;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkC9D;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAqDtE;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAM7E;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAazG;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC;IA0BlB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKhD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAavF;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItD,OAAO,CAAC,KAAK;CAGd"}
|