@mushi-mushi/plugin-cursor-cloud 0.4.0 → 0.5.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/README.md CHANGED
@@ -138,3 +138,9 @@ The test suite covers:
138
138
  ## License
139
139
 
140
140
  MIT — see [LICENSE](./LICENSE).
141
+
142
+
143
+ <!-- mushi-readme-stats-footer -->
144
+ ---
145
+
146
+ <sub>Monorepo scale (June 2026): 43 edge functions · 234 SQL migrations · 13 outbound plugins · 11 inbound adapters. Canonical counts: <a href="https://github.com/kensaurus/mushi-mushi/blob/master/docs/stats.md">docs/stats.md</a> · <code>pnpm docs-stats</code></sub>
package/dist/index.js CHANGED
@@ -158,10 +158,112 @@ function createCursorCloudPlugin(cfg) {
158
158
  model
159
159
  };
160
160
  console.warn("[cursor-cloud] qa_story.failed dispatched", JSON.stringify(result));
161
+ },
162
+ // ── Skill pipeline step dispatch (Phase 5) ───────────────────────────
163
+ // When a pipeline run is started in 'cloud' mode, the skills.ts route
164
+ // fires this event for each step. The plugin creates a Cursor Cloud
165
+ // agent run whose prompt is the pre-composed context_packet for that
166
+ // step, stores the agentId on the step row, and reports back to Mushi
167
+ // via the check-in endpoint.
168
+ "skill_pipeline.step.dispatched": async (e) => {
169
+ const data = e.data;
170
+ const repoUrl = cfg.repoUrl ?? "";
171
+ if (!repoUrl) {
172
+ console.warn("[cursor-cloud] skill_pipeline.step.dispatched skipped: repoUrl not configured.");
173
+ return;
174
+ }
175
+ let run;
176
+ try {
177
+ run = await withRetry(
178
+ () => createCursorAgentRun(
179
+ resolvedCfg,
180
+ {
181
+ repoUrl,
182
+ prompt: buildPromptFromSkillStep(data)
183
+ },
184
+ f
185
+ ),
186
+ { maxAttempts: 3 }
187
+ );
188
+ } catch (err) {
189
+ console.error("[cursor-cloud] skill_pipeline step dispatch failed", String(err));
190
+ const mushiUrl2 = (typeof process !== "undefined" ? process.env.MUSHI_API_URL : void 0) ?? "https://api.mushi.ai";
191
+ const mushiKey2 = (typeof process !== "undefined" ? process.env.MUSHI_API_KEY : void 0) ?? "";
192
+ if (mushiKey2) {
193
+ try {
194
+ await f(`${mushiUrl2}/v1/admin/skills/pipelines/${data.runId}/steps/${data.stepIndex}/checkin`, {
195
+ method: "POST",
196
+ headers: {
197
+ "Content-Type": "application/json",
198
+ "X-Mushi-Api-Key": mushiKey2
199
+ },
200
+ body: JSON.stringify({
201
+ status: "failed",
202
+ notes: `Cursor Cloud dispatch failed: ${String(err).slice(0, 400)}`
203
+ })
204
+ });
205
+ } catch {
206
+ }
207
+ } else {
208
+ console.warn(
209
+ `[cursor-cloud] MUSHI_API_KEY unset \u2014 cannot report the failed dispatch for run ${data.runId} step ${data.stepIndex}. The step will remain 'running' server-side until it is manually checked in.`
210
+ );
211
+ }
212
+ return;
213
+ }
214
+ console.log("[cursor-cloud] skill_pipeline step dispatched", {
215
+ runId: data.runId,
216
+ stepIndex: data.stepIndex,
217
+ agentId: run.agentId
218
+ });
219
+ const mushiUrl = (typeof process !== "undefined" ? process.env.MUSHI_API_URL : void 0) ?? "https://api.mushi.ai";
220
+ const mushiKey = (typeof process !== "undefined" ? process.env.MUSHI_API_KEY : void 0) ?? "";
221
+ if (mushiKey) {
222
+ try {
223
+ await f(`${mushiUrl}/v1/admin/skills/pipelines/${data.runId}/steps/${data.stepIndex}/checkin`, {
224
+ method: "POST",
225
+ headers: {
226
+ "Content-Type": "application/json",
227
+ "X-Mushi-Api-Key": mushiKey
228
+ },
229
+ body: JSON.stringify({
230
+ status: "running",
231
+ agent_ref: run.agentId,
232
+ notes: `Cursor Cloud agent dispatched (model: ${model})`
233
+ })
234
+ });
235
+ } catch (err) {
236
+ console.warn("[cursor-cloud] checkin failed (best-effort)", String(err));
237
+ }
238
+ } else {
239
+ console.warn(
240
+ `[cursor-cloud] MUSHI_API_KEY unset \u2014 agent ${run.agentId} was dispatched for run ${data.runId} step ${data.stepIndex} but its agent_ref/running status cannot be reported back. The console flow will not reflect this step until it is manually checked in.`
241
+ );
242
+ }
161
243
  }
162
244
  }
163
245
  });
164
246
  }
247
+ function buildPromptFromSkillStep(data) {
248
+ return [
249
+ `# Mushi Skill Pipeline \u2014 Step ${data.stepIndex + 1}`,
250
+ ``,
251
+ `Skill: \`${data.skillSlug}\``,
252
+ `Pipeline run: ${data.runId}`,
253
+ ``,
254
+ `You are executing step ${data.stepIndex + 1} of a Mushi skill pipeline. The full context packet below contains your instructions plus the complete report context.`,
255
+ ``,
256
+ `When you have completed this step, call the Mushi MCP tool \`checkin_pipeline_step\` with:`,
257
+ ` run_id: "${data.runId}"`,
258
+ ` step_index: ${data.stepIndex}`,
259
+ ` status: "passed" (or "failed" if you could not complete it)`,
260
+ ` pr_url: <your PR URL if you opened one>`,
261
+ ``,
262
+ `\u2500\u2500\u2500 Context Packet \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
263
+ ``,
264
+ data.contextPacket.slice(0, 32e3)
265
+ ].join("\n");
266
+ }
165
267
  export {
166
268
  createCursorCloudPlugin
167
269
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cursor Cloud Agent plugin for Mushi Mushi.\n *\n * Path A: Marketplace plugin — subscribes to `report.classified`,\n * `qa_story.failed`, and `fix.requested`. When a qualifying event fires,\n * this plugin calls Cursor's HTTP REST API directly (no @cursor/sdk —\n * runs from Deno edge functions and Node alike) to create a Cloud Agent\n * run, and logs the resulting `agentId` + `prUrl` to the Mushi console.\n *\n * This is the *opt-in* path: teams install it from the Marketplace and\n * configure their Cursor API key + workspace ID in the plugin settings.\n * For the project-wide *default* Cursor agent path, see Path B in\n * packages/agents/src/adapters/cursor-cloud.ts.\n *\n * Cursor REST API docs: https://cursor.com/docs/cloud-agent/api/v0.md\n */\n\nimport {\n createPluginHandler,\n withRetry,\n type MushiEventEnvelope,\n type MushiReportClassifiedEvent,\n type MushiFixEvent,\n} from '@mushi-mushi/plugin-sdk'\n\nconst CURSOR_API_BASE = 'https://api.cursor.com/v0'\n\nconst SEVERITY_RANK: Record<string, number> = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n}\n\nexport interface CursorCloudPluginConfig {\n /** Cursor API key (crsr_…). */\n apiKey: string\n /** @deprecated No longer required by Cursor Cloud Agents API. */\n workspaceId?: string\n /** Cursor model slug. Defaults to `composer-2.5`. */\n model?: string\n /** Whether the agent should automatically open a draft PR. Defaults to true. */\n autoCreatePR?: boolean\n /** Maximum iterations for the agent. Defaults to 1. */\n maxIterations?: number\n /** Lowest severity that triggers a Cursor agent run. Defaults to `critical`. */\n severityThreshold?: 'low' | 'medium' | 'high' | 'critical'\n /**\n * URL of the target repository the Cursor agent will work in.\n * If not set, the plugin will attempt to read it from the event payload.\n */\n repoUrl?: string\n /**\n * Standard Webhooks secret for inbound Mushi events. Required for\n * self-hosted installs — never derive this from workspaceId.\n */\n webhookSecret?: string\n /** Override `fetch` for tests. */\n fetchImpl?: typeof fetch\n}\n\nexport interface CursorAgentRunResponse {\n agentId: string\n status: string\n prUrl?: string\n}\n\nexport interface CursorDispatchResult {\n agentId: string\n reportId: string\n model: string\n}\n\n/**\n * Call Cursor's REST API to create a Cloud Agent run.\n * Returns the agentId so the caller can track the run in Mushi console.\n *\n * On non-2xx the raw Response is thrown so `withRetry` can inspect\n * `.status` and `Retry-After` and apply the documented retry policy:\n * - 429 / 5xx → retry with exponential back-off\n * - 4xx (not 429) → throw immediately (no money burned on bad keys)\n * - network error → retry\n */\nasync function createCursorAgentRun(\n cfg: Required<Pick<CursorCloudPluginConfig, 'apiKey' | 'model' | 'autoCreatePR' | 'maxIterations'>>,\n opts: { repoUrl: string; prompt: string; branchName?: string },\n f: typeof fetch,\n): Promise<CursorAgentRunResponse> {\n return withRetry(async () => {\n const res = await f(`${CURSOR_API_BASE}/agents`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n prompt: { text: opts.prompt },\n model: cfg.model || 'default',\n source: {\n repository: opts.repoUrl,\n ref: 'main',\n },\n target: {\n autoCreatePr: cfg.autoCreatePR,\n branchName: opts.branchName ?? `mushi/cursor-${Date.now()}`,\n skipReviewerRequest: true,\n },\n }),\n })\n if (!res.ok) {\n // Throw the Response itself so withRetry can read status / Retry-After.\n // This is the contract documented in @mushi-mushi/plugin-sdk/retry.ts.\n throw res\n }\n const body = (await res.json()) as { agentId?: string; id?: string; status?: string; prUrl?: string }\n return {\n agentId: body.agentId ?? body.id ?? '',\n status: body.status ?? 'queued',\n prUrl: body.prUrl,\n }\n })\n}\n\nfunction buildPromptFromClassifiedReport(\n envelope: MushiEventEnvelope,\n data: MushiReportClassifiedEvent,\n): string {\n const lines = [\n `A bug has been reported in your project and classified as ${data.classification.severity?.toUpperCase()}.`,\n ``,\n `Report ID: ${data.report.id}`,\n `Title: ${data.report.title ?? '(untitled)'}`,\n `Category: ${data.report.category ?? data.classification.category}`,\n `Severity: ${data.classification.severity}`,\n `Project: ${envelope.projectId}`,\n ]\n\n if (data.classification.tags?.length) {\n lines.push(`Tags: ${data.classification.tags.join(', ')}`)\n }\n\n lines.push(\n ``,\n `Please investigate this bug, identify the root cause in the codebase, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n )\n\n return lines.join('\\n')\n}\n\nfunction buildPromptFromFixRequested(envelope: MushiEventEnvelope, fixData: MushiFixEvent): string {\n return [\n `A fix was requested for report ${fixData.report.id} in project ${envelope.projectId}.`,\n ``,\n `Report title: ${fixData.report.title ?? '(untitled)'}`,\n `Fix ID: ${fixData.fix.id}`,\n ``,\n `Please investigate the reported issue, identify the root cause, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n ].join('\\n')\n}\n\nfunction buildPromptFromQaStoryFailed(\n envelope: MushiEventEnvelope,\n data: { storyId?: string; title?: string; failureReason?: string },\n): string {\n return [\n `A QA story failed in project ${envelope.projectId}.`,\n ``,\n `Story ID: ${data.storyId ?? 'unknown'}`,\n `Title: ${data.title ?? '(untitled)'}`,\n data.failureReason ? `Failure: ${data.failureReason}` : '',\n ``,\n `Please investigate the failing assertion, identify the root cause in the codebase, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n ].filter((line) => line !== '').join('\\n')\n}\n\n/** Build the plugin handler and return a callable function. */\nexport function createCursorCloudPlugin(cfg: CursorCloudPluginConfig) {\n const minRank = SEVERITY_RANK[cfg.severityThreshold ?? 'critical']!\n const model = cfg.model ?? 'composer-2.5'\n const autoCreatePR = cfg.autoCreatePR ?? true\n const maxIterations = cfg.maxIterations ?? 1\n const f = cfg.fetchImpl ?? fetch\n\n const resolvedCfg = { apiKey: cfg.apiKey, model, autoCreatePR, maxIterations }\n\n const webhookSecret =\n cfg.webhookSecret ??\n (typeof process !== 'undefined' ? process.env.MUSHI_PLUGIN_WEBHOOK_SECRET : undefined)\n if (!webhookSecret) {\n throw new Error(\n 'Cursor Cloud plugin requires webhookSecret (or MUSHI_PLUGIN_WEBHOOK_SECRET) for inbound event verification.',\n )\n }\n\n return createPluginHandler({\n secret: webhookSecret,\n on: {\n 'report.classified': async (e) => {\n const data = e.data as MushiReportClassifiedEvent\n const rank = SEVERITY_RANK[data.classification.severity ?? ''] ?? 0\n if (rank < minRank) return\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] report.classified skipped: repoUrl not configured. ' +\n 'Set repoUrl in the plugin config so the agent knows which codebase to fix.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromClassifiedReport(e, data),\n },\n f,\n )\n\n // Emit audit log — handler return type is void.\n const result: CursorDispatchResult = { agentId: run.agentId, reportId: data.report.id, model }\n console.warn('[cursor-cloud] dispatched', JSON.stringify(result))\n },\n\n 'fix.requested': async (e) => {\n const data = e.data as MushiFixEvent\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] fix.requested skipped: repoUrl not configured.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromFixRequested(e, data),\n },\n f,\n )\n\n // Emit audit log — handler return type is void.\n const result: CursorDispatchResult = { agentId: run.agentId, reportId: data.report.id, model }\n console.warn('[cursor-cloud] fix.requested dispatched', JSON.stringify(result))\n },\n\n 'qa_story.failed': async (e) => {\n const data = e.data as { storyId?: string; title?: string; failureReason?: string }\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] qa_story.failed skipped: repoUrl not configured.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromQaStoryFailed(e, data),\n },\n f,\n )\n\n const result: CursorDispatchResult = {\n agentId: run.agentId,\n reportId: data.storyId ?? 'unknown',\n model,\n }\n console.warn('[cursor-cloud] qa_story.failed dispatched', JSON.stringify(result))\n },\n },\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cursor Cloud Agent plugin for Mushi Mushi.\n *\n * Path A: Marketplace plugin — subscribes to `report.classified`,\n * `qa_story.failed`, and `fix.requested`. When a qualifying event fires,\n * this plugin calls Cursor's HTTP REST API directly (no @cursor/sdk —\n * runs from Deno edge functions and Node alike) to create a Cloud Agent\n * run, and logs the resulting `agentId` + `prUrl` to the Mushi console.\n *\n * This is the *opt-in* path: teams install it from the Marketplace and\n * configure their Cursor API key + workspace ID in the plugin settings.\n * For the project-wide *default* Cursor agent path, see Path B in\n * packages/agents/src/adapters/cursor-cloud.ts.\n *\n * Cursor REST API docs: https://cursor.com/docs/cloud-agent/api/v0.md\n */\n\nimport {\n createPluginHandler,\n withRetry,\n type MushiEventEnvelope,\n type MushiReportClassifiedEvent,\n type MushiFixEvent,\n} from '@mushi-mushi/plugin-sdk'\n\nconst CURSOR_API_BASE = 'https://api.cursor.com/v0'\n\nconst SEVERITY_RANK: Record<string, number> = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n}\n\nexport interface CursorCloudPluginConfig {\n /** Cursor API key (crsr_…). */\n apiKey: string\n /** @deprecated No longer required by Cursor Cloud Agents API. */\n workspaceId?: string\n /** Cursor model slug. Defaults to `composer-2.5`. */\n model?: string\n /** Whether the agent should automatically open a draft PR. Defaults to true. */\n autoCreatePR?: boolean\n /** Maximum iterations for the agent. Defaults to 1. */\n maxIterations?: number\n /** Lowest severity that triggers a Cursor agent run. Defaults to `critical`. */\n severityThreshold?: 'low' | 'medium' | 'high' | 'critical'\n /**\n * URL of the target repository the Cursor agent will work in.\n * If not set, the plugin will attempt to read it from the event payload.\n */\n repoUrl?: string\n /**\n * Standard Webhooks secret for inbound Mushi events. Required for\n * self-hosted installs — never derive this from workspaceId.\n */\n webhookSecret?: string\n /** Override `fetch` for tests. */\n fetchImpl?: typeof fetch\n}\n\nexport interface CursorAgentRunResponse {\n agentId: string\n status: string\n prUrl?: string\n}\n\nexport interface CursorDispatchResult {\n agentId: string\n reportId: string\n model: string\n}\n\n/**\n * Call Cursor's REST API to create a Cloud Agent run.\n * Returns the agentId so the caller can track the run in Mushi console.\n *\n * On non-2xx the raw Response is thrown so `withRetry` can inspect\n * `.status` and `Retry-After` and apply the documented retry policy:\n * - 429 / 5xx → retry with exponential back-off\n * - 4xx (not 429) → throw immediately (no money burned on bad keys)\n * - network error → retry\n */\nasync function createCursorAgentRun(\n cfg: Required<Pick<CursorCloudPluginConfig, 'apiKey' | 'model' | 'autoCreatePR' | 'maxIterations'>>,\n opts: { repoUrl: string; prompt: string; branchName?: string },\n f: typeof fetch,\n): Promise<CursorAgentRunResponse> {\n return withRetry(async () => {\n const res = await f(`${CURSOR_API_BASE}/agents`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${cfg.apiKey}`,\n },\n body: JSON.stringify({\n prompt: { text: opts.prompt },\n model: cfg.model || 'default',\n source: {\n repository: opts.repoUrl,\n ref: 'main',\n },\n target: {\n autoCreatePr: cfg.autoCreatePR,\n branchName: opts.branchName ?? `mushi/cursor-${Date.now()}`,\n skipReviewerRequest: true,\n },\n }),\n })\n if (!res.ok) {\n // Throw the Response itself so withRetry can read status / Retry-After.\n // This is the contract documented in @mushi-mushi/plugin-sdk/retry.ts.\n throw res\n }\n const body = (await res.json()) as { agentId?: string; id?: string; status?: string; prUrl?: string }\n return {\n agentId: body.agentId ?? body.id ?? '',\n status: body.status ?? 'queued',\n prUrl: body.prUrl,\n }\n })\n}\n\nfunction buildPromptFromClassifiedReport(\n envelope: MushiEventEnvelope,\n data: MushiReportClassifiedEvent,\n): string {\n const lines = [\n `A bug has been reported in your project and classified as ${data.classification.severity?.toUpperCase()}.`,\n ``,\n `Report ID: ${data.report.id}`,\n `Title: ${data.report.title ?? '(untitled)'}`,\n `Category: ${data.report.category ?? data.classification.category}`,\n `Severity: ${data.classification.severity}`,\n `Project: ${envelope.projectId}`,\n ]\n\n if (data.classification.tags?.length) {\n lines.push(`Tags: ${data.classification.tags.join(', ')}`)\n }\n\n lines.push(\n ``,\n `Please investigate this bug, identify the root cause in the codebase, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n )\n\n return lines.join('\\n')\n}\n\nfunction buildPromptFromFixRequested(envelope: MushiEventEnvelope, fixData: MushiFixEvent): string {\n return [\n `A fix was requested for report ${fixData.report.id} in project ${envelope.projectId}.`,\n ``,\n `Report title: ${fixData.report.title ?? '(untitled)'}`,\n `Fix ID: ${fixData.fix.id}`,\n ``,\n `Please investigate the reported issue, identify the root cause, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n ].join('\\n')\n}\n\nfunction buildPromptFromQaStoryFailed(\n envelope: MushiEventEnvelope,\n data: { storyId?: string; title?: string; failureReason?: string },\n): string {\n return [\n `A QA story failed in project ${envelope.projectId}.`,\n ``,\n `Story ID: ${data.storyId ?? 'unknown'}`,\n `Title: ${data.title ?? '(untitled)'}`,\n data.failureReason ? `Failure: ${data.failureReason}` : '',\n ``,\n `Please investigate the failing assertion, identify the root cause in the codebase, ` +\n `and open a draft PR with a minimal fix. Do not refactor unrelated code.`,\n ].filter((line) => line !== '').join('\\n')\n}\n\n/** Build the plugin handler and return a callable function. */\nexport function createCursorCloudPlugin(cfg: CursorCloudPluginConfig) {\n const minRank = SEVERITY_RANK[cfg.severityThreshold ?? 'critical']!\n const model = cfg.model ?? 'composer-2.5'\n const autoCreatePR = cfg.autoCreatePR ?? true\n const maxIterations = cfg.maxIterations ?? 1\n const f = cfg.fetchImpl ?? fetch\n\n const resolvedCfg = { apiKey: cfg.apiKey, model, autoCreatePR, maxIterations }\n\n const webhookSecret =\n cfg.webhookSecret ??\n (typeof process !== 'undefined' ? process.env.MUSHI_PLUGIN_WEBHOOK_SECRET : undefined)\n if (!webhookSecret) {\n throw new Error(\n 'Cursor Cloud plugin requires webhookSecret (or MUSHI_PLUGIN_WEBHOOK_SECRET) for inbound event verification.',\n )\n }\n\n return createPluginHandler({\n secret: webhookSecret,\n on: {\n 'report.classified': async (e) => {\n const data = e.data as MushiReportClassifiedEvent\n const rank = SEVERITY_RANK[data.classification.severity ?? ''] ?? 0\n if (rank < minRank) return\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] report.classified skipped: repoUrl not configured. ' +\n 'Set repoUrl in the plugin config so the agent knows which codebase to fix.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromClassifiedReport(e, data),\n },\n f,\n )\n\n // Emit audit log — handler return type is void.\n const result: CursorDispatchResult = { agentId: run.agentId, reportId: data.report.id, model }\n console.warn('[cursor-cloud] dispatched', JSON.stringify(result))\n },\n\n 'fix.requested': async (e) => {\n const data = e.data as MushiFixEvent\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] fix.requested skipped: repoUrl not configured.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromFixRequested(e, data),\n },\n f,\n )\n\n // Emit audit log — handler return type is void.\n const result: CursorDispatchResult = { agentId: run.agentId, reportId: data.report.id, model }\n console.warn('[cursor-cloud] fix.requested dispatched', JSON.stringify(result))\n },\n\n 'qa_story.failed': async (e) => {\n const data = e.data as { storyId?: string; title?: string; failureReason?: string }\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] qa_story.failed skipped: repoUrl not configured.')\n return\n }\n\n const run = await createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromQaStoryFailed(e, data),\n },\n f,\n )\n\n const result: CursorDispatchResult = {\n agentId: run.agentId,\n reportId: data.storyId ?? 'unknown',\n model,\n }\n console.warn('[cursor-cloud] qa_story.failed dispatched', JSON.stringify(result))\n },\n\n // ── Skill pipeline step dispatch (Phase 5) ───────────────────────────\n // When a pipeline run is started in 'cloud' mode, the skills.ts route\n // fires this event for each step. The plugin creates a Cursor Cloud\n // agent run whose prompt is the pre-composed context_packet for that\n // step, stores the agentId on the step row, and reports back to Mushi\n // via the check-in endpoint.\n 'skill_pipeline.step.dispatched': async (e) => {\n const data = e.data as {\n runId: string\n stepIndex: number\n skillSlug: string\n contextPacket: string\n projectId: string\n }\n\n const repoUrl = cfg.repoUrl ?? ''\n if (!repoUrl) {\n console.warn('[cursor-cloud] skill_pipeline.step.dispatched skipped: repoUrl not configured.')\n return\n }\n\n let run: CursorAgentRunResponse\n try {\n run = await withRetry(\n () =>\n createCursorAgentRun(\n resolvedCfg,\n {\n repoUrl,\n prompt: buildPromptFromSkillStep(data),\n },\n f,\n ),\n { maxAttempts: 3 },\n )\n } catch (err) {\n console.error('[cursor-cloud] skill_pipeline step dispatch failed', String(err))\n const mushiUrl =\n (typeof process !== 'undefined' ? process.env.MUSHI_API_URL : undefined) ?? 'https://api.mushi.ai'\n const mushiKey =\n (typeof process !== 'undefined' ? process.env.MUSHI_API_KEY : undefined) ?? ''\n if (mushiKey) {\n try {\n await f(`${mushiUrl}/v1/admin/skills/pipelines/${data.runId}/steps/${data.stepIndex}/checkin`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': mushiKey,\n },\n body: JSON.stringify({\n status: 'failed',\n notes: `Cursor Cloud dispatch failed: ${String(err).slice(0, 400)}`,\n }),\n })\n } catch { /* best-effort */ }\n } else {\n console.warn(\n `[cursor-cloud] MUSHI_API_KEY unset — cannot report the failed dispatch for run ${data.runId} step ${data.stepIndex}. ` +\n `The step will remain 'running' server-side until it is manually checked in.`,\n )\n }\n return\n }\n\n console.log('[cursor-cloud] skill_pipeline step dispatched', {\n runId: data.runId,\n stepIndex: data.stepIndex,\n agentId: run.agentId,\n })\n\n // Report back to Mushi: update the step row with the agentId.\n // The console React Flow canvas will update via Realtime.\n // Use a best-effort POST to the check-in endpoint.\n const mushiUrl =\n (typeof process !== 'undefined' ? process.env.MUSHI_API_URL : undefined) ?? 'https://api.mushi.ai'\n const mushiKey =\n (typeof process !== 'undefined' ? process.env.MUSHI_API_KEY : undefined) ?? ''\n\n if (mushiKey) {\n try {\n await f(`${mushiUrl}/v1/admin/skills/pipelines/${data.runId}/steps/${data.stepIndex}/checkin`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': mushiKey,\n },\n body: JSON.stringify({\n status: 'running',\n agent_ref: run.agentId,\n notes: `Cursor Cloud agent dispatched (model: ${model})`,\n }),\n })\n } catch (err) {\n console.warn('[cursor-cloud] checkin failed (best-effort)', String(err))\n }\n } else {\n console.warn(\n `[cursor-cloud] MUSHI_API_KEY unset — agent ${run.agentId} was dispatched for run ${data.runId} step ${data.stepIndex} ` +\n `but its agent_ref/running status cannot be reported back. The console flow will not reflect this step until it is manually checked in.`,\n )\n }\n },\n },\n })\n}\n\nfunction buildPromptFromSkillStep(data: {\n runId: string\n stepIndex: number\n skillSlug: string\n contextPacket: string\n}): string {\n return [\n `# Mushi Skill Pipeline — Step ${data.stepIndex + 1}`,\n ``,\n `Skill: \\`${data.skillSlug}\\``,\n `Pipeline run: ${data.runId}`,\n ``,\n `You are executing step ${data.stepIndex + 1} of a Mushi skill pipeline. ` +\n `The full context packet below contains your instructions plus the complete report context.`,\n ``,\n `When you have completed this step, call the Mushi MCP tool \\`checkin_pipeline_step\\` with:`,\n ` run_id: \"${data.runId}\"`,\n ` step_index: ${data.stepIndex}`,\n ` status: \"passed\" (or \"failed\" if you could not complete it)`,\n ` pr_url: <your PR URL if you opened one>`,\n ``,\n `─── Context Packet ────────────────────────────────────────────────────`,\n ``,\n data.contextPacket.slice(0, 32_000),\n ].join('\\n')\n}\n"],"mappings":"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","names":["mushiUrl","mushiKey"]}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@mushi-mushi/plugin-cursor-cloud",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
- "description": "Mushi Mushi plugin: dispatch a Cursor Cloud Agent when a critical bug is classified or a QA story fails \u00e2\u20ac\u201d opens a signed draft PR automatically.",
5
+ "description": "Mushi Mushi plugin: dispatch a Cursor Cloud Agent when a critical bug is classified or a QA story fails — opens a signed draft PR automatically.",
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": {
@@ -17,23 +17,16 @@
17
17
  "README.md",
18
18
  "LICENSE"
19
19
  ],
20
- "scripts": {
21
- "build": "tsup",
22
- "dev": "tsup --watch",
23
- "lint": "eslint src/",
24
- "test": "vitest run",
25
- "typecheck": "tsc --noEmit"
26
- },
27
20
  "dependencies": {
28
- "@mushi-mushi/plugin-sdk": "workspace:^"
21
+ "@mushi-mushi/plugin-sdk": "^0.7.0"
29
22
  },
30
23
  "devDependencies": {
31
- "@mushi-mushi/eslint-config": "workspace:*",
32
24
  "@types/node": "^22.19.17",
33
25
  "eslint": "^10.3.0",
34
26
  "tsup": "^8.5.1",
35
27
  "typescript": "^6.0.3",
36
- "vitest": "^4.1.5"
28
+ "vitest": "^4.1.5",
29
+ "@mushi-mushi/eslint-config": "0.0.0"
37
30
  },
38
31
  "repository": {
39
32
  "type": "git",
@@ -57,5 +50,12 @@
57
50
  ],
58
51
  "engines": {
59
52
  "node": ">=20"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup",
56
+ "dev": "tsup --watch",
57
+ "lint": "eslint src/",
58
+ "test": "vitest run",
59
+ "typecheck": "tsc --noEmit"
60
60
  }
61
- }
61
+ }