@llodev/pm-tasks-linear 0.0.0-pr-48-70482cb

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.
@@ -0,0 +1,410 @@
1
+ // pm-tasks-linear init flow — library surface (no CLI side effects).
2
+ // The bin entry (bin/init.ts) is a thin shim that imports runInit from here.
3
+ import { readFile } from "node:fs/promises";
4
+ import { fileURLToPath } from "node:url";
5
+ import path from "node:path";
6
+ import { promptPick, promptYesNo, promptLocale, loadStrings, registerI18nRoot, writeConfig, validateConfig, printInstructions, } from "@llodev/pm-tasks-core/init-lib";
7
+ // dist/init-flow.js → package root is one level up.
8
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
+ async function loadSchema() {
10
+ const raw = await readFile(path.join(ROOT, "schemas", "config.json"), "utf8");
11
+ return JSON.parse(raw);
12
+ }
13
+ // ---------------------------------------------------------------------------
14
+ // Constants
15
+ // ---------------------------------------------------------------------------
16
+ const LINEAR_10_VERBS = [
17
+ "task.create",
18
+ "task.move",
19
+ "checklist.check",
20
+ "task.close",
21
+ "task.due-date.set",
22
+ "task.assignee.add",
23
+ "task.comment.add",
24
+ "task.parent.set",
25
+ "task.estimate.set",
26
+ "task.sprint.set",
27
+ ];
28
+ const DEFAULT_FIBONACCI_SCALE = [1, 2, 3, 5, 8, 13];
29
+ const DEFAULT_SIZE_MAP = { XS: 1, S: 2, M: 3, L: 5, XL: 8 };
30
+ const STRATEGY_CHOICES = [
31
+ { label: "fibonacci (default)", value: "fibonacci" },
32
+ { label: "story_points", value: "story_points" },
33
+ { label: "planning_poker", value: "planning_poker" },
34
+ { label: "affinity", value: "affinity" },
35
+ { label: "t_shirt", value: "t_shirt" },
36
+ { label: "ideal_days", value: "ideal_days" },
37
+ { label: "ideal_hours", value: "ideal_hours" },
38
+ { label: "three_point", value: "three_point" },
39
+ ];
40
+ // ---------------------------------------------------------------------------
41
+ // Path A: MCP-driven API
42
+ // ---------------------------------------------------------------------------
43
+ function createMcpApi(mcp) {
44
+ return {
45
+ getTeams: async () => {
46
+ const res = await mcp("list_teams", {});
47
+ return extractNodes(res).map((n) => ({
48
+ id: String(n["id"] ?? ""),
49
+ key: String(n["key"] ?? ""),
50
+ name: String(n["name"] ?? ""),
51
+ }));
52
+ },
53
+ getStates: async (teamId) => {
54
+ const res = await mcp("list_issue_statuses", { team: teamId });
55
+ return extractNodes(res).map((n) => ({
56
+ id: String(n["id"] ?? ""),
57
+ name: String(n["name"] ?? ""),
58
+ type: String(n["type"] ?? ""),
59
+ }));
60
+ },
61
+ getLabels: async () => {
62
+ const res = await mcp("list_issue_labels", {});
63
+ return extractNodes(res).map((n) => ({
64
+ id: String(n["id"] ?? ""),
65
+ name: String(n["name"] ?? ""),
66
+ }));
67
+ },
68
+ getUsers: async () => {
69
+ const res = await mcp("list_users", {});
70
+ return extractNodes(res).map((n) => ({
71
+ id: String(n["id"] ?? ""),
72
+ name: String(n["name"] ?? ""),
73
+ email: typeof n["email"] === "string" ? n["email"] : undefined,
74
+ }));
75
+ },
76
+ getTeamSettings: async (teamId) => {
77
+ const res = await mcp("get_team", { query: teamId });
78
+ const obj = isRecord(res) ? res : {};
79
+ return {
80
+ cyclesEnabled: Boolean(obj["cyclesEnabled"] ?? false),
81
+ issueEstimationType: String(obj["issueEstimationType"] ?? "notUsed"),
82
+ };
83
+ },
84
+ getCycles: async (teamId) => {
85
+ const res = await mcp("list_cycles", { teamId });
86
+ return extractNodes(res);
87
+ },
88
+ getProjects: async (teamId) => {
89
+ const res = await mcp("list_projects", { team: teamId });
90
+ return extractNodes(res).map((n) => ({
91
+ id: String(n["id"] ?? ""),
92
+ name: String(n["name"] ?? ""),
93
+ }));
94
+ },
95
+ };
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Path B: GraphQL standalone (LINEAR_API_KEY in env)
99
+ // ---------------------------------------------------------------------------
100
+ function createGraphQLApi(apiKey) {
101
+ const GQL_URL = "https://api.linear.app/graphql";
102
+ // Linear personal API keys go directly in Authorization (no Bearer prefix).
103
+ async function gql(query, variables) {
104
+ const res = await globalThis.fetch(GQL_URL, {
105
+ method: "POST",
106
+ headers: {
107
+ Authorization: apiKey,
108
+ "Content-Type": "application/json",
109
+ },
110
+ body: JSON.stringify({ query, variables }),
111
+ });
112
+ if (!res.ok)
113
+ throw new Error(`Linear GraphQL HTTP ${res.status}`);
114
+ const body = (await res.json());
115
+ if (body.errors?.length)
116
+ throw new Error(`Linear GraphQL: ${body.errors[0].message}`);
117
+ if (!body.data)
118
+ throw new Error("Linear GraphQL: no data in response");
119
+ return body.data;
120
+ }
121
+ return {
122
+ getTeams: async () => {
123
+ const data = await gql(`{ teams { nodes { id key name } } }`);
124
+ return data.teams.nodes;
125
+ },
126
+ getStates: async (teamId) => {
127
+ const data = await gql(`query($id: String!) { team(id: $id) { states { nodes { id name type } } } }`, {
128
+ id: teamId,
129
+ });
130
+ return data.team.states.nodes;
131
+ },
132
+ getLabels: async () => {
133
+ const data = await gql(`{ issueLabels { nodes { id name } } }`);
134
+ return data.issueLabels.nodes;
135
+ },
136
+ getUsers: async () => {
137
+ const data = await gql(`{ users { nodes { id name email } } }`);
138
+ return data.users.nodes.map((u) => ({
139
+ id: u.id,
140
+ name: u.name,
141
+ email: u.email || undefined,
142
+ }));
143
+ },
144
+ getTeamSettings: async (teamId) => {
145
+ const data = await gql(`query($id: String!) { team(id: $id) { cyclesEnabled issueEstimationType } }`, {
146
+ id: teamId,
147
+ });
148
+ return {
149
+ cyclesEnabled: data.team.cyclesEnabled,
150
+ issueEstimationType: data.team.issueEstimationType,
151
+ };
152
+ },
153
+ getCycles: async (teamId) => {
154
+ const data = await gql(`query($id: String!) { team(id: $id) { cycles { nodes { id name number } } } }`, {
155
+ id: teamId,
156
+ });
157
+ return data.team.cycles.nodes;
158
+ },
159
+ getProjects: async (_teamId) => {
160
+ const data = await gql(`{ projects { nodes { id name } } }`);
161
+ return data.projects.nodes.map((p) => ({ id: p.id, name: p.name }));
162
+ },
163
+ };
164
+ }
165
+ // ---------------------------------------------------------------------------
166
+ // Sanitization (mirror jira — defense against CodeQL js/http-to-file-access)
167
+ // ---------------------------------------------------------------------------
168
+ const MAX_CONFIG_STRING_LEN = 1024;
169
+ function hasControlChar(s) {
170
+ for (let i = 0; i < s.length; i++) {
171
+ const code = s.charCodeAt(i);
172
+ if (code < 0x20 || code === 0x7f)
173
+ return true;
174
+ }
175
+ return false;
176
+ }
177
+ export function sanitizePersistedConfig(value) {
178
+ if (typeof value === "string") {
179
+ if (value.length > MAX_CONFIG_STRING_LEN || hasControlChar(value)) {
180
+ throw new Error(`pm-tasks-linear init: refusing to persist unsafe config value ${JSON.stringify(value.slice(0, 40))}`);
181
+ }
182
+ return value;
183
+ }
184
+ if (Array.isArray(value)) {
185
+ return value.map((item) => sanitizePersistedConfig(item));
186
+ }
187
+ if (value !== null && typeof value === "object") {
188
+ const clean = {};
189
+ for (const [key, item] of Object.entries(value)) {
190
+ clean[key] = sanitizePersistedConfig(item);
191
+ }
192
+ return clean;
193
+ }
194
+ return value;
195
+ }
196
+ // ---------------------------------------------------------------------------
197
+ // Internal helpers
198
+ // ---------------------------------------------------------------------------
199
+ function isRecord(v) {
200
+ return typeof v === "object" && v !== null && !Array.isArray(v);
201
+ }
202
+ function extractNodes(res) {
203
+ if (Array.isArray(res))
204
+ return res.filter(isRecord);
205
+ if (isRecord(res) && Array.isArray(res["nodes"])) {
206
+ return res["nodes"].filter(isRecord);
207
+ }
208
+ return [];
209
+ }
210
+ /** Strip surrounding quotes from an env value (defense against dotenv quoting). */
211
+ export function stripEnvQuotes(value) {
212
+ return value.replace(/^(['"])(.*)\1$/, "$2");
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // Main init flow (exported for testing)
216
+ // ---------------------------------------------------------------------------
217
+ export async function runInit(deps = {}) {
218
+ const outPath = deps.outPath ?? path.resolve(process.cwd(), ".linear.json");
219
+ const doLoadSchema = deps.doLoadSchema ?? loadSchema;
220
+ const doWrite = deps.doWrite ?? writeConfig;
221
+ const doValidate = deps.doValidate ?? validateConfig;
222
+ const doPick = deps.pick ?? promptPick;
223
+ const doYesNo = deps.yesNo ?? ((q) => promptYesNo(q));
224
+ // Resolve API — injected (tests) → MCP caller → GraphQL standalone
225
+ let api;
226
+ if (deps.api) {
227
+ api = deps.api;
228
+ }
229
+ else if (deps.mcp) {
230
+ api = createMcpApi(deps.mcp);
231
+ }
232
+ else {
233
+ const rawKey = process.env.LINEAR_API_KEY;
234
+ if (rawKey) {
235
+ const apiKey = stripEnvQuotes(rawKey);
236
+ api = createGraphQLApi(apiKey);
237
+ }
238
+ else {
239
+ printInstructions([
240
+ "pm-tasks-linear init requires Linear credentials.",
241
+ "Either connect the Linear MCP server in your Claude Code session,",
242
+ "or set LINEAR_API_KEY environment variable for standalone GraphQL discovery.",
243
+ "Linear MCP: https://linear.app/docs/mcp",
244
+ ]);
245
+ process.exit(1);
246
+ }
247
+ }
248
+ // -------------------------------------------------------------------------
249
+ // Step 0: Locale FIRST
250
+ // -------------------------------------------------------------------------
251
+ registerI18nRoot("linear", path.join(ROOT, "i18n"));
252
+ const locale = deps.locale ?? (await promptLocale("core", { defaultLocale: "en-US" }));
253
+ const strings = await loadStrings("linear", locale);
254
+ console.log(`\n${strings.header}\n`);
255
+ // -------------------------------------------------------------------------
256
+ // Step 1: Pick team
257
+ // -------------------------------------------------------------------------
258
+ const teams = await api.getTeams();
259
+ if (teams.length === 0) {
260
+ printInstructions([
261
+ "No Linear teams found.",
262
+ "Ensure your Linear MCP is authenticated or LINEAR_API_KEY is valid.",
263
+ ]);
264
+ process.exit(1);
265
+ }
266
+ let team;
267
+ if (teams.length === 1) {
268
+ team = teams[0];
269
+ }
270
+ else {
271
+ const picked = await doPick(strings.teamPrompt, teams.map((t) => ({ label: `${t.key} — ${t.name}`, value: t })), { defaultIndex: 0 });
272
+ if (!picked) {
273
+ process.stderr.write(`${strings.noTeam}\n`);
274
+ process.exit(1);
275
+ }
276
+ team = picked;
277
+ }
278
+ // -------------------------------------------------------------------------
279
+ // Step 2: Discover states, labels, users, team settings (parallel)
280
+ // -------------------------------------------------------------------------
281
+ const [states, labels, users, teamSettings] = await Promise.all([
282
+ api.getStates(team.id),
283
+ api.getLabels(),
284
+ api.getUsers(),
285
+ api.getTeamSettings(team.id),
286
+ ]);
287
+ // Cycles: team setting OR any cycles exist
288
+ let cyclesEnabled = teamSettings.cyclesEnabled;
289
+ if (!cyclesEnabled) {
290
+ try {
291
+ const cycles = await api.getCycles(team.id);
292
+ if (cycles.length > 0)
293
+ cyclesEnabled = true;
294
+ }
295
+ catch {
296
+ // leave as false
297
+ }
298
+ }
299
+ const members = users.map((u) => ({
300
+ id: u.id,
301
+ name: u.name,
302
+ ...(u.email ? { email: u.email } : {}),
303
+ }));
304
+ // -------------------------------------------------------------------------
305
+ // Step 2b: Discover projects and prompt for optional default
306
+ // -------------------------------------------------------------------------
307
+ let projects = [];
308
+ try {
309
+ projects = await api.getProjects(team.id);
310
+ }
311
+ catch {
312
+ // Non-fatal — proceed without projects
313
+ }
314
+ let defaultProjectId;
315
+ if (projects.length > 0) {
316
+ const projectChoices = [
317
+ { label: "(none)", value: null },
318
+ ...projects.map((p) => ({ label: p.name, value: p.id })),
319
+ ];
320
+ const picked = await doPick(strings.projectPrompt ?? "Default project (optional):", projectChoices, {
321
+ defaultIndex: 0,
322
+ });
323
+ if (picked != null) {
324
+ defaultProjectId = picked;
325
+ }
326
+ }
327
+ // -------------------------------------------------------------------------
328
+ // Step 3: Estimation strategy
329
+ // -------------------------------------------------------------------------
330
+ const strategy = (await doPick(strings.strategyPrompt, STRATEGY_CHOICES, { defaultIndex: 0 })) ?? "fibonacci";
331
+ const usesFibonacciScale = ["fibonacci", "story_points", "planning_poker"].includes(strategy);
332
+ const scale = usesFibonacciScale ? DEFAULT_FIBONACCI_SCALE : undefined;
333
+ // Determine estimation enabled from team setting (M2: always write explicitly)
334
+ const estimationEnabled = teamSettings.issueEstimationType !== "notUsed";
335
+ let linearTarget;
336
+ if (estimationEnabled) {
337
+ linearTarget =
338
+ (await doPick(strings.targetPromptPoints, [
339
+ { label: strings.targetPoints, value: "points" },
340
+ { label: strings.targetNone, value: "none" },
341
+ ], { defaultIndex: 0 })) ?? "points";
342
+ }
343
+ else {
344
+ linearTarget = "none";
345
+ }
346
+ const estimation = {
347
+ strategy,
348
+ linearTarget,
349
+ enabled: estimationEnabled, // M2: always write explicitly (never undefined at runtime)
350
+ };
351
+ if (scale)
352
+ estimation.scale = scale;
353
+ if (strategy === "t_shirt")
354
+ estimation.sizeMap = { ...DEFAULT_SIZE_MAP };
355
+ // -------------------------------------------------------------------------
356
+ // Step 4: Autonomous block
357
+ // -------------------------------------------------------------------------
358
+ const wantAuto = await doYesNo(strings.autonomousPrompt);
359
+ let autonomous;
360
+ if (wantAuto) {
361
+ const scopeProjects = defaultProjectId ? [defaultProjectId] : [];
362
+ autonomous = {
363
+ enabled: false,
364
+ allow: [...LINEAR_10_VERBS],
365
+ scope: {
366
+ teams: [team.id],
367
+ ...(scopeProjects.length > 0 ? { projects: scopeProjects } : {}),
368
+ },
369
+ rateLimit: { writesPerMinute: 30, commentsPerMinute: 10 },
370
+ auditLog: "./logs/linear/audit.log",
371
+ };
372
+ }
373
+ // -------------------------------------------------------------------------
374
+ // Step 5: Assemble, validate, and write config
375
+ // -------------------------------------------------------------------------
376
+ const out = {
377
+ version: "1",
378
+ locale,
379
+ team: { id: team.id, key: team.key, name: team.name },
380
+ };
381
+ if (states.length > 0)
382
+ out.states = states;
383
+ if (labels.length > 0)
384
+ out.labels = labels;
385
+ if (members.length > 0)
386
+ out.members = members;
387
+ if (projects.length > 0)
388
+ out.projects = projects;
389
+ if (defaultProjectId !== undefined)
390
+ out.defaultProjectId = defaultProjectId;
391
+ out.estimation = estimation;
392
+ out.cycles = { enabled: cyclesEnabled };
393
+ if (autonomous !== undefined)
394
+ out.autonomous = autonomous;
395
+ const schema = await doLoadSchema();
396
+ const valid = await doValidate(out, schema);
397
+ if (!valid.ok) {
398
+ console.error("pm-tasks-linear init: config validation failed:", JSON.stringify(valid.errors, null, 2));
399
+ process.exit(1);
400
+ }
401
+ const safeConfig = sanitizePersistedConfig(out);
402
+ await doWrite(outPath, safeConfig, { locale });
403
+ printInstructions([
404
+ `Config written to ${outPath}`,
405
+ strings.nextDoctor,
406
+ "Linear MCP: https://linear.app/docs/mcp",
407
+ ]);
408
+ return safeConfig;
409
+ }
410
+ //# sourceMappingURL=init-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-flow.js","sourceRoot":"","sources":["../src/init-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Linear MCP transport — implements the @llodev/pm-tasks-core Transport
3
+ * interface by dispatching every canonical verb through
4
+ * `mcp__linear__*` tool calls. The MCP dispatcher is injected
5
+ * (caller-supplied callback) so this module stays:
6
+ *
7
+ * - testable — tests inject a recording stub
8
+ * - side-effect free — `import` does not throw, log, or call anything
9
+ * - decoupled at build — no `mcp__*` symbols are referenced at compile time
10
+ *
11
+ * Linear-specific deltas vs Jira transport:
12
+ * - Most mutations collapse into ONE upsert tool `save_issue`:
13
+ * id present = update; absent = create.
14
+ * - State resolution uses type strings ("unstarted", "started", "completed")
15
+ * rather than transition ids. Resolve against config.states by type.
16
+ * - Checklist items are modelled as sub-issues (parentId = parent issue id).
17
+ * "check" = move sub-issue to a completed-type state.
18
+ * - `taskAssigneeAdd` is single-assignee set-not-add (Linear only supports one).
19
+ * - `taskEstimateSet` uses normalizeEstimate + an idempotent `est:<slug>`
20
+ * label (replace-set: read current labels, strip est:*, merge, write full set).
21
+ * Gated on config.estimation.enabled; returns NOT_APPLICABLE when disabled.
22
+ * - `taskSprintSet` assigns a cycle via `save_issue { cycle: sprintRef }`.
23
+ * Gated on config.cycles.enabled; returns NOT_APPLICABLE when disabled.
24
+ * - `taskParentSet` supports arbitrary depth; null parentId detaches.
25
+ */
26
+ import type { Transport, TransportResult, TaskEstimateSetResponse } from "@llodev/pm-tasks-core/runtime";
27
+ import type { EstimateInput, EstimationStrategy } from "@llodev/pm-tasks-core/estimation";
28
+ /**
29
+ * MCP-call dispatcher. The agent runtime that loads this transport
30
+ * provides a function that proxies to the real `mcp__linear__*`
31
+ * tools. Tests inject a recording stub.
32
+ */
33
+ export type McpCaller = (toolName: string, args: Record<string, unknown>) => Promise<unknown>;
34
+ /**
35
+ * Linear workspace/team identity — NOT exported; adapter.ts narrows from
36
+ * the parsed `.linear.json` config. Transport closes over these values at
37
+ * factory time so that no verb needs to read them from the request.
38
+ */
39
+ interface LinearConfig {
40
+ team: {
41
+ id: string;
42
+ key: string;
43
+ name: string;
44
+ };
45
+ states?: Array<{
46
+ id: string;
47
+ name: string;
48
+ type: string;
49
+ }>;
50
+ labels?: Array<{
51
+ id: string;
52
+ name: string;
53
+ }>;
54
+ members?: Array<{
55
+ id: string;
56
+ name: string;
57
+ email?: string;
58
+ alias?: string;
59
+ }>;
60
+ estimation?: {
61
+ strategy: string;
62
+ linearTarget: "points" | "none";
63
+ enabled?: boolean;
64
+ scale?: number[];
65
+ sizeMap?: Record<string, number>;
66
+ };
67
+ cycles?: {
68
+ enabled: boolean;
69
+ };
70
+ projects?: Array<{
71
+ id: string;
72
+ name: string;
73
+ }>;
74
+ defaultProjectId?: string;
75
+ }
76
+ export interface CreateLinearTransportOptions {
77
+ mcp: McpCaller;
78
+ config: LinearConfig;
79
+ }
80
+ /**
81
+ * Linear-specific estimation config — uses `linearTarget` instead of the
82
+ * Jira-named `jiraTarget` field from core's EstimationConfig.
83
+ * Mapped to EstimationConfig internally before calling normalizeEstimate.
84
+ */
85
+ export interface LinearEstimationConfig {
86
+ strategy: EstimationStrategy;
87
+ /** "points" → write Linear estimate field + est: label; "none" → label only */
88
+ linearTarget: "points" | "none";
89
+ scale?: number[];
90
+ sizeMap?: Record<string, number>;
91
+ }
92
+ /** Linear-specific override of TaskEstimateSetRequest with linearTarget config. */
93
+ export interface LinearTaskEstimateSetRequest {
94
+ taskId: string;
95
+ input: EstimateInput;
96
+ config: LinearEstimationConfig;
97
+ }
98
+ /**
99
+ * Linear transport type — identical to Transport but narrows taskEstimateSet
100
+ * to accept LinearTaskEstimateSetRequest (uses linearTarget, not jiraTarget).
101
+ */
102
+ export type LinearTransport = Omit<Transport, "taskEstimateSet"> & {
103
+ taskEstimateSet?(req: LinearTaskEstimateSetRequest): Promise<TransportResult<TaskEstimateSetResponse>>;
104
+ };
105
+ export declare function createLinearTransport(opts: CreateLinearTransportOptions): LinearTransport;
106
+ export {};
107
+ //# sourceMappingURL=transport-linear.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-linear.d.ts","sourceRoot":"","sources":["../src/transport-linear.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EAkBf,uBAAuB,EAGxB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAM1F;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9F;;;;GAIG;AACH,UAAU,YAAY;IACpB,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,QAAQ,GAAG,MAAM,CAAC;QAChC,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC,CAAC;IACF,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,+EAA+E;IAC/E,YAAY,EAAE,QAAQ,GAAG,MAAM,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,mFAAmF;AACnF,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,GAAG;IACjE,eAAe,CAAC,CACd,GAAG,EAAE,4BAA4B,GAChC,OAAO,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,CAAC;CACtD,CAAC;AA+FF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,eAAe,CA+WzF"}