@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.
- package/index.js +260 -3
- 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
|
|
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.
|
|
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"]) {
|