golem-cc 2.1.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.claude/commands/golem/build.md +18 -0
  2. package/.claude/commands/golem/config.md +39 -0
  3. package/.claude/commands/golem/continue.md +73 -0
  4. package/.claude/commands/golem/doctor.md +46 -0
  5. package/.claude/commands/golem/document.md +138 -0
  6. package/.claude/commands/golem/help.md +58 -0
  7. package/.claude/commands/golem/pause.md +130 -0
  8. package/.claude/commands/golem/plan.md +111 -0
  9. package/.claude/commands/golem/review.md +166 -0
  10. package/.claude/commands/golem/security.md +186 -0
  11. package/.claude/commands/golem/simplify.md +76 -0
  12. package/.claude/commands/golem/spec.md +105 -0
  13. package/.claude/commands/golem/status.md +33 -0
  14. package/.golem/agents/code-simplifier.md +54 -0
  15. package/.golem/agents/review-architecture.md +59 -0
  16. package/.golem/agents/review-logic.md +50 -0
  17. package/.golem/agents/review-security.md +50 -0
  18. package/.golem/agents/review-style.md +48 -0
  19. package/.golem/agents/review-tests.md +48 -0
  20. package/.golem/agents/spec-builder.md +60 -0
  21. package/.golem/bin/golem.mjs +270 -0
  22. package/.golem/lib/build.mjs +557 -0
  23. package/.golem/lib/claude.mjs +95 -0
  24. package/.golem/lib/config.mjs +421 -0
  25. package/.golem/lib/display.mjs +191 -0
  26. package/.golem/lib/doctor.mjs +197 -0
  27. package/.golem/lib/document.mjs +792 -0
  28. package/.golem/lib/gates.mjs +78 -0
  29. package/.golem/lib/init.mjs +166 -0
  30. package/.golem/lib/output.mjs +40 -0
  31. package/.golem/lib/ratelimit.mjs +86 -0
  32. package/.golem/lib/security.mjs +603 -0
  33. package/.golem/lib/simplify.mjs +101 -0
  34. package/.golem/lib/tui.mjs +368 -0
  35. package/.golem/lib/usage.mjs +119 -0
  36. package/.golem/lib/worktree.mjs +509 -0
  37. package/.golem/prompts/build.md +23 -0
  38. package/.golem/prompts/document-inline.md +66 -0
  39. package/.golem/prompts/document-markdown.md +80 -0
  40. package/.golem/prompts/simplify.md +35 -0
  41. package/README.md +141 -142
  42. package/bin/golem-shim.mjs +36 -0
  43. package/bin/install.mjs +193 -0
  44. package/package.json +27 -32
  45. package/.env.example +0 -17
  46. package/bin/golem +0 -1040
  47. package/commands/golem/build.md +0 -235
  48. package/commands/golem/config.md +0 -55
  49. package/commands/golem/doctor.md +0 -137
  50. package/commands/golem/help.md +0 -212
  51. package/commands/golem/plan.md +0 -214
  52. package/commands/golem/review.md +0 -376
  53. package/commands/golem/security.md +0 -204
  54. package/commands/golem/simplify.md +0 -94
  55. package/commands/golem/spec.md +0 -226
  56. package/commands/golem/status.md +0 -60
  57. package/dist/api/freshworks.d.ts +0 -61
  58. package/dist/api/freshworks.d.ts.map +0 -1
  59. package/dist/api/freshworks.js +0 -119
  60. package/dist/api/freshworks.js.map +0 -1
  61. package/dist/api/gitea.d.ts +0 -96
  62. package/dist/api/gitea.d.ts.map +0 -1
  63. package/dist/api/gitea.js +0 -154
  64. package/dist/api/gitea.js.map +0 -1
  65. package/dist/cli/index.d.ts +0 -9
  66. package/dist/cli/index.d.ts.map +0 -1
  67. package/dist/cli/index.js +0 -352
  68. package/dist/cli/index.js.map +0 -1
  69. package/dist/sync/ticket-sync.d.ts +0 -53
  70. package/dist/sync/ticket-sync.d.ts.map +0 -1
  71. package/dist/sync/ticket-sync.js +0 -226
  72. package/dist/sync/ticket-sync.js.map +0 -1
  73. package/dist/types.d.ts +0 -125
  74. package/dist/types.d.ts.map +0 -1
  75. package/dist/types.js +0 -5
  76. package/dist/types.js.map +0 -1
  77. package/dist/worktree/manager.d.ts +0 -54
  78. package/dist/worktree/manager.d.ts.map +0 -1
  79. package/dist/worktree/manager.js +0 -190
  80. package/dist/worktree/manager.js.map +0 -1
  81. package/golem/agents/code-simplifier.md +0 -81
  82. package/golem/agents/spec-builder.md +0 -90
  83. package/golem/prompts/PROMPT_build.md +0 -71
  84. package/golem/prompts/PROMPT_plan.md +0 -102
package/dist/cli/index.js DELETED
@@ -1,352 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * golem-api CLI
4
- *
5
- * TypeScript helper for API operations, called by the main golem bash script.
6
- * Handles JSON parsing and API communication cleanly.
7
- */
8
- import { program } from 'commander';
9
- import chalk from 'chalk';
10
- import { createSyncContext, createLinkedTicket, importFreshTicket, updateTicketStatus, loadTicketState, recordCommit } from '../sync/ticket-sync.js';
11
- import { createWorktree, removeWorktree, getRepoRoot, listWorktrees, squashCommits, pushBranch } from '../worktree/manager.js';
12
- import { createFreshworksClient } from '../api/freshworks.js';
13
- import { createGiteaClient } from '../api/gitea.js';
14
- import { join } from 'node:path';
15
- // Load .env from project root or home
16
- import { config } from 'dotenv';
17
- config({ path: join(process.cwd(), '.env') });
18
- config({ path: join(process.env.HOME || '', '.golem/.env') });
19
- const golemDir = join(process.cwd(), '.golem');
20
- const ticketsDir = join(golemDir, 'tickets');
21
- program
22
- .name('golem-api')
23
- .description('Golem API helper for Freshworks/Gitea integration')
24
- .version('0.1.0');
25
- // ============ Ticket Commands ============
26
- program
27
- .command('ticket:new')
28
- .description('Create a new linked ticket in Fresh + Gitea')
29
- .requiredOption('-s, --subject <subject>', 'Ticket subject')
30
- .requiredOption('-d, --description <description>', 'Ticket description')
31
- .requiredOption('-t, --type <type>', 'Commit type (feat|fix|refactor|docs|test|chore)')
32
- .requiredOption('--slug <slug>', 'Human-readable slug for branch name')
33
- .option('-p, --priority <priority>', 'Priority (1-4)', '3')
34
- .option('-r, --repo <repo>', 'Gitea repo (default from GITEA_REPO env)')
35
- .action(async (opts) => {
36
- try {
37
- const repo = opts.repo || process.env.GITEA_REPO;
38
- if (!repo) {
39
- console.error(chalk.red('Error: --repo required or set GITEA_REPO'));
40
- process.exit(1);
41
- }
42
- const ctx = createSyncContext(ticketsDir, repo);
43
- const ticket = await createLinkedTicket(ctx, {
44
- subject: opts.subject,
45
- description: opts.description,
46
- type: opts.type,
47
- slug: opts.slug,
48
- priority: parseInt(opts.priority),
49
- });
50
- console.log(chalk.green(`✓ Created ticket ${ticket.id}`));
51
- console.log(chalk.dim(` Fresh: ${ticket.fresh?.url}`));
52
- console.log(chalk.dim(` Gitea: ${ticket.gitea?.url}`));
53
- console.log(chalk.dim(` Branch: ${ticket.git.branch}`));
54
- // Output JSON for bash script to parse
55
- console.log(JSON.stringify(ticket));
56
- }
57
- catch (e) {
58
- console.error(chalk.red(`Error: ${e}`));
59
- process.exit(1);
60
- }
61
- });
62
- program
63
- .command('ticket:import <freshId>')
64
- .description('Import existing Fresh ticket and create linked Gitea issue')
65
- .requiredOption('-t, --type <type>', 'Commit type (feat|fix|refactor|docs|test|chore)')
66
- .requiredOption('--slug <slug>', 'Human-readable slug for branch name')
67
- .option('-r, --repo <repo>', 'Gitea repo (default from GITEA_REPO env)')
68
- .action(async (freshId, opts) => {
69
- try {
70
- const repo = opts.repo || process.env.GITEA_REPO;
71
- if (!repo) {
72
- console.error(chalk.red('Error: --repo required or set GITEA_REPO'));
73
- process.exit(1);
74
- }
75
- const ctx = createSyncContext(ticketsDir, repo);
76
- const ticket = await importFreshTicket(ctx, freshId, {
77
- type: opts.type,
78
- slug: opts.slug,
79
- });
80
- console.log(chalk.green(`✓ Imported ticket ${ticket.id}`));
81
- console.log(chalk.dim(` Fresh: ${ticket.fresh?.url}`));
82
- console.log(chalk.dim(` Gitea: ${ticket.gitea?.url}`));
83
- console.log(chalk.dim(` Branch: ${ticket.git.branch}`));
84
- console.log(JSON.stringify(ticket));
85
- }
86
- catch (e) {
87
- console.error(chalk.red(`Error: ${e}`));
88
- process.exit(1);
89
- }
90
- });
91
- program
92
- .command('ticket:status <ticketId> <status>')
93
- .description('Update ticket status and sync to Fresh/Gitea')
94
- .option('-n, --note <note>', 'Status note')
95
- .option('-r, --repo <repo>', 'Gitea repo')
96
- .action(async (ticketId, status, opts) => {
97
- try {
98
- const repo = opts.repo || process.env.GITEA_REPO;
99
- if (!repo) {
100
- console.error(chalk.red('Error: --repo required or set GITEA_REPO'));
101
- process.exit(1);
102
- }
103
- const ctx = createSyncContext(ticketsDir, repo);
104
- const result = await updateTicketStatus(ctx, ticketId, status, opts.note);
105
- if (result.success) {
106
- console.log(chalk.green(`✓ Updated ${ticketId} to ${status}`));
107
- if (result.freshUpdated)
108
- console.log(chalk.dim(' Fresh updated'));
109
- if (result.giteaUpdated)
110
- console.log(chalk.dim(' Gitea updated'));
111
- }
112
- else {
113
- console.error(chalk.red(`Error: ${result.error}`));
114
- process.exit(1);
115
- }
116
- }
117
- catch (e) {
118
- console.error(chalk.red(`Error: ${e}`));
119
- process.exit(1);
120
- }
121
- });
122
- program
123
- .command('ticket:get <ticketId>')
124
- .description('Get ticket state as JSON')
125
- .action(async (ticketId) => {
126
- try {
127
- const ticket = await loadTicketState(ticketsDir, ticketId);
128
- if (!ticket) {
129
- console.error(chalk.red(`Ticket ${ticketId} not found`));
130
- process.exit(1);
131
- }
132
- console.log(JSON.stringify(ticket, null, 2));
133
- }
134
- catch (e) {
135
- console.error(chalk.red(`Error: ${e}`));
136
- process.exit(1);
137
- }
138
- });
139
- program
140
- .command('ticket:list')
141
- .description('List all tickets')
142
- .option('--status <status>', 'Filter by status')
143
- .option('--json', 'Output as JSON')
144
- .action(async (opts) => {
145
- try {
146
- const { readdir } = await import('node:fs/promises');
147
- const files = await readdir(ticketsDir).catch(() => []);
148
- const tickets = [];
149
- for (const file of files) {
150
- if (!file.endsWith('.yaml'))
151
- continue;
152
- const ticketId = file.replace('.yaml', '');
153
- const ticket = await loadTicketState(ticketsDir, ticketId);
154
- if (ticket && (!opts.status || ticket.status === opts.status)) {
155
- tickets.push(ticket);
156
- }
157
- }
158
- if (opts.json) {
159
- console.log(JSON.stringify(tickets, null, 2));
160
- }
161
- else {
162
- if (tickets.length === 0) {
163
- console.log(chalk.dim('No tickets found'));
164
- }
165
- else {
166
- for (const t of tickets) {
167
- const statusColor = t.status === 'done' ? chalk.green
168
- : t.status === 'in-progress' ? chalk.yellow
169
- : t.status === 'blocked' ? chalk.red
170
- : chalk.dim;
171
- console.log(`${chalk.bold(t.id)} ${statusColor(`[${t.status}]`)} ${t.fresh?.subject || t.slug}`);
172
- console.log(chalk.dim(` ${t.git.branch}`));
173
- }
174
- }
175
- }
176
- }
177
- catch (e) {
178
- console.error(chalk.red(`Error: ${e}`));
179
- process.exit(1);
180
- }
181
- });
182
- // ============ Worktree Commands ============
183
- program
184
- .command('worktree:create <ticketId>')
185
- .description('Create git worktree for a ticket')
186
- .option('-b, --base <branch>', 'Base branch (default: main)')
187
- .action(async (ticketId, opts) => {
188
- try {
189
- const ticket = await loadTicketState(ticketsDir, ticketId);
190
- if (!ticket) {
191
- console.error(chalk.red(`Ticket ${ticketId} not found`));
192
- process.exit(1);
193
- }
194
- const path = await createWorktree(ticket, { baseBranch: opts.base });
195
- console.log(chalk.green(`✓ Created worktree at ${path}`));
196
- console.log(path); // For bash to capture
197
- }
198
- catch (e) {
199
- console.error(chalk.red(`Error: ${e}`));
200
- process.exit(1);
201
- }
202
- });
203
- program
204
- .command('worktree:list')
205
- .description('List all worktrees')
206
- .option('--json', 'Output as JSON')
207
- .action(async (opts) => {
208
- try {
209
- const worktrees = listWorktrees();
210
- if (opts.json) {
211
- console.log(JSON.stringify(worktrees, null, 2));
212
- }
213
- else {
214
- for (const wt of worktrees) {
215
- console.log(`${chalk.bold(wt.branch)}`);
216
- console.log(chalk.dim(` ${wt.path}`));
217
- }
218
- }
219
- }
220
- catch (e) {
221
- console.error(chalk.red(`Error: ${e}`));
222
- process.exit(1);
223
- }
224
- });
225
- program
226
- .command('worktree:remove <path>')
227
- .description('Remove a worktree')
228
- .action(async (path) => {
229
- try {
230
- await removeWorktree(path);
231
- console.log(chalk.green(`✓ Removed worktree`));
232
- }
233
- catch (e) {
234
- console.error(chalk.red(`Error: ${e}`));
235
- process.exit(1);
236
- }
237
- });
238
- // ============ Git Commands ============
239
- program
240
- .command('git:squash <ticketId>')
241
- .description('Squash all commits for a ticket into one')
242
- .requiredOption('-m, --message <message>', 'Commit message')
243
- .option('-b, --base <branch>', 'Base branch')
244
- .action(async (ticketId, opts) => {
245
- try {
246
- const ticket = await loadTicketState(ticketsDir, ticketId);
247
- if (!ticket) {
248
- console.error(chalk.red(`Ticket ${ticketId} not found`));
249
- process.exit(1);
250
- }
251
- const repoRoot = getRepoRoot();
252
- const worktreePath = join(repoRoot, ticket.git.worktree);
253
- const sha = await squashCommits(worktreePath, opts.message, opts.base);
254
- console.log(chalk.green(`✓ Squashed to ${sha.slice(0, 8)}`));
255
- console.log(sha);
256
- }
257
- catch (e) {
258
- console.error(chalk.red(`Error: ${e}`));
259
- process.exit(1);
260
- }
261
- });
262
- program
263
- .command('git:push <ticketId>')
264
- .description('Push ticket branch to remote')
265
- .option('-f, --force', 'Force push (with lease)')
266
- .action(async (ticketId, opts) => {
267
- try {
268
- const ticket = await loadTicketState(ticketsDir, ticketId);
269
- if (!ticket) {
270
- console.error(chalk.red(`Ticket ${ticketId} not found`));
271
- process.exit(1);
272
- }
273
- const repoRoot = getRepoRoot();
274
- const worktreePath = join(repoRoot, ticket.git.worktree);
275
- await pushBranch(worktreePath, opts.force);
276
- console.log(chalk.green(`✓ Pushed ${ticket.git.branch}`));
277
- }
278
- catch (e) {
279
- console.error(chalk.red(`Error: ${e}`));
280
- process.exit(1);
281
- }
282
- });
283
- program
284
- .command('git:commit <ticketId> <sha>')
285
- .description('Record a commit against a ticket')
286
- .action(async (ticketId, sha) => {
287
- try {
288
- await recordCommit(ticketsDir, ticketId, sha);
289
- console.log(chalk.green(`✓ Recorded commit ${sha.slice(0, 8)}`));
290
- }
291
- catch (e) {
292
- console.error(chalk.red(`Error: ${e}`));
293
- process.exit(1);
294
- }
295
- });
296
- // ============ API Test Commands ============
297
- program
298
- .command('fresh:test')
299
- .description('Test Freshworks API connection')
300
- .action(async () => {
301
- try {
302
- const client = createFreshworksClient();
303
- const tickets = await client.getMyTickets();
304
- console.log(chalk.green(`✓ Connected to Freshworks`));
305
- console.log(chalk.dim(` Found ${tickets.length} tickets assigned to you`));
306
- }
307
- catch (e) {
308
- console.error(chalk.red(`Error: ${e}`));
309
- process.exit(1);
310
- }
311
- });
312
- program
313
- .command('fresh:list')
314
- .description('List your Freshworks tickets')
315
- .option('--json', 'Output as JSON')
316
- .action(async (opts) => {
317
- try {
318
- const client = createFreshworksClient();
319
- const tickets = await client.getMyTickets();
320
- if (opts.json) {
321
- console.log(JSON.stringify(tickets, null, 2));
322
- }
323
- else {
324
- for (const t of tickets) {
325
- const id = client.constructor.prototype.constructor.formatTicketId(t.id, t.ticket_type);
326
- console.log(`${chalk.bold(id)} ${t.subject}`);
327
- console.log(chalk.dim(` Priority: ${t.priority} | Status: ${t.status}`));
328
- }
329
- }
330
- }
331
- catch (e) {
332
- console.error(chalk.red(`Error: ${e}`));
333
- process.exit(1);
334
- }
335
- });
336
- program
337
- .command('gitea:test')
338
- .description('Test Gitea API connection')
339
- .action(async () => {
340
- try {
341
- const client = createGiteaClient();
342
- const repos = await client.listOrgRepos();
343
- console.log(chalk.green(`✓ Connected to Gitea`));
344
- console.log(chalk.dim(` Found ${repos.length} repos in org`));
345
- }
346
- catch (e) {
347
- console.error(chalk.red(`Error: ${e}`));
348
- process.exit(1);
349
- }
350
- });
351
- program.parse();
352
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACrJ,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC/H,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,sCAAsC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAC9C,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;AAE9D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAE7C,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,4CAA4C;AAE5C,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,cAAc,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;KAC3D,cAAc,CAAC,iCAAiC,EAAE,oBAAoB,CAAC;KACvE,cAAc,CAAC,mBAAmB,EAAE,iDAAiD,CAAC;KACtF,cAAc,CAAC,eAAe,EAAE,qCAAqC,CAAC;KACtE,MAAM,CAAC,2BAA2B,EAAE,gBAAgB,EAAE,GAAG,CAAC;KAC1D,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE;YAC3C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAkB;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAkB;SACnD,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEzD,uCAAuC;QACvC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,yBAAyB,CAAC;KAClC,WAAW,CAAC,4DAA4D,CAAC;KACzE,cAAc,CAAC,mBAAmB,EAAE,iDAAiD,CAAC;KACtF,cAAc,CAAC,eAAe,EAAE,qCAAqC,CAAC;KACtE,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE;YACnD,IAAI,EAAE,IAAI,CAAC,IAAkB;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEzD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,mCAAmC,CAAC;KAC5C,WAAW,CAAC,8CAA8C,CAAC;KAC3D,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;KAC1C,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC;KACzC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAsB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE1F,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,QAAQ,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/D,IAAI,MAAM,CAAC,YAAY;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACnE,IAAI,MAAM,CAAC,YAAY;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,uBAAuB,CAAC;KAChC,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;IACzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,kBAAkB,CAAC;KAC/B,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC;KAC/C,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,EAAE,CAAC;QAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC3D,IAAI,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;wBACnD,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;4BAC3C,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;gCACpC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;oBACd,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;oBACjG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,8CAA8C;AAE9C,OAAO;KACJ,OAAO,CAAC,4BAA4B,CAAC;KACrC,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,sBAAsB;IAC3C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,wBAAwB,CAAC;KACjC,WAAW,CAAC,mBAAmB,CAAC;KAChC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,yCAAyC;AAEzC,OAAO;KACJ,OAAO,CAAC,uBAAuB,CAAC;KAChC,WAAW,CAAC,0CAA0C,CAAC;KACvD,cAAc,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;KAC3D,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEzD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,aAAa,EAAE,yBAAyB,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEzD,MAAM,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,6BAA6B,CAAC;KACtC,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;IAC9B,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,8CAA8C;AAE9C,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,0BAA0B,CAAC,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAE5C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;gBACxF,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,eAAe,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1,53 +0,0 @@
1
- /**
2
- * Bi-directional sync between Freshworks, Gitea, and local state
3
- *
4
- * Local state (.golem/tickets/*.yaml) is the source of truth.
5
- * This module handles pushing updates to Fresh and Gitea.
6
- */
7
- import type { TicketState, SyncResult, TicketStatus, CommitType } from '../types.js';
8
- import { FreshworksClient } from '../api/freshworks.js';
9
- import { GiteaClient } from '../api/gitea.js';
10
- export interface SyncContext {
11
- fresh: FreshworksClient;
12
- gitea: GiteaClient;
13
- ticketsDir: string;
14
- repo: string;
15
- }
16
- /**
17
- * Load ticket state from local YAML file
18
- */
19
- export declare function loadTicketState(ticketsDir: string, ticketId: string): Promise<TicketState | null>;
20
- /**
21
- * Save ticket state to local YAML file
22
- */
23
- export declare function saveTicketState(ticketsDir: string, state: TicketState): Promise<void>;
24
- /**
25
- * Create a new ticket in both Fresh and Gitea, linked together
26
- */
27
- export declare function createLinkedTicket(ctx: SyncContext, params: {
28
- subject: string;
29
- description: string;
30
- type: CommitType;
31
- slug: string;
32
- priority?: 1 | 2 | 3 | 4;
33
- }): Promise<TicketState>;
34
- /**
35
- * Import an existing Fresh ticket and create linked Gitea issue
36
- */
37
- export declare function importFreshTicket(ctx: SyncContext, freshTicketId: number | string, params: {
38
- type: CommitType;
39
- slug: string;
40
- }): Promise<TicketState>;
41
- /**
42
- * Update ticket status and sync to Fresh/Gitea
43
- */
44
- export declare function updateTicketStatus(ctx: SyncContext, ticketId: string, newStatus: TicketStatus, note?: string): Promise<SyncResult>;
45
- /**
46
- * Record a commit against a ticket
47
- */
48
- export declare function recordCommit(ticketsDir: string, ticketId: string, commitSha: string): Promise<void>;
49
- /**
50
- * Create sync context from environment
51
- */
52
- export declare function createSyncContext(ticketsDir: string, repo: string): SyncContext;
53
- //# sourceMappingURL=ticket-sync.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ticket-sync.d.ts","sourceRoot":"","sources":["../../src/sync/ticket-sync.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAA0B,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAqB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAQ7B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE;IACN,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC1B,GACA,OAAO,CAAC,WAAW,CAAC,CA+DtB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,WAAW,EAChB,aAAa,EAAE,MAAM,GAAG,MAAM,EAC9B,MAAM,EAAE;IACN,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,GACA,OAAO,CAAC,WAAW,CAAC,CAuEtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,YAAY,EACvB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAoDrB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,WAAW,CAOb"}
@@ -1,226 +0,0 @@
1
- /**
2
- * Bi-directional sync between Freshworks, Gitea, and local state
3
- *
4
- * Local state (.golem/tickets/*.yaml) is the source of truth.
5
- * This module handles pushing updates to Fresh and Gitea.
6
- */
7
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
8
- import { join, dirname } from 'node:path';
9
- import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
10
- import { FreshworksClient, createFreshworksClient } from '../api/freshworks.js';
11
- import { createGiteaClient } from '../api/gitea.js';
12
- /**
13
- * Load ticket state from local YAML file
14
- */
15
- export async function loadTicketState(ticketsDir, ticketId) {
16
- const filePath = join(ticketsDir, `${ticketId}.yaml`);
17
- try {
18
- const content = await readFile(filePath, 'utf-8');
19
- return parseYaml(content);
20
- }
21
- catch {
22
- return null;
23
- }
24
- }
25
- /**
26
- * Save ticket state to local YAML file
27
- */
28
- export async function saveTicketState(ticketsDir, state) {
29
- const filePath = join(ticketsDir, `${state.id}.yaml`);
30
- await mkdir(dirname(filePath), { recursive: true });
31
- state.updated = new Date().toISOString();
32
- await writeFile(filePath, stringifyYaml(state), 'utf-8');
33
- }
34
- /**
35
- * Create a new ticket in both Fresh and Gitea, linked together
36
- */
37
- export async function createLinkedTicket(ctx, params) {
38
- const { fresh, gitea, ticketsDir, repo } = ctx;
39
- // 1. Create Fresh ticket first (gets the ID)
40
- // Required fields from Freshservice: status, group_id, category, email/requester_id, source
41
- const freshTicket = await fresh.createTicket({
42
- subject: params.subject,
43
- description: params.description,
44
- priority: params.priority || 3,
45
- status: 2, // Open
46
- source: parseInt(process.env.FRESH_SOURCE_ID || '1002'), // ACE (API)
47
- group_id: parseInt(process.env.FRESH_DEFAULT_GROUP_ID || '38000120203'),
48
- category: process.env.FRESH_DEFAULT_CATEGORY || 'Applications',
49
- email: process.env.FRESH_DEFAULT_EMAIL || 'ace-bot@pearlriverresort.com',
50
- });
51
- const ticketId = FreshworksClient.formatTicketId(freshTicket.id);
52
- const freshUrl = `https://${process.env.FRESH_DOMAIN}/a/tickets/${freshTicket.id}`;
53
- // 2. Create Gitea issue with link back to Fresh ticket
54
- const giteaIssue = await gitea.createIssue(repo, {
55
- title: `[${ticketId}] ${params.subject}`,
56
- body: `${params.description}\n\n---\n**Freshservice:** [${ticketId}](${freshUrl})\n**Type:** ${params.type}`,
57
- });
58
- // 3. Update Fresh ticket with Gitea link
59
- await fresh.addNote(freshTicket.id, `🔗 Gitea Issue: ${giteaIssue.html_url}`, true // private note
60
- );
61
- // 4. Create local state
62
- const branch = `${params.type}/${ticketId}-${params.slug}`;
63
- const state = {
64
- id: ticketId,
65
- slug: params.slug,
66
- fresh: {
67
- id: ticketId,
68
- url: `https://${process.env.FRESH_DOMAIN}/helpdesk/tickets/${freshTicket.id}`,
69
- subject: freshTicket.subject,
70
- description: freshTicket.description_text,
71
- priority: freshTicket.priority,
72
- status: freshTicket.status,
73
- },
74
- gitea: {
75
- repo,
76
- issueNumber: giteaIssue.number,
77
- url: giteaIssue.html_url,
78
- },
79
- git: {
80
- worktree: join('.golem/worktrees', branch),
81
- branch,
82
- commits: [],
83
- },
84
- status: 'new',
85
- type: params.type,
86
- created: new Date().toISOString(),
87
- updated: new Date().toISOString(),
88
- };
89
- await saveTicketState(ticketsDir, state);
90
- return state;
91
- }
92
- /**
93
- * Import an existing Fresh ticket and create linked Gitea issue
94
- */
95
- export async function importFreshTicket(ctx, freshTicketId, params) {
96
- const { fresh, gitea, ticketsDir, repo } = ctx;
97
- // Parse ticket ID if string
98
- const numericId = typeof freshTicketId === 'string'
99
- ? FreshworksClient.parseTicketId(freshTicketId)
100
- : freshTicketId;
101
- // 1. Fetch existing Fresh ticket
102
- const freshTicket = await fresh.getTicket(numericId);
103
- const ticketId = FreshworksClient.formatTicketId(freshTicket.id, freshTicket.ticket_type);
104
- // 2. Check if local state already exists
105
- const existingState = await loadTicketState(ticketsDir, ticketId);
106
- if (existingState) {
107
- console.log(`Ticket ${ticketId} already imported, returning existing state`);
108
- return existingState;
109
- }
110
- // 3. Check if Gitea issue already exists for this ticket
111
- let giteaIssue = await gitea.findIssueByTicketId(repo, ticketId);
112
- const freshUrl = `https://${process.env.FRESH_DOMAIN}/a/tickets/${freshTicket.id}`;
113
- if (giteaIssue) {
114
- console.log(`Found existing Gitea issue #${giteaIssue.number} for ${ticketId}`);
115
- }
116
- else {
117
- // 4. Create Gitea issue with link back to Fresh
118
- giteaIssue = await gitea.createIssue(repo, {
119
- title: `[${ticketId}] ${freshTicket.subject}`,
120
- body: `${freshTicket.description_text}\n\n---\n**Freshservice:** [${ticketId}](${freshUrl})\n**Type:** ${params.type}`,
121
- });
122
- // 5. Update Fresh ticket with Gitea link
123
- await fresh.addNote(freshTicket.id, `🔗 Gitea Issue: ${giteaIssue.html_url}`, true);
124
- }
125
- // 6. Create local state
126
- const branch = `${params.type}/${ticketId}-${params.slug}`;
127
- const state = {
128
- id: ticketId,
129
- slug: params.slug,
130
- fresh: {
131
- id: ticketId,
132
- url: `https://${process.env.FRESH_DOMAIN}/helpdesk/tickets/${freshTicket.id}`,
133
- subject: freshTicket.subject,
134
- description: freshTicket.description_text,
135
- priority: freshTicket.priority,
136
- status: freshTicket.status,
137
- },
138
- gitea: {
139
- repo,
140
- issueNumber: giteaIssue.number,
141
- url: giteaIssue.html_url,
142
- },
143
- git: {
144
- worktree: join('.golem/worktrees', branch),
145
- branch,
146
- commits: [],
147
- },
148
- status: 'new',
149
- type: params.type,
150
- created: new Date().toISOString(),
151
- updated: new Date().toISOString(),
152
- };
153
- await saveTicketState(ticketsDir, state);
154
- return state;
155
- }
156
- /**
157
- * Update ticket status and sync to Fresh/Gitea
158
- */
159
- export async function updateTicketStatus(ctx, ticketId, newStatus, note) {
160
- const { fresh, gitea, ticketsDir } = ctx;
161
- const state = await loadTicketState(ticketsDir, ticketId);
162
- if (!state) {
163
- return { success: false, freshUpdated: false, giteaUpdated: false, localUpdated: false, error: 'Ticket not found' };
164
- }
165
- const oldStatus = state.status;
166
- state.status = newStatus;
167
- let freshUpdated = false;
168
- let giteaUpdated = false;
169
- // Build status message
170
- const statusMessage = note || `Status: ${oldStatus} → ${newStatus}`;
171
- // Update Fresh
172
- if (state.fresh) {
173
- try {
174
- const freshId = FreshworksClient.parseTicketId(state.fresh.id);
175
- await fresh.addNote(freshId, `🤖 Golem: ${statusMessage}`, true);
176
- // Close ticket if done
177
- if (newStatus === 'done') {
178
- await fresh.closeTicket(freshId, statusMessage);
179
- }
180
- freshUpdated = true;
181
- }
182
- catch (e) {
183
- console.error('Failed to update Fresh:', e);
184
- }
185
- }
186
- // Update Gitea
187
- if (state.gitea) {
188
- try {
189
- await gitea.addIssueComment(state.gitea.repo, state.gitea.issueNumber, `🤖 Golem: ${statusMessage}`);
190
- // Close issue if done
191
- if (newStatus === 'done') {
192
- await gitea.closeIssue(state.gitea.repo, state.gitea.issueNumber);
193
- }
194
- giteaUpdated = true;
195
- }
196
- catch (e) {
197
- console.error('Failed to update Gitea:', e);
198
- }
199
- }
200
- // Save local state
201
- await saveTicketState(ticketsDir, state);
202
- return { success: true, freshUpdated, giteaUpdated, localUpdated: true };
203
- }
204
- /**
205
- * Record a commit against a ticket
206
- */
207
- export async function recordCommit(ticketsDir, ticketId, commitSha) {
208
- const state = await loadTicketState(ticketsDir, ticketId);
209
- if (!state) {
210
- throw new Error(`Ticket ${ticketId} not found`);
211
- }
212
- state.git.commits.push(commitSha);
213
- await saveTicketState(ticketsDir, state);
214
- }
215
- /**
216
- * Create sync context from environment
217
- */
218
- export function createSyncContext(ticketsDir, repo) {
219
- return {
220
- fresh: createFreshworksClient(),
221
- gitea: createGiteaClient(),
222
- ticketsDir,
223
- repo,
224
- };
225
- }
226
- //# sourceMappingURL=ticket-sync.js.map