@bugmole/cli 0.4.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/.bugmole.env.example +20 -0
- package/LICENSE +7 -0
- package/README.md +293 -0
- package/TESTING.md +117 -0
- package/bugmole.config.yaml +39 -0
- package/package.json +85 -0
- package/scripts/billing/paypal-setup.mjs +121 -0
- package/scripts/bugmole-continue.ts +318 -0
- package/scripts/bugmole-init.ts +188 -0
- package/scripts/bugmole.cjs +17 -0
- package/scripts/bugmole.test.ts +344 -0
- package/scripts/bugmole.ts +657 -0
- package/scripts/ensure-maestro.cjs +79 -0
- package/scripts/ios-tunnel-keeper.sh +45 -0
- package/scripts/ios-wda-keeper.sh +66 -0
- package/scripts/sync-plan-catalog.d.mts +3 -0
- package/scripts/sync-plan-catalog.mjs +16 -0
- package/scripts/ui-parity-diff.py +65 -0
- package/scripts/ui-parity-requirements.txt +1 -0
- package/scripts/verify-manage-to-plans.mts +194 -0
- package/spec/app-ui-audit.schema.json +176 -0
- package/spec/blockers.yaml +79 -0
- package/spec/bugs.index.json +42 -0
- package/spec/design-dna.schema.json +38 -0
- package/spec/domain_rules.yaml +24 -0
- package/spec/flows/flow_manage-to-plans-64c3c61b.yaml +8 -0
- package/spec/flows/flow_screen-to-evidence-6c3ab309.yaml +7 -0
- package/spec/journey_graph.yaml +126 -0
- package/spec/journeys.graph.json +2618 -0
- package/spec/plans/dashboard-smoke.flow.yaml +20 -0
- package/spec/plans/example.flow.yaml +99 -0
- package/spec/plans/flow_api-keys-to-logout-7396cd5d.flow.yaml +33 -0
- package/spec/plans/flow_api-keys-to-screen-157e10a6.flow.yaml +33 -0
- package/spec/plans/flow_manage-to-audits-176c1eb8.flow.yaml +33 -0
- package/spec/plans/flow_manage-to-blockers-633282c8.flow.yaml +112 -0
- package/spec/plans/flow_manage-to-devices-ad57e202.flow.yaml +33 -0
- package/spec/plans/flow_manage-to-logout-86c54656.flow.yaml +33 -0
- package/spec/plans/flow_manage-to-manage-resource-action-6325f99a.flow.yaml +185 -0
- package/spec/plans/flow_manage-to-parity-issues-01fa2579.flow.yaml +34 -0
- package/spec/plans/flow_manage-to-plans-64c3c61b.flow.yaml +123 -0
- package/spec/plans/flow_manage-to-screen-6857f915.flow.yaml +106 -0
- package/spec/plans/flow_manage-to-tasks-c5791c95.flow.yaml +33 -0
- package/spec/plans/flow_profile-to-screen-6045aa3d.flow.yaml +33 -0
- package/spec/plans/flow_register-to-api-auth-login-460a9cc8.flow.yaml +34 -0
- package/spec/plans/flow_screen-to-audits-07666356.flow.yaml +33 -0
- package/spec/plans/flow_screen-to-blockers-091d258b.flow.yaml +33 -0
- package/spec/plans/flow_screen-to-devices-cad72f75.flow.yaml +33 -0
- package/spec/plans/flow_screen-to-evidence-6c3ab309.flow.yaml +126 -0
- package/spec/plans/flow_screen-to-parity-issues-2218e3ad.flow.yaml +34 -0
- package/spec/plans/flow_screen-to-plans-8232a94f.flow.yaml +33 -0
- package/spec/plans/flow_screen-to-tasks-540671d1.flow.yaml +33 -0
- package/spec/plans/login.flow.yaml +22 -0
- package/spec/plans/owner-operations.flow.yaml +20 -0
- package/spec/project_config.yaml +55 -0
- package/spec/roles.yaml +30 -0
- package/spec/schema.md +394 -0
- package/spec/test-case-results.schema.json +62 -0
- package/spec/test-cases.schema.json +85 -0
- package/spec/ui-parity-audit.schema.json +194 -0
- package/spec/ui-reverse-engineering.schema.json +94 -0
- package/src/billing/plan-catalog.test.ts +46 -0
- package/src/billing/plan-catalog.ts +199 -0
- package/src/integrations/aws-sigv4.test.ts +42 -0
- package/src/integrations/aws-sigv4.ts +72 -0
- package/src/integrations/device-farm.ts +155 -0
- package/src/integrations/github-app.test.ts +57 -0
- package/src/integrations/github-app.ts +143 -0
- package/src/integrations/gitlab.ts +81 -0
- package/src/integrations/temp-email.test.ts +123 -0
- package/src/integrations/temp-email.ts +175 -0
- package/src/integrations/testflight-feedback.test.ts +51 -0
- package/src/integrations/testflight-feedback.ts +173 -0
- package/src/integrations/webdriver-client.ts +131 -0
- package/src/mcp/server.test.ts +1220 -0
- package/src/mcp/server.ts +3064 -0
- package/src/mcp/write-test-cases.test.ts +287 -0
- package/src/registry/api-key-client.ts +39 -0
- package/src/registry/control-plane-client.ts +212 -0
- package/src/registry/migrations/0001_registry.sql +47 -0
- package/src/registry/migrations/0002_device_authorizations.sql +23 -0
- package/src/registry/migrations/0003_project_environments.sql +25 -0
- package/src/registry/migrations/0004_device_authorization_email.sql +1 -0
- package/src/registry/migrations/0005_testing_control_plane.sql +55 -0
- package/src/registry/migrations/0006_workspaces.sql +36 -0
- package/src/registry/migrations/0007_project_apps.sql +26 -0
- package/src/registry/migrations/0008_agent_tasks.sql +30 -0
- package/src/registry/migrations/0009_journey_revisions.sql +17 -0
- package/src/registry/migrations/0010_agent_task_journey.sql +2 -0
- package/src/registry/migrations/0011_run_journey_revision.sql +1 -0
- package/src/registry/migrations/0012_canonical_flow_execution.sql +10 -0
- package/src/registry/migrations/0013_device_sessions.sql +22 -0
- package/src/registry/migrations/0014_agent_task_step.sql +1 -0
- package/src/registry/migrations/0015_agent_task_attempts.sql +6 -0
- package/src/registry/migrations/0016_github_issue_tracker.sql +54 -0
- package/src/registry/migrations/0017_run_targets.sql +7 -0
- package/src/registry/migrations/0018_run_fix_from.sql +4 -0
- package/src/registry/migrations/0019_workspace_flags.sql +9 -0
- package/src/registry/migrations/0020_orgs.sql +40 -0
- package/src/registry/migrations/0021_billing_core.sql +58 -0
- package/src/registry/migrations/0022_cloud_runners.sql +19 -0
- package/src/registry/migrations/0023_signup.sql +4 -0
- package/src/registry/migrations/0024_billing.sql +67 -0
- package/src/registry/migrations/0025_notifications.sql +47 -0
- package/src/registry/migrations/0026_repo_bindings.sql +28 -0
- package/src/registry/migrations/0027_feedback.sql +29 -0
- package/src/registry/migrations/0028_devices.sql +48 -0
- package/src/registry/migrations/0029_sso.sql +31 -0
- package/src/registry/migrations/0030_workspace_domains.sql +18 -0
- package/src/registry/migrations/0031_gitlab_and_teams.sql +45 -0
- package/src/registry/migrations/0032_personas.sql +15 -0
- package/src/registry/migrations/0033_bugmole_rename.sql +11 -0
- package/src/registry/task-scheduling.test.ts +100 -0
- package/src/registry/task-scheduling.ts +80 -0
- package/src/registry-worker/ai/platform-model.ts +77 -0
- package/src/registry-worker/ai/routes.test.ts +88 -0
- package/src/registry-worker/ai/routes.ts +90 -0
- package/src/registry-worker/artifacts.test.ts +98 -0
- package/src/registry-worker/artifacts.ts +85 -0
- package/src/registry-worker/billing/billing-core.test.ts +175 -0
- package/src/registry-worker/billing/checkout-routes.ts +209 -0
- package/src/registry-worker/billing/enforcement.ts +69 -0
- package/src/registry-worker/billing/entitlements.ts +108 -0
- package/src/registry-worker/billing/ledger.ts +186 -0
- package/src/registry-worker/billing/paypal/api.ts +259 -0
- package/src/registry-worker/billing/paypal/client.ts +91 -0
- package/src/registry-worker/billing/paypal/provider.ts +143 -0
- package/src/registry-worker/billing/paypal.test.ts +466 -0
- package/src/registry-worker/billing/provider.ts +114 -0
- package/src/registry-worker/billing/routes.ts +66 -0
- package/src/registry-worker/billing/subscriptions.ts +780 -0
- package/src/registry-worker/billing/thresholds.ts +107 -0
- package/src/registry-worker/core.ts +308 -0
- package/src/registry-worker/devices/devices.test.ts +185 -0
- package/src/registry-worker/devices/policy.ts +71 -0
- package/src/registry-worker/devices/routes.ts +453 -0
- package/src/registry-worker/domains/domains.test.ts +210 -0
- package/src/registry-worker/domains/routes.ts +139 -0
- package/src/registry-worker/domains.ts +88 -0
- package/src/registry-worker/email/sender.ts +75 -0
- package/src/registry-worker/env.d.ts +14716 -0
- package/src/registry-worker/features.ts +20 -0
- package/src/registry-worker/feedback/feedback.test.ts +230 -0
- package/src/registry-worker/feedback/format.ts +148 -0
- package/src/registry-worker/feedback/routes.ts +386 -0
- package/src/registry-worker/flags.ts +39 -0
- package/src/registry-worker/github/checks.test.ts +177 -0
- package/src/registry-worker/github/checks.ts +374 -0
- package/src/registry-worker/gitlab/checks.test.ts +141 -0
- package/src/registry-worker/gitlab/checks.ts +349 -0
- package/src/registry-worker/hooks.ts +54 -0
- package/src/registry-worker/index.ts +2077 -0
- package/src/registry-worker/jobs/index.ts +29 -0
- package/src/registry-worker/jobs/retention.ts +68 -0
- package/src/registry-worker/mcp/mcp.test.ts +355 -0
- package/src/registry-worker/mcp/routes.ts +215 -0
- package/src/registry-worker/mcp/token.ts +126 -0
- package/src/registry-worker/mcp/tools.ts +563 -0
- package/src/registry-worker/notifications/alerts.ts +212 -0
- package/src/registry-worker/notifications/notifications.test.ts +298 -0
- package/src/registry-worker/notifications/outbox.ts +83 -0
- package/src/registry-worker/notifications/routes.ts +280 -0
- package/src/registry-worker/notifications/secrets.ts +49 -0
- package/src/registry-worker/notifications/slack.ts +96 -0
- package/src/registry-worker/notifications/teams.ts +46 -0
- package/src/registry-worker/org/audit.ts +116 -0
- package/src/registry-worker/org/routes.test.ts +163 -0
- package/src/registry-worker/org/routes.ts +302 -0
- package/src/registry-worker/personas/personas.test.ts +78 -0
- package/src/registry-worker/personas/routes.ts +100 -0
- package/src/registry-worker/repo-triggers.ts +20 -0
- package/src/registry-worker/routes/index.ts +74 -0
- package/src/registry-worker/run-events.ts +24 -0
- package/src/registry-worker/runner/dispatch.ts +219 -0
- package/src/registry-worker/runner/jobs.ts +43 -0
- package/src/registry-worker/runner/metering.ts +82 -0
- package/src/registry-worker/runner/policy.ts +59 -0
- package/src/registry-worker/runner/routes.ts +171 -0
- package/src/registry-worker/runner/runner.test.ts +358 -0
- package/src/registry-worker/runner/tokens.ts +93 -0
- package/src/registry-worker/runs.test.ts +60 -0
- package/src/registry-worker/signup/policy.ts +57 -0
- package/src/registry-worker/signup/routes.ts +106 -0
- package/src/registry-worker/signup/signup.test.ts +81 -0
- package/src/registry-worker/sso/aegis.ts +141 -0
- package/src/registry-worker/sso/membership.ts +157 -0
- package/src/registry-worker/sso/routes.ts +458 -0
- package/src/registry-worker/sso/sso.test.ts +344 -0
- package/src/registry-worker/testing/d1-shim.ts +180 -0
- package/src/registry-worker/testing/harness.ts +137 -0
- package/src/runner-worker/index.ts +108 -0
- package/src/runtime/ai-analysis.ts +97 -0
- package/src/runtime/ai-exploration.test.ts +32 -0
- package/src/runtime/ai-exploration.ts +69 -0
- package/src/runtime/ai-repair.ts +74 -0
- package/src/runtime/ai-work.test.ts +99 -0
- package/src/runtime/android-screen-record.test.ts +75 -0
- package/src/runtime/android-screen-record.ts +192 -0
- package/src/runtime/app-understanding.test.ts +123 -0
- package/src/runtime/app-understanding.ts +201 -0
- package/src/runtime/appium-driver.test.ts +179 -0
- package/src/runtime/appium-driver.ts +295 -0
- package/src/runtime/blocker-resolution.test.ts +113 -0
- package/src/runtime/blocker-resolution.ts +111 -0
- package/src/runtime/browser-matrix.integration.test.ts +212 -0
- package/src/runtime/browser-matrix.test.ts +143 -0
- package/src/runtime/browser-matrix.ts +200 -0
- package/src/runtime/canonical-flow.test.ts +52 -0
- package/src/runtime/config-validate.ts +185 -0
- package/src/runtime/continuous-execution.ts +291 -0
- package/src/runtime/cursor-applescript.ts +573 -0
- package/src/runtime/cursor-cli-driver.test.ts +78 -0
- package/src/runtime/cursor-cli-driver.ts +156 -0
- package/src/runtime/cursor-driver-example.ts +117 -0
- package/src/runtime/cursor-driver-index.ts +65 -0
- package/src/runtime/cursor-driver-init.ts +277 -0
- package/src/runtime/cursor-driver-run.test.ts +15 -0
- package/src/runtime/cursor-driver-run.ts +323 -0
- package/src/runtime/cursor-driver.ts +332 -0
- package/src/runtime/cursor-llm-example.ts +90 -0
- package/src/runtime/cursor-llm.ts +206 -0
- package/src/runtime/cursor-mcp-monitor.ts +386 -0
- package/src/runtime/device-clouds/browserstack.ts +73 -0
- package/src/runtime/device-clouds/device-farm.ts +52 -0
- package/src/runtime/device-clouds/index.ts +92 -0
- package/src/runtime/device-clouds/kobiton.ts +70 -0
- package/src/runtime/device-clouds/targets.ts +44 -0
- package/src/runtime/device-clouds/types.ts +62 -0
- package/src/runtime/diff-proposal.ts +84 -0
- package/src/runtime/discovery-task.test.ts +29 -0
- package/src/runtime/discovery-task.ts +284 -0
- package/src/runtime/driver-recovery.ts +69 -0
- package/src/runtime/driver.ts +79 -0
- package/src/runtime/environment.test.ts +104 -0
- package/src/runtime/environment.ts +137 -0
- package/src/runtime/executor.test.ts +509 -0
- package/src/runtime/executor.ts +921 -0
- package/src/runtime/explorer.test.ts +101 -0
- package/src/runtime/explorer.ts +1013 -0
- package/src/runtime/failure-analysis.test.ts +111 -0
- package/src/runtime/failure-analysis.ts +272 -0
- package/src/runtime/fixtures/fake-maestro.sh +36 -0
- package/src/runtime/flow-language.test.ts +268 -0
- package/src/runtime/flow-language.ts +414 -0
- package/src/runtime/init-wizard.ts +354 -0
- package/src/runtime/ios-screen-record.test.ts +68 -0
- package/src/runtime/ios-screen-record.ts +155 -0
- package/src/runtime/journey-editor.ts +452 -0
- package/src/runtime/journey-evidence.test.ts +161 -0
- package/src/runtime/journey-evidence.ts +180 -0
- package/src/runtime/journey-graph.test.ts +257 -0
- package/src/runtime/journey-graph.ts +170 -0
- package/src/runtime/legacy-names.ts +32 -0
- package/src/runtime/llm-example.ts +105 -0
- package/src/runtime/llm.ts +527 -0
- package/src/runtime/local-browser.test.ts +45 -0
- package/src/runtime/local-browser.ts +48 -0
- package/src/runtime/local-registry-stub.test.ts +325 -0
- package/src/runtime/local-registry-stub.ts +803 -0
- package/src/runtime/maestro-driver.test.ts +84 -0
- package/src/runtime/maestro-driver.ts +209 -0
- package/src/runtime/mole-voice.ts +21 -0
- package/src/runtime/nav-crawl.test.ts +100 -0
- package/src/runtime/nav-crawl.ts +153 -0
- package/src/runtime/pipeline.test.ts +405 -0
- package/src/runtime/pipeline.ts +833 -0
- package/src/runtime/planner.test.ts +37 -0
- package/src/runtime/planner.ts +274 -0
- package/src/runtime/platform-ai.ts +76 -0
- package/src/runtime/playwright-driver.test.ts +93 -0
- package/src/runtime/playwright-driver.ts +620 -0
- package/src/runtime/project-spec.ts +140 -0
- package/src/runtime/record-run-verdicts.ts +68 -0
- package/src/runtime/reporter.test.ts +56 -0
- package/src/runtime/reporter.ts +158 -0
- package/src/runtime/reset.test.ts +44 -0
- package/src/runtime/reset.ts +61 -0
- package/src/runtime/reviewer.test.ts +73 -0
- package/src/runtime/reviewer.ts +158 -0
- package/src/runtime/run-job.ts +136 -0
- package/src/runtime/run-once.test.ts +207 -0
- package/src/runtime/run-once.ts +168 -0
- package/src/runtime/run.ts +132 -0
- package/src/runtime/screen-recording.ts +34 -0
- package/src/runtime/serve-gateway.test.ts +74 -0
- package/src/runtime/serve-gateway.ts +164 -0
- package/src/runtime/serve-worker.test.ts +23 -0
- package/src/runtime/serve-worker.ts +278 -0
- package/src/runtime/site-discovery.test.ts +168 -0
- package/src/runtime/site-discovery.ts +308 -0
- package/src/runtime/target-runner.ts +144 -0
- package/src/runtime/test-case-verdicts.test.ts +94 -0
- package/src/runtime/test-case-verdicts.ts +120 -0
- package/src/runtime/ui-reverse-engineering/coordinator.test.ts +59 -0
- package/src/runtime/ui-reverse-engineering/coordinator.ts +391 -0
- package/src/runtime/ui-reverse-engineering/types.ts +197 -0
- package/src/runtime/web-suite.test.ts +97 -0
- package/src/runtime/web-suite.ts +176 -0
- package/src/storage/create-object-store.ts +144 -0
- package/src/storage/keys.ts +34 -0
- package/src/storage/local-artifact-server.test.ts +314 -0
- package/src/storage/local-artifact-server.ts +357 -0
- package/src/storage/object-store.test.ts +28 -0
- package/src/storage/object-store.ts +101 -0
- package/src/storage/registry-object-store.ts +88 -0
- package/src/storage/remote-object-store.ts +104 -0
- package/src/storage/storage-directory.test.ts +43 -0
- package/src/storage/storage-directory.ts +24 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Creates Bugmole's PayPal product and its four billing plans (Team and
|
|
3
|
+
// Business, monthly and yearly) from the plan catalog, and prints the plan ids
|
|
4
|
+
// to set as registry vars (plan ids aren't secret).
|
|
5
|
+
//
|
|
6
|
+
// Sandbox first, then live; each environment needs its own plans. Credentials
|
|
7
|
+
// come from Arcana so they never reach the shell history:
|
|
8
|
+
//
|
|
9
|
+
// arcana run --secret arcana://paypal/bugmole/sandbox-client-id --env PAYPAL_CLIENT_ID -- \
|
|
10
|
+
// arcana run --secret arcana://paypal/bugmole/sandbox-client-secret --env PAYPAL_CLIENT_SECRET -- \
|
|
11
|
+
// env PAYPAL_ENV=sandbox node scripts/billing/paypal-setup.mjs
|
|
12
|
+
//
|
|
13
|
+
// Set PAYPAL_PLANS=0 to skip creating plans (e.g. to add only the webhook).
|
|
14
|
+
// PAYPAL_PRODUCT_ID=PROD-⦠reuses an existing product. Running it twice
|
|
15
|
+
// creates duplicate plans (PayPal has no "ensure"); deactivate extras in the
|
|
16
|
+
// PayPal dashboard.
|
|
17
|
+
//
|
|
18
|
+
// Plan choices (from realistiz-dd's plan script):
|
|
19
|
+
// - total_cycles 0: renews until cancelled.
|
|
20
|
+
// - auto_bill_outstanding: a failed renewal is retried with the next charge.
|
|
21
|
+
// - payment_failure_threshold 1: one failed renewal suspends the subscription,
|
|
22
|
+
// which Bugmole turns into a 7-day grace period.
|
|
23
|
+
import { PLANS } from "../../src/billing/plan-catalog.ts";
|
|
24
|
+
|
|
25
|
+
const sandbox = process.env.PAYPAL_ENV === "sandbox";
|
|
26
|
+
const apiBase = sandbox ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
|
|
27
|
+
const { PAYPAL_CLIENT_ID: clientId, PAYPAL_CLIENT_SECRET: clientSecret } = process.env;
|
|
28
|
+
if (!clientId || !clientSecret) {
|
|
29
|
+
console.error("Set PAYPAL_CLIENT_ID and PAYPAL_CLIENT_SECRET (and PAYPAL_ENV=sandbox for the sandbox).");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function paypal(path, init = {}) {
|
|
34
|
+
const res = await fetch(`${apiBase}${path}`, init);
|
|
35
|
+
const text = await res.text();
|
|
36
|
+
if (!res.ok) throw new Error(`${init.method ?? "GET"} ${path} failed: ${res.status} ${text}`);
|
|
37
|
+
return text ? JSON.parse(text) : {};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { access_token: token } = await paypal("/v1/oauth2/token", {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
|
|
44
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
45
|
+
},
|
|
46
|
+
body: "grant_type=client_credentials",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const post = (body) => ({
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: {
|
|
52
|
+
Authorization: `Bearer ${token}`,
|
|
53
|
+
"content-type": "application/json",
|
|
54
|
+
Prefer: "return=representation",
|
|
55
|
+
"PayPal-Request-Id": crypto.randomUUID(),
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify(body),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const product = process.env.PAYPAL_PRODUCT_ID
|
|
61
|
+
? { id: process.env.PAYPAL_PRODUCT_ID }
|
|
62
|
+
: await paypal("/v1/catalogs/products", post({
|
|
63
|
+
name: "Bugmole",
|
|
64
|
+
description: "AI-powered end-to-end testing: cloud runs, AI credits and team features.",
|
|
65
|
+
type: "SERVICE",
|
|
66
|
+
category: "SOFTWARE",
|
|
67
|
+
home_url: "https://bugmole.com",
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
const dollars = (cents) => (cents / 100).toFixed(2);
|
|
71
|
+
const lines = [];
|
|
72
|
+
for (const planId of process.env.PAYPAL_PLANS === "0" ? [] : ["team", "business"]) {
|
|
73
|
+
const plan = PLANS[planId];
|
|
74
|
+
for (const interval of ["month", "year"]) {
|
|
75
|
+
const cents = interval === "year" ? plan.priceYearlyMonthlyCents * 12 : plan.priceMonthlyCents;
|
|
76
|
+
const created = await paypal("/v1/billing/plans", post({
|
|
77
|
+
product_id: product.id,
|
|
78
|
+
name: `Bugmole ${plan.name} - ${interval === "year" ? "yearly" : "monthly"}`,
|
|
79
|
+
description: `USD ${dollars(cents)} per ${interval}, renews until cancelled. Usage beyond the allowance is invoiced monthly.`,
|
|
80
|
+
status: "ACTIVE",
|
|
81
|
+
billing_cycles: [{
|
|
82
|
+
frequency: { interval_unit: interval === "year" ? "YEAR" : "MONTH", interval_count: 1 },
|
|
83
|
+
tenure_type: "REGULAR",
|
|
84
|
+
sequence: 1,
|
|
85
|
+
total_cycles: 0,
|
|
86
|
+
pricing_scheme: { fixed_price: { value: dollars(cents), currency_code: "USD" } },
|
|
87
|
+
}],
|
|
88
|
+
payment_preferences: {
|
|
89
|
+
auto_bill_outstanding: true,
|
|
90
|
+
setup_fee_failure_action: "CANCEL",
|
|
91
|
+
payment_failure_threshold: 1,
|
|
92
|
+
},
|
|
93
|
+
}));
|
|
94
|
+
lines.push(`PAYPAL_PLAN_${planId.toUpperCase()}_${interval.toUpperCase()}=${created.id}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// PAYPAL_WEBHOOK_URL (e.g. https://api.bugmole.com/api/billing/webhooks/paypal)
|
|
99
|
+
// also registers the webhook; its id goes in PAYPAL_WEBHOOK_ID.
|
|
100
|
+
if (process.env.PAYPAL_WEBHOOK_URL) {
|
|
101
|
+
const hook = await paypal("/v1/notifications/webhooks", post({
|
|
102
|
+
url: process.env.PAYPAL_WEBHOOK_URL,
|
|
103
|
+
event_types: [
|
|
104
|
+
"BILLING.SUBSCRIPTION.ACTIVATED",
|
|
105
|
+
"BILLING.SUBSCRIPTION.UPDATED",
|
|
106
|
+
"BILLING.SUBSCRIPTION.RE-ACTIVATED",
|
|
107
|
+
"BILLING.SUBSCRIPTION.SUSPENDED",
|
|
108
|
+
"BILLING.SUBSCRIPTION.CANCELLED",
|
|
109
|
+
"BILLING.SUBSCRIPTION.EXPIRED",
|
|
110
|
+
"BILLING.SUBSCRIPTION.PAYMENT.FAILED",
|
|
111
|
+
"PAYMENT.SALE.COMPLETED",
|
|
112
|
+
"PAYMENT.SALE.REFUNDED",
|
|
113
|
+
"INVOICING.INVOICE.PAID",
|
|
114
|
+
"INVOICING.INVOICE.CANCELLED",
|
|
115
|
+
].map((name) => ({ name })),
|
|
116
|
+
}));
|
|
117
|
+
lines.push(`PAYPAL_WEBHOOK_ID=${hook.id}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(`PayPal ${sandbox ? "sandbox" : "LIVE"} product: ${product.id}`);
|
|
121
|
+
for (const line of lines) console.log(line);
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bugmole MCP Continuation Script
|
|
3
|
+
*
|
|
4
|
+
* After initialization, this script uses Cursor LLM to:
|
|
5
|
+
* 1. Investigate the project structure
|
|
6
|
+
* 2. Detect how to start the application
|
|
7
|
+
* 3. Determine URLs and ports
|
|
8
|
+
* 4. Continue with exploration and test creation
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* npm run bugmole:continue
|
|
12
|
+
* npm run bugmole:continue -- --project-directory /path/to/project
|
|
13
|
+
* npm run bugmole:continue -- --max-iterations 100
|
|
14
|
+
* npm run bugmole:continue -- --project-directory /path/to/project --max-iterations 100 --timeout 900000
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { executeContinuously } from "../src/runtime/continuous-execution.js";
|
|
18
|
+
|
|
19
|
+
function readArg(name: string): string | undefined {
|
|
20
|
+
const args = process.argv;
|
|
21
|
+
const i = args.indexOf(name);
|
|
22
|
+
if (i >= 0 && i + 1 < args.length) return args[i + 1];
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hasFlag(name: string): boolean {
|
|
27
|
+
return process.argv.includes(name);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Generates the continuation task that asks Cursor to investigate and continue
|
|
32
|
+
*/
|
|
33
|
+
function generateContinuationTask(projectDirectory?: string): string {
|
|
34
|
+
return `# Bugmole MCP Continuation Task
|
|
35
|
+
|
|
36
|
+
You are continuing the Bugmole MCP setup for this project. The initial spec files have been created, and now you need to:
|
|
37
|
+
|
|
38
|
+
1. **Investigate the project structure** to understand:
|
|
39
|
+
- What type of application(s) this is (monorepo, single app, etc.)
|
|
40
|
+
- How to start the application(s)
|
|
41
|
+
- What URLs/ports the applications run on
|
|
42
|
+
- What dependencies need to be installed or started first
|
|
43
|
+
|
|
44
|
+
2. **Determine the base URL** for testing:
|
|
45
|
+
- Check package.json scripts (start, dev, etc.)
|
|
46
|
+
- Check configuration files (.env, config files)
|
|
47
|
+
- Check documentation (README.md, docs/)
|
|
48
|
+
- Look for port numbers in code or config
|
|
49
|
+
- Identify the main frontend application URL
|
|
50
|
+
|
|
51
|
+
3. **Start the application** (if not already running):
|
|
52
|
+
- Determine the correct start command
|
|
53
|
+
- Check if services are already running on expected ports
|
|
54
|
+
- Use appropriate commands to start the application
|
|
55
|
+
|
|
56
|
+
4. **Continue with exploration**:
|
|
57
|
+
- Once the application is running, use \`bugmole_explore\` to discover user journeys
|
|
58
|
+
- Update the journey graph with discovered screens and actions
|
|
59
|
+
- Create test plans for key user journeys
|
|
60
|
+
|
|
61
|
+
5. **Create initial test plans**:
|
|
62
|
+
- Use \`bugmole_plan\` to generate test plans for discovered journeys
|
|
63
|
+
- Focus on critical user flows first
|
|
64
|
+
|
|
65
|
+
## Available MCP Tools
|
|
66
|
+
|
|
67
|
+
You have access to these Bugmole MCP tools:
|
|
68
|
+
- \`bugmole_explore\` - Explore the application and discover user journeys (requires baseUrl)
|
|
69
|
+
- \`bugmole_read_spec\` - Read existing spec files
|
|
70
|
+
- \`bugmole_write_spec\` - Write or update spec files
|
|
71
|
+
- \`bugmole_plan\` - Generate journey plans from discovered journeys
|
|
72
|
+
- \`bugmole_report_progress\` - Report your progress periodically (use every 2-3 minutes for long tasks)
|
|
73
|
+
|
|
74
|
+
## CRITICAL: About next_steps
|
|
75
|
+
|
|
76
|
+
When you commit your response, if you mention ANY of the following in your answer, you MUST include them in the "next_steps" array:
|
|
77
|
+
- "Next Steps" section
|
|
78
|
+
- "TODO" items
|
|
79
|
+
- "should do", "need to", "use bugmole_", "run bugmole_"
|
|
80
|
+
- Any future actions or commands
|
|
81
|
+
|
|
82
|
+
Example: If you write "Next: Run bugmole_explore with baseUrl=http://localhost:8000", then your commit MUST include:
|
|
83
|
+
\`\`\`json
|
|
84
|
+
{
|
|
85
|
+
"next_steps": ["Run bugmole_explore with baseUrl=http://localhost:8000"]
|
|
86
|
+
}
|
|
87
|
+
\`\`\`
|
|
88
|
+
|
|
89
|
+
ONLY omit next_steps when EVERYTHING is 100% complete and there is NO remaining work.
|
|
90
|
+
|
|
91
|
+
## Your Investigation Steps
|
|
92
|
+
|
|
93
|
+
### Step 1: Understand Project Structure
|
|
94
|
+
|
|
95
|
+
Analyze the codebase to determine:
|
|
96
|
+
- Is this a monorepo? (check for apps/, packages/, libs/ directories)
|
|
97
|
+
- What applications exist? (check apps/ directory or root package.json)
|
|
98
|
+
- What frameworks are used? (React, Next.js, Vue, Express, etc.)
|
|
99
|
+
- Are there multiple services? (APIs, frontends, etc.)
|
|
100
|
+
|
|
101
|
+
### Step 2: Find How to Start the Application
|
|
102
|
+
|
|
103
|
+
Look for:
|
|
104
|
+
- \`package.json\` scripts (start, dev, serve, etc.)
|
|
105
|
+
- \`README.md\` or documentation with setup instructions
|
|
106
|
+
- \`.env\` files or config files with port/URL information
|
|
107
|
+
- Docker compose files or startup scripts
|
|
108
|
+
- Any existing dev scripts (scripts/dev.sh, etc.)
|
|
109
|
+
|
|
110
|
+
### Step 3: Determine Base URL
|
|
111
|
+
|
|
112
|
+
Figure out:
|
|
113
|
+
- What port does the main frontend run on? (common: 3000, 3001, 5173, 8000, etc.)
|
|
114
|
+
- What is the full URL? (usually http://localhost:PORT)
|
|
115
|
+
- Are there multiple services? Which one should be tested first?
|
|
116
|
+
- Check for environment variables like PORT, BASE_URL, etc.
|
|
117
|
+
|
|
118
|
+
### Step 4: Check if Application is Running
|
|
119
|
+
|
|
120
|
+
Before starting, check if services are already running:
|
|
121
|
+
- Try to detect running processes on expected ports
|
|
122
|
+
- Check if the application responds to HTTP requests
|
|
123
|
+
- If running, proceed to exploration
|
|
124
|
+
- If not running, determine how to start it
|
|
125
|
+
|
|
126
|
+
### Step 5: Start the Application (if needed)
|
|
127
|
+
|
|
128
|
+
If the application is not running:
|
|
129
|
+
- Determine the correct command to start it
|
|
130
|
+
- Consider dependencies (databases, other services)
|
|
131
|
+
- Start the application in a way that allows testing
|
|
132
|
+
|
|
133
|
+
### Step 6: Explore the Application (Optional)
|
|
134
|
+
|
|
135
|
+
**NOTE:** The \`bugmole_explore\` tool may not be fully implemented yet. If it returns an error, **do NOT keep retrying**. Instead:
|
|
136
|
+
- Work with existing journey graph if it exists (check spec/journeys.graph.json)
|
|
137
|
+
- Create test plans based on codebase analysis
|
|
138
|
+
- Proceed with other tasks like creating plans, reading/writing specs
|
|
139
|
+
|
|
140
|
+
If you want to try exploration:
|
|
141
|
+
- Use \`bugmole_explore\` with the discovered baseUrl
|
|
142
|
+
- Set appropriate maxDepth (start with 3-5)
|
|
143
|
+
- If it fails, move on immediately - don't get stuck
|
|
144
|
+
|
|
145
|
+
### Step 7: Create Test Plans
|
|
146
|
+
|
|
147
|
+
After exploration:
|
|
148
|
+
- Identify key user journeys from the journey graph
|
|
149
|
+
- Use \`bugmole_plan\` to create test plans for important journeys
|
|
150
|
+
- Start with critical user flows (login, main features, etc.)
|
|
151
|
+
|
|
152
|
+
## Important Notes
|
|
153
|
+
|
|
154
|
+
- **You have full access to the codebase** - use it to understand the project
|
|
155
|
+
- **Use MCP tools** - don't just read files, use the tools to interact with the framework
|
|
156
|
+
- **Be thorough** - investigate multiple sources (package.json, README, code, config files)
|
|
157
|
+
- **Start simple** - focus on the main application first, then expand
|
|
158
|
+
- **Document findings** - update spec files with discovered information
|
|
159
|
+
- **CRITICAL: Do not get stuck on exploration** - If \`bugmole_explore\` fails or returns errors, immediately move on to other productive tasks like creating test plans, reading/writing specs, or executing existing plans. Do NOT retry exploration repeatedly.
|
|
160
|
+
|
|
161
|
+
## Project Context
|
|
162
|
+
|
|
163
|
+
${projectDirectory ? `- Project directory: ${projectDirectory}` : "- Current working directory"}
|
|
164
|
+
- Spec files have been initialized in spec/ directory
|
|
165
|
+
- You need to figure out how to proceed from here
|
|
166
|
+
|
|
167
|
+
## Expected Outcome
|
|
168
|
+
|
|
169
|
+
After completing this task:
|
|
170
|
+
- ā
Application is running (or instructions provided on how to start it)
|
|
171
|
+
- ā
Base URL is determined and documented
|
|
172
|
+
- ā
Journey graph is populated with discovered screens/actions
|
|
173
|
+
- ā
Initial test plans are created for key user journeys
|
|
174
|
+
- ā
All findings are documented in spec files
|
|
175
|
+
|
|
176
|
+
## Important: Next Steps
|
|
177
|
+
|
|
178
|
+
If you cannot complete all steps in a single response, you MUST include a \`next_steps\` field in your commit payload with the remaining steps. For example:
|
|
179
|
+
|
|
180
|
+
\`\`\`json
|
|
181
|
+
{
|
|
182
|
+
"status": "ok",
|
|
183
|
+
"summary": "Investigated project structure, need to start application",
|
|
184
|
+
"next_steps": [
|
|
185
|
+
"Start the application using npm run dev",
|
|
186
|
+
"Wait for application to be ready on port 3000",
|
|
187
|
+
"Use bugmole_explore with http://localhost:3000 to discover journeys"
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
\`\`\`
|
|
191
|
+
|
|
192
|
+
The framework will automatically continue with these next steps. Only omit \`next_steps\` when the task is fully complete.
|
|
193
|
+
|
|
194
|
+
Begin by investigating the project structure and determining how to start the application.`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function main() {
|
|
198
|
+
const projectDirectory =
|
|
199
|
+
readArg("--project-directory") ||
|
|
200
|
+
readArg("--projectDirectory") ||
|
|
201
|
+
process.env.CURSOR_PROJECT_DIRECTORY;
|
|
202
|
+
|
|
203
|
+
const timeout = Number(readArg("--timeout") || "900000"); // 15 minutes default
|
|
204
|
+
const configPath = readArg("--config");
|
|
205
|
+
const maxIterations = Number(readArg("--max-iterations") || readArg("--maxIterations") || "100");
|
|
206
|
+
|
|
207
|
+
console.log("[Bugmole MCP Continue] Starting framework continuation...");
|
|
208
|
+
console.log(
|
|
209
|
+
`[Bugmole MCP Continue] Project Directory: ${projectDirectory || "(current directory)"}`,
|
|
210
|
+
);
|
|
211
|
+
console.log(`[Bugmole MCP Continue] Timeout: ${timeout}ms`);
|
|
212
|
+
console.log(`[Bugmole MCP Continue] Max Iterations: ${maxIterations}\n`);
|
|
213
|
+
|
|
214
|
+
// Generate continuation task
|
|
215
|
+
const continuationTask = generateContinuationTask(projectDirectory);
|
|
216
|
+
|
|
217
|
+
console.log("[Bugmole MCP Continue] Generated continuation task");
|
|
218
|
+
console.log("[Bugmole MCP Continue] Starting continuous execution loop...");
|
|
219
|
+
console.log(
|
|
220
|
+
"[Bugmole MCP Continue] Cursor will investigate and continue until complete...\n",
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
// Use continuous execution to automatically follow next_steps
|
|
224
|
+
const result = await executeContinuously(continuationTask, {
|
|
225
|
+
configPath,
|
|
226
|
+
timeout,
|
|
227
|
+
projectDirectory,
|
|
228
|
+
useCursor: true,
|
|
229
|
+
maxIterations: Number(maxIterations), // Configurable via --max-iterations flag
|
|
230
|
+
iterationDelay: 3000, // 3 second delay between iterations
|
|
231
|
+
customInstructions:
|
|
232
|
+
"Please thoroughly investigate the project structure, determine how to start the application, find the base URL, and continue with exploration and test creation using the MCP tools. Include next_steps in your response if there are more steps to complete.",
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
console.log("\n[Bugmole MCP Continue] Continuous execution completed\n");
|
|
236
|
+
|
|
237
|
+
if (result.success) {
|
|
238
|
+
console.log(`ā
Task completed successfully in ${result.iterations} iteration(s)!`);
|
|
239
|
+
|
|
240
|
+
// Show summary of all iterations
|
|
241
|
+
console.log(`\n--- Execution Summary (${result.iterations} iteration(s)) ---`);
|
|
242
|
+
result.responses.forEach((response, index) => {
|
|
243
|
+
if ("payload" in response && response.payload) {
|
|
244
|
+
const cursorResponse = response as any;
|
|
245
|
+
console.log(`\nIteration ${index + 1}:`);
|
|
246
|
+
console.log(` Summary: ${cursorResponse.payload?.summary || "N/A"}`);
|
|
247
|
+
if (cursorResponse.payload?.next_steps) {
|
|
248
|
+
console.log(
|
|
249
|
+
` Next Steps: ${cursorResponse.payload.next_steps.length} step(s) remaining`,
|
|
250
|
+
);
|
|
251
|
+
} else {
|
|
252
|
+
console.log(` Status: Complete (no next steps)`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Show final response details
|
|
258
|
+
const finalResponse = result.finalResponse;
|
|
259
|
+
if ("payload" in finalResponse && finalResponse.payload) {
|
|
260
|
+
const cursorResponse = finalResponse as any;
|
|
261
|
+
|
|
262
|
+
console.log(`\n--- Final Response ---`);
|
|
263
|
+
console.log(`Summary: ${cursorResponse.payload?.summary || "No summary provided"}`);
|
|
264
|
+
|
|
265
|
+
if (cursorResponse.payload?.answer_markdown) {
|
|
266
|
+
console.log("\n--- Full Answer ---");
|
|
267
|
+
console.log(cursorResponse.payload.answer_markdown);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (cursorResponse.payload?.actions && cursorResponse.payload.actions.length > 0) {
|
|
271
|
+
console.log("\n--- Actions Performed ---");
|
|
272
|
+
cursorResponse.payload.actions.forEach((action: any, i: number) => {
|
|
273
|
+
console.log(`${i + 1}. ${action.type}: ${action.target}`);
|
|
274
|
+
if (action.details) {
|
|
275
|
+
console.log(` ${action.details}`);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (cursorResponse.payload?.artifacts && cursorResponse.payload.artifacts.length > 0) {
|
|
281
|
+
console.log("\n--- Artifacts Generated ---");
|
|
282
|
+
cursorResponse.payload.artifacts.forEach((artifact: any, i: number) => {
|
|
283
|
+
console.log(`${i + 1}. ${artifact.type}`);
|
|
284
|
+
if (artifact.content) {
|
|
285
|
+
const preview = artifact.content.substring(0, 200);
|
|
286
|
+
console.log(` ${preview}${artifact.content.length > 200 ? "..." : ""}`);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
console.log("\nš Check the spec/ directory for updated files:");
|
|
293
|
+
console.log(" - spec/journeys.graph.json (should have discovered journeys)");
|
|
294
|
+
console.log(" - spec/plans/*.flow.yaml (should have test plans)");
|
|
295
|
+
|
|
296
|
+
process.exit(0);
|
|
297
|
+
} else {
|
|
298
|
+
console.error("ā Continuation failed!");
|
|
299
|
+
console.error(`Error: ${result.error}`);
|
|
300
|
+
console.error(`Iterations completed: ${result.iterations}`);
|
|
301
|
+
|
|
302
|
+
if (result.iterations >= Number(maxIterations)) {
|
|
303
|
+
console.error(
|
|
304
|
+
`\nš” Reached maximum iterations (${maxIterations}). The task may be too complex.`,
|
|
305
|
+
);
|
|
306
|
+
console.error(
|
|
307
|
+
" Consider breaking it into smaller tasks or increasing maxIterations with --max-iterations flag.",
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
main().catch((err) => {
|
|
316
|
+
console.error(`[Bugmole MCP Continue] Fatal error: ${err?.message ?? err}`);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Bugmole MCP Initialization Script
|
|
4
|
+
*
|
|
5
|
+
* Uses CURSOR_DRIVER to automatically explore a project and initialize
|
|
6
|
+
* all required spec files using MCP tools.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npm run bugmole:init
|
|
10
|
+
* npm run bugmole:init -- --base-url http://localhost:3000
|
|
11
|
+
* npm run bugmole:init -- --project-directory /path/to/project
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { executeContinuously } from "../src/runtime/continuous-execution.js";
|
|
15
|
+
import { generateInitTask, inferApplicationDetails } from "../src/runtime/cursor-driver-init.js";
|
|
16
|
+
|
|
17
|
+
function readArg(name: string): string | undefined {
|
|
18
|
+
const args = process.argv;
|
|
19
|
+
const i = args.indexOf(name);
|
|
20
|
+
if (i >= 0 && i + 1 < args.length) return args[i + 1];
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function hasFlag(name: string): boolean {
|
|
25
|
+
return process.argv.includes(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function main() {
|
|
29
|
+
// Parse arguments
|
|
30
|
+
const baseUrl = readArg("--base-url") || readArg("--baseUrl") || process.env.PLAYWRIGHT_BASE_URL;
|
|
31
|
+
|
|
32
|
+
const projectDirectory =
|
|
33
|
+
readArg("--project-directory") ||
|
|
34
|
+
readArg("--projectDirectory") ||
|
|
35
|
+
process.env.CURSOR_PROJECT_DIRECTORY;
|
|
36
|
+
|
|
37
|
+
const maxDepth = Number(readArg("--max-depth") || readArg("--maxDepth") || "5");
|
|
38
|
+
const force = hasFlag("--force");
|
|
39
|
+
const timeout = Number(readArg("--timeout") || "600000"); // 10 minutes default for init
|
|
40
|
+
const configPath = readArg("--config");
|
|
41
|
+
const maxIterations = Number(readArg("--max-iterations") || readArg("--maxIterations") || "100");
|
|
42
|
+
|
|
43
|
+
console.log("[Bugmole MCP Init] Starting framework initialization...");
|
|
44
|
+
console.log(
|
|
45
|
+
`[Bugmole MCP Init] Base URL: ${baseUrl || "(not specified, will infer from codebase)"}`,
|
|
46
|
+
);
|
|
47
|
+
console.log(
|
|
48
|
+
`[Bugmole MCP Init] Project Directory: ${projectDirectory || "(current directory)"}`,
|
|
49
|
+
);
|
|
50
|
+
console.log(`[Bugmole MCP Init] Max Depth: ${maxDepth}`);
|
|
51
|
+
console.log(`[Bugmole MCP Init] Force: ${force}`);
|
|
52
|
+
console.log(`[Bugmole MCP Init] Timeout: ${timeout}ms`);
|
|
53
|
+
console.log(`[Bugmole MCP Init] Max Iterations: ${maxIterations}`);
|
|
54
|
+
|
|
55
|
+
// Infer application details if baseUrl not provided
|
|
56
|
+
let inferredBaseUrl = baseUrl;
|
|
57
|
+
if (!inferredBaseUrl && projectDirectory) {
|
|
58
|
+
const details = inferApplicationDetails(projectDirectory);
|
|
59
|
+
if (details.baseUrl) {
|
|
60
|
+
inferredBaseUrl = details.baseUrl;
|
|
61
|
+
console.log(`[Bugmole MCP Init] Inferred base URL: ${inferredBaseUrl}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Generate initialization task
|
|
66
|
+
const initTask = generateInitTask({
|
|
67
|
+
baseUrl: inferredBaseUrl,
|
|
68
|
+
maxDepth,
|
|
69
|
+
projectDirectory,
|
|
70
|
+
force,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
console.log("[Bugmole MCP Init] Generated initialization task");
|
|
74
|
+
console.log("[Bugmole MCP Init] Starting continuous execution loop...");
|
|
75
|
+
console.log(
|
|
76
|
+
"[Bugmole MCP Init] Cursor will initialize the framework and continue until complete...\n",
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Use continuous execution to automatically follow next_steps
|
|
80
|
+
const result = await executeContinuously(initTask, {
|
|
81
|
+
configPath,
|
|
82
|
+
timeout,
|
|
83
|
+
projectDirectory,
|
|
84
|
+
useCursor: true,
|
|
85
|
+
maxIterations: Number(maxIterations), // Configurable via --max-iterations flag
|
|
86
|
+
iterationDelay: 3000, // 3 second delay between iterations
|
|
87
|
+
customInstructions:
|
|
88
|
+
"Please continue with the Bugmole MCP initialization. Use the MCP tools to explore and create spec files. Include next_steps in your response if there are more steps to complete.",
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
console.log("\n[Bugmole MCP Init] Continuous execution completed\n");
|
|
92
|
+
|
|
93
|
+
if (result.success) {
|
|
94
|
+
console.log(`ā
Initialization completed successfully in ${result.iterations} iteration(s)!`);
|
|
95
|
+
|
|
96
|
+
// Show summary of all iterations
|
|
97
|
+
console.log(`\n--- Execution Summary (${result.iterations} iteration(s)) ---`);
|
|
98
|
+
result.responses.forEach((response, index) => {
|
|
99
|
+
if ("payload" in response && response.payload) {
|
|
100
|
+
const cursorResponse = response as any;
|
|
101
|
+
console.log(`\nIteration ${index + 1}:`);
|
|
102
|
+
console.log(` Summary: ${cursorResponse.payload?.summary || "N/A"}`);
|
|
103
|
+
if (cursorResponse.payload?.next_steps) {
|
|
104
|
+
console.log(
|
|
105
|
+
` Next Steps: ${cursorResponse.payload.next_steps.length} step(s) remaining`,
|
|
106
|
+
);
|
|
107
|
+
} else {
|
|
108
|
+
console.log(` Status: Complete (no next steps)`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Show final response details
|
|
114
|
+
const finalResponse = result.finalResponse;
|
|
115
|
+
if ("payload" in finalResponse && finalResponse.payload) {
|
|
116
|
+
const cursorResponse = finalResponse as any;
|
|
117
|
+
|
|
118
|
+
console.log(`\n--- Final Response ---`);
|
|
119
|
+
console.log(`Summary: ${cursorResponse.payload?.summary || "No summary provided"}`);
|
|
120
|
+
|
|
121
|
+
if (cursorResponse.payload?.answer_markdown) {
|
|
122
|
+
console.log("\n--- Full Answer ---");
|
|
123
|
+
console.log(cursorResponse.payload.answer_markdown);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (cursorResponse.payload?.actions && cursorResponse.payload.actions.length > 0) {
|
|
127
|
+
console.log("\n--- Actions Performed ---");
|
|
128
|
+
cursorResponse.payload.actions.forEach((action: any, i: number) => {
|
|
129
|
+
console.log(`${i + 1}. ${action.type}: ${action.target}`);
|
|
130
|
+
if (action.details) {
|
|
131
|
+
console.log(` ${action.details}`);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (cursorResponse.payload?.artifacts && cursorResponse.payload.artifacts.length > 0) {
|
|
137
|
+
console.log("\n--- Artifacts Generated ---");
|
|
138
|
+
cursorResponse.payload.artifacts.forEach((artifact: any, i: number) => {
|
|
139
|
+
console.log(`${i + 1}. ${artifact.type}`);
|
|
140
|
+
if (artifact.content) {
|
|
141
|
+
const preview = artifact.content.substring(0, 200);
|
|
142
|
+
console.log(` ${preview}${artifact.content.length > 200 ? "..." : ""}`);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log("\nš Check the spec/ directory for initialized files:");
|
|
149
|
+
console.log(" - spec/roles.yaml");
|
|
150
|
+
console.log(" - spec/domain_rules.yaml");
|
|
151
|
+
console.log(" - spec/blockers.yaml");
|
|
152
|
+
console.log(" - spec/journeys.graph.json");
|
|
153
|
+
console.log(" - spec/bugs.index.json");
|
|
154
|
+
|
|
155
|
+
process.exit(0);
|
|
156
|
+
} else {
|
|
157
|
+
console.error("ā Initialization failed!");
|
|
158
|
+
console.error(`Error: ${result.error}`);
|
|
159
|
+
console.error(`Iterations completed: ${result.iterations}`);
|
|
160
|
+
|
|
161
|
+
if (result.iterations >= Number(maxIterations)) {
|
|
162
|
+
console.error(
|
|
163
|
+
`\nš” Reached maximum iterations (${maxIterations}). The task may be too complex.`,
|
|
164
|
+
);
|
|
165
|
+
console.error(
|
|
166
|
+
" Consider breaking it into smaller tasks or increasing maxIterations with --max-iterations flag.",
|
|
167
|
+
);
|
|
168
|
+
} else if (result.responses.length > 0) {
|
|
169
|
+
const lastResponse = result.responses[result.responses.length - 1];
|
|
170
|
+
if ("errorCode" in lastResponse) {
|
|
171
|
+
const cursorResponse = lastResponse as any;
|
|
172
|
+
if (cursorResponse.errorCode === "MCP_UNAVAILABLE") {
|
|
173
|
+
console.error("\nš” Make sure:");
|
|
174
|
+
console.error(" 1. MCP server is running (npm run bugmole:mcp)");
|
|
175
|
+
console.error(" 2. Cursor is configured to use the Bugmole MCP server");
|
|
176
|
+
console.error(" 3. MCP tools are available in Cursor");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
main().catch((err) => {
|
|
186
|
+
console.error(`[Bugmole MCP Init] Fatal error: ${err?.message ?? err}`);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawnSync } = require("node:child_process");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
|
|
5
|
+
const tsxCli = require.resolve("tsx/cli");
|
|
6
|
+
const script = path.join(__dirname, "bugmole.ts");
|
|
7
|
+
const result = spawnSync(process.execPath, [tsxCli, script, ...process.argv.slice(2)], {
|
|
8
|
+
stdio: "inherit",
|
|
9
|
+
env: process.env,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (result.error) {
|
|
13
|
+
console.error(`[Bugmole CLI] failed to start: ${result.error.message}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
process.exit(result.status ?? 1);
|