@raysonmeng/agentbridge 0.1.6 → 0.1.8
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +53 -6
- package/README.zh-CN.md +37 -1
- package/dist/cli.js +3983 -440
- package/dist/daemon.js +4713 -0
- package/package.json +18 -5
- package/plugins/agentbridge/.claude-plugin/plugin.json +1 -1
- package/plugins/agentbridge/README.md +2 -2
- package/plugins/agentbridge/scripts/health-check.sh +22 -3
- package/plugins/agentbridge/scripts/plugin-update-notice.mjs +73 -0
- package/plugins/agentbridge/server/bridge-server.js +1170 -142
- package/plugins/agentbridge/server/daemon.js +2690 -358
- package/scripts/install-safety.cjs +209 -0
- package/scripts/postinstall.cjs +114 -34
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raysonmeng/agentbridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Bridge between Claude Code and Codex — bidirectional agent communication via MCP Channel + JSON-RPC",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"packageManager": "bun@1.3.11",
|
|
7
|
+
"engines": {
|
|
8
|
+
"bun": ">=1.3.11"
|
|
9
|
+
},
|
|
6
10
|
"bin": {
|
|
7
11
|
"agentbridge": "dist/cli.js",
|
|
8
12
|
"abg": "dist/cli.js"
|
|
@@ -12,21 +16,30 @@
|
|
|
12
16
|
"plugins/",
|
|
13
17
|
".claude-plugin/",
|
|
14
18
|
"scripts/postinstall.cjs",
|
|
19
|
+
"scripts/install-safety.cjs",
|
|
15
20
|
"README.md",
|
|
16
21
|
"LICENSE"
|
|
17
22
|
],
|
|
18
23
|
"scripts": {
|
|
19
24
|
"start": "bun run src/bridge.ts",
|
|
20
|
-
"build:cli": "
|
|
21
|
-
"build:plugin": "
|
|
25
|
+
"build:cli": "node scripts/build-bundles.mjs cli daemon",
|
|
26
|
+
"build:plugin": "node scripts/build-bundles.mjs bridge-plugin daemon-plugin",
|
|
27
|
+
"smoke:built": "bun scripts/smoke-built-cli.mjs",
|
|
28
|
+
"smoke:pack": "bun scripts/smoke-pack.mjs",
|
|
22
29
|
"verify:plugin-sync": "node scripts/verify-plugin-sync.cjs",
|
|
23
30
|
"postinstall": "node scripts/postinstall.cjs",
|
|
24
|
-
"prepublishOnly": "bun run build:cli && bun run build:plugin",
|
|
31
|
+
"prepublishOnly": "bun run build:cli && bun run build:plugin && bun run verify:plugin-sync && bun scripts/check-plugin-versions.js",
|
|
25
32
|
"validate:plugin": "claude plugin validate plugins/agentbridge && claude plugin validate .claude-plugin/marketplace.json",
|
|
26
33
|
"test": "bun test src",
|
|
34
|
+
"e2e:transport": "bun scripts/e2e-codex-transport.mjs",
|
|
35
|
+
"install:global": "node scripts/install-global.mjs local",
|
|
36
|
+
"install:global:local": "node scripts/install-global.mjs local",
|
|
37
|
+
"install:global:npm": "node scripts/install-global.mjs npm",
|
|
38
|
+
"release:bump": "node scripts/bump-version.mjs",
|
|
27
39
|
"typecheck": "tsc --noEmit",
|
|
28
40
|
"validate:plugin-versions": "bun scripts/check-plugin-versions.js",
|
|
29
|
-
"check": "tsc --noEmit && bun test src && bun run verify:plugin-sync && bun scripts/check-plugin-versions.js"
|
|
41
|
+
"check": "tsc --noEmit && bun test src && bun run verify:plugin-sync && bun scripts/check-plugin-versions.js",
|
|
42
|
+
"ci:local": "bun run check && bun run smoke:built && bun run smoke:pack"
|
|
30
43
|
},
|
|
31
44
|
"repository": {
|
|
32
45
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AgentBridge Plugin
|
|
2
2
|
|
|
3
|
-
Claude Code plugin for AgentBridge. This plugin packages the AgentBridge MCP frontend
|
|
3
|
+
Claude Code plugin for AgentBridge. This plugin packages the AgentBridge MCP frontend with push channel delivery (a failed push falls back to an in-memory queue drained by `get_messages`), the `/agentbridge:init` command, and a non-blocking SessionStart health check.
|
|
4
4
|
|
|
5
5
|
## Structure
|
|
6
6
|
|
|
@@ -38,6 +38,6 @@ This creates self-contained bundles at:
|
|
|
38
38
|
## Notes
|
|
39
39
|
|
|
40
40
|
- The plugin frontend launches the sibling daemon bundle via `AGENTBRIDGE_DAEMON_ENTRY=./daemon.js`.
|
|
41
|
-
- Claude delivery
|
|
41
|
+
- Claude delivery is always push notifications. If a push fails, the message is queued and can be drained via `get_messages` (per-message fallback — the legacy `AGENTBRIDGE_MODE=pull` mode was removed and the env var is ignored with a one-time warning).
|
|
42
42
|
- The SessionStart hook is informational only. It never starts or stops the daemon.
|
|
43
43
|
- The command at `/agentbridge:init` edits project-local `.agentbridge/` files only; plugin installation and marketplace registration remain terminal-side tasks (`agentbridge init` / `agentbridge dev`).
|
|
@@ -9,6 +9,16 @@ cooldown_seconds="${AGENTBRIDGE_HEALTH_HOOK_COOLDOWN_SECONDS:-120}"
|
|
|
9
9
|
state_root="${AGENTBRIDGE_HOOK_STATE_DIR:-${TMPDIR:-/tmp}/agentbridge-hooks}"
|
|
10
10
|
port="${AGENTBRIDGE_CONTROL_PORT:-4502}"
|
|
11
11
|
|
|
12
|
+
# In multi-pair mode the resolver exports AGENTBRIDGE_PAIR_ID, inherited here via
|
|
13
|
+
# the SessionStart hook env. Scope the suggested commands to that pair so the
|
|
14
|
+
# user is not sent to a different (cwd-derived) pair. Guard the charset (the
|
|
15
|
+
# resolver already restricts it) so nothing unsafe is interpolated into the JSON.
|
|
16
|
+
pair_id="${AGENTBRIDGE_PAIR_ID:-}"
|
|
17
|
+
pair_arg=""
|
|
18
|
+
if printf '%s' "$pair_id" | grep -Eq '^[A-Za-z0-9._-]+$'; then
|
|
19
|
+
pair_arg=" --pair ${pair_id}"
|
|
20
|
+
fi
|
|
21
|
+
|
|
12
22
|
if ! command -v curl >/dev/null 2>&1; then
|
|
13
23
|
exit 0
|
|
14
24
|
fi
|
|
@@ -27,6 +37,15 @@ fi
|
|
|
27
37
|
|
|
28
38
|
printf '%s' "$now" >"$stamp_file" 2>/dev/null || true
|
|
29
39
|
|
|
40
|
+
# In-session plugin-update reminder: compare the INSTALLED plugin version against
|
|
41
|
+
# the latest npm version cached by the CLI notifier (src/update-notifier.ts). This
|
|
42
|
+
# is how a user who updated the npm CLI but not the plugin learns of the mismatch
|
|
43
|
+
# from inside Claude Code. Best-effort + silent: never blocks the hook.
|
|
44
|
+
plugin_notice=""
|
|
45
|
+
if command -v bun >/dev/null 2>&1 && [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
46
|
+
plugin_notice="$(bun "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-update-notice.mjs" "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json" 2>/dev/null || true)"
|
|
47
|
+
fi
|
|
48
|
+
|
|
30
49
|
health_json="$(curl -fsS --max-time 1 "http://127.0.0.1:${port}/healthz" 2>/dev/null || true)"
|
|
31
50
|
|
|
32
51
|
if [ -n "$health_json" ]; then
|
|
@@ -37,15 +56,15 @@ if [ -n "$health_json" ]; then
|
|
|
37
56
|
|
|
38
57
|
if [ "$tui_connected" = "true" ]; then
|
|
39
58
|
cat <<EOF
|
|
40
|
-
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge is running. Daemon healthy, Codex TUI connected. Bridge is ready for communication
|
|
59
|
+
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge is running. Daemon healthy, Codex TUI connected. Bridge is ready for communication.${plugin_notice:+ $plugin_notice}"}}
|
|
41
60
|
EOF
|
|
42
61
|
else
|
|
43
62
|
cat <<EOF
|
|
44
|
-
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge daemon is running but Codex TUI is not connected yet. Start Codex in another terminal with: agentbridge codex"}}
|
|
63
|
+
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge daemon is running but Codex TUI is not connected yet. Start Codex in another terminal with: agentbridge codex${pair_arg}${plugin_notice:+ $plugin_notice}"}}
|
|
45
64
|
EOF
|
|
46
65
|
fi
|
|
47
66
|
else
|
|
48
67
|
cat <<EOF
|
|
49
|
-
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge daemon is not reachable on http://127.0.0.1:${port}/healthz yet. Start the bridge with: agentbridge claude (this terminal) + agentbridge codex (another terminal). If you're already using agentbridge claude, the daemon may still be starting up
|
|
68
|
+
{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"AgentBridge daemon is not reachable on http://127.0.0.1:${port}/healthz yet. Start the bridge with: agentbridge claude${pair_arg} (this terminal) + agentbridge codex${pair_arg} (another terminal). If you're already using agentbridge claude${pair_arg}, the daemon may still be starting up.${plugin_notice:+ $plugin_notice}"}}
|
|
50
69
|
EOF
|
|
51
70
|
fi
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* In-session plugin-update reminder.
|
|
4
|
+
*
|
|
5
|
+
* The CLI notifier (src/update-notifier.ts) writes the latest npm version to the
|
|
6
|
+
* update-check cache. This script — invoked by the SessionStart hook
|
|
7
|
+
* (scripts/health-check.sh) — compares that `latest` against the INSTALLED
|
|
8
|
+
* plugin version (plugin.json, passed as argv[2]) and prints a one-line reminder
|
|
9
|
+
* to stdout if the plugin is behind. Prints NOTHING otherwise.
|
|
10
|
+
*
|
|
11
|
+
* Why a separate plugin-side reminder: the CLI prints its notice to the terminal
|
|
12
|
+
* before Claude Code's TUI takes over, so a user who updates npm but not the
|
|
13
|
+
* plugin would otherwise never see the mismatch from inside the session.
|
|
14
|
+
*
|
|
15
|
+
* Self-contained on purpose: the shipped plugin does not include src/, so the
|
|
16
|
+
* tiny state-dir resolution + stable-semver compare are inlined here. Keep them
|
|
17
|
+
* in sync with src/state-dir.ts (StateDirResolver) and src/version-utils.ts.
|
|
18
|
+
* Silent on ANY error — it must never break the SessionStart hook.
|
|
19
|
+
*/
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import { homedir, platform } from "node:os";
|
|
23
|
+
|
|
24
|
+
/** Mirror of StateDirResolver (src/state-dir.ts). */
|
|
25
|
+
function stateDir() {
|
|
26
|
+
const override = process.env.AGENTBRIDGE_STATE_DIR;
|
|
27
|
+
if (override) return override;
|
|
28
|
+
if (platform() === "darwin") {
|
|
29
|
+
return join(homedir(), "Library", "Application Support", "AgentBridge");
|
|
30
|
+
}
|
|
31
|
+
const xdg = process.env.XDG_STATE_HOME ?? join(homedir(), ".local", "state");
|
|
32
|
+
return join(xdg, "agentbridge");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const STABLE = /^\d+\.\d+\.\d+$/;
|
|
36
|
+
|
|
37
|
+
/** Mirror of isStableUpgrade (src/version-utils.ts): stable latest strictly > stable current. */
|
|
38
|
+
function isStableUpgrade(current, latest) {
|
|
39
|
+
if (!STABLE.test(current) || !STABLE.test(latest)) return false;
|
|
40
|
+
const a = current.split(".").map(Number);
|
|
41
|
+
const b = latest.split(".").map(Number);
|
|
42
|
+
for (let i = 0; i < 3; i++) {
|
|
43
|
+
if (b[i] > a[i]) return true;
|
|
44
|
+
if (b[i] < a[i]) return false;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Honor the same opt-out as the CLI notifier (src/update-notifier.ts): a user
|
|
51
|
+
// who silenced update notices must not still get the in-session reminder.
|
|
52
|
+
if (process.env.NO_UPDATE_NOTIFIER || process.env.AGENTBRIDGE_NO_UPDATE_NOTIFIER) {
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const pluginJsonPath = process.argv[2];
|
|
57
|
+
if (!pluginJsonPath) process.exit(0);
|
|
58
|
+
|
|
59
|
+
const current = JSON.parse(readFileSync(pluginJsonPath, "utf-8")).version;
|
|
60
|
+
const cache = JSON.parse(readFileSync(join(stateDir(), "update-check.json"), "utf-8"));
|
|
61
|
+
const latest = cache?.latest;
|
|
62
|
+
|
|
63
|
+
if (typeof current === "string" && typeof latest === "string" && isStableUpgrade(current, latest)) {
|
|
64
|
+
process.stdout.write(
|
|
65
|
+
`AgentBridge plugin update available: ${current} -> ${latest}. ` +
|
|
66
|
+
`Update the plugin with /plugin marketplace update agentbridge then /reload-plugins ` +
|
|
67
|
+
`(and the CLI with npm install -g @raysonmeng/agentbridge@latest) so the CLI and plugin versions match.`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// No cache yet / no plugin.json / malformed — stay silent.
|
|
72
|
+
}
|
|
73
|
+
process.exit(0);
|