@grackle-ai/server 0.75.1 → 0.75.3

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 (88) hide show
  1. package/dist/__mocks__/adapter-manager.d.ts +9 -0
  2. package/dist/__mocks__/adapter-manager.d.ts.map +1 -0
  3. package/dist/__mocks__/adapter-manager.js +10 -0
  4. package/dist/__mocks__/adapter-manager.js.map +1 -0
  5. package/dist/__mocks__/auto-reconnect.d.ts +5 -0
  6. package/dist/__mocks__/auto-reconnect.d.ts.map +1 -0
  7. package/dist/__mocks__/auto-reconnect.js +6 -0
  8. package/dist/__mocks__/auto-reconnect.js.map +1 -0
  9. package/dist/__mocks__/event-bus.d.ts +4 -0
  10. package/dist/__mocks__/event-bus.d.ts.map +1 -0
  11. package/dist/__mocks__/event-bus.js +5 -0
  12. package/dist/__mocks__/event-bus.js.map +1 -0
  13. package/dist/__mocks__/event-processor.d.ts +4 -0
  14. package/dist/__mocks__/event-processor.d.ts.map +1 -0
  15. package/dist/__mocks__/event-processor.js +5 -0
  16. package/dist/__mocks__/event-processor.js.map +1 -0
  17. package/dist/__mocks__/github-import.d.ts +7 -0
  18. package/dist/__mocks__/github-import.d.ts.map +1 -0
  19. package/dist/__mocks__/github-import.js +8 -0
  20. package/dist/__mocks__/github-import.js.map +1 -0
  21. package/dist/__mocks__/knowledge-init.d.ts +4 -0
  22. package/dist/__mocks__/knowledge-init.d.ts.map +1 -0
  23. package/dist/__mocks__/knowledge-init.js +5 -0
  24. package/dist/__mocks__/knowledge-init.js.map +1 -0
  25. package/dist/__mocks__/lifecycle.d.ts +4 -0
  26. package/dist/__mocks__/lifecycle.d.ts.map +1 -0
  27. package/dist/__mocks__/lifecycle.js +5 -0
  28. package/dist/__mocks__/lifecycle.js.map +1 -0
  29. package/dist/__mocks__/log-writer.d.ts +7 -0
  30. package/dist/__mocks__/log-writer.d.ts.map +1 -0
  31. package/dist/__mocks__/log-writer.js +8 -0
  32. package/dist/__mocks__/log-writer.js.map +1 -0
  33. package/dist/__mocks__/logger.d.ts +7 -0
  34. package/dist/__mocks__/logger.d.ts.map +1 -0
  35. package/dist/__mocks__/logger.js +3 -0
  36. package/dist/__mocks__/logger.js.map +1 -0
  37. package/dist/__mocks__/pipe-delivery.d.ts +6 -0
  38. package/dist/__mocks__/pipe-delivery.d.ts.map +1 -0
  39. package/dist/__mocks__/pipe-delivery.js +7 -0
  40. package/dist/__mocks__/pipe-delivery.js.map +1 -0
  41. package/dist/__mocks__/processor-registry.d.ts +6 -0
  42. package/dist/__mocks__/processor-registry.d.ts.map +1 -0
  43. package/dist/__mocks__/processor-registry.js +7 -0
  44. package/dist/__mocks__/processor-registry.js.map +1 -0
  45. package/dist/__mocks__/reanimate-agent.d.ts +2 -0
  46. package/dist/__mocks__/reanimate-agent.d.ts.map +1 -0
  47. package/dist/__mocks__/reanimate-agent.js +3 -0
  48. package/dist/__mocks__/reanimate-agent.js.map +1 -0
  49. package/dist/__mocks__/session-recovery.d.ts +3 -0
  50. package/dist/__mocks__/session-recovery.d.ts.map +1 -0
  51. package/dist/__mocks__/session-recovery.js +4 -0
  52. package/dist/__mocks__/session-recovery.js.map +1 -0
  53. package/dist/__mocks__/stream-hub.d.ts +9 -0
  54. package/dist/__mocks__/stream-hub.d.ts.map +1 -0
  55. package/dist/__mocks__/stream-hub.js +10 -0
  56. package/dist/__mocks__/stream-hub.js.map +1 -0
  57. package/dist/__mocks__/stream-registry.d.ts +16 -0
  58. package/dist/__mocks__/stream-registry.d.ts.map +1 -0
  59. package/dist/__mocks__/stream-registry.js +17 -0
  60. package/dist/__mocks__/stream-registry.js.map +1 -0
  61. package/dist/__mocks__/token-push.d.ts +5 -0
  62. package/dist/__mocks__/token-push.d.ts.map +1 -0
  63. package/dist/__mocks__/token-push.js +6 -0
  64. package/dist/__mocks__/token-push.js.map +1 -0
  65. package/dist/__mocks__/utils/exec.d.ts +3 -0
  66. package/dist/__mocks__/utils/exec.d.ts.map +1 -0
  67. package/dist/__mocks__/utils/exec.js +3 -0
  68. package/dist/__mocks__/utils/exec.js.map +1 -0
  69. package/dist/__mocks__/utils/format-gh-error.d.ts +3 -0
  70. package/dist/__mocks__/utils/format-gh-error.d.ts.map +1 -0
  71. package/dist/__mocks__/utils/format-gh-error.js +3 -0
  72. package/dist/__mocks__/utils/format-gh-error.js.map +1 -0
  73. package/dist/__mocks__/utils/network.d.ts +3 -0
  74. package/dist/__mocks__/utils/network.d.ts.map +1 -0
  75. package/dist/__mocks__/utils/network.js +3 -0
  76. package/dist/__mocks__/utils/network.js.map +1 -0
  77. package/dist/grpc-service.d.ts.map +1 -1
  78. package/dist/grpc-service.js +0 -12
  79. package/dist/grpc-service.js.map +1 -1
  80. package/dist/test-utils/integration-setup.d.ts +11 -0
  81. package/dist/test-utils/integration-setup.d.ts.map +1 -0
  82. package/dist/test-utils/integration-setup.js +32 -0
  83. package/dist/test-utils/integration-setup.js.map +1 -0
  84. package/package.json +15 -15
  85. package/dist/github-import.d.ts +0 -209
  86. package/dist/github-import.d.ts.map +0 -1
  87. package/dist/github-import.js +0 -427
  88. package/dist/github-import.js.map +0 -1
@@ -1,209 +0,0 @@
1
- /** Wraps `gh` CLI execution for testability. */
2
- export interface GitHubClient {
3
- /** Execute a `gh` CLI command and return stdout. */
4
- exec(args: string[], options: {
5
- encoding: BufferEncoding;
6
- maxBuffer: number;
7
- timeout?: number;
8
- }): Promise<string>;
9
- }
10
- /** Wraps task/workspace store operations for testability. */
11
- export interface TaskPersistence {
12
- /** Look up a workspace by ID. */
13
- getWorkspace(workspaceId: string): {
14
- name: string;
15
- } | undefined;
16
- /** List all tasks in a workspace. */
17
- listTasks(workspaceId: string): Array<{
18
- id: string;
19
- title: string;
20
- }>;
21
- /** Create a new task. */
22
- createTask(id: string, workspaceId: string, title: string, description: string, dependsOn: string[], workspaceSlug: string, parentTaskId: string, canDecompose: boolean): void;
23
- /** Set the dependsOn list for a task. */
24
- setTaskDependsOn(taskId: string, dependsOn: string[]): void;
25
- }
26
- /** Wraps event bus broadcasting for testability. */
27
- export interface ImportEventEmitter {
28
- /** Emit a task lifecycle event. */
29
- emit(type: "task.created" | "task.updated", payload: {
30
- taskId: string;
31
- workspaceId: string;
32
- }): void;
33
- }
34
- /** Concurrency guard for imports. */
35
- export interface ImportLock {
36
- /** Acquire the lock. Throws if already held. */
37
- acquire(): void;
38
- /** Release the lock. */
39
- release(): void;
40
- }
41
- /** Shape of a single GitHub issue comment as returned by the GraphQL query. */
42
- export interface GitHubComment {
43
- /** Login of the comment author. */
44
- author: string;
45
- /** ISO-8601 timestamp of when the comment was created. */
46
- createdAt: string;
47
- /** Markdown body of the comment. */
48
- body: string;
49
- }
50
- /** Shape of a GitHub issue as returned by the GraphQL query. */
51
- export interface GitHubIssue {
52
- number: number;
53
- title: string;
54
- body: string;
55
- parentNumber: number | undefined;
56
- labels: string[];
57
- /** Issue numbers that block this issue (i.e., this issue depends on them). */
58
- blockedByNumbers: number[];
59
- /** Comments on the issue. Empty array when fetched without `includeComments`. */
60
- comments: GitHubComment[];
61
- /**
62
- * `true` when the issue had more than {@link COMMENTS_PER_ISSUE} comments
63
- * and only the first batch was fetched. The imported description will
64
- * include a truncation notice when this is `true`.
65
- */
66
- commentsHasNextPage: boolean;
67
- }
68
- /** Result summary returned by {@link importGitHubIssues}. */
69
- export interface ImportResult {
70
- imported: number;
71
- linked: number;
72
- skipped: number;
73
- /** Number of blocking (dependsOn) relationships created. */
74
- dependencies: number;
75
- }
76
- /** Instruction to create a single task during the persist phase. */
77
- export interface TaskCreateInstruction {
78
- /** Generated task ID. */
79
- id: string;
80
- /** Formatted title (e.g., "#42: Fix the bug"). */
81
- title: string;
82
- /** Full task description including comments. */
83
- description: string;
84
- /** Resolved parent task ID, or empty string for root tasks. */
85
- parentTaskId: string;
86
- /** Original GitHub issue number. */
87
- issueNumber: number;
88
- }
89
- /** Instruction to set dependsOn for a task during the persist phase. */
90
- export interface DependencyInstruction {
91
- /** Task ID to update. */
92
- taskId: string;
93
- /** Resolved task IDs that this task depends on. */
94
- dependsOn: string[];
95
- }
96
- /** The output of {@link planImport}: a pure description of what to persist. */
97
- export interface ImportPlan {
98
- /** Tasks to create, in topological order. */
99
- tasksToCreate: TaskCreateInstruction[];
100
- /** Dependency relationships to set after task creation. */
101
- dependenciesToSet: DependencyInstruction[];
102
- /** Number of issues skipped because they already exist. */
103
- skipped: number;
104
- /** Number of parent links resolved. */
105
- linked: number;
106
- }
107
- /** Options for dependency injection in {@link importGitHubIssues}. */
108
- export interface ImportGitHubIssuesOptions {
109
- /** @internal GitHub CLI client for testing. */
110
- githubClient?: GitHubClient;
111
- /** @internal Task/workspace persistence for testing. */
112
- persistence?: TaskPersistence;
113
- /** @internal Event broadcaster for testing. */
114
- eventEmitter?: ImportEventEmitter;
115
- /** @internal Concurrency lock for testing. */
116
- importLock?: ImportLock;
117
- /** @internal ID generator for testing. */
118
- generateId?: () => string;
119
- }
120
- /**
121
- * Builds the full task description from an issue body and its comments.
122
- *
123
- * Comments are appended after the body, each preceded by a `---` separator
124
- * and a header line showing the author login and creation timestamp.
125
- * When `hasMoreComments` is `true`, a truncation notice is appended after
126
- * the last fetched comment to indicate that additional comments exist.
127
- *
128
- * @param body - The issue body text (may be empty).
129
- * @param comments - Array of comments to append. Pass an empty array to omit.
130
- * @param hasMoreComments - When `true`, appends a notice that the comment list
131
- * was truncated at the fetch limit.
132
- * @returns The formatted description string.
133
- */
134
- export declare function buildDescriptionWithComments(body: string, comments: GitHubComment[], hasMoreComments?: boolean): string;
135
- /**
136
- * Builds a deduplication map from existing tasks whose titles match
137
- * the `#<number>: <title>` pattern used by imported GitHub issues.
138
- *
139
- * @param existingTasks - Tasks already in the workspace.
140
- * @returns Maps and sets for deduplication during import planning.
141
- */
142
- export declare function buildExistingIssueMap(existingTasks: Array<{
143
- id: string;
144
- title: string;
145
- }>): {
146
- issueNumberToTaskId: Map<number, string>;
147
- existingIssueNumbers: Set<number>;
148
- };
149
- /**
150
- * Given fetched issues and existing state, computes what to create and link
151
- * without performing any side effects.
152
- *
153
- * Performs topological sort, skips existing issues, generates IDs upfront,
154
- * resolves parent links and blockedBy dependencies, and returns a plan.
155
- *
156
- * @param issues - Fetched GitHub issues to import.
157
- * @param existingIssueNumbers - Issue numbers already imported (to skip).
158
- * @param existingIssueNumberToTaskId - Map from issue number to existing task ID.
159
- * @param generateId - Optional ID generator (defaults to `uuid().slice(0, 8)`).
160
- * @returns An {@link ImportPlan} describing all tasks to create and dependencies to set.
161
- */
162
- export declare function planImport(issues: GitHubIssue[], existingIssueNumbers: Set<number>, existingIssueNumberToTaskId: Map<number, string>, generateId?: () => string): ImportPlan;
163
- /**
164
- * Fetches GitHub issues from a repository via the `gh` CLI GraphQL API.
165
- * Paginates automatically and includes parent sub-issue information.
166
- *
167
- * @param repo - Repository in "owner/repo" format.
168
- * @param state - Issue state filter ("open" or "closed").
169
- * @param label - Optional label to filter issues by (client-side).
170
- * @param includeComments - When `true` (default), fetches issue comments and
171
- * includes them in each returned {@link GitHubIssue}. Pass `false` to omit
172
- * comments and reduce payload size.
173
- * @param client - Optional {@link GitHubClient} for testing (defaults to `gh` CLI).
174
- * @returns Array of parsed GitHub issues.
175
- */
176
- export declare function fetchGitHubIssues(repo: string, state: string, label?: string, includeComments?: boolean, client?: GitHubClient): Promise<GitHubIssue[]>;
177
- /**
178
- * Topologically sorts issues so that parents appear before their children.
179
- * Issues whose parent is outside the import set are treated as roots.
180
- * Falls back to original order for issues at the same depth.
181
- *
182
- * @param issues - The list of GitHub issues to sort.
183
- * @param issueSet - Set of issue numbers in the current import batch.
184
- * @returns A new array of issues sorted with parents before children.
185
- */
186
- export declare function topologicalSortIssues<T extends {
187
- number: number;
188
- parentNumber: number | undefined;
189
- }>(issues: T[], issueSet: Set<number>): T[];
190
- /**
191
- * Imports GitHub issues as Grackle tasks, with deduplication and parent linking.
192
- *
193
- * Orchestrates: fetch issues → dedup against existing tasks → plan (pure) →
194
- * persist tasks → broadcast updates → return summary.
195
- *
196
- * Only one import may run at a time; concurrent calls are rejected.
197
- *
198
- * @param workspaceId - The Grackle workspace ID to import tasks into.
199
- * @param repo - Repository in "owner/repo" format.
200
- * @param state - Issue state filter ("open" or "closed").
201
- * @param label - Optional label to filter issues by.
202
- * @param environmentId - Optional environment ID to assign to created tasks.
203
- * @param includeComments - When `true` (default), appends issue comments to each
204
- * task description. Pass `false` to import only the issue body (old behavior).
205
- * @param options - Optional dependency overrides for testing.
206
- * @returns Summary of imported, linked, and skipped issues.
207
- */
208
- export declare function importGitHubIssues(workspaceId: string, repo: string, state: string, label?: string, _environmentId?: string, includeComments?: boolean, options?: ImportGitHubIssuesOptions): Promise<ImportResult>;
209
- //# sourceMappingURL=github-import.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"github-import.d.ts","sourceRoot":"","sources":["../src/github-import.ts"],"names":[],"mappings":"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"}
@@ -1,427 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- import { v4 as uuid } from "uuid";
3
- import { taskStore, workspaceStore, slugify } from "@grackle-ai/database";
4
- import { emit } from "./event-bus.js";
5
- import { logger } from "./logger.js";
6
- /** Maximum buffer size for `gh` CLI output (50 MB). */
7
- const MAX_BUFFER_BYTES = 50 * 1024 * 1024;
8
- /** Default timeout for `gh` CLI invocations (5 minutes). */
9
- const GH_CLI_TIMEOUT_MS = 5 * 60 * 1000;
10
- /** Number of issues fetched per GraphQL page. */
11
- const ISSUES_PER_PAGE = 100;
12
- /**
13
- * Maximum number of comments fetched per issue in a single GraphQL page.
14
- *
15
- * Kept at 25 as a practical upper bound. Fetching 100 issues × N comments
16
- * per issue in one GraphQL request can produce very large payloads for
17
- * active repositories. Issues with more than this many comments will have
18
- * their descriptions annotated with a truncation notice.
19
- */
20
- const COMMENTS_PER_ISSUE = 25;
21
- /** Separator inserted between the issue body and each appended comment block. */
22
- const COMMENT_SEPARATOR = "\n\n---\n\n";
23
- /** Maximum number of blockedBy relationships fetched per issue. */
24
- const BLOCKED_BY_PER_ISSUE = 25;
25
- // ── Default Implementations ─────────────────────────────────────
26
- /** Default {@link GitHubClient} that shells out to the `gh` CLI. */
27
- const NODE_GITHUB_CLIENT = {
28
- exec(args, options) {
29
- const timeout = options.timeout ?? GH_CLI_TIMEOUT_MS;
30
- return new Promise((resolve, reject) => {
31
- execFile("gh", args, { ...options, timeout }, (err, stdout, stderr) => {
32
- if (err) {
33
- err.stderr = String(stderr);
34
- reject(err);
35
- }
36
- else {
37
- resolve(String(stdout));
38
- }
39
- });
40
- });
41
- },
42
- };
43
- /** Default {@link TaskPersistence} delegating to the real stores. */
44
- const NODE_TASK_PERSISTENCE = {
45
- getWorkspace(workspaceId) {
46
- return workspaceStore.getWorkspace(workspaceId);
47
- },
48
- listTasks(workspaceId) {
49
- return taskStore.listTasks(workspaceId);
50
- },
51
- createTask(id, workspaceId, title, description, dependsOn, workspaceSlug, parentTaskId, canDecompose) {
52
- taskStore.createTask(id, workspaceId, title, description, dependsOn, workspaceSlug, parentTaskId, canDecompose);
53
- },
54
- setTaskDependsOn(taskId, dependsOn) {
55
- taskStore.setTaskDependsOn(taskId, dependsOn);
56
- },
57
- };
58
- /** Default {@link ImportEventEmitter} delegating to the real event bus. */
59
- const NODE_IMPORT_EVENT_EMITTER = {
60
- emit(type, payload) {
61
- emit(type, payload);
62
- },
63
- };
64
- /**
65
- * Simple concurrency guard — only one import runs at a time within this process.
66
- * Does not prevent concurrent imports from separate server processes sharing the same DB.
67
- */
68
- const importLockState = { active: false };
69
- /** Default {@link ImportLock} using a process-global boolean. */
70
- const DEFAULT_IMPORT_LOCK = {
71
- acquire() {
72
- if (importLockState.active) {
73
- throw new Error("An import is already in progress. Please wait for it to complete.");
74
- }
75
- importLockState.active = true;
76
- },
77
- release() {
78
- importLockState.active = false;
79
- },
80
- };
81
- // ── Helper Functions ────────────────────────────────────────────
82
- /**
83
- * Extracts a human-readable message from an unknown error value.
84
- *
85
- * @param err - The caught error value.
86
- * @returns A string suitable for logging or re-throwing.
87
- */
88
- function formatError(err) {
89
- if (err instanceof Error) {
90
- const stderr = err.stderr;
91
- return stderr ? `${err.message} (stderr: ${stderr})` : err.message;
92
- }
93
- return String(err);
94
- }
95
- /**
96
- * Builds the full task description from an issue body and its comments.
97
- *
98
- * Comments are appended after the body, each preceded by a `---` separator
99
- * and a header line showing the author login and creation timestamp.
100
- * When `hasMoreComments` is `true`, a truncation notice is appended after
101
- * the last fetched comment to indicate that additional comments exist.
102
- *
103
- * @param body - The issue body text (may be empty).
104
- * @param comments - Array of comments to append. Pass an empty array to omit.
105
- * @param hasMoreComments - When `true`, appends a notice that the comment list
106
- * was truncated at the fetch limit.
107
- * @returns The formatted description string.
108
- */
109
- export function buildDescriptionWithComments(body, comments, hasMoreComments = false) {
110
- if (comments.length === 0) {
111
- return body;
112
- }
113
- const commentBlocks = comments.map((c) => {
114
- const header = `**@${c.author}** — ${c.createdAt}`;
115
- return `${header}\n\n${c.body}`;
116
- });
117
- let result = body + COMMENT_SEPARATOR + commentBlocks.join(COMMENT_SEPARATOR);
118
- if (hasMoreComments) {
119
- result += `${COMMENT_SEPARATOR}> **Note:** This issue has additional comments that were not fetched (limit: ${COMMENTS_PER_ISSUE}). View the full discussion on GitHub.`;
120
- }
121
- return result;
122
- }
123
- // ── Pure Transform Functions ────────────────────────────────────
124
- /**
125
- * Builds a deduplication map from existing tasks whose titles match
126
- * the `#<number>: <title>` pattern used by imported GitHub issues.
127
- *
128
- * @param existingTasks - Tasks already in the workspace.
129
- * @returns Maps and sets for deduplication during import planning.
130
- */
131
- export function buildExistingIssueMap(existingTasks) {
132
- const issueNumberPattern = /^#(\d+):/;
133
- const issueNumberToTaskId = new Map();
134
- const existingIssueNumbers = new Set();
135
- for (const t of existingTasks) {
136
- const match = t.title.match(issueNumberPattern);
137
- if (match) {
138
- const num = Number(match[1]);
139
- existingIssueNumbers.add(num);
140
- issueNumberToTaskId.set(num, t.id);
141
- }
142
- }
143
- return { issueNumberToTaskId, existingIssueNumbers };
144
- }
145
- /**
146
- * Given fetched issues and existing state, computes what to create and link
147
- * without performing any side effects.
148
- *
149
- * Performs topological sort, skips existing issues, generates IDs upfront,
150
- * resolves parent links and blockedBy dependencies, and returns a plan.
151
- *
152
- * @param issues - Fetched GitHub issues to import.
153
- * @param existingIssueNumbers - Issue numbers already imported (to skip).
154
- * @param existingIssueNumberToTaskId - Map from issue number to existing task ID.
155
- * @param generateId - Optional ID generator (defaults to `uuid().slice(0, 8)`).
156
- * @returns An {@link ImportPlan} describing all tasks to create and dependencies to set.
157
- */
158
- export function planImport(issues, existingIssueNumbers, existingIssueNumberToTaskId, generateId = () => uuid().slice(0, 8)) {
159
- // Topological sort: parents before children
160
- const issueSet = new Set(issues.map((i) => i.number));
161
- const sorted = topologicalSortIssues(issues, issueSet);
162
- // Mutable copy of the issue→taskId map so we can track newly generated IDs
163
- const issueNumberToTaskId = new Map(existingIssueNumberToTaskId);
164
- const tasksToCreate = [];
165
- const dependenciesToSet = [];
166
- let skipped = 0;
167
- let linked = 0;
168
- // First pass: generate IDs and resolve parent links
169
- for (const issue of sorted) {
170
- if (existingIssueNumbers.has(issue.number)) {
171
- skipped++;
172
- continue;
173
- }
174
- const id = generateId();
175
- issueNumberToTaskId.set(issue.number, id);
176
- const title = `#${issue.number}: ${issue.title}`;
177
- let parentTaskId = "";
178
- if (issue.parentNumber !== undefined) {
179
- const resolvedParentId = issueNumberToTaskId.get(issue.parentNumber);
180
- if (resolvedParentId) {
181
- parentTaskId = resolvedParentId;
182
- linked++;
183
- }
184
- }
185
- const description = buildDescriptionWithComments(issue.body, issue.comments, issue.commentsHasNextPage);
186
- tasksToCreate.push({ id, title, description, parentTaskId, issueNumber: issue.number });
187
- }
188
- // Build a map for O(1) lookup of issues by number during dependency resolution
189
- const issueNumberToIssue = new Map();
190
- for (const issue of sorted) {
191
- issueNumberToIssue.set(issue.number, issue);
192
- }
193
- // Second pass: resolve blockedBy → dependsOn for newly created tasks only
194
- for (const instruction of tasksToCreate) {
195
- const issue = issueNumberToIssue.get(instruction.issueNumber);
196
- if (!issue || issue.blockedByNumbers.length === 0) {
197
- continue;
198
- }
199
- const resolvedDeps = [];
200
- for (const blockerNumber of issue.blockedByNumbers) {
201
- const blockerTaskId = issueNumberToTaskId.get(blockerNumber);
202
- if (blockerTaskId) {
203
- resolvedDeps.push(blockerTaskId);
204
- }
205
- }
206
- if (resolvedDeps.length > 0) {
207
- dependenciesToSet.push({ taskId: instruction.id, dependsOn: resolvedDeps });
208
- }
209
- }
210
- return { tasksToCreate, dependenciesToSet, skipped, linked };
211
- }
212
- // ── Fetch Function ──────────────────────────────────────────────
213
- /**
214
- * Fetches GitHub issues from a repository via the `gh` CLI GraphQL API.
215
- * Paginates automatically and includes parent sub-issue information.
216
- *
217
- * @param repo - Repository in "owner/repo" format.
218
- * @param state - Issue state filter ("open" or "closed").
219
- * @param label - Optional label to filter issues by (client-side).
220
- * @param includeComments - When `true` (default), fetches issue comments and
221
- * includes them in each returned {@link GitHubIssue}. Pass `false` to omit
222
- * comments and reduce payload size.
223
- * @param client - Optional {@link GitHubClient} for testing (defaults to `gh` CLI).
224
- * @returns Array of parsed GitHub issues.
225
- */
226
- export async function fetchGitHubIssues(repo, state, label, includeComments = true, client = NODE_GITHUB_CLIENT) {
227
- const segments = repo.split("/");
228
- if (segments.length !== 2 || !segments[0] || !segments[1]) {
229
- throw new Error(`repo must be in "owner/repo" format (received: "${repo}")`);
230
- }
231
- const [owner, repoName] = segments;
232
- const upper = state.toUpperCase();
233
- if (upper !== "OPEN" && upper !== "CLOSED") {
234
- throw new Error(`state must be "open" or "closed" (received: "${state}")`);
235
- }
236
- const stateEnum = upper;
237
- const issues = [];
238
- let cursor;
239
- let hasNextPage = true;
240
- const commentsFragment = includeComments
241
- ? `comments(first: ${COMMENTS_PER_ISSUE}) {
242
- pageInfo { hasNextPage }
243
- nodes {
244
- author { login }
245
- createdAt
246
- body
247
- }
248
- }`
249
- : "";
250
- while (hasNextPage) {
251
- const query = `
252
- query($owner: String!, $repo: String!, $cursor: String) {
253
- repository(owner: $owner, name: $repo) {
254
- issues(first: ${ISSUES_PER_PAGE}, states: [${stateEnum}], after: $cursor) {
255
- pageInfo { hasNextPage endCursor }
256
- nodes {
257
- number
258
- title
259
- body
260
- parent { number }
261
- labels(first: 100) { nodes { name } }
262
- blockedBy(first: ${BLOCKED_BY_PER_ISSUE}) { nodes { number } }
263
- ${commentsFragment}
264
- }
265
- }
266
- }
267
- }`;
268
- const ghArgs = [
269
- "api", "graphql",
270
- "-f", `query=${query}`,
271
- "-f", `owner=${owner}`,
272
- "-f", `repo=${repoName}`,
273
- ];
274
- if (cursor !== undefined) {
275
- ghArgs.push("-f", `cursor=${cursor}`);
276
- }
277
- let ghOutput;
278
- try {
279
- ghOutput = await client.exec(ghArgs, {
280
- encoding: "utf8",
281
- maxBuffer: MAX_BUFFER_BYTES,
282
- });
283
- }
284
- catch (err) {
285
- throw new Error(`Failed to fetch issues via GraphQL for ${repo} (state=${state}): ${formatError(err)}`);
286
- }
287
- let parsed;
288
- try {
289
- parsed = JSON.parse(ghOutput);
290
- }
291
- catch (err) {
292
- throw new Error(`Failed to parse GraphQL response: ${formatError(err)}`);
293
- }
294
- if (parsed.errors && parsed.errors.length > 0) {
295
- const messages = parsed.errors.map((e) => e.message).join("; ");
296
- throw new Error(`GraphQL errors for ${repo}: ${messages}`);
297
- }
298
- if (!parsed.data?.repository) {
299
- throw new Error(`Repository not found or inaccessible: ${repo}`);
300
- }
301
- const issuesPage = parsed.data.repository.issues;
302
- for (const node of issuesPage.nodes) {
303
- const comments = (node.comments?.nodes ?? []).map((c) => ({
304
- author: c.author?.login ?? "ghost",
305
- createdAt: c.createdAt,
306
- body: c.body,
307
- }));
308
- issues.push({
309
- number: node.number,
310
- title: node.title,
311
- body: node.body,
312
- parentNumber: node.parent?.number ?? undefined,
313
- labels: node.labels.nodes.map((l) => l.name),
314
- blockedByNumbers: node.blockedBy.nodes.map((b) => b.number),
315
- comments,
316
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- pageInfo may be undefined when comments is present but empty
317
- commentsHasNextPage: node.comments?.pageInfo?.hasNextPage ?? false,
318
- });
319
- }
320
- hasNextPage = issuesPage.pageInfo.hasNextPage;
321
- cursor = issuesPage.pageInfo.endCursor ?? undefined;
322
- }
323
- // Filter by label client-side (GraphQL filterBy labels requires exact match array)
324
- if (label) {
325
- const beforeCount = issues.length;
326
- const filtered = issues.filter((i) => i.labels.includes(label));
327
- if (filtered.length < beforeCount) {
328
- logger.info({ label, before: beforeCount, after: filtered.length }, "Filtered issues by label");
329
- }
330
- return filtered;
331
- }
332
- return issues;
333
- }
334
- // ── Topological Sort ────────────────────────────────────────────
335
- /**
336
- * Topologically sorts issues so that parents appear before their children.
337
- * Issues whose parent is outside the import set are treated as roots.
338
- * Falls back to original order for issues at the same depth.
339
- *
340
- * @param issues - The list of GitHub issues to sort.
341
- * @param issueSet - Set of issue numbers in the current import batch.
342
- * @returns A new array of issues sorted with parents before children.
343
- */
344
- export function topologicalSortIssues(issues, issueSet) {
345
- const issueByNumber = new Map(issues.map((i) => [i.number, i]));
346
- const visited = new Set();
347
- const sorted = [];
348
- function visit(issue) {
349
- if (visited.has(issue.number)) {
350
- return;
351
- }
352
- visited.add(issue.number);
353
- // Visit parent first if it's in the import set
354
- if (issue.parentNumber !== undefined && issueSet.has(issue.parentNumber)) {
355
- const parent = issueByNumber.get(issue.parentNumber);
356
- if (parent) {
357
- visit(parent);
358
- }
359
- }
360
- sorted.push(issue);
361
- }
362
- for (const issue of issues) {
363
- visit(issue);
364
- }
365
- return sorted;
366
- }
367
- // ── Main Entry Point ────────────────────────────────────────────
368
- /**
369
- * Imports GitHub issues as Grackle tasks, with deduplication and parent linking.
370
- *
371
- * Orchestrates: fetch issues → dedup against existing tasks → plan (pure) →
372
- * persist tasks → broadcast updates → return summary.
373
- *
374
- * Only one import may run at a time; concurrent calls are rejected.
375
- *
376
- * @param workspaceId - The Grackle workspace ID to import tasks into.
377
- * @param repo - Repository in "owner/repo" format.
378
- * @param state - Issue state filter ("open" or "closed").
379
- * @param label - Optional label to filter issues by.
380
- * @param environmentId - Optional environment ID to assign to created tasks.
381
- * @param includeComments - When `true` (default), appends issue comments to each
382
- * task description. Pass `false` to import only the issue body (old behavior).
383
- * @param options - Optional dependency overrides for testing.
384
- * @returns Summary of imported, linked, and skipped issues.
385
- */
386
- export async function importGitHubIssues(workspaceId, repo, state, label, _environmentId, includeComments = true, options = {}) {
387
- const lock = options.importLock ?? DEFAULT_IMPORT_LOCK;
388
- lock.acquire();
389
- try {
390
- const client = options.githubClient ?? NODE_GITHUB_CLIENT;
391
- const persistence = options.persistence ?? NODE_TASK_PERSISTENCE;
392
- const emitter = options.eventEmitter ?? NODE_IMPORT_EVENT_EMITTER;
393
- const generateId = options.generateId ?? (() => uuid().slice(0, 8));
394
- // 1. Validate workspace
395
- const workspace = persistence.getWorkspace(workspaceId);
396
- if (!workspace) {
397
- throw new Error(`Workspace not found: ${workspaceId}`);
398
- }
399
- const workspaceSlug = slugify(workspace.name);
400
- // 2. FETCH — get issues from GitHub
401
- const issues = await fetchGitHubIssues(repo, state, label, includeComments, client);
402
- logger.info({ repo, state, label, count: issues.length, includeComments }, "Fetched GitHub issues");
403
- // 3. Read existing state for deduplication
404
- const existingTasks = persistence.listTasks(workspaceId);
405
- const { issueNumberToTaskId, existingIssueNumbers } = buildExistingIssueMap(existingTasks);
406
- // 4. TRANSFORM — pure planning step
407
- const plan = planImport(issues, existingIssueNumbers, issueNumberToTaskId, generateId);
408
- // 5. PERSIST — create tasks
409
- for (const task of plan.tasksToCreate) {
410
- persistence.createTask(task.id, workspaceId, task.title, task.description, [], workspaceSlug, task.parentTaskId, true);
411
- emitter.emit("task.created", { taskId: task.id, workspaceId });
412
- }
413
- // 6. PERSIST — set dependency relationships
414
- let dependencies = 0;
415
- for (const dep of plan.dependenciesToSet) {
416
- persistence.setTaskDependsOn(dep.taskId, dep.dependsOn);
417
- dependencies += dep.dependsOn.length;
418
- emitter.emit("task.updated", { taskId: dep.taskId, workspaceId });
419
- }
420
- logger.info({ workspaceId, imported: plan.tasksToCreate.length, linked: plan.linked, skipped: plan.skipped, dependencies }, "GitHub import complete");
421
- return { imported: plan.tasksToCreate.length, linked: plan.linked, skipped: plan.skipped, dependencies };
422
- }
423
- finally {
424
- lock.release();
425
- }
426
- }
427
- //# sourceMappingURL=github-import.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"github-import.js","sourceRoot":"","sources":["../src/github-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,uDAAuD;AACvD,MAAM,gBAAgB,GAAW,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAElD,4DAA4D;AAC5D,MAAM,iBAAiB,GAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,iDAAiD;AACjD,MAAM,eAAe,GAAW,GAAG,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAW,EAAE,CAAC;AAEtC,iFAAiF;AACjF,MAAM,iBAAiB,GAAW,aAAa,CAAC;AAEhD,mEAAmE;AACnE,MAAM,oBAAoB,GAAW,EAAE,CAAC;AAuCxC,mEAAmE;AAEnE,oEAAoE;AACpE,MAAM,kBAAkB,GAAiB;IACvC,IAAI,CACF,IAAc,EACd,OAA0E;QAE1E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,iBAAiB,CAAC;QACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,QAAQ,CACN,IAAI,EACJ,IAAI,EACJ,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EACvB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACtB,IAAI,GAAG,EAAE,CAAC;oBACP,GAAmD,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC7E,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,qEAAqE;AACrE,MAAM,qBAAqB,GAAoB;IAC7C,YAAY,CAAC,WAAmB;QAC9B,OAAO,cAAc,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IACD,SAAS,CAAC,WAAmB;QAC3B,OAAO,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IACD,UAAU,CACR,EAAU,EAAE,WAAmB,EAAE,KAAa,EAAE,WAAmB,EACnE,SAAmB,EAAE,aAAqB,EAAE,YAAoB,EAAE,YAAqB;QAEvF,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;IAClH,CAAC;IACD,gBAAgB,CAAC,MAAc,EAAE,SAAmB;QAClD,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC;CACF,CAAC;AAEF,2EAA2E;AAC3E,MAAM,yBAAyB,GAAuB;IACpD,IAAI,CACF,IAAqC,EACrC,OAAgD;QAEhD,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtB,CAAC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,eAAe,GAAwB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAE/D,iEAAiE;AACjE,MAAM,mBAAmB,GAAe;IACtC,OAAO;QACL,IAAI,eAAe,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACvF,CAAC;QACD,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC;IAChC,CAAC;IACD,OAAO;QACL,eAAe,CAAC,MAAM,GAAG,KAAK,CAAC;IACjC,CAAC;CACF,CAAC;AA0FF,mEAAmE;AAEnE;;;;;GAKG;AACH,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAI,GAAmD,CAAC,MAAM,CAAC;QAC3E,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,aAAa,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,4BAA4B,CAC1C,IAAY,EACZ,QAAyB,EACzB,kBAA2B,KAAK;IAEhC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACvC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,SAAS,EAAE,CAAC;QACnD,OAAO,GAAG,MAAM,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE9E,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,iBAAiB,gFAAgF,kBAAkB,wCAAwC,CAAC;IAC3K,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mEAAmE;AAEnE;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAmD;IAEnD,MAAM,kBAAkB,GAAW,UAAU,CAAC;IAC9C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtD,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/C,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7B,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CACxB,MAAqB,EACrB,oBAAiC,EACjC,2BAAgD,EAChD,aAA2B,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IAEnD,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEvD,2EAA2E;IAC3E,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAEjE,MAAM,aAAa,GAA4B,EAAE,CAAC;IAClD,MAAM,iBAAiB,GAA4B,EAAE,CAAC;IACtD,IAAI,OAAO,GAAW,CAAC,CAAC;IACxB,IAAI,MAAM,GAAW,CAAC,CAAC;IAEvB,oDAAoD;IACpD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAE1C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;QACjD,IAAI,YAAY,GAAW,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACrE,IAAI,gBAAgB,EAAE,CAAC;gBACrB,YAAY,GAAG,gBAAgB,CAAC;gBAChC,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG,4BAA4B,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAExG,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,+EAA+E;IAC/E,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,0EAA0E;IAC1E,KAAK,MAAM,WAAW,IAAI,aAAa,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC7D,IAAI,aAAa,EAAE,CAAC;gBAClB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC/D,CAAC;AAED,mEAAmE;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAY,EACZ,KAAa,EACb,KAAc,EACd,kBAA2B,IAAI,EAC/B,SAAuB,kBAAkB;IAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,IAAI,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAEnC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,gDAAgD,KAAK,IAAI,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC;IACxB,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,MAA0B,CAAC;IAC/B,IAAI,WAAW,GAAY,IAAI,CAAC;IAEhC,MAAM,gBAAgB,GAAG,eAAe;QACtC,CAAC,CAAC,mBAAmB,kBAAkB;;;;;;;cAO7B;QACV,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,WAAW,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG;;;0BAGQ,eAAe,cAAc,SAAS;;;;;;;;iCAQ/B,oBAAoB;gBACrC,gBAAgB;;;;QAIxB,CAAC;QAEL,MAAM,MAAM,GAAG;YACb,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,SAAS,KAAK,EAAE;YACtB,IAAI,EAAE,SAAS,KAAK,EAAE;YACtB,IAAI,EAAE,QAAQ,QAAQ,EAAE;SACzB,CAAC;QACF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE;gBACnC,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,gBAAgB;aAC5B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,WAAW,KAAK,MAAM,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1G,CAAC;QAED,IAAI,MAyBH,CAAC;QACF,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAkB,CAAC;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qCAAqC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,KAAK,QAAQ,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QACjD,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO;gBAClC,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CAAC,CAAC;YAEJ,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,SAAS;gBAC9C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5C,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC3D,QAAQ;gBACR,uIAAuI;gBACvI,mBAAmB,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,IAAI,KAAK;aACnE,CAAC,CAAC;QACL,CAAC;QAED,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC9C,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,SAAS,IAAI,SAAS,CAAC;IACtD,CAAC;IAED,mFAAmF;IACnF,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAChE,IAAI,QAAQ,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAClG,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mEAAmE;AAEnE;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAW,EACX,QAAqB;IAErB,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,MAAM,GAAQ,EAAE,CAAC;IAEvB,SAAS,KAAK,CAAC,KAAQ;QACrB,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE1B,+CAA+C;QAC/C,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YACzE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACrD,IAAI,MAAM,EAAE,CAAC;gBACX,KAAK,CAAC,MAAM,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mEAAmE;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB,EACnB,IAAY,EACZ,KAAa,EACb,KAAc,EACd,cAAuB,EACvB,kBAA2B,IAAI,EAC/B,UAAqC,EAAE;IAEvC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IACvD,IAAI,CAAC,OAAO,EAAE,CAAC;IACf,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,IAAI,kBAAkB,CAAC;QAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,qBAAqB,CAAC;QACjE,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,IAAI,yBAAyB,CAAC;QAClE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpE,wBAAwB;QACxB,MAAM,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE9C,oCAAoC;QACpC,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACpF,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,uBAAuB,CAAC,CAAC;QAEpG,2CAA2C;QAC3C,MAAM,aAAa,GAAG,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;QAE3F,oCAAoC;QACpC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;QAEvF,4BAA4B;QAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACtC,WAAW,CAAC,UAAU,CACpB,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAClD,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAC3C,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,4CAA4C;QAC5C,IAAI,YAAY,GAAW,CAAC,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzC,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;YACxD,YAAY,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,CAAC,IAAI,CACT,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,EAC9G,wBAAwB,CACzB,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IAC3G,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}