@straiffi/archon 1.1.3 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/client/assets/TestsDialog-4_jJ_cnr.js +5 -0
- package/dist/client/assets/badge-Bpry9xkS.js +41 -0
- package/dist/client/assets/index-BgmAtYCf.js +151 -0
- package/dist/client/assets/index-Bw66dtZG.css +2 -0
- package/dist/client/index.html +3 -3
- package/dist/server/index.js +206 -445
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/chatOperations.js +126 -0
- package/dist/server/lib/chatOperations.js.map +1 -0
- package/dist/server/lib/desktopServerHost.js +16 -0
- package/dist/server/lib/desktopServerHost.js.map +1 -0
- package/dist/server/lib/mobileAccess.js +1051 -0
- package/dist/server/lib/mobileAccess.js.map +1 -0
- package/dist/server/lib/mobileAccessSecurity.js +42 -0
- package/dist/server/lib/mobileAccessSecurity.js.map +1 -0
- package/dist/server/lib/ngrok.js +144 -0
- package/dist/server/lib/ngrok.js.map +1 -0
- package/dist/server/lib/projects.js +1 -0
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/realtime.js +2 -0
- package/dist/server/lib/realtime.js.map +1 -0
- package/dist/server/lib/run.js +3 -0
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/staticClient.js +14 -3
- package/dist/server/lib/staticClient.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +87 -0
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -0
- package/dist/server/lib/ticketRunOperations.js +333 -0
- package/dist/server/lib/ticketRunOperations.js.map +1 -0
- package/dist/server/lib/ticketSettingsOperations.js +62 -0
- package/dist/server/lib/ticketSettingsOperations.js.map +1 -0
- package/dist/server/lib/ticketWorkflowOperations.js +114 -0
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -0
- package/package.json +1 -1
- package/dist/client/assets/TestsDialog-Buw5J9nT.js +0 -5
- package/dist/client/assets/badge-BentDQnz.js +0 -41
- package/dist/client/assets/index-Dr_tNX7Y.css +0 -2
- package/dist/client/assets/index-kbsOL4Bp.js +0 -142
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { resolveWorktreePath } from './git.js';
|
|
3
|
+
import { getEffectiveProject } from './projects.js';
|
|
4
|
+
import { getTicket, resolveTicketBranch } from './tickets.js';
|
|
5
|
+
import { createTicketMessage } from './ticketMessages.js';
|
|
6
|
+
import { startFollowUp } from '../workers/followUp.js';
|
|
7
|
+
import { startPlanFollowUp } from '../workers/planFollowUp.js';
|
|
8
|
+
const isWorktreeReady = (branch, project) => {
|
|
9
|
+
return existsSync(resolveWorktreePath(branch, project));
|
|
10
|
+
};
|
|
11
|
+
const getInstruction = (payload) => {
|
|
12
|
+
return typeof payload?.instruction === 'string'
|
|
13
|
+
? payload.instruction.trim()
|
|
14
|
+
: '';
|
|
15
|
+
};
|
|
16
|
+
const matchesRequestedProject = (ticket, requestedProjectId) => {
|
|
17
|
+
return requestedProjectId === undefined || ticket.project_id === requestedProjectId;
|
|
18
|
+
};
|
|
19
|
+
export const submitTicketFollowUp = ({ ticketId, requestedProjectId, payload, broadcaster, }) => {
|
|
20
|
+
const ticket = getTicket(ticketId);
|
|
21
|
+
if (!ticket) {
|
|
22
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
23
|
+
}
|
|
24
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
25
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
26
|
+
}
|
|
27
|
+
if (ticket.state === 'plan') {
|
|
28
|
+
return { ok: false, status: 400, error: 'Only non-plan tickets can accept follow-up prompts' };
|
|
29
|
+
}
|
|
30
|
+
if (ticket.agent_status === 'running') {
|
|
31
|
+
return { ok: false, status: 409, error: 'Ticket is already running' };
|
|
32
|
+
}
|
|
33
|
+
const instruction = getInstruction(payload);
|
|
34
|
+
if (!instruction) {
|
|
35
|
+
return { ok: false, status: 400, error: 'instruction is required' };
|
|
36
|
+
}
|
|
37
|
+
const project = getEffectiveProject(ticket);
|
|
38
|
+
if (!project) {
|
|
39
|
+
return { ok: false, status: 400, error: 'Ticket project no longer exists' };
|
|
40
|
+
}
|
|
41
|
+
const branch = resolveTicketBranch(ticket);
|
|
42
|
+
if (!branch || ticket.has_worktree === false || !isWorktreeReady(branch, project)) {
|
|
43
|
+
return { ok: false, status: 400, error: 'Worktree not ready yet' };
|
|
44
|
+
}
|
|
45
|
+
createTicketMessage({
|
|
46
|
+
ticketId: ticket.id,
|
|
47
|
+
role: 'user',
|
|
48
|
+
kind: 'follow_up',
|
|
49
|
+
content: instruction,
|
|
50
|
+
});
|
|
51
|
+
const started = startFollowUp(ticket, broadcaster, instruction);
|
|
52
|
+
if (!started) {
|
|
53
|
+
return { ok: false, status: 409, error: 'Ticket is already running' };
|
|
54
|
+
}
|
|
55
|
+
return { ok: true, status: 200, value: getTicket(ticket.id) ?? ticket };
|
|
56
|
+
};
|
|
57
|
+
export const submitPlanTicketFollowUp = ({ ticketId, requestedProjectId, payload, broadcaster, }) => {
|
|
58
|
+
const ticket = getTicket(ticketId);
|
|
59
|
+
if (!ticket) {
|
|
60
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
61
|
+
}
|
|
62
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
63
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
64
|
+
}
|
|
65
|
+
if (ticket.state !== 'plan') {
|
|
66
|
+
return { ok: false, status: 400, error: 'Only plan tickets can accept planning follow-up prompts' };
|
|
67
|
+
}
|
|
68
|
+
if (ticket.agent_status === 'running') {
|
|
69
|
+
return { ok: false, status: 409, error: 'Ticket is already running' };
|
|
70
|
+
}
|
|
71
|
+
const instruction = getInstruction(payload);
|
|
72
|
+
if (!instruction) {
|
|
73
|
+
return { ok: false, status: 400, error: 'instruction is required' };
|
|
74
|
+
}
|
|
75
|
+
createTicketMessage({
|
|
76
|
+
ticketId: ticket.id,
|
|
77
|
+
role: 'user',
|
|
78
|
+
kind: 'planning_follow_up',
|
|
79
|
+
content: instruction,
|
|
80
|
+
});
|
|
81
|
+
const started = startPlanFollowUp(ticket, broadcaster, instruction);
|
|
82
|
+
if (!started) {
|
|
83
|
+
return { ok: false, status: 409, error: 'Ticket is already running' };
|
|
84
|
+
}
|
|
85
|
+
return { ok: true, status: 200, value: getTicket(ticket.id) ?? ticket };
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=ticketFollowUpOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticketFollowUpOperations.js","sourceRoot":"","sources":["../../../server/lib/ticketFollowUpOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import db from '../db.js';
|
|
3
|
+
import { isBuildAgentRunning, stopBuildAgent } from './agent.js';
|
|
4
|
+
import { getProjectBranch, resolveExistingWorktreePath, resolveWorktreePath } from './git.js';
|
|
5
|
+
import { getEffectiveProject, getProjectById } from './projects.js';
|
|
6
|
+
import { getActiveRunStatusForContextKey, getActiveRunStatusForProject, hasRunConfig, isRunning, resolveProjectRunContextKey, runProject, runTicketInWorkspace, stopProjectRun, stopTicket, } from './run.js';
|
|
7
|
+
import { isTicketRunSetupReady } from './ticketDependencies.js';
|
|
8
|
+
import { getBundle, getTicket, isProjectRootBundle, listTicketsInRunContext, resolveTicketBranch, } from './tickets.js';
|
|
9
|
+
import { resumeBuild } from '../workers/build.js';
|
|
10
|
+
const isWorktreeReady = (branch, project) => {
|
|
11
|
+
return existsSync(resolveWorktreePath(branch, project));
|
|
12
|
+
};
|
|
13
|
+
export const canUseBuildControls = (ticket) => {
|
|
14
|
+
return ticket.state === 'build' || (ticket.state === 'review' && ticket.review_follow_up_active === true);
|
|
15
|
+
};
|
|
16
|
+
export const getTicketRunReadinessError = (ticket, project) => {
|
|
17
|
+
const branch = resolveTicketBranch(ticket);
|
|
18
|
+
if (!branch || !isWorktreeReady(branch, project)) {
|
|
19
|
+
return 'Worktree not ready yet';
|
|
20
|
+
}
|
|
21
|
+
if (isTicketRunSetupReady(ticket)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (ticket.run_setup_status === 'preparing') {
|
|
25
|
+
return 'Worktree setup is still running. Try again in a moment.';
|
|
26
|
+
}
|
|
27
|
+
return 'Worktree setup has not finished yet.';
|
|
28
|
+
};
|
|
29
|
+
const matchesRequestedProject = (ticket, requestedProjectId) => {
|
|
30
|
+
return requestedProjectId === undefined || ticket.project_id === requestedProjectId;
|
|
31
|
+
};
|
|
32
|
+
const emitRunStateForContext = (broadcaster, ticket, isRunningValue) => {
|
|
33
|
+
const relatedTickets = listTicketsInRunContext(ticket);
|
|
34
|
+
if (relatedTickets.length === 0) {
|
|
35
|
+
broadcaster.emit('ticket:updated', { ...ticket, is_running: isRunningValue });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const relatedTicket of relatedTickets) {
|
|
39
|
+
broadcaster.emit('ticket:updated', { ...relatedTicket, is_running: isRunningValue });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const resolveTicketRunWorkspace = (ticket) => {
|
|
43
|
+
const project = getEffectiveProject(ticket);
|
|
44
|
+
if (!project) {
|
|
45
|
+
return { error: 'Ticket project no longer exists', status: 400 };
|
|
46
|
+
}
|
|
47
|
+
const bundle = ticket.worktree_bundle_id ? getBundle(ticket.worktree_bundle_id, project.id) : null;
|
|
48
|
+
if (bundle && isProjectRootBundle(bundle)) {
|
|
49
|
+
const branchState = getProjectBranch(project, { includeDiffStats: false });
|
|
50
|
+
if (branchState.status !== 'ready' || !branchState.branch) {
|
|
51
|
+
return { error: 'Project root must be on a named branch', status: 409 };
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
project,
|
|
55
|
+
branch: branchState.branch,
|
|
56
|
+
cwd: project.repo_path,
|
|
57
|
+
kind: 'project_root',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const branch = resolveTicketBranch(ticket);
|
|
61
|
+
if (!branch || !isWorktreeReady(branch, project)) {
|
|
62
|
+
return { error: 'Worktree not ready yet', status: 400 };
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
project,
|
|
66
|
+
branch,
|
|
67
|
+
cwd: resolveWorktreePath(branch, project),
|
|
68
|
+
kind: 'worktree',
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const resolveProjectRootRunWorkspace = (project) => {
|
|
72
|
+
const branchState = getProjectBranch(project, { includeDiffStats: false });
|
|
73
|
+
if (branchState.status !== 'ready' || !branchState.branch) {
|
|
74
|
+
return { error: 'Project root must be on a named branch', status: 409 };
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
project,
|
|
78
|
+
branch: branchState.branch,
|
|
79
|
+
cwd: project.repo_path,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const resolveProjectTargetRunWorkspace = (project) => {
|
|
83
|
+
if (project.active_target_kind === 'bundle' && project.active_target_bundle_id) {
|
|
84
|
+
const bundle = getBundle(project.active_target_bundle_id, project.id);
|
|
85
|
+
if (!bundle || isProjectRootBundle(bundle)) {
|
|
86
|
+
return { error: 'Selected bundle target no longer exists', status: 409 };
|
|
87
|
+
}
|
|
88
|
+
const existingWorktreePath = resolveExistingWorktreePath(bundle.branch, project);
|
|
89
|
+
if (!existingWorktreePath) {
|
|
90
|
+
return { error: 'Selected bundle target does not have a prepared worktree', status: 409 };
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
project,
|
|
94
|
+
branch: bundle.branch,
|
|
95
|
+
cwd: existingWorktreePath,
|
|
96
|
+
kind: 'bundle',
|
|
97
|
+
target_kind: 'bundle',
|
|
98
|
+
target_bundle_id: bundle.id,
|
|
99
|
+
bundle,
|
|
100
|
+
run_context_key: resolveProjectRunContextKey(project.id, {
|
|
101
|
+
kind: 'bundle',
|
|
102
|
+
bundleId: bundle.id,
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const workspace = resolveProjectRootRunWorkspace(project);
|
|
107
|
+
if ('error' in workspace) {
|
|
108
|
+
return workspace;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
...workspace,
|
|
112
|
+
kind: 'repo_root',
|
|
113
|
+
target_kind: 'repo_root',
|
|
114
|
+
target_bundle_id: null,
|
|
115
|
+
bundle: null,
|
|
116
|
+
run_context_key: resolveProjectRunContextKey(project.id, {
|
|
117
|
+
kind: 'repo_root',
|
|
118
|
+
}),
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
export const formatActiveRunConflict = (projectId) => {
|
|
122
|
+
const activeRun = getActiveRunStatusForProject(projectId);
|
|
123
|
+
if (!activeRun) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (activeRun.kind === 'project') {
|
|
127
|
+
const activeProject = getProjectById(activeRun.project_id);
|
|
128
|
+
const activeTargetBundle = activeRun.target_kind === 'bundle' && activeRun.target_bundle_id
|
|
129
|
+
? getBundle(activeRun.target_bundle_id, activeRun.project_id)
|
|
130
|
+
: null;
|
|
131
|
+
return {
|
|
132
|
+
active_project_id: activeRun.project_id,
|
|
133
|
+
error: activeProject
|
|
134
|
+
? activeTargetBundle
|
|
135
|
+
? `Bundle target run for "${activeProject.name}" (${activeTargetBundle.name}) is already running. Stop it before starting another run.`
|
|
136
|
+
: `Repo root run for "${activeProject.name}" is already running. Stop it before starting another run.`
|
|
137
|
+
: activeTargetBundle
|
|
138
|
+
? 'A bundle target run is already running. Stop it before starting another run.'
|
|
139
|
+
: 'A repo root run is already running. Stop it before starting another run.',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const activeTicket = getTicket(activeRun.ticket_id);
|
|
143
|
+
return {
|
|
144
|
+
active_ticket_id: activeRun.ticket_id,
|
|
145
|
+
error: activeTicket
|
|
146
|
+
? activeTicket.bundle
|
|
147
|
+
? `Ticket "${activeTicket.title}" in bundle "${activeTicket.bundle.name}" is already running. Stop it before starting another run.`
|
|
148
|
+
: `Ticket "${activeTicket.title}" is already running. Stop it before starting another run.`
|
|
149
|
+
: 'Another ticket is already running. Stop it before starting another run.',
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
export const runTicketRun = ({ ticketId, requestedProjectId, broadcaster, }) => {
|
|
153
|
+
const ticket = getTicket(ticketId);
|
|
154
|
+
if (!ticket) {
|
|
155
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
156
|
+
}
|
|
157
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
158
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
159
|
+
}
|
|
160
|
+
const workspace = resolveTicketRunWorkspace(ticket);
|
|
161
|
+
if ('error' in workspace) {
|
|
162
|
+
return { ok: false, status: workspace.status, error: workspace.error };
|
|
163
|
+
}
|
|
164
|
+
if (!hasRunConfig(workspace.project)) {
|
|
165
|
+
return { ok: false, status: 400, error: 'No run config' };
|
|
166
|
+
}
|
|
167
|
+
const runReadinessError = getTicketRunReadinessError(ticket, workspace.project);
|
|
168
|
+
if (runReadinessError) {
|
|
169
|
+
return { ok: false, status: 409, error: runReadinessError };
|
|
170
|
+
}
|
|
171
|
+
if (isRunning(ticket)) {
|
|
172
|
+
emitRunStateForContext(broadcaster, ticket, true);
|
|
173
|
+
const runningTicket = listTicketsInRunContext(ticket).find(entry => entry.id === ticket.id);
|
|
174
|
+
return { ok: true, status: 200, value: runningTicket ?? { ...ticket, is_running: true, has_run_config: true } };
|
|
175
|
+
}
|
|
176
|
+
const activeRunConflict = formatActiveRunConflict(ticket.project_id);
|
|
177
|
+
if (activeRunConflict) {
|
|
178
|
+
return { ok: false, status: 409, error: activeRunConflict.error, details: activeRunConflict };
|
|
179
|
+
}
|
|
180
|
+
const running = { ...ticket, is_running: true, has_run_config: true };
|
|
181
|
+
emitRunStateForContext(broadcaster, ticket, true);
|
|
182
|
+
return {
|
|
183
|
+
ok: true,
|
|
184
|
+
status: 200,
|
|
185
|
+
value: running,
|
|
186
|
+
afterResponse: () => {
|
|
187
|
+
void runTicketInWorkspace(ticket, broadcaster, workspace.project, workspace.cwd);
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
export const runProjectTarget = ({ projectId, }) => {
|
|
192
|
+
const project = getProjectById(projectId);
|
|
193
|
+
if (!project) {
|
|
194
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
195
|
+
}
|
|
196
|
+
if (!hasRunConfig(project)) {
|
|
197
|
+
return { ok: false, status: 400, error: 'No run config' };
|
|
198
|
+
}
|
|
199
|
+
const workspace = resolveProjectTargetRunWorkspace(project);
|
|
200
|
+
if ('error' in workspace) {
|
|
201
|
+
return { ok: false, status: workspace.status, error: workspace.error };
|
|
202
|
+
}
|
|
203
|
+
const contextKey = workspace.run_context_key;
|
|
204
|
+
if (isRunning(contextKey)) {
|
|
205
|
+
return {
|
|
206
|
+
ok: true,
|
|
207
|
+
status: 200,
|
|
208
|
+
value: {
|
|
209
|
+
active_run: {
|
|
210
|
+
kind: 'project',
|
|
211
|
+
context_key: contextKey,
|
|
212
|
+
project_id: project.id,
|
|
213
|
+
target_kind: workspace.target_kind,
|
|
214
|
+
target_bundle_id: workspace.target_bundle_id,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const activeRunConflict = formatActiveRunConflict(project.id);
|
|
220
|
+
if (activeRunConflict) {
|
|
221
|
+
return { ok: false, status: 409, error: activeRunConflict.error, details: activeRunConflict };
|
|
222
|
+
}
|
|
223
|
+
const activeRun = {
|
|
224
|
+
kind: 'project',
|
|
225
|
+
context_key: contextKey,
|
|
226
|
+
project_id: project.id,
|
|
227
|
+
target_kind: workspace.target_kind,
|
|
228
|
+
target_bundle_id: workspace.target_bundle_id,
|
|
229
|
+
};
|
|
230
|
+
return {
|
|
231
|
+
ok: true,
|
|
232
|
+
status: 200,
|
|
233
|
+
value: { active_run: activeRun },
|
|
234
|
+
afterResponse: () => {
|
|
235
|
+
void runProject(project, {
|
|
236
|
+
cwd: workspace.cwd,
|
|
237
|
+
targetKind: workspace.target_kind,
|
|
238
|
+
targetBundleId: workspace.target_bundle_id,
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
export const stopTicketRun = async ({ ticketId, requestedProjectId, broadcaster, }) => {
|
|
244
|
+
const ticket = getTicket(ticketId);
|
|
245
|
+
if (!ticket) {
|
|
246
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
247
|
+
}
|
|
248
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
249
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
250
|
+
}
|
|
251
|
+
await stopTicket(ticket);
|
|
252
|
+
emitRunStateForContext(broadcaster, ticket, false);
|
|
253
|
+
const updated = listTicketsInRunContext(ticket).find(entry => entry.id === ticket.id) ?? { ...ticket, is_running: false };
|
|
254
|
+
return { ok: true, status: 200, value: updated };
|
|
255
|
+
};
|
|
256
|
+
export const stopProjectTargetRun = async ({ projectId, }) => {
|
|
257
|
+
const project = getProjectById(projectId);
|
|
258
|
+
if (!project) {
|
|
259
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
260
|
+
}
|
|
261
|
+
await stopProjectRun(project.id, {
|
|
262
|
+
kind: project.active_target_kind,
|
|
263
|
+
bundleId: project.active_target_bundle_id,
|
|
264
|
+
});
|
|
265
|
+
return { ok: true, status: 200, value: { active_run: getActiveRunStatusForProject(project.id) } };
|
|
266
|
+
};
|
|
267
|
+
export const stopActiveRunByContextKey = async ({ runContextKey, broadcaster, }) => {
|
|
268
|
+
const activeRun = getActiveRunStatusForContextKey(runContextKey);
|
|
269
|
+
if (!activeRun) {
|
|
270
|
+
return { ok: false, status: 404, error: 'Active run not found' };
|
|
271
|
+
}
|
|
272
|
+
await stopTicket(runContextKey);
|
|
273
|
+
if (activeRun.kind === 'ticket') {
|
|
274
|
+
const activeTicket = getTicket(activeRun.ticket_id);
|
|
275
|
+
if (activeTicket) {
|
|
276
|
+
emitRunStateForContext(broadcaster, activeTicket, false);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return { ok: true, status: 200, value: { active_run: getActiveRunStatusForProject(activeRun.project_id) } };
|
|
280
|
+
};
|
|
281
|
+
export const stopBuildTicketRun = async ({ ticketId, requestedProjectId, }) => {
|
|
282
|
+
const ticket = getTicket(ticketId);
|
|
283
|
+
if (!ticket) {
|
|
284
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
285
|
+
}
|
|
286
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
287
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
288
|
+
}
|
|
289
|
+
if (!canUseBuildControls(ticket)) {
|
|
290
|
+
return { ok: false, status: 400, error: 'Only build-stage and review follow-up tickets can stop builds' };
|
|
291
|
+
}
|
|
292
|
+
if (ticket.agent_status !== 'running') {
|
|
293
|
+
return { ok: false, status: 400, error: 'Ticket build is not running' };
|
|
294
|
+
}
|
|
295
|
+
if (!ticket.session_id) {
|
|
296
|
+
return { ok: false, status: 400, error: 'Build session is not ready to stop yet' };
|
|
297
|
+
}
|
|
298
|
+
if (!isBuildAgentRunning(ticket.id)) {
|
|
299
|
+
return { ok: false, status: 409, error: 'No active build process found for this ticket' };
|
|
300
|
+
}
|
|
301
|
+
await stopBuildAgent(ticket.id);
|
|
302
|
+
const updated = getTicket(ticket.id);
|
|
303
|
+
if (!updated) {
|
|
304
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
305
|
+
}
|
|
306
|
+
return { ok: true, status: 200, value: updated };
|
|
307
|
+
};
|
|
308
|
+
export const resumeBuildTicketRun = ({ ticketId, requestedProjectId, broadcaster, }) => {
|
|
309
|
+
const existing = getTicket(ticketId);
|
|
310
|
+
if (!existing) {
|
|
311
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
312
|
+
}
|
|
313
|
+
if (!matchesRequestedProject(existing, requestedProjectId)) {
|
|
314
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
315
|
+
}
|
|
316
|
+
if (!canUseBuildControls(existing)) {
|
|
317
|
+
return { ok: false, status: 400, error: 'Only build-stage and review follow-up tickets can resume builds' };
|
|
318
|
+
}
|
|
319
|
+
if (existing.agent_status !== 'stopped') {
|
|
320
|
+
return { ok: false, status: 400, error: 'Only manually stopped builds can be resumed' };
|
|
321
|
+
}
|
|
322
|
+
if (!existing.session_id) {
|
|
323
|
+
return { ok: false, status: 400, error: 'Build session is not available to resume' };
|
|
324
|
+
}
|
|
325
|
+
db.prepare('UPDATE tickets SET build_completed_at = NULL, auto_park_dismissed_at = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(existing.id);
|
|
326
|
+
const ticket = getTicket(existing.id);
|
|
327
|
+
if (!ticket) {
|
|
328
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
329
|
+
}
|
|
330
|
+
resumeBuild(ticket, broadcaster);
|
|
331
|
+
return { ok: true, status: 200, value: ticket };
|
|
332
|
+
};
|
|
333
|
+
//# sourceMappingURL=ticketRunOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticketRunOperations.js","sourceRoot":"","sources":["../../../server/lib/ticketRunOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import db from '../db.js';
|
|
2
|
+
import { normalizeModelId } from './models.js';
|
|
3
|
+
import { normalizeSkillNames } from './skills.js';
|
|
4
|
+
import { getTicket } from './tickets.js';
|
|
5
|
+
const hasOwn = (object, key) => {
|
|
6
|
+
return !!object && typeof object === 'object' && Object.prototype.hasOwnProperty.call(object, key);
|
|
7
|
+
};
|
|
8
|
+
const matchesRequestedProject = (ticket, requestedProjectId) => {
|
|
9
|
+
return requestedProjectId === undefined || ticket.project_id === requestedProjectId;
|
|
10
|
+
};
|
|
11
|
+
export const isTicketAgentSettingsPayload = (payload) => {
|
|
12
|
+
if (!payload) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const hasModelField = hasOwn(payload, 'model');
|
|
16
|
+
const hasVariantField = hasOwn(payload, 'variant');
|
|
17
|
+
const hasSkillsField = hasOwn(payload, 'skills');
|
|
18
|
+
const hasEditableContentField = hasOwn(payload, 'title')
|
|
19
|
+
|| hasOwn(payload, 'description')
|
|
20
|
+
|| hasOwn(payload, 'project_id')
|
|
21
|
+
|| hasOwn(payload, 'worktree_bundle_id');
|
|
22
|
+
return !hasEditableContentField && (hasModelField || hasVariantField || hasSkillsField);
|
|
23
|
+
};
|
|
24
|
+
export const updateTicketAgentSettings = ({ ticketId, requestedProjectId, payload, broadcaster, }) => {
|
|
25
|
+
const ticket = getTicket(ticketId);
|
|
26
|
+
if (!ticket) {
|
|
27
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
28
|
+
}
|
|
29
|
+
if (!matchesRequestedProject(ticket, requestedProjectId)) {
|
|
30
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
31
|
+
}
|
|
32
|
+
let resolvedModel = ticket.model;
|
|
33
|
+
let resolvedVariant = ticket.variant;
|
|
34
|
+
let resolvedSkills = ticket.skills;
|
|
35
|
+
if (hasOwn(payload, 'model')) {
|
|
36
|
+
if (payload?.model == null) {
|
|
37
|
+
resolvedModel = null;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const normalizedModel = normalizeModelId(payload.model);
|
|
41
|
+
if (normalizedModel) {
|
|
42
|
+
resolvedModel = normalizedModel;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (hasOwn(payload, 'variant')) {
|
|
47
|
+
if (payload?.variant == null || payload.variant === '') {
|
|
48
|
+
resolvedVariant = null;
|
|
49
|
+
}
|
|
50
|
+
else if (typeof payload.variant === 'string') {
|
|
51
|
+
resolvedVariant = payload.variant.trim() || null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (hasOwn(payload, 'skills')) {
|
|
55
|
+
resolvedSkills = normalizeSkillNames(payload?.skills);
|
|
56
|
+
}
|
|
57
|
+
db.prepare('UPDATE tickets SET model = ?, variant = ?, skills_json = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(resolvedModel, resolvedVariant, JSON.stringify(resolvedSkills), ticket.id);
|
|
58
|
+
const updated = getTicket(ticket.id);
|
|
59
|
+
broadcaster.emit('ticket:updated', updated);
|
|
60
|
+
return { ok: true, status: 200, value: updated };
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=ticketSettingsOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticketSettingsOperations.js","sourceRoot":"","sources":["../../../server/lib/ticketSettingsOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import db from '../db.js';
|
|
2
|
+
import config from './config.js';
|
|
3
|
+
import { enqueueBundledBuild, hasActiveSequenceForBundle } from './buildSequences.js';
|
|
4
|
+
import { prepareTicketForBuild } from './buildFlow.js';
|
|
5
|
+
import { isBundleBuildBlocked } from './bundleActivity.js';
|
|
6
|
+
import { getEffectiveProject } from './projects.js';
|
|
7
|
+
import { assignTicketLaneOrder, autoParkTicketIfStale, getTicket, resolveTicketTool } from './tickets.js';
|
|
8
|
+
import { startBuild } from '../workers/build.js';
|
|
9
|
+
import { startReview } from '../workers/review.js';
|
|
10
|
+
const VALID_TICKET_STATES = ['plan', 'build', 'review'];
|
|
11
|
+
const getBundleBuildBlockerError = (kind) => {
|
|
12
|
+
if (kind === 'review') {
|
|
13
|
+
return 'A review is currently active in this bundle. Finish or stop it before starting a new build.';
|
|
14
|
+
}
|
|
15
|
+
return 'A follow-up job is currently modifying this bundle. Finish it before starting a new build.';
|
|
16
|
+
};
|
|
17
|
+
const isBuildBlockerKind = (kind) => {
|
|
18
|
+
return kind === 'review' || kind === 'build_follow_up' || kind === 'review_follow_up';
|
|
19
|
+
};
|
|
20
|
+
export const getBundleBuildBlockerResponse = (ticket) => {
|
|
21
|
+
const blocker = isBundleBuildBlocked(ticket);
|
|
22
|
+
if (!blocker || !isBuildBlockerKind(blocker.kind)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
error: getBundleBuildBlockerError(blocker.kind),
|
|
27
|
+
blocker_ticket_id: blocker.ticketId,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export const shouldStartBundleBuildNow = (ticket) => {
|
|
31
|
+
if (!ticket.project_id || !ticket.worktree_bundle_id) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return !hasActiveSequenceForBundle(ticket.project_id, ticket.worktree_bundle_id);
|
|
35
|
+
};
|
|
36
|
+
export const transitionTicketState = ({ ticketId, requestedState, requestedProjectId, broadcaster, reviewBundleTickets, }) => {
|
|
37
|
+
const state = typeof requestedState === 'string' ? requestedState : '';
|
|
38
|
+
if (!VALID_TICKET_STATES.includes(state)) {
|
|
39
|
+
return { ok: false, status: 400, error: 'Invalid state' };
|
|
40
|
+
}
|
|
41
|
+
const ticketState = state;
|
|
42
|
+
const existing = getTicket(ticketId);
|
|
43
|
+
if (!existing) {
|
|
44
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
45
|
+
}
|
|
46
|
+
if (requestedProjectId !== undefined && existing.project_id !== requestedProjectId) {
|
|
47
|
+
return { ok: false, status: 404, error: 'Not found' };
|
|
48
|
+
}
|
|
49
|
+
if (ticketState === 'plan' && existing.state !== 'plan') {
|
|
50
|
+
return { ok: false, status: 409, error: 'Tickets cannot be moved back to plan after work begins' };
|
|
51
|
+
}
|
|
52
|
+
if (ticketState === 'build') {
|
|
53
|
+
const buildBlocker = getBundleBuildBlockerResponse(existing);
|
|
54
|
+
if (buildBlocker) {
|
|
55
|
+
return { ok: false, status: 409, error: buildBlocker.error, details: { blocker_ticket_id: buildBlocker.blocker_ticket_id } };
|
|
56
|
+
}
|
|
57
|
+
const buildTransition = prepareTicketForBuild(existing.id);
|
|
58
|
+
if (!buildTransition.ok) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
status: buildTransition.status,
|
|
62
|
+
error: buildTransition.error,
|
|
63
|
+
...(buildTransition.blockers ? { details: { blockers: buildTransition.blockers } } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
broadcaster.emit('ticket:updated', buildTransition.ticket);
|
|
67
|
+
let shouldStartBuild = true;
|
|
68
|
+
if (buildTransition.ticket.project_id && buildTransition.ticket.worktree_bundle_id) {
|
|
69
|
+
const queuedBuild = enqueueBundledBuild({
|
|
70
|
+
ticketId: buildTransition.ticket.id,
|
|
71
|
+
projectId: buildTransition.ticket.project_id,
|
|
72
|
+
worktreeBundleId: buildTransition.ticket.worktree_bundle_id,
|
|
73
|
+
activate: shouldStartBundleBuildNow(buildTransition.ticket),
|
|
74
|
+
});
|
|
75
|
+
shouldStartBuild = queuedBuild.shouldStartNow;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
ok: true,
|
|
79
|
+
status: 200,
|
|
80
|
+
value: buildTransition.ticket,
|
|
81
|
+
...(shouldStartBuild ? { afterResponse: () => startBuild(buildTransition.ticket, broadcaster) } : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (ticketState === 'review' && (existing.state !== 'build' || existing.agent_status !== 'done')) {
|
|
85
|
+
return { ok: false, status: 409, error: 'Tickets can only be moved to review from build when done' };
|
|
86
|
+
}
|
|
87
|
+
const project = getEffectiveProject(existing);
|
|
88
|
+
if (ticketState === 'review' && !project) {
|
|
89
|
+
return { ok: false, status: 400, error: 'Ticket project no longer exists' };
|
|
90
|
+
}
|
|
91
|
+
if (ticketState === 'review' && existing.project_id && existing.worktree_bundle_id) {
|
|
92
|
+
const reviewResult = reviewBundleTickets(existing.project_id, existing.worktree_bundle_id);
|
|
93
|
+
if (!reviewResult.ok) {
|
|
94
|
+
return { ok: false, status: reviewResult.status, error: reviewResult.error };
|
|
95
|
+
}
|
|
96
|
+
const updated = reviewResult.details.tickets.find(ticket => ticket.id === existing.id);
|
|
97
|
+
if (!updated) {
|
|
98
|
+
return { ok: false, status: 409, error: 'Unable to update the requested ticket in this bundle' };
|
|
99
|
+
}
|
|
100
|
+
return { ok: true, status: 200, value: updated };
|
|
101
|
+
}
|
|
102
|
+
const nextAgentStatus = ticketState === 'review' ? null : existing.agent_status;
|
|
103
|
+
const nextAgentLog = ticketState === 'review' ? null : existing.agent_log;
|
|
104
|
+
const nextSessionId = existing.session_id;
|
|
105
|
+
db.prepare('UPDATE tickets SET state = ?, tool = ?, agent_status = ?, agent_log = ?, session_id = ?, streaming_response = NULL, lane_order = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(ticketState, resolveTicketTool(existing, config.tool ?? 'opencode'), nextAgentStatus, nextAgentLog, nextSessionId, assignTicketLaneOrder({ ...existing, state: ticketState }) ?? null, ticketId);
|
|
106
|
+
const ticket = autoParkTicketIfStale(ticketId);
|
|
107
|
+
if (ticketState === 'review' && ticket) {
|
|
108
|
+
startReview(ticket, broadcaster);
|
|
109
|
+
return { ok: true, status: 200, value: getTicket(ticketId) };
|
|
110
|
+
}
|
|
111
|
+
broadcaster.emit('ticket:updated', ticket);
|
|
112
|
+
return { ok: true, status: 200, value: ticket };
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=ticketWorkflowOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticketWorkflowOperations.js","sourceRoot":"","sources":["../../../server/lib/ticketWorkflowOperations.ts"],"names":[],"mappings":"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"}
|