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.
- package/.claude/commands/golem/build.md +18 -0
- package/.claude/commands/golem/config.md +39 -0
- package/.claude/commands/golem/continue.md +73 -0
- package/.claude/commands/golem/doctor.md +46 -0
- package/.claude/commands/golem/document.md +138 -0
- package/.claude/commands/golem/help.md +58 -0
- package/.claude/commands/golem/pause.md +130 -0
- package/.claude/commands/golem/plan.md +111 -0
- package/.claude/commands/golem/review.md +166 -0
- package/.claude/commands/golem/security.md +186 -0
- package/.claude/commands/golem/simplify.md +76 -0
- package/.claude/commands/golem/spec.md +105 -0
- package/.claude/commands/golem/status.md +33 -0
- package/.golem/agents/code-simplifier.md +54 -0
- package/.golem/agents/review-architecture.md +59 -0
- package/.golem/agents/review-logic.md +50 -0
- package/.golem/agents/review-security.md +50 -0
- package/.golem/agents/review-style.md +48 -0
- package/.golem/agents/review-tests.md +48 -0
- package/.golem/agents/spec-builder.md +60 -0
- package/.golem/bin/golem.mjs +270 -0
- package/.golem/lib/build.mjs +557 -0
- package/.golem/lib/claude.mjs +95 -0
- package/.golem/lib/config.mjs +421 -0
- package/.golem/lib/display.mjs +191 -0
- package/.golem/lib/doctor.mjs +197 -0
- package/.golem/lib/document.mjs +792 -0
- package/.golem/lib/gates.mjs +78 -0
- package/.golem/lib/init.mjs +166 -0
- package/.golem/lib/output.mjs +40 -0
- package/.golem/lib/ratelimit.mjs +86 -0
- package/.golem/lib/security.mjs +603 -0
- package/.golem/lib/simplify.mjs +101 -0
- package/.golem/lib/tui.mjs +368 -0
- package/.golem/lib/usage.mjs +119 -0
- package/.golem/lib/worktree.mjs +509 -0
- package/.golem/prompts/build.md +23 -0
- package/.golem/prompts/document-inline.md +66 -0
- package/.golem/prompts/document-markdown.md +80 -0
- package/.golem/prompts/simplify.md +35 -0
- package/README.md +141 -142
- package/bin/golem-shim.mjs +36 -0
- package/bin/install.mjs +193 -0
- package/package.json +27 -32
- package/.env.example +0 -17
- package/bin/golem +0 -1040
- package/commands/golem/build.md +0 -235
- package/commands/golem/config.md +0 -55
- package/commands/golem/doctor.md +0 -137
- package/commands/golem/help.md +0 -212
- package/commands/golem/plan.md +0 -214
- package/commands/golem/review.md +0 -376
- package/commands/golem/security.md +0 -204
- package/commands/golem/simplify.md +0 -94
- package/commands/golem/spec.md +0 -226
- package/commands/golem/status.md +0 -60
- package/dist/api/freshworks.d.ts +0 -61
- package/dist/api/freshworks.d.ts.map +0 -1
- package/dist/api/freshworks.js +0 -119
- package/dist/api/freshworks.js.map +0 -1
- package/dist/api/gitea.d.ts +0 -96
- package/dist/api/gitea.d.ts.map +0 -1
- package/dist/api/gitea.js +0 -154
- package/dist/api/gitea.js.map +0 -1
- package/dist/cli/index.d.ts +0 -9
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -352
- package/dist/cli/index.js.map +0 -1
- package/dist/sync/ticket-sync.d.ts +0 -53
- package/dist/sync/ticket-sync.d.ts.map +0 -1
- package/dist/sync/ticket-sync.js +0 -226
- package/dist/sync/ticket-sync.js.map +0 -1
- package/dist/types.d.ts +0 -125
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/dist/worktree/manager.d.ts +0 -54
- package/dist/worktree/manager.d.ts.map +0 -1
- package/dist/worktree/manager.js +0 -190
- package/dist/worktree/manager.js.map +0 -1
- package/golem/agents/code-simplifier.md +0 -81
- package/golem/agents/spec-builder.md +0 -90
- package/golem/prompts/PROMPT_build.md +0 -71
- 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
|
package/dist/cli/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|
package/dist/sync/ticket-sync.js
DELETED
|
@@ -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
|