codekin 0.4.0 → 0.5.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/README.md +12 -15
- package/bin/codekin.mjs +52 -32
- package/dist/assets/index-BwKZeT4V.css +1 -0
- package/dist/assets/index-CfBnNU24.js +186 -0
- package/dist/index.html +2 -2
- package/package.json +2 -7
- package/server/dist/approval-manager.d.ts +7 -2
- package/server/dist/approval-manager.js +45 -79
- package/server/dist/approval-manager.js.map +1 -1
- package/server/dist/claude-process.d.ts +23 -3
- package/server/dist/claude-process.js +123 -23
- package/server/dist/claude-process.js.map +1 -1
- package/server/dist/commit-event-handler.js.map +1 -1
- package/server/dist/config.d.ts +4 -0
- package/server/dist/config.js +17 -0
- package/server/dist/config.js.map +1 -1
- package/server/dist/diff-manager.d.ts +41 -0
- package/server/dist/diff-manager.js +303 -0
- package/server/dist/diff-manager.js.map +1 -0
- package/server/dist/diff-parser.js +8 -2
- package/server/dist/diff-parser.js.map +1 -1
- package/server/dist/error-page.d.ts +5 -0
- package/server/dist/error-page.js +144 -0
- package/server/dist/error-page.js.map +1 -0
- package/server/dist/native-permissions.d.ts +44 -0
- package/server/dist/native-permissions.js +163 -0
- package/server/dist/native-permissions.js.map +1 -0
- package/server/dist/orchestrator-children.d.ts +74 -0
- package/server/dist/orchestrator-children.js +281 -0
- package/server/dist/orchestrator-children.js.map +1 -0
- package/server/dist/orchestrator-learning.d.ts +134 -0
- package/server/dist/orchestrator-learning.js +567 -0
- package/server/dist/orchestrator-learning.js.map +1 -0
- package/server/dist/orchestrator-manager.d.ts +25 -0
- package/server/dist/orchestrator-manager.js +353 -0
- package/server/dist/orchestrator-manager.js.map +1 -0
- package/server/dist/orchestrator-memory.d.ts +77 -0
- package/server/dist/orchestrator-memory.js +288 -0
- package/server/dist/orchestrator-memory.js.map +1 -0
- package/server/dist/orchestrator-monitor.d.ts +59 -0
- package/server/dist/orchestrator-monitor.js +238 -0
- package/server/dist/orchestrator-monitor.js.map +1 -0
- package/server/dist/orchestrator-reports.d.ts +45 -0
- package/server/dist/orchestrator-reports.js +124 -0
- package/server/dist/orchestrator-reports.js.map +1 -0
- package/server/dist/orchestrator-routes.d.ts +17 -0
- package/server/dist/orchestrator-routes.js +526 -0
- package/server/dist/orchestrator-routes.js.map +1 -0
- package/server/dist/session-archive.js +9 -2
- package/server/dist/session-archive.js.map +1 -1
- package/server/dist/session-manager.d.ts +101 -39
- package/server/dist/session-manager.js +573 -397
- package/server/dist/session-manager.js.map +1 -1
- package/server/dist/session-naming.d.ts +6 -10
- package/server/dist/session-naming.js +60 -62
- package/server/dist/session-naming.js.map +1 -1
- package/server/dist/session-persistence.d.ts +6 -1
- package/server/dist/session-persistence.js +6 -0
- package/server/dist/session-persistence.js.map +1 -1
- package/server/dist/session-restart-scheduler.d.ts +30 -0
- package/server/dist/session-restart-scheduler.js +41 -0
- package/server/dist/session-restart-scheduler.js.map +1 -0
- package/server/dist/session-routes.js +127 -58
- package/server/dist/session-routes.js.map +1 -1
- package/server/dist/stepflow-types.d.ts +1 -1
- package/server/dist/tsconfig.tsbuildinfo +1 -1
- package/server/dist/types.d.ts +34 -2
- package/server/dist/types.js +8 -1
- package/server/dist/types.js.map +1 -1
- package/server/dist/upload-routes.js +13 -4
- package/server/dist/upload-routes.js.map +1 -1
- package/server/dist/version-check.d.ts +17 -0
- package/server/dist/version-check.js +89 -0
- package/server/dist/version-check.js.map +1 -0
- package/server/dist/workflow-engine.d.ts +74 -1
- package/server/dist/workflow-engine.js +20 -1
- package/server/dist/workflow-engine.js.map +1 -1
- package/server/dist/ws-message-handler.js +115 -9
- package/server/dist/ws-message-handler.js.map +1 -1
- package/server/dist/ws-server.js +90 -15
- package/server/dist/ws-server.js.map +1 -1
- package/dist/assets/index-BAdQqYEY.js +0 -182
- package/dist/assets/index-CeZYNLWt.css +0 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native permissions utility for Codekin.
|
|
3
|
+
*
|
|
4
|
+
* Reads/writes `.claude/settings.local.json` in the project directory so that
|
|
5
|
+
* Claude Code's native permission system remembers approvals across sessions
|
|
6
|
+
* without re-prompting.
|
|
7
|
+
*
|
|
8
|
+
* Also converts Codekin's approval registry into `--allowedTools` patterns
|
|
9
|
+
* for passing at spawn time.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
/** In-process mutex map keyed by repo path to prevent concurrent write races. */
|
|
14
|
+
const writeLocks = new Map();
|
|
15
|
+
/** Acquire a per-repo write lock. All sessions share one Node process. */
|
|
16
|
+
function withLock(repoDir, fn) {
|
|
17
|
+
const prev = writeLocks.get(repoDir) ?? Promise.resolve();
|
|
18
|
+
const next = prev.then(fn, fn);
|
|
19
|
+
writeLocks.set(repoDir, next);
|
|
20
|
+
// Clean up the reference once done so we don't leak memory
|
|
21
|
+
void next.then(() => {
|
|
22
|
+
if (writeLocks.get(repoDir) === next)
|
|
23
|
+
writeLocks.delete(repoDir);
|
|
24
|
+
});
|
|
25
|
+
return next;
|
|
26
|
+
}
|
|
27
|
+
function settingsPath(repoDir) {
|
|
28
|
+
return join(repoDir, '.claude', 'settings.local.json');
|
|
29
|
+
}
|
|
30
|
+
/** Read existing native permissions from `.claude/settings.local.json`. */
|
|
31
|
+
export function readNativePermissions(repoDir) {
|
|
32
|
+
const filePath = settingsPath(repoDir);
|
|
33
|
+
if (!existsSync(filePath))
|
|
34
|
+
return [];
|
|
35
|
+
try {
|
|
36
|
+
const data = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
37
|
+
return data.permissions?.allow ?? [];
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Add a native permission to `.claude/settings.local.json` (append-only, atomic write). */
|
|
44
|
+
export async function addNativePermission(repoDir, permission) {
|
|
45
|
+
await withLock(repoDir, async () => {
|
|
46
|
+
const filePath = settingsPath(repoDir);
|
|
47
|
+
const dir = join(repoDir, '.claude');
|
|
48
|
+
let settings = {};
|
|
49
|
+
if (existsSync(filePath)) {
|
|
50
|
+
try {
|
|
51
|
+
settings = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Corrupted file — start fresh but preserve structure
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!settings.permissions)
|
|
58
|
+
settings.permissions = {};
|
|
59
|
+
if (!settings.permissions.allow)
|
|
60
|
+
settings.permissions.allow = [];
|
|
61
|
+
// Don't add duplicates
|
|
62
|
+
if (settings.permissions.allow.includes(permission))
|
|
63
|
+
return;
|
|
64
|
+
settings.permissions.allow.push(permission);
|
|
65
|
+
mkdirSync(dir, { recursive: true });
|
|
66
|
+
const tmp = filePath + '.tmp';
|
|
67
|
+
writeFileSync(tmp, JSON.stringify(settings, null, 2) + '\n', { mode: 0o600 });
|
|
68
|
+
renameSync(tmp, filePath);
|
|
69
|
+
console.log(`[native-permissions] added "${permission}" to ${filePath}`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** Remove a native permission from `.claude/settings.local.json`. */
|
|
73
|
+
export async function removeNativePermission(repoDir, permission) {
|
|
74
|
+
await withLock(repoDir, async () => {
|
|
75
|
+
const filePath = settingsPath(repoDir);
|
|
76
|
+
if (!existsSync(filePath))
|
|
77
|
+
return;
|
|
78
|
+
let settings = {};
|
|
79
|
+
try {
|
|
80
|
+
settings = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const allow = settings.permissions?.allow;
|
|
86
|
+
if (!allow)
|
|
87
|
+
return;
|
|
88
|
+
const idx = allow.indexOf(permission);
|
|
89
|
+
if (idx === -1)
|
|
90
|
+
return;
|
|
91
|
+
allow.splice(idx, 1);
|
|
92
|
+
const tmp = filePath + '.tmp';
|
|
93
|
+
writeFileSync(tmp, JSON.stringify(settings, null, 2) + '\n', { mode: 0o600 });
|
|
94
|
+
renameSync(tmp, filePath);
|
|
95
|
+
console.log(`[native-permissions] removed "${permission}" from ${filePath}`);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Convert a tool invocation to Claude Code's native permission format.
|
|
100
|
+
*
|
|
101
|
+
* Examples:
|
|
102
|
+
* - Bash + `{ command: "npm run build" }` → `"Bash(npm run build)"`
|
|
103
|
+
* - WebFetch (any input) → `"WebFetch"`
|
|
104
|
+
* - Read (file tool, pre-approved) → `null`
|
|
105
|
+
*/
|
|
106
|
+
export function toNativePermission(toolName, toolInput) {
|
|
107
|
+
// File tools are pre-approved by permission mode — no need to persist
|
|
108
|
+
const preApproved = new Set(['Read', 'Write', 'Edit', 'Glob', 'Grep', 'NotebookEdit']);
|
|
109
|
+
if (preApproved.has(toolName))
|
|
110
|
+
return null;
|
|
111
|
+
if (toolName === 'Bash') {
|
|
112
|
+
const cmd = (typeof toolInput.command === 'string' ? toolInput.command : '').trim();
|
|
113
|
+
if (!cmd)
|
|
114
|
+
return null;
|
|
115
|
+
return `Bash(${cmd})`;
|
|
116
|
+
}
|
|
117
|
+
return toolName;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Escape parentheses and backslashes in a string for use inside a
|
|
121
|
+
* `Bash(...)` allowedTools pattern. The Claude CLI's `--allowedTools`
|
|
122
|
+
* parser splits on commas/spaces but tracks a single level of `(…)`.
|
|
123
|
+
* Unescaped `)` inside the command prematurely closes the pattern,
|
|
124
|
+
* corrupting the entire allowedTools list and breaking tool resolution
|
|
125
|
+
* (manifests as "A.split is not a function" errors on unrelated tools).
|
|
126
|
+
*/
|
|
127
|
+
function escapeForAllowedTools(s) {
|
|
128
|
+
return s.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Convert Codekin's approval registry into `--allowedTools` patterns.
|
|
132
|
+
*
|
|
133
|
+
* Only includes tool names and wildcard patterns — NOT exact commands.
|
|
134
|
+
* Exact commands accumulate over time (hundreds of multi-line scripts)
|
|
135
|
+
* and when included in `--allowedTools` they create an argument so large
|
|
136
|
+
* and complex that it breaks the CLI's parser (manifests as "A.split is
|
|
137
|
+
* not a function" errors on unrelated tools like Agent and TodoWrite).
|
|
138
|
+
* Exact commands are still auto-approved at runtime via the approval hook.
|
|
139
|
+
*
|
|
140
|
+
* Translations:
|
|
141
|
+
* - Pattern `"git diff *"` → `"Bash(git diff:*)"`
|
|
142
|
+
* - Tool `"WebFetch"` → `"WebFetch"`
|
|
143
|
+
*/
|
|
144
|
+
export function toAllowedToolsPatterns(approvals) {
|
|
145
|
+
const result = [];
|
|
146
|
+
for (const tool of approvals.tools) {
|
|
147
|
+
result.push(tool);
|
|
148
|
+
}
|
|
149
|
+
// Exact commands are intentionally excluded from --allowedTools.
|
|
150
|
+
// They are handled by the auto-approval hook at prompt time instead.
|
|
151
|
+
for (const pattern of approvals.patterns) {
|
|
152
|
+
// Convert "prefix *" → "Bash(prefix:*)"
|
|
153
|
+
if (pattern.endsWith(' *')) {
|
|
154
|
+
const prefix = pattern.slice(0, -2);
|
|
155
|
+
result.push(`Bash(${escapeForAllowedTools(prefix)}:*)`);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
result.push(`Bash(${escapeForAllowedTools(pattern)})`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=native-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-permissions.js","sourceRoot":"","sources":["../native-permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator child session manager — spawns, monitors, and reports on
|
|
3
|
+
* implementation sessions created by the orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Follows the same patterns as workflow-loader.ts for session creation
|
|
6
|
+
* and result polling.
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionManager } from './session-manager.js';
|
|
9
|
+
export interface ChildSessionRequest {
|
|
10
|
+
/** Target repository path. */
|
|
11
|
+
repo: string;
|
|
12
|
+
/** Human-readable task description. */
|
|
13
|
+
task: string;
|
|
14
|
+
/** Branch name for the fix. */
|
|
15
|
+
branchName: string;
|
|
16
|
+
/** How changes should land. */
|
|
17
|
+
completionPolicy: 'pr' | 'merge' | 'commit-only';
|
|
18
|
+
/** Whether to deploy after merge. */
|
|
19
|
+
deployAfter: boolean;
|
|
20
|
+
/** Use a git worktree for isolation. */
|
|
21
|
+
useWorktree: boolean;
|
|
22
|
+
/** Timeout in ms (default 10 minutes). */
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
/** Optional model override. */
|
|
25
|
+
model?: string;
|
|
26
|
+
}
|
|
27
|
+
export type ChildStatus = 'starting' | 'running' | 'completed' | 'failed' | 'timed_out';
|
|
28
|
+
export interface ChildSession {
|
|
29
|
+
id: string;
|
|
30
|
+
request: ChildSessionRequest;
|
|
31
|
+
status: ChildStatus;
|
|
32
|
+
startedAt: string;
|
|
33
|
+
completedAt: string | null;
|
|
34
|
+
result: string | null;
|
|
35
|
+
error: string | null;
|
|
36
|
+
}
|
|
37
|
+
export declare class OrchestratorChildManager {
|
|
38
|
+
private children;
|
|
39
|
+
private sessions;
|
|
40
|
+
constructor(sessions: SessionManager);
|
|
41
|
+
/** Get all active/recent child sessions. */
|
|
42
|
+
list(): ChildSession[];
|
|
43
|
+
/** Get a child session by ID. */
|
|
44
|
+
get(id: string): ChildSession | null;
|
|
45
|
+
/** Purge completed/failed children older than the retention period. */
|
|
46
|
+
private purgeStaleChildren;
|
|
47
|
+
/** Count currently active (non-terminal) child sessions. */
|
|
48
|
+
activeCount(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Spawn a child session to implement a task in a target repo.
|
|
51
|
+
* Returns the child session info or throws if at capacity.
|
|
52
|
+
*/
|
|
53
|
+
spawn(request: ChildSessionRequest): Promise<ChildSession>;
|
|
54
|
+
/**
|
|
55
|
+
* Build a focused task prompt for a child session.
|
|
56
|
+
*/
|
|
57
|
+
private buildPrompt;
|
|
58
|
+
/**
|
|
59
|
+
* Monitor a child session until completion or timeout using event hooks.
|
|
60
|
+
* Replaces the old polling loop with SessionManager's onSessionResult and
|
|
61
|
+
* onSessionExit hooks for lower latency and no wasted CPU.
|
|
62
|
+
*/
|
|
63
|
+
private monitorChild;
|
|
64
|
+
/**
|
|
65
|
+
* Check whether the session completed the expected final step (PR, push, deploy).
|
|
66
|
+
* If not, send a follow-up instruction and return true so monitoring continues.
|
|
67
|
+
* Only nudges once per child to avoid infinite loops.
|
|
68
|
+
*/
|
|
69
|
+
private ensureFinalStep;
|
|
70
|
+
/**
|
|
71
|
+
* Extract assistant text from session output history.
|
|
72
|
+
*/
|
|
73
|
+
private extractText;
|
|
74
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator child session manager — spawns, monitors, and reports on
|
|
3
|
+
* implementation sessions created by the orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Follows the same patterns as workflow-loader.ts for session creation
|
|
6
|
+
* and result polling.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from 'crypto';
|
|
9
|
+
import { getAgentDisplayName } from './config.js';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Constants
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const MAX_CONCURRENT = 5;
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes
|
|
15
|
+
const CHILD_RETENTION_MS = 3_600_000; // keep completed/failed children for 1 hour
|
|
16
|
+
const MAX_RETAINED_CHILDREN = 100; // hard cap on total entries
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Manager
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export class OrchestratorChildManager {
|
|
21
|
+
children = new Map();
|
|
22
|
+
sessions;
|
|
23
|
+
constructor(sessions) {
|
|
24
|
+
this.sessions = sessions;
|
|
25
|
+
}
|
|
26
|
+
/** Get all active/recent child sessions. */
|
|
27
|
+
list() {
|
|
28
|
+
this.purgeStaleChildren();
|
|
29
|
+
return Array.from(this.children.values())
|
|
30
|
+
.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
31
|
+
}
|
|
32
|
+
/** Get a child session by ID. */
|
|
33
|
+
get(id) {
|
|
34
|
+
return this.children.get(id) ?? null;
|
|
35
|
+
}
|
|
36
|
+
/** Purge completed/failed children older than the retention period. */
|
|
37
|
+
purgeStaleChildren() {
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
for (const [id, child] of this.children) {
|
|
40
|
+
if (child.status === 'starting' || child.status === 'running')
|
|
41
|
+
continue;
|
|
42
|
+
if (child.completedAt && now - new Date(child.completedAt).getTime() > CHILD_RETENTION_MS) {
|
|
43
|
+
this.children.delete(id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Hard cap: if still over limit, remove oldest completed entries
|
|
47
|
+
if (this.children.size > MAX_RETAINED_CHILDREN) {
|
|
48
|
+
const completed = Array.from(this.children.entries())
|
|
49
|
+
.filter(([, c]) => c.status !== 'starting' && c.status !== 'running')
|
|
50
|
+
.sort((a, b) => (a[1].completedAt ?? '').localeCompare(b[1].completedAt ?? ''));
|
|
51
|
+
while (this.children.size > MAX_RETAINED_CHILDREN && completed.length > 0) {
|
|
52
|
+
const [id] = completed.shift();
|
|
53
|
+
this.children.delete(id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Count currently active (non-terminal) child sessions. */
|
|
58
|
+
activeCount() {
|
|
59
|
+
return Array.from(this.children.values())
|
|
60
|
+
.filter(c => c.status === 'starting' || c.status === 'running')
|
|
61
|
+
.length;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Spawn a child session to implement a task in a target repo.
|
|
65
|
+
* Returns the child session info or throws if at capacity.
|
|
66
|
+
*/
|
|
67
|
+
async spawn(request) {
|
|
68
|
+
this.purgeStaleChildren();
|
|
69
|
+
if (this.activeCount() >= MAX_CONCURRENT) {
|
|
70
|
+
throw new Error(`Cannot spawn child session: ${MAX_CONCURRENT} concurrent sessions already running`);
|
|
71
|
+
}
|
|
72
|
+
const sessionId = randomUUID();
|
|
73
|
+
const sessionName = `${getAgentDisplayName().toLowerCase()}:${request.branchName}`;
|
|
74
|
+
const now = new Date().toISOString();
|
|
75
|
+
const child = {
|
|
76
|
+
id: sessionId,
|
|
77
|
+
request,
|
|
78
|
+
status: 'starting',
|
|
79
|
+
startedAt: now,
|
|
80
|
+
completedAt: null,
|
|
81
|
+
result: null,
|
|
82
|
+
error: null,
|
|
83
|
+
};
|
|
84
|
+
this.children.set(sessionId, child);
|
|
85
|
+
try {
|
|
86
|
+
// Create the session
|
|
87
|
+
this.sessions.create(sessionName, request.repo, {
|
|
88
|
+
source: 'agent',
|
|
89
|
+
id: sessionId,
|
|
90
|
+
groupDir: request.repo,
|
|
91
|
+
model: request.model,
|
|
92
|
+
permissionMode: 'acceptEdits',
|
|
93
|
+
allowedTools: ['Bash(curl:*)'],
|
|
94
|
+
});
|
|
95
|
+
// Create a git worktree for isolation if requested (default for Joe children).
|
|
96
|
+
// This must happen BEFORE startClaude so Claude runs in the worktree directory.
|
|
97
|
+
if (request.useWorktree) {
|
|
98
|
+
const wtPath = await this.sessions.createWorktree(sessionId, request.repo);
|
|
99
|
+
if (!wtPath) {
|
|
100
|
+
console.warn(`[orchestrator-child] Failed to create worktree for ${sessionId}, falling back to main directory`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Start Claude
|
|
104
|
+
this.sessions.startClaude(sessionId);
|
|
105
|
+
child.status = 'running';
|
|
106
|
+
// Build and send the task prompt
|
|
107
|
+
const prompt = this.buildPrompt(request);
|
|
108
|
+
this.sessions.sendInput(sessionId, prompt);
|
|
109
|
+
// Monitor completion asynchronously
|
|
110
|
+
void this.monitorChild(child);
|
|
111
|
+
return child;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
child.status = 'failed';
|
|
115
|
+
child.error = err instanceof Error ? err.message : String(err);
|
|
116
|
+
child.completedAt = new Date().toISOString();
|
|
117
|
+
return child;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Build a focused task prompt for a child session.
|
|
122
|
+
*/
|
|
123
|
+
buildPrompt(request) {
|
|
124
|
+
const lines = [
|
|
125
|
+
`# Task: ${request.task}`,
|
|
126
|
+
'',
|
|
127
|
+
'## Instructions',
|
|
128
|
+
'',
|
|
129
|
+
`You have been spawned by Agent ${getAgentDisplayName()} (the Codekin orchestrator) to implement a specific task in this repository.`,
|
|
130
|
+
'',
|
|
131
|
+
`**Task**: ${request.task}`,
|
|
132
|
+
`**Branch**: Create your changes on branch \`${request.branchName}\``,
|
|
133
|
+
'',
|
|
134
|
+
];
|
|
135
|
+
if (request.completionPolicy === 'pr') {
|
|
136
|
+
lines.push('## Completion', '', '1. Create a new branch with the name specified above', '2. Make the necessary changes', '3. Commit your changes with a clear commit message', '4. Push the branch and create a Pull Request', '5. Include a clear PR description explaining what was changed and why', '');
|
|
137
|
+
}
|
|
138
|
+
else if (request.completionPolicy === 'merge') {
|
|
139
|
+
lines.push('## Completion', '', '1. Make the necessary changes on the current branch', '2. Commit your changes with a clear commit message', '3. Push directly to the current branch', '');
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
lines.push('## Completion', '', '1. Make the necessary changes', '2. Commit your changes with a clear commit message', '3. Do NOT push — just commit locally', '');
|
|
143
|
+
}
|
|
144
|
+
lines.push('## Guidelines', '', '- Keep changes minimal and focused on the task', '- Do not refactor unrelated code', '- If you encounter issues that block the task, explain what went wrong', '- When done, provide a brief summary of what you changed');
|
|
145
|
+
return lines.join('\n');
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Monitor a child session until completion or timeout using event hooks.
|
|
149
|
+
* Replaces the old polling loop with SessionManager's onSessionResult and
|
|
150
|
+
* onSessionExit hooks for lower latency and no wasted CPU.
|
|
151
|
+
*/
|
|
152
|
+
async monitorChild(child) {
|
|
153
|
+
const timeoutMs = child.request.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
154
|
+
try {
|
|
155
|
+
await new Promise((resolve) => {
|
|
156
|
+
let settled = false;
|
|
157
|
+
const settle = () => { if (!settled) {
|
|
158
|
+
settled = true;
|
|
159
|
+
resolve();
|
|
160
|
+
} };
|
|
161
|
+
// Timeout handler
|
|
162
|
+
const timer = setTimeout(() => {
|
|
163
|
+
if (settled)
|
|
164
|
+
return;
|
|
165
|
+
child.status = 'timed_out';
|
|
166
|
+
child.error = `Timed out after ${timeoutMs}ms`;
|
|
167
|
+
child.completedAt = new Date().toISOString();
|
|
168
|
+
const session = this.sessions.get(child.id);
|
|
169
|
+
if (session?.claudeProcess?.isAlive()) {
|
|
170
|
+
session.claudeProcess.stop();
|
|
171
|
+
}
|
|
172
|
+
settle();
|
|
173
|
+
}, timeoutMs);
|
|
174
|
+
// Result hook: Claude completed a turn
|
|
175
|
+
const onResult = (sessionId, isError) => {
|
|
176
|
+
if (sessionId !== child.id || settled)
|
|
177
|
+
return;
|
|
178
|
+
const session = this.sessions.get(child.id);
|
|
179
|
+
if (!session) {
|
|
180
|
+
child.status = 'failed';
|
|
181
|
+
child.error = 'Session was deleted';
|
|
182
|
+
child.completedAt = new Date().toISOString();
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
settle();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const text = this.extractText(session.outputHistory);
|
|
188
|
+
// Check if the final step was done; if not, nudge (keep listening)
|
|
189
|
+
if (this.ensureFinalStep(child, session, text))
|
|
190
|
+
return;
|
|
191
|
+
// Don't mark as completed while the session still has pending
|
|
192
|
+
// tool approvals or control requests — the Claude process may
|
|
193
|
+
// still be alive and blocked on an approval (e.g. git push).
|
|
194
|
+
// Keep monitoring; the next result/exit event will re-evaluate.
|
|
195
|
+
if (session.pendingToolApprovals.size > 0 || session.pendingControlRequests.size > 0)
|
|
196
|
+
return;
|
|
197
|
+
child.status = isError ? 'failed' : 'completed';
|
|
198
|
+
child.result = text || null;
|
|
199
|
+
child.error = isError ? 'Claude returned an error' : null;
|
|
200
|
+
child.completedAt = new Date().toISOString();
|
|
201
|
+
clearTimeout(timer);
|
|
202
|
+
settle();
|
|
203
|
+
};
|
|
204
|
+
// Exit hook: Claude process exited
|
|
205
|
+
const onExit = (sessionId, _code, _signal, willRestart) => {
|
|
206
|
+
if (sessionId !== child.id || settled)
|
|
207
|
+
return;
|
|
208
|
+
if (willRestart)
|
|
209
|
+
return; // Will auto-restart, keep monitoring
|
|
210
|
+
const session = this.sessions.get(child.id);
|
|
211
|
+
const text = session ? this.extractText(session.outputHistory) : '';
|
|
212
|
+
child.status = text.length > 100 ? 'completed' : 'failed';
|
|
213
|
+
child.result = text || null;
|
|
214
|
+
child.error = text.length <= 100 ? 'Claude exited without sufficient output' : null;
|
|
215
|
+
child.completedAt = new Date().toISOString();
|
|
216
|
+
clearTimeout(timer);
|
|
217
|
+
settle();
|
|
218
|
+
};
|
|
219
|
+
this.sessions.onSessionResult(onResult);
|
|
220
|
+
this.sessions.onSessionExit(onExit);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
// Safety net: ensure isProcessing is cleared when monitoring ends.
|
|
225
|
+
// handleClaudeResult should have already done this, but edge cases
|
|
226
|
+
// (nudge race, missed result event) can leave the flag stuck.
|
|
227
|
+
this.sessions.clearProcessingFlag(child.id);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Check whether the session completed the expected final step (PR, push, deploy).
|
|
232
|
+
* If not, send a follow-up instruction and return true so monitoring continues.
|
|
233
|
+
* Only nudges once per child to avoid infinite loops.
|
|
234
|
+
*/
|
|
235
|
+
ensureFinalStep(child, session, text) {
|
|
236
|
+
// Only nudge once
|
|
237
|
+
if (child._nudged)
|
|
238
|
+
return false;
|
|
239
|
+
const policy = child.request.completionPolicy;
|
|
240
|
+
const lowerText = text.toLowerCase();
|
|
241
|
+
let missing = false;
|
|
242
|
+
let instruction = '';
|
|
243
|
+
if (policy === 'pr') {
|
|
244
|
+
// Check if a PR was created
|
|
245
|
+
const prCreated = lowerText.includes('pull request') || lowerText.includes('created a pr') || lowerText.includes('gh pr create');
|
|
246
|
+
if (!prCreated) {
|
|
247
|
+
missing = true;
|
|
248
|
+
instruction = 'You completed the code changes but did not create a Pull Request. Please push your branch and create a PR now with a clear description of what was changed and why.';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else if (policy === 'merge') {
|
|
252
|
+
// Check if changes were pushed
|
|
253
|
+
const pushed = lowerText.includes('git push') || lowerText.includes('pushed');
|
|
254
|
+
if (!pushed) {
|
|
255
|
+
missing = true;
|
|
256
|
+
instruction = 'You completed the code changes but did not push them. Please push your changes to the remote now.';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (missing && instruction && session.claudeProcess?.isAlive()) {
|
|
260
|
+
child._nudged = true;
|
|
261
|
+
// Mark the result message as superseded so monitoring can ignore it
|
|
262
|
+
// without mutating the outputHistory array (which would break replay)
|
|
263
|
+
const resultMsg = session.outputHistory.find(m => m.type === 'result');
|
|
264
|
+
if (resultMsg)
|
|
265
|
+
resultMsg._superseded = true;
|
|
266
|
+
this.sessions.sendInput(child.id, instruction);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Extract assistant text from session output history.
|
|
273
|
+
*/
|
|
274
|
+
extractText(history) {
|
|
275
|
+
return history
|
|
276
|
+
.filter((m) => m.type === 'output')
|
|
277
|
+
.map(m => m.data)
|
|
278
|
+
.join('');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=orchestrator-children.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator-children.js","sourceRoot":"","sources":["../orchestrator-children.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAqCjD,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,cAAc,GAAG,CAAC,CAAA;AACxB,MAAM,kBAAkB,GAAG,OAAO,CAAA,CAAE,aAAa;AACjD,MAAM,kBAAkB,GAAG,SAAS,CAAA,CAAE,4CAA4C;AAClF,MAAM,qBAAqB,GAAG,GAAG,CAAA,CAAI,4BAA4B;AAEjE,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,OAAO,wBAAwB;IAC3B,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAA;IAC1C,QAAQ,CAAgB;IAEhC,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED,4CAA4C;IAC5C,IAAI;QACF,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;aACtC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,iCAAiC;IACjC,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAA;IACtC,CAAC;IAED,uEAAuE;IAC/D,kBAAkB;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAQ;YACvE,IAAI,KAAK,CAAC,WAAW,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAAC;gBAC1F,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;QACD,iEAAiE;QACjE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,qBAAqB,EAAE,CAAC;YAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;iBAClD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;iBACpE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAA;YACjF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,qBAAqB,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1E,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,KAAK,EAAG,CAAA;gBAC/B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,WAAW;QACT,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;aACtC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;aAC9D,MAAM,CAAA;IACX,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,OAA4B;QACtC,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,cAAc,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,+BAA+B,cAAc,sCAAsC,CAAC,CAAA;QACtG,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,EAAE,CAAA;QAC9B,MAAM,WAAW,GAAG,GAAG,mBAAmB,EAAE,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,UAAU,EAAE,CAAA;QAClF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAEpC,MAAM,KAAK,GAAiB;YAC1B,EAAE,EAAE,SAAS;YACb,OAAO;YACP,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,GAAG;YACd,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI;SACZ,CAAA;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAEnC,IAAI,CAAC;YACH,qBAAqB;YACrB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE;gBAC9C,MAAM,EAAE,OAAO;gBACf,EAAE,EAAE,SAAS;gBACb,QAAQ,EAAE,OAAO,CAAC,IAAI;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,cAAc,EAAE,aAAa;gBAC7B,YAAY,EAAE,CAAC,cAAc,CAAC;aAC/B,CAAC,CAAA;YAEF,+EAA+E;YAC/E,gFAAgF;YAChF,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;gBAC1E,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,CAAC,IAAI,CAAC,sDAAsD,SAAS,kCAAkC,CAAC,CAAA;gBACjH,CAAC;YACH,CAAC;YAED,eAAe;YACf,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;YACpC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAA;YAExB,iCAAiC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YACxC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;YAE1C,oCAAoC;YACpC,KAAK,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;YAE7B,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAA;YACvB,KAAK,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9D,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;YAC5C,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,OAA4B;QAC9C,MAAM,KAAK,GAAG;YACZ,WAAW,OAAO,CAAC,IAAI,EAAE;YACzB,EAAE;YACF,iBAAiB;YACjB,EAAE;YACF,kCAAkC,mBAAmB,EAAE,8EAA8E;YACrI,EAAE;YACF,aAAa,OAAO,CAAC,IAAI,EAAE;YAC3B,+CAA+C,OAAO,CAAC,UAAU,IAAI;YACrE,EAAE;SACH,CAAA;QAED,IAAI,OAAO,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CACR,eAAe,EACf,EAAE,EACF,sDAAsD,EACtD,+BAA+B,EAC/B,oDAAoD,EACpD,8CAA8C,EAC9C,uEAAuE,EACvE,EAAE,CACH,CAAA;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CACR,eAAe,EACf,EAAE,EACF,qDAAqD,EACrD,oDAAoD,EACpD,wCAAwC,EACxC,EAAE,CACH,CAAA;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CACR,eAAe,EACf,EAAE,EACF,+BAA+B,EAC/B,oDAAoD,EACpD,sCAAsC,EACtC,EAAE,CACH,CAAA;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CACR,eAAe,EACf,EAAE,EACF,gDAAgD,EAChD,kCAAkC,EAClC,wEAAwE,EACxE,0DAA0D,CAC3D,CAAA;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,YAAY,CAAC,KAAmB;QAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;QAE/D,IAAI,CAAC;YACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,IAAI,OAAO,GAAG,KAAK,CAAA;gBACnB,MAAM,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;oBAAC,OAAO,GAAG,IAAI,CAAC;oBAAC,OAAO,EAAE,CAAA;gBAAC,CAAC,CAAC,CAAC,CAAA;gBAEpE,kBAAkB;gBAClB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC5B,IAAI,OAAO;wBAAE,OAAM;oBACnB,KAAK,CAAC,MAAM,GAAG,WAAW,CAAA;oBAC1B,KAAK,CAAC,KAAK,GAAG,mBAAmB,SAAS,IAAI,CAAA;oBAC9C,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;oBAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;oBAC3C,IAAI,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC;wBACtC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAA;oBAC9B,CAAC;oBACD,MAAM,EAAE,CAAA;gBACV,CAAC,EAAE,SAAS,CAAC,CAAA;gBAEb,uCAAuC;gBACvC,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,OAAgB,EAAE,EAAE;oBACvD,IAAI,SAAS,KAAK,KAAK,CAAC,EAAE,IAAI,OAAO;wBAAE,OAAM;oBAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;oBAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAA;wBACvB,KAAK,CAAC,KAAK,GAAG,qBAAqB,CAAA;wBACnC,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;wBAC5C,YAAY,CAAC,KAAK,CAAC,CAAA;wBACnB,MAAM,EAAE,CAAA;wBACR,OAAM;oBACR,CAAC;oBAED,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;oBACpD,mEAAmE;oBACnE,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;wBAAE,OAAM;oBAEtD,8DAA8D;oBAC9D,8DAA8D;oBAC9D,6DAA6D;oBAC7D,gEAAgE;oBAChE,IAAI,OAAO,CAAC,oBAAoB,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,sBAAsB,CAAC,IAAI,GAAG,CAAC;wBAAE,OAAM;oBAE5F,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAA;oBAC/C,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,IAAI,CAAA;oBAC3B,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAA;oBACzD,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;oBAC5C,YAAY,CAAC,KAAK,CAAC,CAAA;oBACnB,MAAM,EAAE,CAAA;gBACV,CAAC,CAAA;gBAED,mCAAmC;gBACnC,MAAM,MAAM,GAAG,CAAC,SAAiB,EAAE,KAAoB,EAAE,OAAsB,EAAE,WAAoB,EAAE,EAAE;oBACvG,IAAI,SAAS,KAAK,KAAK,CAAC,EAAE,IAAI,OAAO;wBAAE,OAAM;oBAC7C,IAAI,WAAW;wBAAE,OAAM,CAAE,qCAAqC;oBAE9D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;oBAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;oBACnE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAA;oBACzD,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,IAAI,CAAA;oBAC3B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC,CAAC,IAAI,CAAA;oBACnF,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;oBAC5C,YAAY,CAAC,KAAK,CAAC,CAAA;oBACnB,MAAM,EAAE,CAAA;gBACV,CAAC,CAAA;gBAED,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;gBACvC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;QACJ,CAAC;gBAAS,CAAC;YACT,mEAAmE;YACnE,mEAAmE;YACnE,8DAA8D;YAC9D,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,eAAe,CAAC,KAAmB,EAAE,OAAgB,EAAE,IAAY;QACzE,kBAAkB;QAClB,IAAK,KAA8C,CAAC,OAAO;YAAE,OAAO,KAAK,CAAA;QAEzE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAA;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAEpC,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,IAAI,WAAW,GAAG,EAAE,CAAA;QAEpB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,4BAA4B;YAC5B,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;YAChI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,GAAG,IAAI,CAAA;gBACd,WAAW,GAAG,qKAAqK,CAAA;YACrL,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,+BAA+B;YAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC7E,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,GAAG,IAAI,CAAA;gBACd,WAAW,GAAG,mGAAmG,CAAA;YACnH,CAAC;QACH,CAAC;QAED,IAAI,OAAO,IAAI,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC;YAC9D,KAA8C,CAAC,OAAO,GAAG,IAAI,CAAA;YAC9D,oEAAoE;YACpE,sEAAsE;YACtE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;YACtE,IAAI,SAAS;gBAAG,SAAqC,CAAC,WAAW,GAAG,IAAI,CAAA;YACxE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAA;YAC9C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,OAA0B;QAC5C,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAqD,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;aACrF,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAChB,IAAI,CAAC,EAAE,CAAC,CAAA;IACb,CAAC;CACF"}
|