@mycompbox/compbox-mcp 1.17.2 → 1.19.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.
Files changed (2) hide show
  1. package/index.js +260 -3
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -118,7 +118,8 @@ var init_mailbox = __esm({
118
118
  JOB_TYPES = [
119
119
  "epic_request",
120
120
  "interview_reply",
121
- "start_execution"
121
+ "start_execution",
122
+ "connect_repo"
122
123
  ];
123
124
  JOB_STATUSES = [
124
125
  "pending",
@@ -328,6 +329,74 @@ var init_skill_packs = __esm({
328
329
  }
329
330
  });
330
331
 
332
+ // ../shared/dist/ai-providers.js
333
+ var aiRouteValues, aiProviderValues, AI_PROVIDERS;
334
+ var init_ai_providers = __esm({
335
+ "../shared/dist/ai-providers.js"() {
336
+ "use strict";
337
+ aiRouteValues = ["machine", "api_key"];
338
+ aiProviderValues = ["anthropic", "openai", "xai", "openrouter"];
339
+ AI_PROVIDERS = {
340
+ anthropic: {
341
+ id: "anthropic",
342
+ name: "Anthropic (Claude)",
343
+ keyPageUrl: "https://console.anthropic.com/settings/keys",
344
+ limitsPageUrl: "https://console.anthropic.com/settings/limits",
345
+ keyPrefix: "sk-ant-",
346
+ steps: [
347
+ "Sign in to the Anthropic Console and add a payment method or credits under Billing.",
348
+ 'Open API keys and choose Create key. Name it after this project, for example "CompBox \u2013 My App".',
349
+ "Copy the key. Anthropic shows it only once.",
350
+ "Optional: set a monthly spend limit under Limits."
351
+ ],
352
+ reportsBalance: false
353
+ },
354
+ openai: {
355
+ id: "openai",
356
+ name: "OpenAI",
357
+ keyPageUrl: "https://platform.openai.com/api-keys",
358
+ limitsPageUrl: "https://platform.openai.com/settings/organization/limits",
359
+ keyPrefix: "sk-",
360
+ steps: [
361
+ "Sign in to the OpenAI Platform and add credits under Billing.",
362
+ "Open API keys and choose Create new secret key. Name it after this project.",
363
+ "Copy the key. OpenAI shows it only once.",
364
+ "Optional: set a monthly budget under Limits."
365
+ ],
366
+ reportsBalance: false
367
+ },
368
+ xai: {
369
+ id: "xai",
370
+ name: "xAI (Grok)",
371
+ keyPageUrl: "https://console.x.ai",
372
+ limitsPageUrl: "https://console.x.ai",
373
+ keyPrefix: "xai-",
374
+ steps: [
375
+ "Sign in to the xAI Console and add credits under Billing.",
376
+ "Open API Keys and create a key. Name it after this project.",
377
+ "Copy the key. xAI shows it only once.",
378
+ "Optional: set a spending limit in the console."
379
+ ],
380
+ reportsBalance: false
381
+ },
382
+ openrouter: {
383
+ id: "openrouter",
384
+ name: "OpenRouter",
385
+ keyPageUrl: "https://openrouter.ai/settings/keys",
386
+ limitsPageUrl: "https://openrouter.ai/settings/credits",
387
+ keyPrefix: "sk-or-",
388
+ note: "One key for models from many providers, including free models with daily limits.",
389
+ steps: [
390
+ "Sign in to OpenRouter. Free models work without credits; add credits under Credits for paid models and higher limits.",
391
+ "Open Keys and choose Create key. Name it after yourself or your company, and optionally set a credit limit on the key.",
392
+ "Copy the key. OpenRouter shows it only once."
393
+ ],
394
+ reportsBalance: true
395
+ }
396
+ };
397
+ }
398
+ });
399
+
331
400
  // ../shared/dist/model-catalog.js
332
401
  function getModelById(id) {
333
402
  return MODEL_CATALOG.find((m) => m.id === id);
@@ -631,10 +700,142 @@ var init_interview_definition = __esm({
631
700
  }
632
701
  });
633
702
 
703
+ // ../shared/dist/interview-completion.js
704
+ function meetsComplianceTarget(compliance) {
705
+ return !compliance || compliance.tier === TARGET_COMPLIANCE_TIER;
706
+ }
707
+ function buildAuditFeedback(compliance) {
708
+ const ordered = [
709
+ ...compliance.issues.filter((i) => i.tier === "critical"),
710
+ ...compliance.issues.filter((i) => i.tier === "advisory")
711
+ ].slice(0, 8);
712
+ const list = ordered.length > 0 ? ordered.map((i) => `- ${i.message}`).join("\n") : "- (no specific issues returned; expand the required fields with more concrete detail)";
713
+ return `The epic request you just produced scored ${String(compliance.overall)}/100 (tier: ${compliance.tier}). It must reach 90/100 with ZERO critical issues before the interview can finish. Fix these:
714
+ ${list}
715
+
716
+ If you can resolve these by EXPANDING what the employee already told you \u2014 a longer, more complete and concrete problemStatement / proposedSolution / impactAssessment / description that comfortably clear the length minimums \u2014 re-emit the completion JSON now with richer fields. Do NOT re-ask something you already have an answer for. Only if you genuinely need NEW information from the employee, ask ONE focused question to get it.`;
717
+ }
718
+ function isEpicRequestDraft(value) {
719
+ if (typeof value !== "object" || value === null)
720
+ return false;
721
+ const v = value;
722
+ const nonEmpty = (x) => typeof x === "string" && x.trim().length > 0;
723
+ const requiredOk = nonEmpty(v.title) && nonEmpty(v.problemStatement) && nonEmpty(v.proposedSolution) && nonEmpty(v.impactAssessment) && nonEmpty(v.description);
724
+ if (!requiredOk)
725
+ return false;
726
+ for (const key of OPTIONAL_DRAFT_KEYS) {
727
+ if (key in v && v[key] !== void 0 && typeof v[key] !== "string")
728
+ return false;
729
+ }
730
+ return true;
731
+ }
732
+ function stripTrailingCommas(json) {
733
+ return json.replace(/,(\s*[}\]])/g, "$1");
734
+ }
735
+ function escapeRawControlCharsInStrings(json) {
736
+ let out = "";
737
+ let inString = false;
738
+ let escaped = false;
739
+ for (const ch of json) {
740
+ if (escaped) {
741
+ out += ch;
742
+ escaped = false;
743
+ continue;
744
+ }
745
+ if (ch === "\\") {
746
+ out += ch;
747
+ escaped = true;
748
+ continue;
749
+ }
750
+ if (ch === '"') {
751
+ inString = !inString;
752
+ out += ch;
753
+ continue;
754
+ }
755
+ if (inString && (ch === "\n" || ch === "\r" || ch === " ")) {
756
+ out += ch === "\n" ? "\\n" : ch === "\r" ? "\\r" : "\\t";
757
+ continue;
758
+ }
759
+ out += ch;
760
+ }
761
+ return out;
762
+ }
763
+ function completionJsonCandidates(text) {
764
+ const candidates = [];
765
+ const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(text);
766
+ if (fenced?.[1])
767
+ candidates.push(fenced[1]);
768
+ const trimmed = text.trim();
769
+ if (trimmed.startsWith("{"))
770
+ candidates.push(trimmed);
771
+ const first = text.indexOf("{");
772
+ const last = text.lastIndexOf("}");
773
+ if (first !== -1 && last > first)
774
+ candidates.push(text.slice(first, last + 1));
775
+ return candidates;
776
+ }
777
+ function toDraft(parsed) {
778
+ const draft = {
779
+ title: parsed.title,
780
+ problemStatement: parsed.problemStatement,
781
+ proposedSolution: parsed.proposedSolution,
782
+ impactAssessment: parsed.impactAssessment,
783
+ description: parsed.description
784
+ };
785
+ for (const key of OPTIONAL_DRAFT_KEYS) {
786
+ const raw = parsed[key];
787
+ if (typeof raw === "string" && raw.trim().length > 0) {
788
+ draft[key] = raw;
789
+ }
790
+ }
791
+ return draft;
792
+ }
793
+ function extractCompletionJson(text) {
794
+ for (const candidate of completionJsonCandidates(text)) {
795
+ for (const variant of [
796
+ candidate,
797
+ stripTrailingCommas(candidate),
798
+ escapeRawControlCharsInStrings(candidate),
799
+ escapeRawControlCharsInStrings(stripTrailingCommas(candidate))
800
+ ]) {
801
+ try {
802
+ const parsed = JSON.parse(variant);
803
+ if (isEpicRequestDraft(parsed))
804
+ return toDraft(parsed);
805
+ } catch {
806
+ }
807
+ }
808
+ }
809
+ return null;
810
+ }
811
+ function looksLikeCompletionAttempt(text) {
812
+ const hasObject = /```(?:json)?\s*\{/i.test(text) || text.trim().startsWith("{");
813
+ if (!hasObject)
814
+ return false;
815
+ return /"(?:done|title|problemStatement|proposedSolution|impactAssessment|description)"\s*:/i.test(text);
816
+ }
817
+ var TARGET_COMPLIANCE_TIER, OPTIONAL_DRAFT_KEYS, COMPLETION_REPAIR_INSTRUCTION;
818
+ var init_interview_completion = __esm({
819
+ "../shared/dist/interview-completion.js"() {
820
+ "use strict";
821
+ TARGET_COMPLIANCE_TIER = "pass";
822
+ OPTIONAL_DRAFT_KEYS = [
823
+ "successMetrics",
824
+ "targetAudience",
825
+ "alternatives",
826
+ "dependencies",
827
+ "estimatedEffort"
828
+ ];
829
+ COMPLETION_REPAIR_INSTRUCTION = 'Your last message looked like a completion but I could NOT parse it as a valid JSON object with all required fields. Re-emit ONLY a single valid JSON object inside a ```json code fence \u2014 no other text \u2014 with every string value properly escaped (escape any internal double-quotes as \\" and any line breaks as \\n), and make sure title, problemStatement, proposedSolution, impactAssessment, and description are all present and non-empty:\n```json\n{"done": true, "title": "...", "problemStatement": "...", "proposedSolution": "...", "impactAssessment": "...", "description": "..."}\n```';
830
+ }
831
+ });
832
+
634
833
  // ../shared/dist/index.js
635
834
  var dist_exports = {};
636
835
  __export(dist_exports, {
836
+ AI_PROVIDERS: () => AI_PROVIDERS,
637
837
  APPEND_DESCRIPTION_MAX: () => APPEND_DESCRIPTION_MAX,
838
+ COMPLETION_REPAIR_INSTRUCTION: () => COMPLETION_REPAIR_INSTRUCTION,
638
839
  DESCRIPTION_MAX: () => DESCRIPTION_MAX,
639
840
  INTERVIEW_DEFINITION: () => INTERVIEW_DEFINITION,
640
841
  INTERVIEW_FIELD_MIN_WORDS: () => INTERVIEW_FIELD_MIN_WORDS,
@@ -649,10 +850,15 @@ __export(dist_exports, {
649
850
  SUBSCRIPTION_STATUSES: () => SUBSCRIPTION_STATUSES,
650
851
  SUMMARY_MAX: () => SUMMARY_MAX,
651
852
  SessionEventType: () => SessionEventType,
853
+ TARGET_COMPLIANCE_TIER: () => TARGET_COMPLIANCE_TIER,
652
854
  TURN_ROLES: () => TURN_ROLES,
653
855
  agentSchema: () => agentSchema,
856
+ aiProviderValues: () => aiProviderValues,
857
+ aiRouteValues: () => aiRouteValues,
858
+ buildAuditFeedback: () => buildAuditFeedback,
654
859
  buildInterviewSystemPrompt: () => buildInterviewSystemPrompt,
655
860
  err: () => err,
861
+ extractCompletionJson: () => extractCompletionJson,
656
862
  getAnthropicProxyUrl: () => getAnthropicProxyUrl,
657
863
  getModelById: () => getModelById,
658
864
  getModelDisplayName: () => getModelDisplayName,
@@ -675,8 +881,10 @@ __export(dist_exports, {
675
881
  isSubscriptionStatus: () => isSubscriptionStatus,
676
882
  isTurnRole: () => isTurnRole,
677
883
  isValidModelId: () => isValidModelId,
884
+ looksLikeCompletionAttempt: () => looksLikeCompletionAttempt,
678
885
  mcpConfigSchema: () => mcpConfigSchema,
679
886
  mcpServerConfigSchema: () => mcpServerConfigSchema,
887
+ meetsComplianceTarget: () => meetsComplianceTarget,
680
888
  modelRecommendationSourceValues: () => modelRecommendationSourceValues,
681
889
  normalizeGitRemote: () => normalizeGitRemote,
682
890
  ok: () => ok,
@@ -696,9 +904,11 @@ var init_dist = __esm({
696
904
  init_types();
697
905
  init_utils();
698
906
  init_skill_packs();
907
+ init_ai_providers();
699
908
  init_model_catalog();
700
909
  init_pxpipe();
701
910
  init_interview_definition();
911
+ init_interview_completion();
702
912
  }
703
913
  });
704
914
 
@@ -1182,6 +1392,16 @@ var ApiClient = class {
1182
1392
  input
1183
1393
  );
1184
1394
  }
1395
+ /**
1396
+ * Resolve (clear) a blocker on a feature - inverse of reportFeatureBlocker
1397
+ */
1398
+ async resolveFeatureBlocker(featureId, input) {
1399
+ return this.request(
1400
+ "POST",
1401
+ `/api/v1/features/${encodeURIComponent(featureId)}/progress/unblock`,
1402
+ input
1403
+ );
1404
+ }
1185
1405
  /**
1186
1406
  * Start work on a task - sets status to "In Progress" and records start time
1187
1407
  */
@@ -1222,6 +1442,16 @@ var ApiClient = class {
1222
1442
  input
1223
1443
  );
1224
1444
  }
1445
+ /**
1446
+ * Resolve (clear) a blocker on a task - inverse of reportTaskBlocker
1447
+ */
1448
+ async resolveTaskBlocker(taskId, input) {
1449
+ return this.request(
1450
+ "POST",
1451
+ `/api/v1/tasks/${encodeURIComponent(taskId)}/progress/unblock`,
1452
+ input
1453
+ );
1454
+ }
1225
1455
  // ---------------------------------------------------------------------------
1226
1456
  // Structured Description Methods
1227
1457
  // ---------------------------------------------------------------------------
@@ -6588,7 +6818,7 @@ function registerProgressTools(server2) {
6588
6818
  server2.registerTool(
6589
6819
  "compbox__manage_progress",
6590
6820
  {
6591
- description: "Manage progress tracking for features and tasks using a unified interface. This composite tool consolidates 4 progress operations into a single tool with action-based routing.\n\nActions:\n- 'start_work': Begin working on an item (sets status to In Progress)\n- 'complete_work': Mark an item as complete (sets status to Done)\n- 'log_progress': Record progress without changing status\n- 'report_blocker': Report that an item is blocked\n\nUse this instead of the individual progress tools for a more streamlined workflow.",
6821
+ description: "Manage progress tracking for features and tasks using a unified interface. This composite tool consolidates 5 progress operations into a single tool with action-based routing.\n\nActions:\n- 'start_work': Begin working on an item (sets status to In Progress)\n- 'complete_work': Mark an item as complete (sets status to Done)\n- 'log_progress': Record progress without changing status\n- 'report_blocker': Report that an item is blocked\n- 'resolve_blocker': Clear a blocker and resume the item (inverse of 'report_blocker')\n\nUse this instead of the individual progress tools for a more streamlined workflow.",
6592
6822
  inputSchema: z13.discriminatedUnion("action", [
6593
6823
  z13.object({
6594
6824
  action: z13.literal("start_work"),
@@ -6618,6 +6848,14 @@ function registerProgressTools(server2) {
6618
6848
  reason: z13.string().min(1).max(5e3).describe("Description of what is blocking progress"),
6619
6849
  blockedById: z13.string().uuid().optional().describe("Optional UUID of the blocking item"),
6620
6850
  sessionId: z13.string().max(255).optional().describe("Optional AI session identifier")
6851
+ }),
6852
+ z13.object({
6853
+ action: z13.literal("resolve_blocker"),
6854
+ id: z13.string().describe("Feature or task identifier (UUID or human-readable like 'COM-123')"),
6855
+ type: z13.enum(["feature", "task"]).describe("Whether this is a 'feature' or 'task'"),
6856
+ resolution: z13.string().min(1).max(5e3).describe("Description of how the blocker was resolved"),
6857
+ unblockedFromId: z13.string().uuid().optional().describe("Optional UUID of the blocking item to drop from this item's dependencies"),
6858
+ sessionId: z13.string().max(255).optional().describe("Optional AI session identifier")
6621
6859
  })
6622
6860
  ])
6623
6861
  },
@@ -6695,6 +6933,25 @@ function registerProgressTools(server2) {
6695
6933
  return createResponse(result);
6696
6934
  }
6697
6935
  }
6936
+ case "resolve_blocker": {
6937
+ if (input.type === "feature") {
6938
+ const { data: feature } = await apiClient.getFeature(input.id);
6939
+ const { data: result } = await apiClient.resolveFeatureBlocker(feature.id, {
6940
+ resolution: input.resolution,
6941
+ unblockedFromId: input.unblockedFromId,
6942
+ sessionId: input.sessionId
6943
+ });
6944
+ return createResponse(result);
6945
+ } else {
6946
+ const { data: task } = await apiClient.getTask(input.id);
6947
+ const { data: result } = await apiClient.resolveTaskBlocker(task.id, {
6948
+ resolution: input.resolution,
6949
+ unblockedFromId: input.unblockedFromId,
6950
+ sessionId: input.sessionId
6951
+ });
6952
+ return createResponse(result);
6953
+ }
6954
+ }
6698
6955
  }
6699
6956
  } catch (error) {
6700
6957
  if (error instanceof ApiError && error.status === 404) {
@@ -10832,7 +11089,7 @@ function withLegacyToolCallRewrite(transport) {
10832
11089
  var SERVER_NAME = "compbox-mcp";
10833
11090
  function resolveServerVersion() {
10834
11091
  if (true) {
10835
- return "1.17.2";
11092
+ return "1.19.0";
10836
11093
  }
10837
11094
  const require2 = createRequire(import.meta.url);
10838
11095
  for (const candidate of ["../package.json", "./package.json"]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mycompbox/compbox-mcp",
3
- "version": "1.17.2",
3
+ "version": "1.19.0",
4
4
  "description": "CompBox MCP server - Uses HTTP API client (no direct database access)",
5
5
  "license": "MIT",
6
6
  "type": "module",