@bridge_gpt/mcp-server 0.1.16 → 0.1.17
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 +36 -1
- package/build/agent-launchers/claude.js +85 -0
- package/build/agent-launchers/index.js +17 -0
- package/build/agent-launchers/types.js +1 -0
- package/build/chain-orchestrator.js +1150 -0
- package/build/chain-utils.js +68 -0
- package/build/commands.generated.js +3 -1
- package/build/fetch-stub.js +139 -0
- package/build/index.js +137 -10
- package/build/pipeline-orchestrator.js +57 -0
- package/build/pipelines.generated.js +132 -3
- package/build/schedule-run.js +951 -0
- package/build/schedule-store.js +132 -0
- package/build/scheduler-backends/at-fallback.js +144 -0
- package/build/scheduler-backends/escaping.js +113 -0
- package/build/scheduler-backends/index.js +72 -0
- package/build/scheduler-backends/launchd.js +216 -0
- package/build/scheduler-backends/systemd-user.js +237 -0
- package/build/scheduler-backends/task-scheduler.js +219 -0
- package/build/scheduler-backends/types.js +23 -0
- package/build/start-tickets.js +119 -59
- package/build/version.generated.js +1 -1
- package/package.json +7 -7
- package/pipelines/full-automation.json +47 -0
- package/pipelines/idea-to-ticket.json +71 -0
- package/smoke-test/SMOKE-TEST.md +509 -0
- package/smoke-test/smoke-test-mcp.md +23 -0
package/README.md
CHANGED
|
@@ -47,7 +47,8 @@ npx -y @bridge_gpt/mcp-server start-tickets [flags] KEY [KEY ...]
|
|
|
47
47
|
| `--terminal terminal\|iterm` | auto-detect via `$TERM_PROGRAM` | Override the macOS terminal app (honored on macOS only) |
|
|
48
48
|
| `--dry-run` | off | Print intended actions; create no worktrees, open no tabs (any OS) |
|
|
49
49
|
| `--branch KEY=BRANCH` | `feature/<KEY>` | Use a custom branch for that ticket (repeatable) |
|
|
50
|
-
| `--
|
|
50
|
+
| `--base-branch <BRANCH>` | `main` | Cut new worktrees from `<BRANCH>` and refresh `origin/<BRANCH>` instead of `main` |
|
|
51
|
+
| `--no-refresh-main` | off (the configured base branch is refreshed) | Skip refresh of the configured base branch (default `main`). Historical flag name preserved for backward compatibility — despite the name, it now skips refresh of whatever `--base-branch` resolves to. |
|
|
51
52
|
| `--max-parallel N` | `3` | Max worktrees created concurrently |
|
|
52
53
|
| `-h`, `--help` | — | Show usage |
|
|
53
54
|
|
|
@@ -244,6 +245,40 @@ Commands are slash commands you invoke from your AI assistant's chat. Most orche
|
|
|
244
245
|
|
|
245
246
|
> Commands are designed for Claude Code. Other editors may support slash commands differently — check your editor's documentation for how to invoke prompt files.
|
|
246
247
|
|
|
248
|
+
## Smoke testing
|
|
249
|
+
|
|
250
|
+
The package ships a canonical, **opt-in** in-host smoke-test runbook at
|
|
251
|
+
`smoke-test/SMOKE-TEST.md`. An AI agent running inside your host (Claude Code,
|
|
252
|
+
Cursor, Codex, Windsurf, or VS Code/Copilot) executes it to verify that the MCP
|
|
253
|
+
server actually works end-to-end *inside that host* — it calls the real tools and
|
|
254
|
+
records a PASS/FAIL verdict for each one in a markdown report.
|
|
255
|
+
|
|
256
|
+
- `smoke-test/SMOKE-TEST.md` **ships with the npm package** and is the
|
|
257
|
+
**canonical** source of truth for the smoke test.
|
|
258
|
+
- The smoke test **adds no MCP tool** and **does not change the registered
|
|
259
|
+
tool surface** (the server still registers its existing 51 tools).
|
|
260
|
+
- It is **opt-in**: default `--init` **does not scaffold `/smoke-test-mcp`**, so
|
|
261
|
+
consumer command palettes are not polluted.
|
|
262
|
+
|
|
263
|
+
### Running it
|
|
264
|
+
|
|
265
|
+
You have two options:
|
|
266
|
+
|
|
267
|
+
1. **Copy the opt-in command manually.** Copy the packaged command stub into your
|
|
268
|
+
host's command directory, then invoke `/smoke-test-mcp`:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Claude Code
|
|
272
|
+
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .claude/commands/smoke-test-mcp.md
|
|
273
|
+
# Cursor
|
|
274
|
+
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .cursor/commands/smoke-test-mcp.md
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
2. **Open the runbook directly.** Alternatively, open
|
|
278
|
+
`smoke-test/SMOKE-TEST.md` and ask the host agent to execute it.
|
|
279
|
+
|
|
280
|
+
Reports are written to `<BAPI_DOCS_DIR>/smoke-test/REPORT-<host>-<timestamp>.md`.
|
|
281
|
+
|
|
247
282
|
## Available Tools
|
|
248
283
|
|
|
249
284
|
MCP tools are the low-level primitives Bridge exposes to your AI assistant. You don't call them directly — ask your AI assistant to perform the task you need, or compose them into a custom pipeline.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The v1 `claude` agent launcher (BAPI-327).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the `claude` binary against the *baked schedule-time PATH* (not the
|
|
5
|
+
* ambient process default), builds the locked
|
|
6
|
+
* `/full-automation --scheduled-at <T> --idea-file <abs> [--auto-approve]`
|
|
7
|
+
* prompt, and emits `{ exe, args: ["-p", prompt] }`. Claude Code has no
|
|
8
|
+
* working-directory flag, so the cwd is always set by the scheduler unit — this
|
|
9
|
+
* adapter must never add a cwd argument to the invocation.
|
|
10
|
+
*/
|
|
11
|
+
import { pathApiForPlatform } from "../scheduler-backends/types.js";
|
|
12
|
+
import { posixShellQuote, windowsCmdQuote } from "../scheduler-backends/escaping.js";
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a bare command to an absolute path using the platform PATH-probe,
|
|
15
|
+
* forcing the baked PATH so the schedule resolves the same binary the user had
|
|
16
|
+
* at creation time. On Windows both `PATH` and `Path` are overridden (Node and
|
|
17
|
+
* `where.exe` disagree on casing). Returns the first non-empty *absolute* path
|
|
18
|
+
* from stdout, or `null` when the probe fails or yields only relative paths.
|
|
19
|
+
*/
|
|
20
|
+
export async function resolveCommandOnPath(command, envPath, deps) {
|
|
21
|
+
const pathApi = pathApiForPlatform(deps.platform);
|
|
22
|
+
const probe = deps.platform === "win32" ? "where.exe" : "which";
|
|
23
|
+
const env = { ...deps.env, PATH: envPath };
|
|
24
|
+
if (deps.platform === "win32") {
|
|
25
|
+
// Windows env var lookup is case-insensitive but Node preserves the literal
|
|
26
|
+
// key; override both casings so neither the probe nor child sees a stale one.
|
|
27
|
+
env.Path = envPath;
|
|
28
|
+
}
|
|
29
|
+
const result = await deps.runCommand(probe, [command], { env });
|
|
30
|
+
if (result.exitCode !== 0)
|
|
31
|
+
return null;
|
|
32
|
+
const candidate = result.stdout
|
|
33
|
+
.split(/\r?\n/)
|
|
34
|
+
.map((line) => line.trim())
|
|
35
|
+
.find((line) => line.length > 0);
|
|
36
|
+
if (!candidate)
|
|
37
|
+
return null;
|
|
38
|
+
if (!pathApi.isAbsolute(candidate))
|
|
39
|
+
return null;
|
|
40
|
+
return pathApi.normalize(candidate);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Quote the idea-file path so it survives as a single `/full-automation`
|
|
44
|
+
* argument even when it contains spaces or markup-significant characters
|
|
45
|
+
* (`&`, `<`, `>`, …) that would otherwise be split or mangled when the slash
|
|
46
|
+
* command is parsed. Only an embedded double quote needs escaping; the same
|
|
47
|
+
* absolute path is additionally baked into `BRIDGE_GPT_IDEA_FILE` by every
|
|
48
|
+
* backend as a robust environment fallback.
|
|
49
|
+
*/
|
|
50
|
+
export function quoteIdeaFileForPrompt(ideaFile) {
|
|
51
|
+
return `"${ideaFile.replace(/"/g, '\\"')}"`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the exact full-automation prompt. `--auto-approve` is appended by
|
|
55
|
+
* default; it is omitted only when the caller selected `--no-auto-approve`.
|
|
56
|
+
*/
|
|
57
|
+
export function buildClaudePrompt(input) {
|
|
58
|
+
const base = `/full-automation --scheduled-at ${input.runAtIso} ` +
|
|
59
|
+
`--idea-file ${quoteIdeaFileForPrompt(input.ideaFile)}`;
|
|
60
|
+
return input.autoApprove ? `${base} --auto-approve` : base;
|
|
61
|
+
}
|
|
62
|
+
const CLAUDE_CAPABILITY = {
|
|
63
|
+
name: "claude",
|
|
64
|
+
command: "claude",
|
|
65
|
+
supportsCwdFlag: false,
|
|
66
|
+
promptFlag: "-p",
|
|
67
|
+
};
|
|
68
|
+
/** Create the v1 Claude agent launcher. */
|
|
69
|
+
export function createClaudeLauncher() {
|
|
70
|
+
return {
|
|
71
|
+
capability: CLAUDE_CAPABILITY,
|
|
72
|
+
resolveBinary(envPath, deps) {
|
|
73
|
+
return resolveCommandOnPath("claude", envPath, deps);
|
|
74
|
+
},
|
|
75
|
+
buildInvocation(exe, input) {
|
|
76
|
+
const prompt = buildClaudePrompt(input);
|
|
77
|
+
// No working-directory flag: cwd is owned by the scheduler unit.
|
|
78
|
+
return { exe, args: [CLAUDE_CAPABILITY.promptFlag, prompt], prompt };
|
|
79
|
+
},
|
|
80
|
+
formatInvocationLine(invocation, platform) {
|
|
81
|
+
const quote = platform === "win32" ? windowsCmdQuote : posixShellQuote;
|
|
82
|
+
return [invocation.exe, ...invocation.args].map((part) => quote(part)).join(" ");
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-launcher registry (BAPI-327). v1 ships only `claude`; the lookup returns
|
|
3
|
+
* `null` for every other name so the CLI can reject unsupported agents with a
|
|
4
|
+
* clear message rather than silently falling back.
|
|
5
|
+
*/
|
|
6
|
+
import { createClaudeLauncher } from "./claude.js";
|
|
7
|
+
export { createClaudeLauncher } from "./claude.js";
|
|
8
|
+
const CLAUDE_LAUNCHER = createClaudeLauncher();
|
|
9
|
+
/** Return the launcher for a name, or `null` when unsupported in v1. */
|
|
10
|
+
export function getAgentLauncher(name) {
|
|
11
|
+
return name === "claude" ? CLAUDE_LAUNCHER : null;
|
|
12
|
+
}
|
|
13
|
+
/** Comma-separated list of valid agent-launcher names (just `claude` in v1). */
|
|
14
|
+
export function formatValidAgentLauncherNames() {
|
|
15
|
+
const names = ["claude"];
|
|
16
|
+
return names.join(", ");
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|