@moxxy/cli 0.0.3 → 0.0.4

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 CHANGED
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
 
36
36
  // ../types/dist/index.mjs
37
- var import_zod, import_zod2, import_zod3, import_zod4, import_zod5, import_zod6, import_zod7, import_zod8, import_zod9, import_zod10, import_zod11, uuidSchema, timestampSchema, paginationSchema, activityTypeSchema, taskActivitySchema, createActivitySchema, agentStatusSchema, agentTypeSchema, agentCapabilitySchema, agentIdentitySchema, agentModelConfigSchema, agentSchema, createAgentSchema, updateAgentSchema, taskFiltersSchema, INTEGRATION_TYPES, NOTIFICATION_EVENTS, createIntegrationSchema, updateIntegrationSchema, projectStatusSchema, workflowModeSchema, validationSettingsSchema, workflowSettingsSchema, prdStatusSchema, prdTemplateSchema, prdTaskSchema, projectSchema, generatePRDInputSchema, importPRDTasksInputSchema, updatePRDInputSchema, createProjectSchema, updateProjectSchema, taskStatusSchema, taskTypeSchema, taskPrioritySchema, agentNoteTypeSchema, agentNoteSchema, taskSchema, createTaskSchema, updateTaskSchema, clientEventTypeSchema, serverEventTypeSchema, gatewayConfigSchema, githubAuthConfigSchema, webhookServerConfigSchema, watchedRepoSchema, agentRunConfigSchema, sdkProviderSchema, claudeConfigSchema, moxxyConfigSchema, agentCommandResultSchema, argDefSchema, optionDefSchema, agentCLICommandDefSchema, workflowStepSchema, workflowSchema, workflowStepResultSchema, workflowResultSchema, githubIssuePayloadSchema, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_COMPLEXITIES, issueClassificationSchema, PIPELINE_STAGES, PIPELINE_STATUSES, pipelineStageResultSchema, pipelineRunSchema;
37
+ var import_zod, import_zod2, import_zod3, import_zod4, import_zod5, import_zod6, import_zod7, import_zod8, import_zod9, import_zod10, import_zod11, uuidSchema, timestampSchema, paginationSchema, activityTypeSchema, taskActivitySchema, createActivitySchema, agentStatusSchema, agentTypeSchema, agentCapabilitySchema, agentIdentitySchema, agentModelConfigSchema, agentSchema, createAgentSchema, updateAgentSchema, taskFiltersSchema, INTEGRATION_TYPES, NOTIFICATION_EVENTS, createIntegrationSchema, updateIntegrationSchema, projectStatusSchema, workflowModeSchema, validationSettingsSchema, workflowSettingsSchema, prdStatusSchema, prdTemplateSchema, prdTaskSchema, projectSchema, generatePRDInputSchema, importPRDTasksInputSchema, updatePRDInputSchema, createProjectSchema, updateProjectSchema, taskStatusSchema, taskTypeSchema, taskPrioritySchema, agentNoteTypeSchema, agentNoteSchema, taskSchema, createTaskSchema, updateTaskSchema, clientEventTypeSchema, serverEventTypeSchema, githubIssuePayloadSchema, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_COMPLEXITIES, issueClassificationSchema, PIPELINE_STAGES, PIPELINE_STATUSES, pipelineStageResultSchema, pipelineRunSchema, gatewayConfigSchema, githubAuthConfigSchema, webhookServerConfigSchema, watchedRepoSchema, agentRunConfigSchema, sdkProviderSchema, claudeConfigSchema, pipelineConfigSchema, moxxyConfigSchema, agentCommandResultSchema, argDefSchema, optionDefSchema, agentCLICommandDefSchema, workflowStepSchema, workflowSchema, workflowStepResultSchema, workflowResultSchema;
38
38
  var init_dist = __esm({
39
39
  "../types/dist/index.mjs"() {
40
40
  "use strict";
@@ -390,6 +390,69 @@ var init_dist = __esm({
390
390
  "project:prd_status_changed",
391
391
  "error"
392
392
  ]);
393
+ githubIssuePayloadSchema = import_zod10.z.object({
394
+ action: import_zod10.z.string(),
395
+ issueNumber: import_zod10.z.number().int().positive(),
396
+ title: import_zod10.z.string(),
397
+ body: import_zod10.z.string().nullable(),
398
+ labels: import_zod10.z.array(import_zod10.z.string()),
399
+ author: import_zod10.z.string(),
400
+ repo: import_zod10.z.object({
401
+ owner: import_zod10.z.string(),
402
+ name: import_zod10.z.string(),
403
+ fullName: import_zod10.z.string(),
404
+ defaultBranch: import_zod10.z.string(),
405
+ cloneUrl: import_zod10.z.string()
406
+ }),
407
+ url: import_zod10.z.string().url(),
408
+ createdAt: import_zod10.z.string()
409
+ });
410
+ ISSUE_TYPES = ["feature", "bug", "refactor", "docs", "test", "chore"];
411
+ ISSUE_PRIORITIES = ["low", "medium", "high", "urgent"];
412
+ ISSUE_COMPLEXITIES = ["trivial", "small", "medium", "large", "epic"];
413
+ issueClassificationSchema = import_zod10.z.object({
414
+ type: import_zod10.z.enum(ISSUE_TYPES),
415
+ priority: import_zod10.z.enum(ISSUE_PRIORITIES),
416
+ complexity: import_zod10.z.enum(ISSUE_COMPLEXITIES),
417
+ confidence: import_zod10.z.number().min(0).max(1),
418
+ reasoning: import_zod10.z.string()
419
+ });
420
+ PIPELINE_STAGES = [
421
+ "triage",
422
+ "research",
423
+ "inspect",
424
+ "plan",
425
+ "implement"
426
+ ];
427
+ PIPELINE_STATUSES = [
428
+ "pending",
429
+ "running",
430
+ "completed",
431
+ "failed",
432
+ "cancelled"
433
+ ];
434
+ pipelineStageResultSchema = import_zod10.z.object({
435
+ stage: import_zod10.z.enum(PIPELINE_STAGES),
436
+ status: import_zod10.z.enum(PIPELINE_STATUSES),
437
+ output: import_zod10.z.unknown().optional(),
438
+ error: import_zod10.z.string().optional(),
439
+ duration_ms: import_zod10.z.number().optional()
440
+ });
441
+ pipelineRunSchema = import_zod10.z.object({
442
+ id: import_zod10.z.string(),
443
+ issueNumber: import_zod10.z.number().int().positive(),
444
+ repo: import_zod10.z.object({
445
+ owner: import_zod10.z.string(),
446
+ name: import_zod10.z.string()
447
+ }),
448
+ stages: import_zod10.z.array(pipelineStageResultSchema),
449
+ status: import_zod10.z.enum(PIPELINE_STATUSES),
450
+ branchName: import_zod10.z.string().optional(),
451
+ prNumber: import_zod10.z.number().int().positive().optional(),
452
+ classification: issueClassificationSchema.optional(),
453
+ createdAt: import_zod10.z.number(),
454
+ updatedAt: import_zod10.z.number()
455
+ });
393
456
  gatewayConfigSchema = import_zod9.z.object({
394
457
  url: import_zod9.z.string().url(),
395
458
  authToken: import_zod9.z.string().optional(),
@@ -426,6 +489,9 @@ var init_dist = __esm({
426
489
  timeout: import_zod9.z.number().int().positive().default(3e5),
427
490
  permissionMode: import_zod9.z.string().default("default")
428
491
  });
492
+ pipelineConfigSchema = import_zod9.z.object({
493
+ enabledStages: import_zod9.z.array(import_zod9.z.enum(PIPELINE_STAGES)).default(["triage", "research", "inspect", "plan", "implement"])
494
+ });
429
495
  moxxyConfigSchema = import_zod9.z.object({
430
496
  version: import_zod9.z.number().int().positive().default(1),
431
497
  sdk: sdkProviderSchema,
@@ -434,129 +500,67 @@ var init_dist = __esm({
434
500
  webhook: webhookServerConfigSchema.optional(),
435
501
  repos: import_zod9.z.array(watchedRepoSchema).default([]),
436
502
  agent: agentRunConfigSchema.optional(),
503
+ pipeline: pipelineConfigSchema.optional(),
437
504
  claude: claudeConfigSchema.optional()
438
505
  });
439
- agentCommandResultSchema = import_zod10.z.object({
440
- success: import_zod10.z.boolean(),
441
- command: import_zod10.z.string(),
442
- data: import_zod10.z.unknown().optional(),
443
- error: import_zod10.z.object({
444
- code: import_zod10.z.string(),
445
- message: import_zod10.z.string(),
446
- details: import_zod10.z.string().optional()
506
+ agentCommandResultSchema = import_zod11.z.object({
507
+ success: import_zod11.z.boolean(),
508
+ command: import_zod11.z.string(),
509
+ data: import_zod11.z.unknown().optional(),
510
+ error: import_zod11.z.object({
511
+ code: import_zod11.z.string(),
512
+ message: import_zod11.z.string(),
513
+ details: import_zod11.z.string().optional()
447
514
  }).optional(),
448
- duration_ms: import_zod10.z.number()
515
+ duration_ms: import_zod11.z.number()
449
516
  });
450
- argDefSchema = import_zod10.z.object({
451
- name: import_zod10.z.string(),
452
- description: import_zod10.z.string(),
453
- required: import_zod10.z.boolean().default(false),
454
- type: import_zod10.z.enum(["string", "number", "boolean"]).default("string")
517
+ argDefSchema = import_zod11.z.object({
518
+ name: import_zod11.z.string(),
519
+ description: import_zod11.z.string(),
520
+ required: import_zod11.z.boolean().default(false),
521
+ type: import_zod11.z.enum(["string", "number", "boolean"]).default("string")
455
522
  });
456
- optionDefSchema = import_zod10.z.object({
457
- name: import_zod10.z.string(),
458
- short: import_zod10.z.string().optional(),
459
- description: import_zod10.z.string(),
460
- required: import_zod10.z.boolean().default(false),
461
- type: import_zod10.z.enum(["string", "number", "boolean"]).default("string"),
462
- defaultValue: import_zod10.z.unknown().optional()
523
+ optionDefSchema = import_zod11.z.object({
524
+ name: import_zod11.z.string(),
525
+ short: import_zod11.z.string().optional(),
526
+ description: import_zod11.z.string(),
527
+ required: import_zod11.z.boolean().default(false),
528
+ type: import_zod11.z.enum(["string", "number", "boolean"]).default("string"),
529
+ defaultValue: import_zod11.z.unknown().optional()
463
530
  });
464
- agentCLICommandDefSchema = import_zod10.z.object({
465
- name: import_zod10.z.string(),
466
- description: import_zod10.z.string(),
467
- args: import_zod10.z.array(argDefSchema),
468
- options: import_zod10.z.array(optionDefSchema),
469
- examples: import_zod10.z.array(import_zod10.z.string())
531
+ agentCLICommandDefSchema = import_zod11.z.object({
532
+ name: import_zod11.z.string(),
533
+ description: import_zod11.z.string(),
534
+ args: import_zod11.z.array(argDefSchema),
535
+ options: import_zod11.z.array(optionDefSchema),
536
+ examples: import_zod11.z.array(import_zod11.z.string())
470
537
  });
471
- workflowStepSchema = import_zod10.z.object({
472
- id: import_zod10.z.string(),
473
- plugin: import_zod10.z.string(),
474
- command: import_zod10.z.string(),
475
- args: import_zod10.z.record(import_zod10.z.unknown()),
476
- description: import_zod10.z.string(),
477
- dependsOn: import_zod10.z.array(import_zod10.z.string()).optional(),
478
- optional: import_zod10.z.boolean().optional()
538
+ workflowStepSchema = import_zod11.z.object({
539
+ id: import_zod11.z.string(),
540
+ plugin: import_zod11.z.string(),
541
+ command: import_zod11.z.string(),
542
+ args: import_zod11.z.record(import_zod11.z.unknown()),
543
+ description: import_zod11.z.string(),
544
+ dependsOn: import_zod11.z.array(import_zod11.z.string()).optional(),
545
+ optional: import_zod11.z.boolean().optional()
479
546
  });
480
- workflowSchema = import_zod10.z.object({
481
- id: import_zod10.z.string(),
482
- name: import_zod10.z.string(),
483
- description: import_zod10.z.string(),
484
- steps: import_zod10.z.array(workflowStepSchema),
485
- context: import_zod10.z.record(import_zod10.z.unknown())
547
+ workflowSchema = import_zod11.z.object({
548
+ id: import_zod11.z.string(),
549
+ name: import_zod11.z.string(),
550
+ description: import_zod11.z.string(),
551
+ steps: import_zod11.z.array(workflowStepSchema),
552
+ context: import_zod11.z.record(import_zod11.z.unknown())
486
553
  });
487
- workflowStepResultSchema = import_zod10.z.object({
488
- stepId: import_zod10.z.string(),
554
+ workflowStepResultSchema = import_zod11.z.object({
555
+ stepId: import_zod11.z.string(),
489
556
  result: agentCommandResultSchema,
490
- skipped: import_zod10.z.boolean().default(false)
557
+ skipped: import_zod11.z.boolean().default(false)
491
558
  });
492
- workflowResultSchema = import_zod10.z.object({
493
- workflowId: import_zod10.z.string(),
494
- success: import_zod10.z.boolean(),
495
- stepResults: import_zod10.z.array(workflowStepResultSchema),
496
- duration_ms: import_zod10.z.number()
497
- });
498
- githubIssuePayloadSchema = import_zod11.z.object({
499
- action: import_zod11.z.string(),
500
- issueNumber: import_zod11.z.number().int().positive(),
501
- title: import_zod11.z.string(),
502
- body: import_zod11.z.string().nullable(),
503
- labels: import_zod11.z.array(import_zod11.z.string()),
504
- author: import_zod11.z.string(),
505
- repo: import_zod11.z.object({
506
- owner: import_zod11.z.string(),
507
- name: import_zod11.z.string(),
508
- fullName: import_zod11.z.string(),
509
- defaultBranch: import_zod11.z.string(),
510
- cloneUrl: import_zod11.z.string()
511
- }),
512
- url: import_zod11.z.string().url(),
513
- createdAt: import_zod11.z.string()
514
- });
515
- ISSUE_TYPES = ["feature", "bug", "refactor", "docs", "test", "chore"];
516
- ISSUE_PRIORITIES = ["low", "medium", "high", "urgent"];
517
- ISSUE_COMPLEXITIES = ["trivial", "small", "medium", "large", "epic"];
518
- issueClassificationSchema = import_zod11.z.object({
519
- type: import_zod11.z.enum(ISSUE_TYPES),
520
- priority: import_zod11.z.enum(ISSUE_PRIORITIES),
521
- complexity: import_zod11.z.enum(ISSUE_COMPLEXITIES),
522
- confidence: import_zod11.z.number().min(0).max(1),
523
- reasoning: import_zod11.z.string()
524
- });
525
- PIPELINE_STAGES = [
526
- "triage",
527
- "research",
528
- "inspect",
529
- "plan",
530
- "implement"
531
- ];
532
- PIPELINE_STATUSES = [
533
- "pending",
534
- "running",
535
- "completed",
536
- "failed",
537
- "cancelled"
538
- ];
539
- pipelineStageResultSchema = import_zod11.z.object({
540
- stage: import_zod11.z.enum(PIPELINE_STAGES),
541
- status: import_zod11.z.enum(PIPELINE_STATUSES),
542
- output: import_zod11.z.unknown().optional(),
543
- error: import_zod11.z.string().optional(),
544
- duration_ms: import_zod11.z.number().optional()
545
- });
546
- pipelineRunSchema = import_zod11.z.object({
547
- id: import_zod11.z.string(),
548
- issueNumber: import_zod11.z.number().int().positive(),
549
- repo: import_zod11.z.object({
550
- owner: import_zod11.z.string(),
551
- name: import_zod11.z.string()
552
- }),
553
- stages: import_zod11.z.array(pipelineStageResultSchema),
554
- status: import_zod11.z.enum(PIPELINE_STATUSES),
555
- branchName: import_zod11.z.string().optional(),
556
- prNumber: import_zod11.z.number().int().positive().optional(),
557
- classification: issueClassificationSchema.optional(),
558
- createdAt: import_zod11.z.number(),
559
- updatedAt: import_zod11.z.number()
559
+ workflowResultSchema = import_zod11.z.object({
560
+ workflowId: import_zod11.z.string(),
561
+ success: import_zod11.z.boolean(),
562
+ stepResults: import_zod11.z.array(workflowStepResultSchema),
563
+ duration_ms: import_zod11.z.number()
560
564
  });
561
565
  }
562
566
  });
@@ -23354,69 +23358,114 @@ __export(dist_exports4, {
23354
23358
  parseIssuePayload: () => parseIssuePayload,
23355
23359
  verifyWebhookSignature: () => verifyWebhookSignature
23356
23360
  });
23357
- function verifyWebhookSignature(payload, signature, secret) {
23358
- const expected = "sha256=" + (0, import_crypto4.createHmac)("sha256", secret).update(payload).digest("hex");
23359
- if (expected.length !== signature.length) return false;
23360
- return (0, import_crypto4.timingSafeEqual)(Buffer.from(expected), Buffer.from(signature));
23361
+ function formatDuration(ms) {
23362
+ if (ms < 1e3) return `${ms}ms`;
23363
+ const seconds = ms / 1e3;
23364
+ if (seconds < 60) return `${seconds.toFixed(1)}s`;
23365
+ const minutes = Math.floor(seconds / 60);
23366
+ const remaining = Math.round(seconds % 60);
23367
+ return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
23361
23368
  }
23362
- function parseIssuePayload(body) {
23363
- const issue = body.issue;
23364
- if (!issue) return null;
23365
- return {
23366
- action: body.action,
23367
- issueNumber: issue.number,
23368
- title: issue.title,
23369
- body: issue.body ?? null,
23370
- labels: (issue.labels || []).map((l) => l.name),
23371
- author: issue.user?.login || "unknown",
23372
- repo: {
23373
- owner: body.repository.owner.login,
23374
- name: body.repository.name,
23375
- fullName: body.repository.full_name,
23376
- defaultBranch: body.repository.default_branch,
23377
- cloneUrl: body.repository.clone_url
23378
- },
23379
- url: issue.html_url,
23380
- createdAt: issue.created_at
23381
- };
23369
+ function statusIcon(status) {
23370
+ switch (status) {
23371
+ case "completed":
23372
+ return "\u2705";
23373
+ case "failed":
23374
+ return "\u274C";
23375
+ case "running":
23376
+ return "\u23F3";
23377
+ default:
23378
+ return "\u2B1C";
23379
+ }
23382
23380
  }
23383
- async function triageIssue(supervisor, agentId, payload) {
23384
- const instruction = {
23385
- prompt: `Classify this GitHub issue. Return ONLY a JSON object.
23386
-
23387
- Issue #${payload.issueNumber}: ${payload.title}
23388
- ${payload.body || "No description provided."}
23389
- Labels: ${payload.labels.join(", ") || "none"}
23390
-
23391
- Return JSON: {"type": "feature|bug|refactor|docs|test|chore", "priority": "low|medium|high|urgent", "complexity": "trivial|small|medium|large|epic", "confidence": 0.0-1.0, "reasoning": "..."}`,
23392
- metadata: { stage: "triage", issueNumber: payload.issueNumber }
23393
- };
23394
- const result = await supervisor.sendInstruction(agentId, instruction);
23395
- const jsonMatch = result.response.match(/\{[\s\S]*\}/);
23396
- if (!jsonMatch) throw new Error("No JSON found in triage response");
23397
- return JSON.parse(jsonMatch[0]);
23381
+ function buildStartComment(payload, enabledStages) {
23382
+ const stageFlow = enabledStages.map((s) => STAGE_LABELS[s]).join(" \u2192 ");
23383
+ return [
23384
+ `> **Moxxy** is working on this issue`,
23385
+ "",
23386
+ "| | |",
23387
+ "|---|---|",
23388
+ `| **Issue** | #${payload.issueNumber} \u2014 ${payload.title} |`,
23389
+ `| **Branch** | \`moxxy/issue-${payload.issueNumber}\` |`,
23390
+ `| **Stages** | ${stageFlow} |`,
23391
+ "",
23392
+ "_This comment will be updated when the pipeline completes._"
23393
+ ].join("\n");
23398
23394
  }
23399
- async function researchIssue(supervisor, agentId, payload, classification) {
23395
+ function buildSuccessComment(run2, _payload) {
23396
+ const lines = [];
23397
+ lines.push(`> **Moxxy** has completed this issue`);
23398
+ lines.push("");
23399
+ if (run2.classification) {
23400
+ const c = run2.classification;
23401
+ lines.push("| | |");
23402
+ lines.push("|---|---|");
23403
+ lines.push(`| **Type** | ${c.type} |`);
23404
+ lines.push(`| **Priority** | ${c.priority} |`);
23405
+ lines.push(`| **Complexity** | ${c.complexity} |`);
23406
+ lines.push(`| **Confidence** | ${(c.confidence * 100).toFixed(0)}% |`);
23407
+ lines.push("");
23408
+ if (c.reasoning) {
23409
+ lines.push(`> ${c.reasoning}`);
23410
+ lines.push("");
23411
+ }
23412
+ }
23413
+ lines.push("| Stage | Status | Duration |");
23414
+ lines.push("|-------|--------|----------|");
23415
+ for (const stage of run2.stages) {
23416
+ const icon = statusIcon(stage.status);
23417
+ const duration = stage.duration_ms != null ? formatDuration(stage.duration_ms) : "\u2014";
23418
+ lines.push(`| ${STAGE_LABELS[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
23419
+ }
23420
+ lines.push("");
23421
+ if (run2.prNumber) {
23422
+ lines.push(`**Result:** PR #${run2.prNumber} created on branch \`${run2.branchName}\``);
23423
+ }
23424
+ lines.push("");
23425
+ lines.push("<sub>Automated by Moxxy</sub>");
23426
+ return lines.join("\n");
23427
+ }
23428
+ function buildFailureComment(run2, error2) {
23429
+ const lines = [];
23430
+ lines.push(`> **Moxxy** pipeline failed`);
23431
+ lines.push("");
23432
+ if (run2.stages.length > 0) {
23433
+ lines.push("| Stage | Status | Duration |");
23434
+ lines.push("|-------|--------|----------|");
23435
+ for (const stage of run2.stages) {
23436
+ const icon = statusIcon(stage.status);
23437
+ const duration = stage.duration_ms != null ? formatDuration(stage.duration_ms) : "\u2014";
23438
+ lines.push(`| ${STAGE_LABELS[stage.stage]} | ${icon} ${stage.status} | ${duration} |`);
23439
+ }
23440
+ lines.push("");
23441
+ }
23442
+ const errorMessage = error2 instanceof Error ? error2.message : String(error2);
23443
+ lines.push("```");
23444
+ lines.push(errorMessage);
23445
+ lines.push("```");
23446
+ lines.push("");
23447
+ lines.push("<sub>Automated by Moxxy</sub>");
23448
+ return lines.join("\n");
23449
+ }
23450
+ async function implementIssue(supervisor, agentId, payload, workflow) {
23400
23451
  const instruction = {
23401
- prompt: `Research this ${classification.type} issue in the codebase.
23452
+ prompt: `Execute this workflow for issue #${payload.issueNumber}: ${payload.title}
23402
23453
 
23403
- Issue #${payload.issueNumber}: ${payload.title}
23404
- ${payload.body || ""}
23405
- Repository: ${payload.repo.fullName}
23406
- Classification: ${JSON.stringify(classification)}
23454
+ Workflow:
23455
+ ${JSON.stringify(workflow, null, 2)}
23407
23456
 
23408
- Analyze the codebase and identify:
23409
- 1. Relevant files and code areas
23410
- 2. Dependencies and related modules
23411
- 3. Potential impact areas
23457
+ Execute each step using the moxxy-agent CLI tool. For each step, run:
23458
+ moxxy-agent <plugin> <command> <args>
23412
23459
 
23413
- Return JSON: {"relevantFiles": [...], "relatedModules": [...], "potentialImpact": "...", "techStack": [...]}`,
23414
- metadata: { stage: "research", issueNumber: payload.issueNumber }
23460
+ Handle any errors by adapting. Report the results of each step.`,
23461
+ metadata: {
23462
+ stage: "implement",
23463
+ issueNumber: payload.issueNumber,
23464
+ workflowId: workflow.id
23465
+ }
23415
23466
  };
23416
23467
  const result = await supervisor.sendInstruction(agentId, instruction);
23417
- const jsonMatch = result.response.match(/\{[\s\S]*\}/);
23418
- if (!jsonMatch) throw new Error("No JSON found in research response");
23419
- return JSON.parse(jsonMatch[0]);
23468
+ return { response: result.response, sessionKey: result.sessionKey };
23420
23469
  }
23421
23470
  async function inspectIssue(supervisor, agentId, payload, research) {
23422
23471
  const instruction = {
@@ -23458,25 +23507,43 @@ Return JSON: {"steps": [{"action": "create|modify|delete", "path": "...", "descr
23458
23507
  if (!jsonMatch) throw new Error("No JSON found in plan response");
23459
23508
  return JSON.parse(jsonMatch[0]);
23460
23509
  }
23461
- async function implementIssue(supervisor, agentId, payload, workflow) {
23510
+ async function researchIssue(supervisor, agentId, payload, classification) {
23462
23511
  const instruction = {
23463
- prompt: `Execute this workflow for issue #${payload.issueNumber}: ${payload.title}
23512
+ prompt: `Research this ${classification.type} issue in the codebase.
23464
23513
 
23465
- Workflow:
23466
- ${JSON.stringify(workflow, null, 2)}
23514
+ Issue #${payload.issueNumber}: ${payload.title}
23515
+ ${payload.body || ""}
23516
+ Repository: ${payload.repo.fullName}
23517
+ Classification: ${JSON.stringify(classification)}
23467
23518
 
23468
- Execute each step using the moxxy-agent CLI tool. For each step, run:
23469
- moxxy-agent <plugin> <command> <args>
23519
+ Analyze the codebase and identify:
23520
+ 1. Relevant files and code areas
23521
+ 2. Dependencies and related modules
23522
+ 3. Potential impact areas
23470
23523
 
23471
- Handle any errors by adapting. Report the results of each step.`,
23472
- metadata: {
23473
- stage: "implement",
23474
- issueNumber: payload.issueNumber,
23475
- workflowId: workflow.id
23476
- }
23524
+ Return JSON: {"relevantFiles": [...], "relatedModules": [...], "potentialImpact": "...", "techStack": [...]}`,
23525
+ metadata: { stage: "research", issueNumber: payload.issueNumber }
23477
23526
  };
23478
23527
  const result = await supervisor.sendInstruction(agentId, instruction);
23479
- return { response: result.response, sessionKey: result.sessionKey };
23528
+ const jsonMatch = result.response.match(/\{[\s\S]*\}/);
23529
+ if (!jsonMatch) throw new Error("No JSON found in research response");
23530
+ return JSON.parse(jsonMatch[0]);
23531
+ }
23532
+ async function triageIssue(supervisor, agentId, payload) {
23533
+ const instruction = {
23534
+ prompt: `Classify this GitHub issue. Return ONLY a JSON object.
23535
+
23536
+ Issue #${payload.issueNumber}: ${payload.title}
23537
+ ${payload.body || "No description provided."}
23538
+ Labels: ${payload.labels.join(", ") || "none"}
23539
+
23540
+ Return JSON: {"type": "feature|bug|refactor|docs|test|chore", "priority": "low|medium|high|urgent", "complexity": "trivial|small|medium|large|epic", "confidence": 0.0-1.0, "reasoning": "..."}`,
23541
+ metadata: { stage: "triage", issueNumber: payload.issueNumber }
23542
+ };
23543
+ const result = await supervisor.sendInstruction(agentId, instruction);
23544
+ const jsonMatch = result.response.match(/\{[\s\S]*\}/);
23545
+ if (!jsonMatch) throw new Error("No JSON found in triage response");
23546
+ return JSON.parse(jsonMatch[0]);
23480
23547
  }
23481
23548
  function buildWorkflow(payload, plan, branchName) {
23482
23549
  const steps = [];
@@ -23540,6 +23607,32 @@ function buildWorkflow(payload, plan, branchName) {
23540
23607
  }
23541
23608
  };
23542
23609
  }
23610
+ function verifyWebhookSignature(payload, signature, secret) {
23611
+ const expected = "sha256=" + (0, import_crypto4.createHmac)("sha256", secret).update(payload).digest("hex");
23612
+ if (expected.length !== signature.length) return false;
23613
+ return (0, import_crypto4.timingSafeEqual)(Buffer.from(expected), Buffer.from(signature));
23614
+ }
23615
+ function parseIssuePayload(body) {
23616
+ const issue = body.issue;
23617
+ if (!issue) return null;
23618
+ return {
23619
+ action: body.action,
23620
+ issueNumber: issue.number,
23621
+ title: issue.title,
23622
+ body: issue.body ?? null,
23623
+ labels: (issue.labels || []).map((l) => l.name),
23624
+ author: issue.user?.login || "unknown",
23625
+ repo: {
23626
+ owner: body.repository.owner.login,
23627
+ name: body.repository.name,
23628
+ fullName: body.repository.full_name,
23629
+ defaultBranch: body.repository.default_branch,
23630
+ cloneUrl: body.repository.clone_url
23631
+ },
23632
+ url: issue.html_url,
23633
+ createdAt: issue.created_at
23634
+ };
23635
+ }
23543
23636
  async function createBranchFromDefault(client, owner, repo, branchName, defaultBranch) {
23544
23637
  await client.createBranch(owner, repo, branchName, defaultBranch);
23545
23638
  }
@@ -23553,12 +23646,13 @@ Automated by Moxxy.`,
23553
23646
  base: defaultBranch
23554
23647
  });
23555
23648
  }
23556
- var import_crypto4, GitHubError, GitHubAuthError, GitHubWebhookError, GitHubPipelineError, GitHubClient, WebhookServer, IssuePipeline, GitHubIntegration;
23649
+ var import_crypto4, GitHubError, GitHubAuthError, GitHubWebhookError, GitHubPipelineError, GitHubClient, STAGE_LABELS, DEFAULT_CLASSIFICATION, DEFAULT_RESEARCH, DEFAULT_INSPECT, IssuePipeline, WebhookServer, GitHubIntegration;
23557
23650
  var init_dist7 = __esm({
23558
23651
  "../integration-github/dist/index.mjs"() {
23559
23652
  "use strict";
23560
23653
  init_dist4();
23561
23654
  init_dist_src5();
23655
+ init_dist();
23562
23656
  init_dist5();
23563
23657
  init_dist6();
23564
23658
  import_crypto4 = require("crypto");
@@ -23646,86 +23740,43 @@ var init_dist7 = __esm({
23646
23740
  return data;
23647
23741
  }
23648
23742
  };
23649
- WebhookServer = class {
23650
- server = null;
23651
- app;
23652
- config;
23653
- constructor(config) {
23654
- this.config = config;
23655
- this.app = new Hono2();
23656
- this.setupRoutes();
23657
- }
23658
- setupRoutes() {
23659
- this.app.get("/health", (c) => {
23660
- return c.json({ status: "ok", timestamp: Date.now() });
23661
- });
23662
- this.app.post(this.config.path, async (c) => {
23663
- try {
23664
- const rawBody = await c.req.text();
23665
- if (this.config.secret) {
23666
- const signature = c.req.header("x-hub-signature-256") || "";
23667
- if (!signature) {
23668
- return c.json({ error: "Missing signature" }, 401);
23669
- }
23670
- if (!verifyWebhookSignature(rawBody, signature, this.config.secret)) {
23671
- return c.json({ error: "Invalid signature" }, 401);
23672
- }
23673
- }
23674
- const body = JSON.parse(rawBody);
23675
- const event = c.req.header("x-github-event") || "";
23676
- if (event === "issues") {
23677
- const payload = parseIssuePayload(body);
23678
- if (payload) {
23679
- this.config.onIssue(payload).catch((err) => {
23680
- console.error("Error processing issue webhook:", err);
23681
- });
23682
- }
23683
- }
23684
- return c.json({ received: true });
23685
- } catch (error2) {
23686
- const message = error2 instanceof Error ? error2.message : String(error2);
23687
- throw new GitHubWebhookError(
23688
- `Failed to process webhook: ${message}`,
23689
- error2 instanceof Error ? error2 : void 0
23690
- );
23691
- }
23692
- });
23693
- }
23694
- async start() {
23695
- return new Promise((resolve) => {
23696
- this.server = serve(
23697
- {
23698
- fetch: this.app.fetch,
23699
- port: this.config.port,
23700
- hostname: this.config.host
23701
- },
23702
- () => {
23703
- resolve();
23704
- }
23705
- );
23706
- });
23707
- }
23708
- async stop() {
23709
- if (this.server) {
23710
- await new Promise((resolve, reject) => {
23711
- this.server.close((err) => {
23712
- if (err) {
23713
- reject(err);
23714
- } else {
23715
- resolve();
23716
- }
23717
- });
23718
- });
23719
- this.server = null;
23720
- }
23721
- }
23743
+ STAGE_LABELS = {
23744
+ triage: "Triage",
23745
+ research: "Research",
23746
+ inspect: "Inspect",
23747
+ plan: "Plan",
23748
+ implement: "Implement"
23749
+ };
23750
+ DEFAULT_CLASSIFICATION = {
23751
+ type: "feature",
23752
+ priority: "medium",
23753
+ complexity: "medium",
23754
+ confidence: 0.5,
23755
+ reasoning: "Auto-classified"
23756
+ };
23757
+ DEFAULT_RESEARCH = {
23758
+ relevantFiles: [],
23759
+ relatedModules: [],
23760
+ potentialImpact: "Unknown",
23761
+ techStack: []
23762
+ };
23763
+ DEFAULT_INSPECT = {
23764
+ findings: [],
23765
+ rootCause: "Not inspected",
23766
+ suggestedApproach: "",
23767
+ estimatedChanges: []
23722
23768
  };
23723
23769
  IssuePipeline = class {
23724
- constructor(supervisor, moltAgentId, github) {
23770
+ constructor(supervisor, moltAgentId, github, enabledStages) {
23725
23771
  this.supervisor = supervisor;
23726
23772
  this.moltAgentId = moltAgentId;
23727
23773
  this.github = github;
23774
+ const stages = enabledStages ?? [...PIPELINE_STAGES];
23775
+ if (!stages.includes("plan")) stages.push("plan");
23776
+ if (!stages.includes("implement")) stages.push("implement");
23777
+ this.enabledStages = new Set(stages);
23728
23778
  }
23779
+ enabledStages;
23729
23780
  async run(payload) {
23730
23781
  const pipelineRun = {
23731
23782
  id: `pipeline-${Date.now()}`,
@@ -23736,63 +23787,62 @@ var init_dist7 = __esm({
23736
23787
  createdAt: Date.now(),
23737
23788
  updatedAt: Date.now()
23738
23789
  };
23790
+ const activeStages = PIPELINE_STAGES.filter((s) => this.enabledStages.has(s));
23739
23791
  try {
23740
23792
  await this.github.commentOnIssue(
23741
23793
  payload.repo.owner,
23742
23794
  payload.repo.name,
23743
23795
  payload.issueNumber,
23744
- "\u{1F916} Moxxy is analyzing this issue..."
23745
- );
23746
- const triageResult = await this.runStage(
23747
- "triage",
23748
- () => triageIssue(this.supervisor, this.moltAgentId, payload)
23796
+ buildStartComment(payload, activeStages)
23749
23797
  );
23750
- pipelineRun.stages.push(triageResult);
23751
- if (triageResult.status === "failed")
23752
- throw new Error(`Triage failed: ${triageResult.error}`);
23753
- pipelineRun.classification = triageResult.output;
23754
- const researchResult = await this.runStage(
23755
- "research",
23756
- () => researchIssue(
23757
- this.supervisor,
23758
- this.moltAgentId,
23759
- payload,
23760
- pipelineRun.classification
23761
- )
23762
- );
23763
- pipelineRun.stages.push(researchResult);
23764
- if (researchResult.status === "failed")
23765
- throw new Error(`Research failed: ${researchResult.error}`);
23766
- const inspectResult = await this.runStage(
23767
- "inspect",
23768
- () => inspectIssue(
23769
- this.supervisor,
23770
- this.moltAgentId,
23771
- payload,
23772
- researchResult.output
23773
- )
23774
- );
23775
- pipelineRun.stages.push(inspectResult);
23776
- if (inspectResult.status === "failed")
23777
- throw new Error(`Inspect failed: ${inspectResult.error}`);
23798
+ let classification;
23799
+ if (this.enabledStages.has("triage")) {
23800
+ const triageResult = await this.runStage(
23801
+ "triage",
23802
+ () => triageIssue(this.supervisor, this.moltAgentId, payload)
23803
+ );
23804
+ pipelineRun.stages.push(triageResult);
23805
+ if (triageResult.status === "failed")
23806
+ throw new Error(`Triage failed: ${triageResult.error}`);
23807
+ classification = triageResult.output;
23808
+ } else {
23809
+ classification = DEFAULT_CLASSIFICATION;
23810
+ }
23811
+ pipelineRun.classification = classification;
23812
+ let researchOutput;
23813
+ if (this.enabledStages.has("research")) {
23814
+ const researchResult = await this.runStage(
23815
+ "research",
23816
+ () => researchIssue(this.supervisor, this.moltAgentId, payload, classification)
23817
+ );
23818
+ pipelineRun.stages.push(researchResult);
23819
+ if (researchResult.status === "failed")
23820
+ throw new Error(`Research failed: ${researchResult.error}`);
23821
+ researchOutput = researchResult.output;
23822
+ } else {
23823
+ researchOutput = DEFAULT_RESEARCH;
23824
+ }
23825
+ let inspectOutput;
23826
+ if (this.enabledStages.has("inspect")) {
23827
+ const inspectResult = await this.runStage(
23828
+ "inspect",
23829
+ () => inspectIssue(this.supervisor, this.moltAgentId, payload, researchOutput)
23830
+ );
23831
+ pipelineRun.stages.push(inspectResult);
23832
+ if (inspectResult.status === "failed")
23833
+ throw new Error(`Inspect failed: ${inspectResult.error}`);
23834
+ inspectOutput = inspectResult.output;
23835
+ } else {
23836
+ inspectOutput = DEFAULT_INSPECT;
23837
+ }
23778
23838
  const planResult = await this.runStage(
23779
23839
  "plan",
23780
- () => planIssue(
23781
- this.supervisor,
23782
- this.moltAgentId,
23783
- payload,
23784
- inspectResult.output
23785
- )
23840
+ () => planIssue(this.supervisor, this.moltAgentId, payload, inspectOutput)
23786
23841
  );
23787
23842
  pipelineRun.stages.push(planResult);
23788
- if (planResult.status === "failed")
23789
- throw new Error(`Plan failed: ${planResult.error}`);
23843
+ if (planResult.status === "failed") throw new Error(`Plan failed: ${planResult.error}`);
23790
23844
  const branchName = `moxxy/issue-${payload.issueNumber}`;
23791
- const workflow = buildWorkflow(
23792
- payload,
23793
- planResult.output,
23794
- branchName
23795
- );
23845
+ const workflow = buildWorkflow(payload, planResult.output, branchName);
23796
23846
  const implementResult = await this.runStage(
23797
23847
  "implement",
23798
23848
  () => implementIssue(this.supervisor, this.moltAgentId, payload, workflow)
@@ -23801,18 +23851,17 @@ var init_dist7 = __esm({
23801
23851
  if (implementResult.status === "failed")
23802
23852
  throw new Error(`Implement failed: ${implementResult.error}`);
23803
23853
  pipelineRun.branchName = branchName;
23804
- const prNumber = await this.github.createPR(
23805
- payload.repo.owner,
23806
- payload.repo.name,
23807
- {
23808
- title: `[Moxxy] ${payload.title}`,
23809
- body: `Closes #${payload.issueNumber}
23854
+ const classificationNote = pipelineRun.classification ? `
23810
23855
 
23811
- Automated implementation by Moxxy.`,
23812
- head: branchName,
23813
- base: payload.repo.defaultBranch
23814
- }
23815
- );
23856
+ **Classification:** ${pipelineRun.classification.type} (${pipelineRun.classification.priority} priority, ${pipelineRun.classification.complexity} complexity)` : "";
23857
+ const prNumber = await this.github.createPR(payload.repo.owner, payload.repo.name, {
23858
+ title: `[Moxxy] ${payload.title}`,
23859
+ body: `Closes #${payload.issueNumber}
23860
+
23861
+ Automated implementation by Moxxy.${classificationNote}`,
23862
+ head: branchName,
23863
+ base: payload.repo.defaultBranch
23864
+ });
23816
23865
  pipelineRun.prNumber = prNumber;
23817
23866
  pipelineRun.status = "completed";
23818
23867
  pipelineRun.updatedAt = Date.now();
@@ -23820,7 +23869,7 @@ Automated implementation by Moxxy.`,
23820
23869
  payload.repo.owner,
23821
23870
  payload.repo.name,
23822
23871
  payload.issueNumber,
23823
- `\u2705 Implementation complete! PR #${prNumber} created.`
23872
+ buildSuccessComment(pipelineRun, payload)
23824
23873
  );
23825
23874
  return pipelineRun;
23826
23875
  } catch (error2) {
@@ -23830,7 +23879,7 @@ Automated implementation by Moxxy.`,
23830
23879
  payload.repo.owner,
23831
23880
  payload.repo.name,
23832
23881
  payload.issueNumber,
23833
- `\u274C Pipeline failed: ${error2 instanceof Error ? error2.message : String(error2)}`
23882
+ buildFailureComment(pipelineRun, error2)
23834
23883
  ).catch(() => {
23835
23884
  });
23836
23885
  return pipelineRun;
@@ -23856,12 +23905,87 @@ Automated implementation by Moxxy.`,
23856
23905
  }
23857
23906
  }
23858
23907
  };
23908
+ WebhookServer = class {
23909
+ server = null;
23910
+ app;
23911
+ config;
23912
+ constructor(config) {
23913
+ this.config = config;
23914
+ this.app = new Hono2();
23915
+ this.setupRoutes();
23916
+ }
23917
+ setupRoutes() {
23918
+ this.app.get("/health", (c) => {
23919
+ return c.json({ status: "ok", timestamp: Date.now() });
23920
+ });
23921
+ this.app.post(this.config.path, async (c) => {
23922
+ try {
23923
+ const rawBody = await c.req.text();
23924
+ if (this.config.secret) {
23925
+ const signature = c.req.header("x-hub-signature-256") || "";
23926
+ if (!signature) {
23927
+ return c.json({ error: "Missing signature" }, 401);
23928
+ }
23929
+ if (!verifyWebhookSignature(rawBody, signature, this.config.secret)) {
23930
+ return c.json({ error: "Invalid signature" }, 401);
23931
+ }
23932
+ }
23933
+ const body = JSON.parse(rawBody);
23934
+ const event = c.req.header("x-github-event") || "";
23935
+ if (event === "issues") {
23936
+ const payload = parseIssuePayload(body);
23937
+ if (payload) {
23938
+ this.config.onIssue(payload).catch((err) => {
23939
+ console.error("Error processing issue webhook:", err);
23940
+ });
23941
+ }
23942
+ }
23943
+ return c.json({ received: true });
23944
+ } catch (error2) {
23945
+ const message = error2 instanceof Error ? error2.message : String(error2);
23946
+ throw new GitHubWebhookError(
23947
+ `Failed to process webhook: ${message}`,
23948
+ error2 instanceof Error ? error2 : void 0
23949
+ );
23950
+ }
23951
+ });
23952
+ }
23953
+ async start() {
23954
+ return new Promise((resolve) => {
23955
+ this.server = serve(
23956
+ {
23957
+ fetch: this.app.fetch,
23958
+ port: this.config.port,
23959
+ hostname: this.config.host
23960
+ },
23961
+ () => {
23962
+ resolve();
23963
+ }
23964
+ );
23965
+ });
23966
+ }
23967
+ async stop() {
23968
+ if (this.server) {
23969
+ await new Promise((resolve, reject) => {
23970
+ this.server.close((err) => {
23971
+ if (err) {
23972
+ reject(err);
23973
+ } else {
23974
+ resolve();
23975
+ }
23976
+ });
23977
+ });
23978
+ this.server = null;
23979
+ }
23980
+ }
23981
+ };
23859
23982
  GitHubIntegration = class extends BaseIntegration {
23860
23983
  client;
23861
23984
  webhookServer;
23862
23985
  pipeline;
23863
23986
  config;
23864
23987
  watchedRepos = [];
23988
+ activeIssues = /* @__PURE__ */ new Map();
23865
23989
  constructor() {
23866
23990
  super("github", "github");
23867
23991
  }
@@ -23871,7 +23995,8 @@ Automated implementation by Moxxy.`,
23871
23995
  this.pipeline = new IssuePipeline(
23872
23996
  this.config.supervisor,
23873
23997
  this.config.moltAgentId,
23874
- this.client
23998
+ this.client,
23999
+ this.config.enabledStages
23875
24000
  );
23876
24001
  await this.client.verifyAuth();
23877
24002
  this.webhookServer = new WebhookServer({
@@ -23889,6 +24014,11 @@ Automated implementation by Moxxy.`,
23889
24014
  await this.webhookServer.stop();
23890
24015
  }
23891
24016
  this.watchedRepos = [];
24017
+ this.activeIssues.clear();
24018
+ }
24019
+ async watchRepos(repos) {
24020
+ this.watchedRepos.push(...repos);
24021
+ this.emit("watching", { repos: this.watchedRepos });
23892
24022
  }
23893
24023
  async onWatch(targets) {
23894
24024
  for (const target of targets) {
@@ -23905,21 +24035,31 @@ Automated implementation by Moxxy.`,
23905
24035
  this.emit("watching", { repos: this.watchedRepos });
23906
24036
  }
23907
24037
  async onUnwatch(targets) {
23908
- this.watchedRepos = this.watchedRepos.filter(
23909
- (r) => !targets.includes(`${r.owner}/${r.repo}`)
23910
- );
24038
+ this.watchedRepos = this.watchedRepos.filter((r) => !targets.includes(`${r.owner}/${r.repo}`));
23911
24039
  }
23912
24040
  async handleIssue(payload) {
23913
24041
  const watched = this.watchedRepos.find(
23914
24042
  (r) => r.owner === payload.repo.owner && r.repo === payload.repo.name
23915
24043
  );
23916
24044
  if (!watched) return;
24045
+ const eventKey = `issues.${payload.action}`;
24046
+ if (watched.enabledEvents && !watched.enabledEvents.includes(eventKey)) {
24047
+ return;
24048
+ }
24049
+ const issueKey = `${payload.repo.owner}/${payload.repo.name}#${payload.issueNumber}`;
24050
+ if (this.activeIssues.has(issueKey)) {
24051
+ this.emit("issue:skipped", { key: issueKey, reason: "already processing" });
24052
+ return;
24053
+ }
24054
+ this.activeIssues.set(issueKey, `pipeline-${Date.now()}`);
23917
24055
  this.emit("issue:received", payload);
23918
24056
  try {
23919
24057
  const run2 = await this.pipeline.run(payload);
23920
24058
  this.emit("pipeline:completed", run2);
23921
24059
  } catch (error2) {
23922
24060
  this.emit("pipeline:error", { issue: payload, error: error2 });
24061
+ } finally {
24062
+ this.activeIssues.delete(issueKey);
23923
24063
  }
23924
24064
  }
23925
24065
  };
@@ -23942,7 +24082,9 @@ async function createSDK(config) {
23942
24082
  return { sdk: sdk2, sdkName };
23943
24083
  }
23944
24084
  if (!config.gateway) {
23945
- throw new Error('Gateway configuration is required for the molt SDK. Run "moxxy config init --sdk molt --gateway-url <url>".');
24085
+ throw new Error(
24086
+ 'Gateway configuration is required for the molt SDK. Run "moxxy config init --sdk molt --gateway-url <url>".'
24087
+ );
23946
24088
  }
23947
24089
  const { MoltSDK: MoltSDK2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
23948
24090
  const sdk = await MoltSDK2.create({
@@ -23996,17 +24138,16 @@ function registerStartCommand(program) {
23996
24138
  webhook: webhookConfig,
23997
24139
  sdk,
23998
24140
  supervisor,
23999
- moltAgentId: agentId || ""
24141
+ moltAgentId: agentId || "",
24142
+ enabledStages: config.pipeline?.enabledStages
24000
24143
  });
24001
24144
  webhookSpinner.succeed(
24002
24145
  `Webhook server listening on ${import_chalk.default.cyan(`${webhookConfig.host}:${webhookConfig.port}${webhookConfig.path}`)}`
24003
24146
  );
24004
24147
  if (config.repos.length > 0) {
24005
- const watchSpinner = spinner(
24006
- `Watching ${config.repos.length} repositories`
24007
- );
24148
+ const watchSpinner = spinner(`Watching ${config.repos.length} repositories`);
24149
+ await github.watchRepos(config.repos);
24008
24150
  const targets = config.repos.map((r) => `${r.owner}/${r.repo}`);
24009
- await github.watch(targets);
24010
24151
  watchSpinner.succeed(
24011
24152
  `Watching ${import_chalk.default.bold(String(targets.length))} repositories: ${targets.join(", ")}`
24012
24153
  );
@@ -24209,6 +24350,19 @@ async function interactiveInit() {
24209
24350
  }
24210
24351
  ]);
24211
24352
  if (!shared.githubToken) return null;
24353
+ const { pipelineStages } = await (0, import_prompts.default)({
24354
+ type: "multiselect",
24355
+ name: "pipelineStages",
24356
+ message: "Pipeline stages to enable",
24357
+ choices: [
24358
+ { title: "Triage", value: "triage", selected: true },
24359
+ { title: "Research", value: "research", selected: true },
24360
+ { title: "Inspect", value: "inspect", selected: true },
24361
+ { title: "Plan", value: "plan", selected: true },
24362
+ { title: "Implement", value: "implement", selected: true }
24363
+ ],
24364
+ hint: "- Space to toggle. Plan & Implement are always on."
24365
+ });
24212
24366
  return {
24213
24367
  sdk,
24214
24368
  gatewayUrl,
@@ -24219,22 +24373,238 @@ async function interactiveInit() {
24219
24373
  githubToken: shared.githubToken,
24220
24374
  webhookSecret: shared.webhookSecret || void 0,
24221
24375
  webhookPort: String(shared.webhookPort ?? 3456),
24222
- agentId: shared.agentId || void 0
24376
+ agentId: shared.agentId || void 0,
24377
+ pipelineStages: pipelineStages?.length ? pipelineStages : void 0
24223
24378
  };
24224
24379
  }
24225
- var import_prompts, import_chalk2;
24380
+ async function interactiveConfig(manager) {
24381
+ const config = manager.getConfig();
24382
+ console.log();
24383
+ console.log(import_chalk2.default.bold.cyan(" Moxxy Config Editor"));
24384
+ console.log(import_chalk2.default.dim(' Select a section to edit. Ctrl+C or "Done" to exit.\n'));
24385
+ while (true) {
24386
+ const { group } = await (0, import_prompts.default)({
24387
+ type: "select",
24388
+ name: "group",
24389
+ message: "Config section",
24390
+ choices: [...CONFIG_GROUPS]
24391
+ });
24392
+ if (!group || group === "done") break;
24393
+ switch (group) {
24394
+ case "sdk":
24395
+ await editSDK(manager, config);
24396
+ break;
24397
+ case "github":
24398
+ await editGitHub(manager, config);
24399
+ break;
24400
+ case "webhook":
24401
+ await editWebhook(manager, config);
24402
+ break;
24403
+ case "pipeline":
24404
+ await editPipeline(manager, config);
24405
+ break;
24406
+ case "agent":
24407
+ await editAgent(manager, config);
24408
+ break;
24409
+ }
24410
+ }
24411
+ }
24412
+ async function editSDK(manager, config) {
24413
+ const { provider } = await (0, import_prompts.default)({
24414
+ type: "select",
24415
+ name: "provider",
24416
+ message: "SDK provider",
24417
+ choices: [
24418
+ { title: "Molt", value: "molt" },
24419
+ { title: "Claude", value: "claude" }
24420
+ ],
24421
+ initial: config.sdk === "claude" ? 1 : 0
24422
+ });
24423
+ if (!provider) return;
24424
+ if (provider === "molt") {
24425
+ const result = await (0, import_prompts.default)([
24426
+ {
24427
+ type: "text",
24428
+ name: "gatewayUrl",
24429
+ message: "Gateway URL",
24430
+ initial: config.gateway?.url || ""
24431
+ },
24432
+ {
24433
+ type: "text",
24434
+ name: "authToken",
24435
+ message: "Auth token",
24436
+ initial: config.gateway?.authToken || ""
24437
+ }
24438
+ ]);
24439
+ if (result.gatewayUrl === void 0) return;
24440
+ await manager.set("sdk", "molt");
24441
+ await manager.set("gateway", {
24442
+ url: result.gatewayUrl,
24443
+ authToken: result.authToken || void 0
24444
+ });
24445
+ } else {
24446
+ const result = await (0, import_prompts.default)([
24447
+ {
24448
+ type: "text",
24449
+ name: "apiKey",
24450
+ message: "API key",
24451
+ initial: config.claude?.apiKey || ""
24452
+ },
24453
+ {
24454
+ type: "text",
24455
+ name: "model",
24456
+ message: "Model",
24457
+ initial: config.claude?.model || "claude-sonnet-4-5"
24458
+ },
24459
+ {
24460
+ type: "text",
24461
+ name: "cliPath",
24462
+ message: "CLI path",
24463
+ initial: config.claude?.cliPath || "claude"
24464
+ }
24465
+ ]);
24466
+ if (result.model === void 0) return;
24467
+ await manager.set("sdk", "claude");
24468
+ await manager.set("claude", {
24469
+ apiKey: result.apiKey || void 0,
24470
+ model: result.model,
24471
+ cliPath: result.cliPath
24472
+ });
24473
+ }
24474
+ console.log(import_chalk2.default.green(" SDK config updated.\n"));
24475
+ }
24476
+ async function editGitHub(manager, config) {
24477
+ const result = await (0, import_prompts.default)([
24478
+ {
24479
+ type: "password",
24480
+ name: "token",
24481
+ message: "GitHub token",
24482
+ initial: config.github?.token || ""
24483
+ },
24484
+ {
24485
+ type: "password",
24486
+ name: "webhookSecret",
24487
+ message: "Webhook secret",
24488
+ initial: config.github?.webhookSecret || ""
24489
+ }
24490
+ ]);
24491
+ if (result.token === void 0) return;
24492
+ await manager.set("github", {
24493
+ token: result.token,
24494
+ webhookSecret: result.webhookSecret || void 0
24495
+ });
24496
+ console.log(import_chalk2.default.green(" GitHub config updated.\n"));
24497
+ }
24498
+ async function editWebhook(manager, config) {
24499
+ const webhook = config.webhook || { port: 3456, host: "0.0.0.0", path: "/webhook/github" };
24500
+ const result = await (0, import_prompts.default)([
24501
+ {
24502
+ type: "number",
24503
+ name: "port",
24504
+ message: "Port",
24505
+ initial: webhook.port
24506
+ },
24507
+ {
24508
+ type: "text",
24509
+ name: "host",
24510
+ message: "Host",
24511
+ initial: webhook.host
24512
+ },
24513
+ {
24514
+ type: "text",
24515
+ name: "path",
24516
+ message: "Path",
24517
+ initial: webhook.path
24518
+ }
24519
+ ]);
24520
+ if (result.port === void 0) return;
24521
+ await manager.set("webhook", {
24522
+ port: result.port,
24523
+ host: result.host,
24524
+ path: result.path
24525
+ });
24526
+ console.log(import_chalk2.default.green(" Webhook config updated.\n"));
24527
+ }
24528
+ async function editPipeline(manager, config) {
24529
+ const currentStages = config.pipeline?.enabledStages ?? [...PIPELINE_STAGES];
24530
+ const currentSet = new Set(currentStages);
24531
+ const { stages } = await (0, import_prompts.default)({
24532
+ type: "multiselect",
24533
+ name: "stages",
24534
+ message: "Enabled pipeline stages",
24535
+ choices: PIPELINE_STAGES.map((s) => ({
24536
+ title: s.charAt(0).toUpperCase() + s.slice(1),
24537
+ value: s,
24538
+ selected: currentSet.has(s)
24539
+ })),
24540
+ hint: "- Space to toggle. Plan & Implement are always on."
24541
+ });
24542
+ if (!stages) return;
24543
+ const final = [...stages];
24544
+ if (!final.includes("plan")) final.push("plan");
24545
+ if (!final.includes("implement")) final.push("implement");
24546
+ await manager.set("pipeline", { enabledStages: final });
24547
+ console.log(import_chalk2.default.green(" Pipeline config updated.\n"));
24548
+ }
24549
+ async function editAgent(manager, config) {
24550
+ const agent = config.agent || {};
24551
+ const result = await (0, import_prompts.default)([
24552
+ {
24553
+ type: "text",
24554
+ name: "moltAgentId",
24555
+ message: "Agent ID",
24556
+ initial: agent.moltAgentId || ""
24557
+ },
24558
+ {
24559
+ type: "number",
24560
+ name: "maxConcurrentTasks",
24561
+ message: "Max concurrent tasks",
24562
+ initial: agent.maxConcurrentTasks || 1
24563
+ }
24564
+ ]);
24565
+ if (result.moltAgentId === void 0) return;
24566
+ await manager.set("agent", {
24567
+ moltAgentId: result.moltAgentId || void 0,
24568
+ maxConcurrentTasks: result.maxConcurrentTasks || 1
24569
+ });
24570
+ console.log(import_chalk2.default.green(" Agent config updated.\n"));
24571
+ }
24572
+ var import_chalk2, import_prompts, CONFIG_GROUPS;
24226
24573
  var init_prompt = __esm({
24227
24574
  "src/utils/prompt.ts"() {
24228
24575
  "use strict";
24229
- import_prompts = __toESM(require("prompts"));
24576
+ init_dist();
24230
24577
  import_chalk2 = __toESM(require("chalk"));
24578
+ import_prompts = __toESM(require("prompts"));
24579
+ CONFIG_GROUPS = [
24580
+ { title: "SDK Provider", value: "sdk" },
24581
+ { title: "GitHub", value: "github" },
24582
+ { title: "Webhook", value: "webhook" },
24583
+ { title: "Pipeline Stages", value: "pipeline" },
24584
+ { title: "Agent", value: "agent" },
24585
+ { title: "Done", value: "done" }
24586
+ ];
24231
24587
  }
24232
24588
  });
24233
24589
 
24234
24590
  // src/commands/config.ts
24235
24591
  function registerConfigCommand(program) {
24236
24592
  const config = program.command("config").description("Manage Moxxy configuration");
24237
- config.command("init").description("Initialize Moxxy configuration").option("--sdk <provider>", "SDK provider (molt or claude)").option("--github-token <token>", "GitHub personal access token").option("--gateway-url <url>", "Gateway URL (molt SDK)").option("--auth-token <token>", "Gateway auth token (molt SDK)").option("--claude-api-key <key>", "Anthropic API key (claude SDK)").option("--claude-model <model>", "Claude model (claude SDK)", "claude-sonnet-4-5").option("--claude-cli-path <path>", "Claude CLI path (claude SDK)", "claude").option("--webhook-secret <secret>", "GitHub webhook secret").option("--webhook-port <port>", "Webhook server port", "3456").option("--agent-id <id>", "Agent ID").action(async (options) => {
24593
+ config.action(async () => {
24594
+ const manager = new ConfigManager();
24595
+ try {
24596
+ await manager.load();
24597
+ } catch {
24598
+ error("No config found. Run 'moxxy config init' first.");
24599
+ process.exitCode = 1;
24600
+ return;
24601
+ }
24602
+ await interactiveConfig(manager);
24603
+ });
24604
+ config.command("init").description("Initialize Moxxy configuration").option("--sdk <provider>", "SDK provider (molt or claude)").option("--github-token <token>", "GitHub personal access token").option("--gateway-url <url>", "Gateway URL (molt SDK)").option("--auth-token <token>", "Gateway auth token (molt SDK)").option("--claude-api-key <key>", "Anthropic API key (claude SDK)").option("--claude-model <model>", "Claude model (claude SDK)", "claude-sonnet-4-5").option("--claude-cli-path <path>", "Claude CLI path (claude SDK)", "claude").option("--webhook-secret <secret>", "GitHub webhook secret").option("--webhook-port <port>", "Webhook server port", "3456").option("--agent-id <id>", "Agent ID").option(
24605
+ "--pipeline-stages <stages>",
24606
+ "Comma-separated pipeline stages (triage,research,inspect,plan,implement)"
24607
+ ).action(async (options) => {
24238
24608
  if (!options.sdk) {
24239
24609
  const result = await interactiveInit();
24240
24610
  if (!result) {
@@ -24259,6 +24629,14 @@ function registerConfigCommand(program) {
24259
24629
  process.exitCode = 1;
24260
24630
  return;
24261
24631
  }
24632
+ let enabledStages;
24633
+ if (options.pipelineStages) {
24634
+ if (typeof options.pipelineStages === "string") {
24635
+ enabledStages = options.pipelineStages.split(",").map((s) => s.trim());
24636
+ } else if (Array.isArray(options.pipelineStages)) {
24637
+ enabledStages = options.pipelineStages;
24638
+ }
24639
+ }
24262
24640
  const manager = new ConfigManager();
24263
24641
  try {
24264
24642
  await manager.init({
@@ -24273,6 +24651,7 @@ function registerConfigCommand(program) {
24273
24651
  },
24274
24652
  repos: [],
24275
24653
  agent: options.agentId ? { moltAgentId: options.agentId } : void 0,
24654
+ pipeline: enabledStages ? { enabledStages } : void 0,
24276
24655
  claude: sdk === "claude" ? {
24277
24656
  apiKey: options.claudeApiKey,
24278
24657
  cliPath: options.claudeCliPath,