@promptprojectmanager/mcp-server 4.6.8 → 4.7.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/dist/index.js +0 -480
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
- package/dist/chunk-PY22KZ7Z.js +0 -143
- package/dist/chunk-PY22KZ7Z.js.map +0 -1
- package/dist/watcher/watcher_daemon.d.ts +0 -1
- package/dist/watcher/watcher_daemon.js +0 -564
- package/dist/watcher/watcher_daemon.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
getWatcherDir,
|
|
4
|
-
isWatcherRunning,
|
|
5
|
-
readPid,
|
|
6
|
-
readStatus,
|
|
7
|
-
removePid,
|
|
8
|
-
writeStatus
|
|
9
|
-
} from "./chunk-PY22KZ7Z.js";
|
|
10
2
|
|
|
11
3
|
// src/index.ts
|
|
12
4
|
import minimist from "minimist";
|
|
@@ -98,314 +90,6 @@ function parsePromptsUpdateArgs(args) {
|
|
|
98
90
|
changeLogMessage: typeof parsed?.changeLogMessage === "string" ? parsed.changeLogMessage : void 0
|
|
99
91
|
};
|
|
100
92
|
}
|
|
101
|
-
function parseWatcherStartArgs(args) {
|
|
102
|
-
const parsed = args;
|
|
103
|
-
return {
|
|
104
|
-
pollIntervalMs: typeof parsed?.pollIntervalMs === "number" ? parsed.pollIntervalMs : void 0,
|
|
105
|
-
maxParallel: typeof parsed?.maxParallel === "number" ? parsed.maxParallel : void 0,
|
|
106
|
-
ticketTimeout: typeof parsed?.ticketTimeout === "number" ? parsed.ticketTimeout : void 0,
|
|
107
|
-
enableNotifications: typeof parsed?.enableNotifications === "boolean" ? parsed.enableNotifications : void 0,
|
|
108
|
-
workingDirectory: typeof parsed?.workingDirectory === "string" ? parsed.workingDirectory : void 0
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// src/watcher/watcher_controller.ts
|
|
113
|
-
import { spawn } from "child_process";
|
|
114
|
-
import { fileURLToPath } from "url";
|
|
115
|
-
import { dirname, join } from "path";
|
|
116
|
-
function startWatcher(baseConfig, args) {
|
|
117
|
-
const workingDirectory = args?.workingDirectory ?? baseConfig.workingDirectory;
|
|
118
|
-
if (isWatcherRunning(workingDirectory)) {
|
|
119
|
-
const existingPid = readPid(workingDirectory);
|
|
120
|
-
const status = readStatus(workingDirectory);
|
|
121
|
-
return {
|
|
122
|
-
success: true,
|
|
123
|
-
message: `Watcher already running (PID: ${existingPid})`,
|
|
124
|
-
pid: existingPid,
|
|
125
|
-
alreadyRunning: true,
|
|
126
|
-
config: status?.config
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
const config = {
|
|
130
|
-
projectSlug: baseConfig.projectSlug,
|
|
131
|
-
projectToken: baseConfig.projectToken,
|
|
132
|
-
convexUrl: baseConfig.convexUrl,
|
|
133
|
-
pollIntervalMs: args?.pollIntervalMs ?? 3e4,
|
|
134
|
-
maxParallel: args?.maxParallel ?? 1,
|
|
135
|
-
ticketTimeout: args?.ticketTimeout ?? 18e5,
|
|
136
|
-
enableNotifications: args?.enableNotifications ?? true,
|
|
137
|
-
workingDirectory
|
|
138
|
-
};
|
|
139
|
-
getWatcherDir(workingDirectory);
|
|
140
|
-
const daemonPath = getDaemonPath();
|
|
141
|
-
const configJson = JSON.stringify(config);
|
|
142
|
-
const configB64 = Buffer.from(configJson).toString("base64");
|
|
143
|
-
try {
|
|
144
|
-
const child = spawn("node", [daemonPath, "--config", configB64], {
|
|
145
|
-
detached: true,
|
|
146
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
147
|
-
cwd: workingDirectory
|
|
148
|
-
});
|
|
149
|
-
child.unref();
|
|
150
|
-
const pid = child.pid;
|
|
151
|
-
if (!pid) {
|
|
152
|
-
return {
|
|
153
|
-
success: false,
|
|
154
|
-
message: "Failed to spawn daemon - no PID returned"
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
const configWithoutToken = {
|
|
158
|
-
projectSlug: config.projectSlug,
|
|
159
|
-
convexUrl: config.convexUrl,
|
|
160
|
-
pollIntervalMs: config.pollIntervalMs,
|
|
161
|
-
maxParallel: config.maxParallel,
|
|
162
|
-
ticketTimeout: config.ticketTimeout,
|
|
163
|
-
enableNotifications: config.enableNotifications,
|
|
164
|
-
workingDirectory: config.workingDirectory
|
|
165
|
-
};
|
|
166
|
-
const statusFile = join(getWatcherDir(workingDirectory), "status.json");
|
|
167
|
-
const monitoringPrompt = generateMonitoringPrompt(statusFile, workingDirectory);
|
|
168
|
-
return {
|
|
169
|
-
success: true,
|
|
170
|
-
message: `Watcher started (PID: ${pid})`,
|
|
171
|
-
pid,
|
|
172
|
-
alreadyRunning: false,
|
|
173
|
-
config: configWithoutToken,
|
|
174
|
-
monitoringPrompt,
|
|
175
|
-
statusFile
|
|
176
|
-
};
|
|
177
|
-
} catch (error) {
|
|
178
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
179
|
-
return {
|
|
180
|
-
success: false,
|
|
181
|
-
message: `Failed to start watcher: ${errorMessage}`
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function getDaemonPath() {
|
|
186
|
-
const currentFile = fileURLToPath(import.meta.url);
|
|
187
|
-
const currentDir = dirname(currentFile);
|
|
188
|
-
return join(currentDir, "watcher", "watcher_daemon.js");
|
|
189
|
-
}
|
|
190
|
-
function stopWatcher(workingDirectory) {
|
|
191
|
-
const pid = readPid(workingDirectory);
|
|
192
|
-
if (!pid) {
|
|
193
|
-
return {
|
|
194
|
-
success: true,
|
|
195
|
-
message: "No watcher running (no PID file)",
|
|
196
|
-
wasRunning: false
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
if (!isWatcherRunning(workingDirectory)) {
|
|
200
|
-
removePid(workingDirectory);
|
|
201
|
-
return {
|
|
202
|
-
success: true,
|
|
203
|
-
message: "Watcher was not running (stale PID file cleaned up)",
|
|
204
|
-
wasRunning: false
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
try {
|
|
208
|
-
process.kill(pid, "SIGTERM");
|
|
209
|
-
const status = readStatus(workingDirectory);
|
|
210
|
-
if (status) {
|
|
211
|
-
writeStatus(workingDirectory, {
|
|
212
|
-
...status,
|
|
213
|
-
state: "stopped"
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
removePid(workingDirectory);
|
|
217
|
-
return {
|
|
218
|
-
success: true,
|
|
219
|
-
message: `Watcher stopped (PID: ${pid})`,
|
|
220
|
-
wasRunning: true
|
|
221
|
-
};
|
|
222
|
-
} catch (error) {
|
|
223
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
224
|
-
removePid(workingDirectory);
|
|
225
|
-
return {
|
|
226
|
-
success: false,
|
|
227
|
-
message: `Failed to stop watcher: ${errorMessage}`,
|
|
228
|
-
wasRunning: true
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function getWatcherStatus(workingDirectory) {
|
|
233
|
-
const status = readStatus(workingDirectory);
|
|
234
|
-
const isRunning = isWatcherRunning(workingDirectory);
|
|
235
|
-
if (status?.state === "running" && !isRunning) {
|
|
236
|
-
const updatedStatus = {
|
|
237
|
-
...status,
|
|
238
|
-
state: "stopped"
|
|
239
|
-
};
|
|
240
|
-
writeStatus(workingDirectory, updatedStatus);
|
|
241
|
-
return {
|
|
242
|
-
success: true,
|
|
243
|
-
status: updatedStatus,
|
|
244
|
-
formattedStatus: formatStatus(updatedStatus),
|
|
245
|
-
message: "Watcher died unexpectedly - status updated"
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
if (!status) {
|
|
249
|
-
return {
|
|
250
|
-
success: true,
|
|
251
|
-
message: "No watcher session found for this project",
|
|
252
|
-
formattedStatus: formatStatus(null)
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
return {
|
|
256
|
-
success: true,
|
|
257
|
-
status,
|
|
258
|
-
formattedStatus: formatStatus(status)
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
function formatStatus(status) {
|
|
262
|
-
if (!status) {
|
|
263
|
-
return `# YOLO Watcher Status
|
|
264
|
-
|
|
265
|
-
**State**: Not started
|
|
266
|
-
|
|
267
|
-
_Use \`tickets_yolo_start\` to begin watching for YOLO tickets._`;
|
|
268
|
-
}
|
|
269
|
-
const lines = [
|
|
270
|
-
"# YOLO Watcher Status",
|
|
271
|
-
"",
|
|
272
|
-
`**State**: ${status.state}`,
|
|
273
|
-
`**Project**: ${status.projectSlug}`
|
|
274
|
-
];
|
|
275
|
-
if (status.pid) {
|
|
276
|
-
lines.push(`**Daemon PID**: ${status.pid}`);
|
|
277
|
-
}
|
|
278
|
-
if (status.startedAt) {
|
|
279
|
-
lines.push(`**Started**: ${status.startedAt}`);
|
|
280
|
-
}
|
|
281
|
-
if (status.lastPollAt) {
|
|
282
|
-
lines.push(`**Last Poll**: ${status.lastPollAt}`);
|
|
283
|
-
}
|
|
284
|
-
lines.push(`**Tickets Processed**: ${status.ticketsProcessed}`);
|
|
285
|
-
if (status.config) {
|
|
286
|
-
lines.push("");
|
|
287
|
-
lines.push("## Configuration");
|
|
288
|
-
lines.push(`- Poll Interval: ${status.config.pollIntervalMs / 1e3}s`);
|
|
289
|
-
lines.push(`- Max Parallel: ${status.config.maxParallel}`);
|
|
290
|
-
lines.push(`- Ticket Timeout: ${status.config.ticketTimeout / 1e3 / 60} min`);
|
|
291
|
-
lines.push(`- Notifications: ${status.config.enableNotifications ? "enabled" : "disabled"}`);
|
|
292
|
-
}
|
|
293
|
-
if (status.currentlyExecuting && status.currentlyExecuting.length > 0) {
|
|
294
|
-
lines.push("");
|
|
295
|
-
lines.push("## Currently Executing");
|
|
296
|
-
for (const exec of status.currentlyExecuting) {
|
|
297
|
-
const num = exec.ticketNumber ? `#${exec.ticketNumber}` : "";
|
|
298
|
-
const elapsed = getElapsedTime(exec.startedAt);
|
|
299
|
-
lines.push(`- **${num} ${exec.ticketSlug}** (${elapsed})`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (status.completedTickets && status.completedTickets.length > 0) {
|
|
303
|
-
lines.push("");
|
|
304
|
-
lines.push("## Recently Completed");
|
|
305
|
-
for (const completed of status.completedTickets.slice(0, 10)) {
|
|
306
|
-
const num = completed.ticketNumber ? `#${completed.ticketNumber}` : "";
|
|
307
|
-
const emoji = completed.success ? "\u2705" : completed.ticketClosed ? "\u26A0\uFE0F" : "\u274C";
|
|
308
|
-
const duration = formatDuration(completed.durationMs);
|
|
309
|
-
lines.push(`### ${emoji} ${num} ${completed.ticketSlug} (${duration})`);
|
|
310
|
-
if (completed.toolCalls && completed.toolCalls.length > 0) {
|
|
311
|
-
const toolNames = [...new Set(completed.toolCalls.map((t) => t.tool))];
|
|
312
|
-
lines.push(`- **Tools**: ${toolNames.join(", ")}`);
|
|
313
|
-
}
|
|
314
|
-
if (completed.ticketClosed) {
|
|
315
|
-
lines.push(`- **Status**: Ticket closed successfully`);
|
|
316
|
-
} else if (completed.exitCode === 0) {
|
|
317
|
-
lines.push(`- **Status**: Completed but ticket not closed`);
|
|
318
|
-
}
|
|
319
|
-
if (completed.errors && completed.errors.length > 0) {
|
|
320
|
-
lines.push(`- **Errors**: ${completed.errors.slice(0, 2).join("; ")}`);
|
|
321
|
-
}
|
|
322
|
-
if (completed.summary) {
|
|
323
|
-
lines.push(`- **Summary**: ${completed.summary.slice(0, 150)}`);
|
|
324
|
-
}
|
|
325
|
-
lines.push("");
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (status.lastError) {
|
|
329
|
-
lines.push("");
|
|
330
|
-
lines.push("## Last Error");
|
|
331
|
-
lines.push(`\`${status.lastError}\``);
|
|
332
|
-
}
|
|
333
|
-
return lines.join("\n");
|
|
334
|
-
}
|
|
335
|
-
function getElapsedTime(startedAt) {
|
|
336
|
-
const start = new Date(startedAt).getTime();
|
|
337
|
-
const elapsed = Date.now() - start;
|
|
338
|
-
const minutes = Math.floor(elapsed / 1e3 / 60);
|
|
339
|
-
const seconds = Math.floor(elapsed / 1e3 % 60);
|
|
340
|
-
if (minutes > 0) {
|
|
341
|
-
return `${minutes}m ${seconds}s`;
|
|
342
|
-
}
|
|
343
|
-
return `${seconds}s`;
|
|
344
|
-
}
|
|
345
|
-
function formatDuration(ms) {
|
|
346
|
-
if (ms < 1e3) {
|
|
347
|
-
return `${ms}ms`;
|
|
348
|
-
}
|
|
349
|
-
const seconds = Math.floor(ms / 1e3);
|
|
350
|
-
const minutes = Math.floor(seconds / 60);
|
|
351
|
-
if (minutes > 0) {
|
|
352
|
-
const remainingSeconds = seconds % 60;
|
|
353
|
-
return `${minutes}m ${remainingSeconds}s`;
|
|
354
|
-
}
|
|
355
|
-
return `${seconds}s`;
|
|
356
|
-
}
|
|
357
|
-
function generateMonitoringPrompt(statusFile, workingDirectory) {
|
|
358
|
-
const pidFile = join(getWatcherDir(workingDirectory), "watcher.pid");
|
|
359
|
-
return `You are a YOLO Watcher Monitor. Watch for ticket completions and report them.
|
|
360
|
-
|
|
361
|
-
## Status File
|
|
362
|
-
${statusFile}
|
|
363
|
-
|
|
364
|
-
## PID File (check if daemon is running)
|
|
365
|
-
${pidFile}
|
|
366
|
-
|
|
367
|
-
## Your Workflow
|
|
368
|
-
|
|
369
|
-
1. Read status.json and record the current count of completedTickets
|
|
370
|
-
2. Run this bash loop to wait for changes (bash does the waiting, not you):
|
|
371
|
-
\`\`\`bash
|
|
372
|
-
last_count=$(cat "${statusFile}" 2>/dev/null | grep -o '"ticketSlug"' | wc -l | tr -d ' ')
|
|
373
|
-
while [ -f "${pidFile}" ]; do
|
|
374
|
-
current=$(cat "${statusFile}" 2>/dev/null | grep -o '"ticketSlug"' | wc -l | tr -d ' ')
|
|
375
|
-
if [ "$current" != "$last_count" ]; then
|
|
376
|
-
echo "CHANGED: $last_count -> $current"
|
|
377
|
-
exit 0
|
|
378
|
-
fi
|
|
379
|
-
sleep 5
|
|
380
|
-
done
|
|
381
|
-
echo "DAEMON_STOPPED"
|
|
382
|
-
\`\`\`
|
|
383
|
-
3. When the loop exits:
|
|
384
|
-
- If "CHANGED": read status.json and report the NEW completed ticket(s)
|
|
385
|
-
- If "DAEMON_STOPPED": report that the watcher has stopped and exit
|
|
386
|
-
4. Loop back to step 1 (unless daemon stopped)
|
|
387
|
-
|
|
388
|
-
## Reporting Format
|
|
389
|
-
|
|
390
|
-
When a ticket completes:
|
|
391
|
-
\`\`\`
|
|
392
|
-
\u{1F3AB} YOLO TICKET COMPLETED
|
|
393
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
394
|
-
Ticket: {slug} (#{number})
|
|
395
|
-
Duration: {X}s
|
|
396
|
-
Status: {\u2705 Success | \u26A0\uFE0F Completed (not closed) | \u274C Failed}
|
|
397
|
-
Tools: {comma-separated list}
|
|
398
|
-
Summary: {brief from status}
|
|
399
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
400
|
-
\`\`\`
|
|
401
|
-
|
|
402
|
-
## Important
|
|
403
|
-
- Let bash do the waiting (cheap) - only "think" when reporting
|
|
404
|
-
- Exit gracefully when daemon stops
|
|
405
|
-
- Keep reports concise
|
|
406
|
-
|
|
407
|
-
Start monitoring now!`;
|
|
408
|
-
}
|
|
409
93
|
|
|
410
94
|
// src/prompt-builder.ts
|
|
411
95
|
var AmbiguousPromptError = class extends Error {
|
|
@@ -547,28 +231,6 @@ async function startServer(config, convexClientRaw) {
|
|
|
547
231
|
slashDescription: `Update a ticket by appending content with timestamp`,
|
|
548
232
|
projectSlug,
|
|
549
233
|
type: "update"
|
|
550
|
-
},
|
|
551
|
-
// YOLO orchestrator tools - sub-agent based autonomous ticket execution
|
|
552
|
-
{
|
|
553
|
-
name: `tickets_yolo_start`,
|
|
554
|
-
description: `Start the YOLO ticket watcher for "${projectSlug}". Polls for open tickets with yolo flag and spawns Terminal windows with Claude Code to execute them autonomously.`,
|
|
555
|
-
slashDescription: `Start YOLO orchestrator for autonomous ticket execution`,
|
|
556
|
-
projectSlug,
|
|
557
|
-
type: "yolo_start"
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
name: `tickets_yolo_stop`,
|
|
561
|
-
description: `Stop the YOLO ticket watcher for "${projectSlug}"`,
|
|
562
|
-
slashDescription: `Stop the YOLO orchestrator`,
|
|
563
|
-
projectSlug,
|
|
564
|
-
type: "yolo_stop"
|
|
565
|
-
},
|
|
566
|
-
{
|
|
567
|
-
name: `tickets_yolo_status`,
|
|
568
|
-
description: `Get YOLO watcher status for "${projectSlug}"`,
|
|
569
|
-
slashDescription: `Check YOLO orchestrator status and pending tickets`,
|
|
570
|
-
projectSlug,
|
|
571
|
-
type: "yolo_status"
|
|
572
234
|
}
|
|
573
235
|
];
|
|
574
236
|
console.error(`[MCP] Registering ${dynamicTicketTools.length} ticket tools...`);
|
|
@@ -881,45 +543,6 @@ This will execute the "code-review" prompt.`;
|
|
|
881
543
|
},
|
|
882
544
|
required: ["ticketSlug", "content"]
|
|
883
545
|
};
|
|
884
|
-
} else if (tt.type === "yolo_start") {
|
|
885
|
-
inputSchema = {
|
|
886
|
-
type: "object",
|
|
887
|
-
properties: {
|
|
888
|
-
pollIntervalMs: {
|
|
889
|
-
type: "number",
|
|
890
|
-
description: "Milliseconds between polls (default: 30000 = 30s)"
|
|
891
|
-
},
|
|
892
|
-
maxParallel: {
|
|
893
|
-
type: "number",
|
|
894
|
-
description: "Maximum concurrent ticket executions (default: 1)"
|
|
895
|
-
},
|
|
896
|
-
ticketTimeout: {
|
|
897
|
-
type: "number",
|
|
898
|
-
description: "Timeout for ticket execution in ms (default: 1800000 = 30 min)"
|
|
899
|
-
},
|
|
900
|
-
enableNotifications: {
|
|
901
|
-
type: "boolean",
|
|
902
|
-
description: "Show macOS notifications (default: true)"
|
|
903
|
-
},
|
|
904
|
-
workingDirectory: {
|
|
905
|
-
type: "string",
|
|
906
|
-
description: "Working directory for Claude Code sessions (default: current working directory)"
|
|
907
|
-
}
|
|
908
|
-
},
|
|
909
|
-
required: []
|
|
910
|
-
};
|
|
911
|
-
} else if (tt.type === "yolo_stop") {
|
|
912
|
-
inputSchema = {
|
|
913
|
-
type: "object",
|
|
914
|
-
properties: {},
|
|
915
|
-
required: []
|
|
916
|
-
};
|
|
917
|
-
} else if (tt.type === "yolo_status") {
|
|
918
|
-
inputSchema = {
|
|
919
|
-
type: "object",
|
|
920
|
-
properties: {},
|
|
921
|
-
required: []
|
|
922
|
-
};
|
|
923
546
|
} else {
|
|
924
547
|
inputSchema = {
|
|
925
548
|
type: "object",
|
|
@@ -1649,109 +1272,6 @@ _Ticket content has been appended with your update._`
|
|
|
1649
1272
|
isError: true
|
|
1650
1273
|
};
|
|
1651
1274
|
}
|
|
1652
|
-
} else if (ticketTool.type === "yolo_start") {
|
|
1653
|
-
const args = parseWatcherStartArgs(request.params.arguments);
|
|
1654
|
-
const workingDirectory = args.workingDirectory ?? process.cwd();
|
|
1655
|
-
try {
|
|
1656
|
-
const result = startWatcher(
|
|
1657
|
-
{
|
|
1658
|
-
projectSlug: ticketTool.projectSlug,
|
|
1659
|
-
projectToken: config.projectToken,
|
|
1660
|
-
convexUrl: config.convexUrl,
|
|
1661
|
-
workingDirectory
|
|
1662
|
-
},
|
|
1663
|
-
args
|
|
1664
|
-
);
|
|
1665
|
-
if (result.success) {
|
|
1666
|
-
const configInfo = result.config ? `
|
|
1667
|
-
|
|
1668
|
-
**Configuration:**
|
|
1669
|
-
- Poll Interval: ${result.config.pollIntervalMs / 1e3}s
|
|
1670
|
-
- Max Parallel: ${result.config.maxParallel}
|
|
1671
|
-
- Ticket Timeout: ${result.config.ticketTimeout / 1e3 / 60} min
|
|
1672
|
-
- Working Directory: ${result.config.workingDirectory}` : "";
|
|
1673
|
-
const monitoringSection = result.monitoringPrompt && !result.alreadyRunning ? `
|
|
1674
|
-
|
|
1675
|
-
---
|
|
1676
|
-
|
|
1677
|
-
## \u{1F514} Real-time Monitoring
|
|
1678
|
-
|
|
1679
|
-
To receive notifications when tickets complete, spawn a background monitoring agent:
|
|
1680
|
-
|
|
1681
|
-
<monitoring_prompt>
|
|
1682
|
-
${result.monitoringPrompt}
|
|
1683
|
-
</monitoring_prompt>
|
|
1684
|
-
|
|
1685
|
-
**Usage:** Use the Task tool with subagent_type="general-purpose", run_in_background=true, and the prompt above.` : "";
|
|
1686
|
-
const text = result.alreadyRunning ? `\u2139\uFE0F ${result.message}${configInfo}` : `\u2705 ${result.message}
|
|
1687
|
-
|
|
1688
|
-
The daemon is now polling for YOLO-flagged tickets and will spawn Claude CLI processes to execute them.
|
|
1689
|
-
|
|
1690
|
-
Logs: \`.ppm/yolo/logs/\`${configInfo}${monitoringSection}`;
|
|
1691
|
-
return {
|
|
1692
|
-
content: [{ type: "text", text }]
|
|
1693
|
-
};
|
|
1694
|
-
} else {
|
|
1695
|
-
return {
|
|
1696
|
-
content: [{ type: "text", text: `\u274C ${result.message}` }],
|
|
1697
|
-
isError: true
|
|
1698
|
-
};
|
|
1699
|
-
}
|
|
1700
|
-
} catch (error) {
|
|
1701
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1702
|
-
console.error(`[MCP] tickets_yolo_start error:`, error);
|
|
1703
|
-
return {
|
|
1704
|
-
content: [{ type: "text", text: `Error starting watcher daemon: ${errorMessage}` }],
|
|
1705
|
-
isError: true
|
|
1706
|
-
};
|
|
1707
|
-
}
|
|
1708
|
-
} else if (ticketTool.type === "yolo_stop") {
|
|
1709
|
-
const workingDirectory = process.cwd();
|
|
1710
|
-
try {
|
|
1711
|
-
const result = stopWatcher(workingDirectory);
|
|
1712
|
-
if (result.success) {
|
|
1713
|
-
return {
|
|
1714
|
-
content: [{
|
|
1715
|
-
type: "text",
|
|
1716
|
-
text: result.wasRunning ? `\u2705 ${result.message}
|
|
1717
|
-
|
|
1718
|
-
The daemon has been stopped. Any running ticket executions will complete.` : `\u2139\uFE0F ${result.message}`
|
|
1719
|
-
}]
|
|
1720
|
-
};
|
|
1721
|
-
} else {
|
|
1722
|
-
return {
|
|
1723
|
-
content: [{ type: "text", text: `\u274C ${result.message}` }],
|
|
1724
|
-
isError: true
|
|
1725
|
-
};
|
|
1726
|
-
}
|
|
1727
|
-
} catch (error) {
|
|
1728
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1729
|
-
console.error(`[MCP] tickets_yolo_stop error:`, error);
|
|
1730
|
-
return {
|
|
1731
|
-
content: [{ type: "text", text: `Error stopping watcher daemon: ${errorMessage}` }],
|
|
1732
|
-
isError: true
|
|
1733
|
-
};
|
|
1734
|
-
}
|
|
1735
|
-
} else if (ticketTool.type === "yolo_status") {
|
|
1736
|
-
const workingDirectory = process.cwd();
|
|
1737
|
-
try {
|
|
1738
|
-
const result = getWatcherStatus(workingDirectory);
|
|
1739
|
-
if (result.formattedStatus) {
|
|
1740
|
-
return {
|
|
1741
|
-
content: [{ type: "text", text: result.formattedStatus }]
|
|
1742
|
-
};
|
|
1743
|
-
}
|
|
1744
|
-
return {
|
|
1745
|
-
content: [{ type: "text", text: `\u2139\uFE0F ${result.message ?? "No watcher status available"}` }]
|
|
1746
|
-
};
|
|
1747
|
-
} catch (error) {
|
|
1748
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1749
|
-
console.error(`[MCP] tickets_yolo_status error:`, error);
|
|
1750
|
-
return {
|
|
1751
|
-
content: [{ type: "text", text: `Error getting watcher status: ${errorMessage}` }],
|
|
1752
|
-
isError: true
|
|
1753
|
-
};
|
|
1754
|
-
}
|
|
1755
1275
|
}
|
|
1756
1276
|
}
|
|
1757
1277
|
const promptTool = dynamicPromptTools.find((pt) => pt.name === toolName);
|