@bridge_gpt/mcp-server 0.2.29 → 0.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/build/agent-registry.js +0 -5
- package/build/commands.generated.js +2 -2
- package/build/conductor-bin.js +1 -1
- package/build/index.js +37 -16
- package/build/install-bridge.js +87 -83
- package/build/readme.generated.js +1 -1
- package/build/start-tickets.js +14 -19
- package/build/version.generated.js +1 -1
- package/package.json +2 -2
package/build/install-bridge.js
CHANGED
|
@@ -150,18 +150,27 @@ export function buildPrewarmCommandPreview() {
|
|
|
150
150
|
* (`maybe_auto_parse_if_ready`), with no prompt on any path.
|
|
151
151
|
*/
|
|
152
152
|
export const INSTALL_BRIDGE_AGENT_PROMPT = "Execute the /install-bridge command in the install-spawn context (tell the command it is running " +
|
|
153
|
-
"in the install-spawn context so it SKIPS its Stage 8, Stage 9, and Stage 10 offers
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
153
|
+
"in the install-spawn context so it SKIPS its Stage 8, Stage 9, and Stage 10 offers). " +
|
|
154
|
+
"The command chooses its own mode from the install manifest's `configured` flag — do NOT force a " +
|
|
155
|
+
"mode: when `configured` is false it runs its fresh-configuration flow, and when `configured` is " +
|
|
156
|
+
"true it runs JOIN MODE. In JOIN MODE the command must NOT derive, approve, apply, or offer any " +
|
|
157
|
+
"configuration and applies zero fields for any caller; a joining member's only closing interaction " +
|
|
158
|
+
"is the welcome plus the concise capability report (no /learn-repository prompt for a member). " +
|
|
159
|
+
"Complete the command's concise capability report: the single 'What Bridge " +
|
|
157
160
|
"can help with' section, rendered exactly as the server's concise_tool_capabilities field gives it " +
|
|
158
161
|
"(Regularly useful, then Occasionally useful, each tool's display_name only, plus each tier's " +
|
|
159
162
|
"server-computed '+N more' where non-zero). Do not render the obsolete five-section report, and do " +
|
|
160
163
|
"not locally filter, count, or fall back to the complete tool_capabilities catalog. " +
|
|
164
|
+
"The install-spawn skip set is exactly Stage 8, Stage 9, and Stage 10. The command-owned Stage 11 " +
|
|
165
|
+
"(invite teammates) is NOT in that skip set: it is independently gated and may run only when the " +
|
|
166
|
+
"caller's role is admin AND customer_type is b2b AND an interactive response is available; " +
|
|
167
|
+
"otherwise it is skipped silently. If Stage 11 mints a teammate key, show that plaintext key " +
|
|
168
|
+
"exactly once and never repeat it in any summary, retry, or diagnostic. " +
|
|
161
169
|
"Do NOT ask any indexing question, call parse_repository, mention /parse-repository, or claim " +
|
|
162
170
|
"indexing has started or is pending — indexing is decided entirely by the server-side readiness " +
|
|
163
171
|
"funnel with no visibility from this session, so say nothing about it at all. " +
|
|
164
|
-
"After the capability report, recommend /learn-repository as the
|
|
172
|
+
"After the capability report on the fresh-configuration path, recommend /learn-repository as the " +
|
|
173
|
+
"next step: explain briefly that it " +
|
|
165
174
|
"learns repository-specific architecture, review, testing, correctness, and validation-manual " +
|
|
166
175
|
"configuration by researching the actual codebase. Do NOT run /learn-repository yourself — only " +
|
|
167
176
|
"recommend it; running it is the human's next explicit invocation. " +
|
|
@@ -169,9 +178,11 @@ export const INSTALL_BRIDGE_AGENT_PROMPT = "Execute the /install-bridge command
|
|
|
169
178
|
"integration's own configure_in pointer, verbatim. The pointer is per-integration and is NOT " +
|
|
170
179
|
"always the setup UI: GitHub's is a terminal command (connect-github), while Jira, SFCC, and " +
|
|
171
180
|
"Bitbucket point at the setup UI. Follow whatever the report says rather than assuming. " +
|
|
172
|
-
"
|
|
181
|
+
"On the fresh-configuration path, end with an explicit summary line stating how many config fields " +
|
|
182
|
+
"the apply_install_manifest call " +
|
|
173
183
|
"applied (e.g. 'Applied 8 of 9 derived fields') — if 0 fields were applied, say so loudly and " +
|
|
174
|
-
"explain what is still pending."
|
|
184
|
+
"explain what is still pending. In JOIN MODE there is no apply — state instead that the project " +
|
|
185
|
+
"was already configured and zero changes were made, without a fabricated applied count.";
|
|
175
186
|
/** Default base URL when `BAPI_BASE_URL` is unset (mirrors index.ts). */
|
|
176
187
|
export const DEFAULT_BAPI_BASE_URL = "https://bridgegpt-api.com";
|
|
177
188
|
/** Default docs dir when `BAPI_DOCS_DIR` is unset (mirrors index.ts). */
|
|
@@ -185,10 +196,13 @@ export function getInstallBridgeUsage() {
|
|
|
185
196
|
"One-command Bridge API project bootstrap. Scaffolds the project, writes the",
|
|
186
197
|
"per-host MCP config with your credentials, verifies connectivity, persists the",
|
|
187
198
|
"routing credential, then — on a TTY, only after a Y/N consent prompt — opens a",
|
|
188
|
-
"fresh session in your selected tool
|
|
189
|
-
"
|
|
190
|
-
"
|
|
191
|
-
"
|
|
199
|
+
"fresh session in your selected tool. If the project is not yet configured it",
|
|
200
|
+
"derives the remaining config, presents a concise capability report, and",
|
|
201
|
+
"recommends /learn-repository. If the project is already configured it instead",
|
|
202
|
+
"joins you to it without proposing or applying any changes and just shows the",
|
|
203
|
+
"concise capability report (a b2b admin is additionally offered a teammate-invite",
|
|
204
|
+
"step). So not every run applies config fields. Indexing is never asked about —",
|
|
205
|
+
"it starts automatically once the repository reaches full parse readiness.",
|
|
192
206
|
"",
|
|
193
207
|
"Run it bare — `install-bridge` with no flags — in a terminal and it asks",
|
|
194
208
|
`\`${INSTALL_BRIDGE_KEY_SELECTOR_PROMPT.trim()}\` first. Answer yes (or press Enter) for the`,
|
|
@@ -261,10 +275,12 @@ export function getInstallBridgeUsage() {
|
|
|
261
275
|
` ${HOST_PLATFORM_ORDER.join(", ")}.`,
|
|
262
276
|
" Both --tools=claude-code,codex and",
|
|
263
277
|
" --tools claude-code,codex are accepted. On an",
|
|
264
|
-
" interactive terminal WITHOUT this flag
|
|
265
|
-
"
|
|
266
|
-
" (
|
|
267
|
-
"
|
|
278
|
+
" interactive terminal WITHOUT this flag you get a",
|
|
279
|
+
" numbered picker: enter one or more tool numbers,",
|
|
280
|
+
" comma-separated (e.g. 1,3), and press Enter once —",
|
|
281
|
+
" no tool is pre-selected (not even Claude Code) and",
|
|
282
|
+
" you must select at least one. A non-interactive",
|
|
283
|
+
" (non-TTY) run without",
|
|
268
284
|
" --tools writes the legacy automatic set (Claude",
|
|
269
285
|
" Code plus any detected Cursor / Copilot VS Code)",
|
|
270
286
|
" and never opens an agent terminal (it prints",
|
|
@@ -1009,88 +1025,78 @@ export async function resolveRepoName(options, deps, mode = "existing-registrati
|
|
|
1009
1025
|
/** A per-host MCP config target (mirrors runInit's configTargets shape). */
|
|
1010
1026
|
/** Stable wording of the interactive tool-selection prompt (BAPI-635). */
|
|
1011
1027
|
export const INSTALL_BRIDGE_TOOL_SELECTOR_PROMPT = "Which AI coding tools do you use on this project?";
|
|
1028
|
+
/** A one-based selection token is exactly one or more digits, no sign/decimal/leading-zero. */
|
|
1029
|
+
const SELECTION_TOKEN_PATTERN = /^[1-9][0-9]*$/;
|
|
1012
1030
|
/**
|
|
1013
|
-
* Interactive numbered
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1031
|
+
* Interactive single-shot numbered picker on stderr (TTY only). Renders the
|
|
1032
|
+
* heading and each option exactly once, then accepts ONE strict
|
|
1033
|
+
* comma-separated line of one-based numbers and resolves immediately — there
|
|
1034
|
+
* is no preselected/toggle state and no separate confirmation step (BAPI-663).
|
|
1035
|
+
*
|
|
1036
|
+
* A blank line or a line containing any invalid token (non-numeric, zero,
|
|
1037
|
+
* signed, leading-zero, decimal, out-of-range) is rejected atomically — the
|
|
1038
|
+
* whole line is discarded, one error line is printed, and the picker
|
|
1039
|
+
* re-prompts without re-rendering the option list. A valid line is
|
|
1040
|
+
* deduplicated and returned in `options` order regardless of entry order.
|
|
1041
|
+
*
|
|
1042
|
+
* Resolves to `[]` on EOF / synchronous close before any line has been
|
|
1043
|
+
* committed, so a readline regression can never hang. Returns `[]`
|
|
1044
|
+
* immediately, without creating a readline interface, when `options` is
|
|
1045
|
+
* empty.
|
|
1021
1046
|
*/
|
|
1022
|
-
export function promptMultiSelectViaReadline(promptText, options,
|
|
1047
|
+
export function promptMultiSelectViaReadline(promptText, options, input = process.stdin, output = process.stderr) {
|
|
1048
|
+
if (options.length === 0)
|
|
1049
|
+
return Promise.resolve([]);
|
|
1023
1050
|
return new Promise((resolve) => {
|
|
1024
|
-
const selected = new Set(defaults);
|
|
1025
|
-
const render = () => {
|
|
1026
|
-
output.write(`\n${promptText}\n`);
|
|
1027
|
-
output.write("[x] = selected · [ ] = not selected\n");
|
|
1028
|
-
options.forEach((opt, idx) => {
|
|
1029
|
-
const mark = selected.has(opt.id) ? "[x]" : "[ ]";
|
|
1030
|
-
output.write(` ${idx + 1}. ${mark} ${opt.label}\n`);
|
|
1031
|
-
});
|
|
1032
|
-
output.write("Type numbers to toggle, e.g. 1,3 — then Enter.\n");
|
|
1033
|
-
output.write("Press Enter on an empty line to confirm — re-typing a number un-selects it.\n");
|
|
1034
|
-
output.write("Enter numbers to toggle (comma-separated), or press Enter to accept: ");
|
|
1035
|
-
};
|
|
1036
1051
|
const rl = readline.createInterface({ input, output });
|
|
1037
|
-
let
|
|
1038
|
-
const finish = () => {
|
|
1039
|
-
|
|
1052
|
+
let settled = false;
|
|
1053
|
+
const finish = (result) => {
|
|
1054
|
+
if (settled)
|
|
1055
|
+
return;
|
|
1056
|
+
settled = true;
|
|
1040
1057
|
rl.close();
|
|
1041
|
-
resolve(
|
|
1058
|
+
resolve(result);
|
|
1042
1059
|
};
|
|
1043
1060
|
// EOF / synchronous close must resolve rather than deadlock the top-level
|
|
1044
|
-
// await; `
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1061
|
+
// await; the `settled` guard stops a synchronous `close` (fired by `rl.close()`
|
|
1062
|
+
// above) from replacing an already-committed answer with the EOF fallback.
|
|
1063
|
+
rl.on("close", () => finish([]));
|
|
1064
|
+
output.write(`\n${promptText}\n`);
|
|
1065
|
+
options.forEach((opt, idx) => {
|
|
1066
|
+
output.write(` ${idx + 1}. ${opt.label}\n`);
|
|
1048
1067
|
});
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
rl.question("", (answer) => {
|
|
1068
|
+
output.write("Enter the number(s) of the tools you use (e.g. 1,3), then Enter.\n");
|
|
1069
|
+
const prompt = () => {
|
|
1070
|
+
rl.question("> ", (answer) => {
|
|
1052
1071
|
const trimmed = answer.trim();
|
|
1053
1072
|
if (trimmed.length === 0) {
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
// still resolves the current — possibly empty — set so input can never hang.
|
|
1057
|
-
if (selected.size === 0) {
|
|
1058
|
-
output.write("Select at least one tool.\n");
|
|
1059
|
-
ask();
|
|
1060
|
-
return;
|
|
1061
|
-
}
|
|
1062
|
-
finish();
|
|
1073
|
+
output.write("Select at least one tool.\n");
|
|
1074
|
+
prompt();
|
|
1063
1075
|
return;
|
|
1064
1076
|
}
|
|
1065
1077
|
const tokens = trimmed.split(",").map((t) => t.trim());
|
|
1066
|
-
const
|
|
1067
|
-
let bad = false;
|
|
1078
|
+
const indices = [];
|
|
1068
1079
|
for (const tok of tokens) {
|
|
1080
|
+
if (!SELECTION_TOKEN_PATTERN.test(tok)) {
|
|
1081
|
+
output.write(`Invalid selection. Enter numbers between 1 and ${options.length}.\n`);
|
|
1082
|
+
prompt();
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1069
1085
|
const n = Number(tok);
|
|
1070
|
-
if (
|
|
1071
|
-
|
|
1072
|
-
|
|
1086
|
+
if (n < 1 || n > options.length) {
|
|
1087
|
+
output.write(`Invalid selection. Enter numbers between 1 and ${options.length}.\n`);
|
|
1088
|
+
prompt();
|
|
1089
|
+
return;
|
|
1073
1090
|
}
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1076
|
-
if (bad) {
|
|
1077
|
-
output.write(`Invalid selection. Enter numbers between 1 and ${options.length}.\n`);
|
|
1078
|
-
ask();
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
for (const n of nums) {
|
|
1082
|
-
const opt = options[n - 1];
|
|
1083
|
-
if (selected.has(opt.id))
|
|
1084
|
-
selected.delete(opt.id);
|
|
1085
|
-
else
|
|
1086
|
-
selected.add(opt.id);
|
|
1091
|
+
indices.push(n);
|
|
1087
1092
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1093
|
+
const chosen = new Set(indices);
|
|
1094
|
+
finish(options
|
|
1095
|
+
.filter((_, idx) => chosen.has(idx + 1))
|
|
1096
|
+
.map((o) => o.id));
|
|
1091
1097
|
});
|
|
1092
1098
|
};
|
|
1093
|
-
|
|
1099
|
+
prompt();
|
|
1094
1100
|
});
|
|
1095
1101
|
}
|
|
1096
1102
|
/**
|
|
@@ -1110,13 +1116,11 @@ export async function resolveSelectedHostPlatforms(deps, options) {
|
|
|
1110
1116
|
}
|
|
1111
1117
|
const ctx = await buildDetectionContext(deps);
|
|
1112
1118
|
const detected = new Set(detectDefaultPlatforms(ctx));
|
|
1113
|
-
// 2. Interactive
|
|
1114
|
-
// picker
|
|
1115
|
-
// inclusion and detected-platform seeding) and requires an explicit selection.
|
|
1119
|
+
// 2. Interactive single-shot numbered picker on a TTY. No row is pre-selected
|
|
1120
|
+
// — the picker has no default state and requires an explicit selection.
|
|
1116
1121
|
if (deps.isTTY && deps.promptMultiSelect) {
|
|
1117
1122
|
const optionList = allHostTargets().map((t) => ({ id: t.id, label: t.label }));
|
|
1118
|
-
const
|
|
1119
|
-
const chosen = await deps.promptMultiSelect(INSTALL_BRIDGE_TOOL_SELECTOR_PROMPT, optionList, defaults);
|
|
1123
|
+
const chosen = await deps.promptMultiSelect(INSTALL_BRIDGE_TOOL_SELECTOR_PROMPT, optionList);
|
|
1120
1124
|
return HOST_PLATFORM_ORDER.filter((id) => chosen.includes(id));
|
|
1121
1125
|
}
|
|
1122
1126
|
// 3. Legacy non-TTY automatic set: Claude + detected Cursor / Copilot VS Code.
|