@actions-json/bridge 0.1.120 → 0.1.121
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 +17 -14
- package/bin/cli.js +21 -8
- package/lib/storage.js +55 -0
- package/package.json +3 -2
- package/scaffold/README.md +76 -0
- package/scaffold/scopes/private/scope.json +17 -0
- package/scaffold/scopes/private/sites/.gitkeep +0 -0
- package/scaffold/scopes/public/scope.json +17 -0
- package/scaffold/scopes/public/sites/.gitkeep +0 -0
- package/scaffold/scopes/shared/.gitkeep +0 -0
- package/scaffold/storage.json +33 -0
package/README.md
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
# @actions-json/bridge
|
|
2
2
|
|
|
3
3
|
Run the [actions.json](https://yaniv256.github.io/actions.json/) MCP bridge with
|
|
4
|
-
`npx` — no Rust toolchain
|
|
5
|
-
`actions-json-mcp` binary for your platform
|
|
6
|
-
|
|
7
|
-
so you don't pass `--
|
|
4
|
+
`npx` — no Rust toolchain, no setup. On first run it downloads the prebuilt
|
|
5
|
+
`actions-json-mcp` binary for your platform, bundles the primitive dictionary
|
|
6
|
+
(so you don't pass `--actions`), and scaffolds a storage workspace at
|
|
7
|
+
`~/.actions-json/storage` (so you don't pass `--storage-root`).
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx @actions-json/bridge mcp
|
|
12
|
+
npx @actions-json/bridge mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Register it with a coding agent —
|
|
15
|
+
Register it with a coding agent — Claude Code:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
claude mcp add actions-json --
|
|
19
|
-
npx -y @actions-json/bridge mcp --storage-root /path/to/.storage
|
|
18
|
+
claude mcp add actions-json -- npx -y @actions-json/bridge mcp
|
|
20
19
|
```
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Codex:
|
|
23
22
|
|
|
24
23
|
```bash
|
|
25
|
-
codex mcp add actions-json --
|
|
26
|
-
npx -y @actions-json/bridge mcp --storage-root /path/to/.storage
|
|
24
|
+
codex mcp add actions-json -- npx -y @actions-json/bridge mcp
|
|
27
25
|
```
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
Overrides (the defaults are skipped when you pass your own):
|
|
28
|
+
|
|
29
|
+
- `--storage-root <dir>` — use a different storage workspace. Or set
|
|
30
|
+
`ACTIONS_JSON_STORAGE`.
|
|
31
|
+
- `--actions <file>` — use a custom primitive dictionary instead of the bundled
|
|
32
|
+
one.
|
|
33
|
+
|
|
34
|
+
All arguments after the binary pass straight through to `actions-json-mcp`. See
|
|
32
35
|
[Getting Started](https://yaniv256.github.io/actions.json/getting-started.html).
|
|
33
36
|
|
|
34
37
|
## Platforms
|
package/bin/cli.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
const path = require('node:path');
|
|
10
10
|
const { spawn } = require('node:child_process');
|
|
11
11
|
const { ensureBinary } = require('../lib/install');
|
|
12
|
+
const { ensureStorageRoot } = require('../lib/storage');
|
|
12
13
|
|
|
13
14
|
// The primitive dictionary (browser-control tool catalog) ships with this
|
|
14
15
|
// package — it's a fixed runtime file, not user config. When the caller runs a
|
|
@@ -17,13 +18,25 @@ const { ensureBinary } = require('../lib/install');
|
|
|
17
18
|
const BUNDLED_ACTIONS = path.join(__dirname, '..', 'dictionary', 'overlay.actions.json');
|
|
18
19
|
const SUBCOMMANDS_NEEDING_ACTIONS = new Set(['mcp', 'serve']);
|
|
19
20
|
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
function isRunSubcommand(args) {
|
|
22
|
+
return SUBCOMMANDS_NEEDING_ACTIONS.has(args[0]) &&
|
|
23
|
+
!args.includes('--help') && !args.includes('-h');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Inject defaults the user shouldn't have to specify: the bundled primitive
|
|
27
|
+
// dictionary (--actions) and a scaffolded storage root (--storage-root). Both
|
|
28
|
+
// are skipped if the user passed their own.
|
|
29
|
+
function withDefaults(args) {
|
|
30
|
+
if (!isRunSubcommand(args)) return args;
|
|
31
|
+
const out = [args[0]];
|
|
32
|
+
if (!args.includes('--actions')) {
|
|
33
|
+
out.push('--actions', BUNDLED_ACTIONS);
|
|
34
|
+
}
|
|
35
|
+
if (!args.includes('--storage-root')) {
|
|
36
|
+
out.push('--storage-root', ensureStorageRoot());
|
|
37
|
+
}
|
|
38
|
+
out.push(...args.slice(1));
|
|
39
|
+
return out;
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
async function main() {
|
|
@@ -36,7 +49,7 @@ async function main() {
|
|
|
36
49
|
return;
|
|
37
50
|
}
|
|
38
51
|
|
|
39
|
-
const args =
|
|
52
|
+
const args = withDefaults(process.argv.slice(2));
|
|
40
53
|
const child = spawn(bin, args, { stdio: 'inherit' });
|
|
41
54
|
|
|
42
55
|
// Forward termination signals so the bridge shuts down cleanly.
|
package/lib/storage.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
// Default storage location when the caller doesn't pass --storage-root.
|
|
8
|
+
// Lives in the user's home dir (not cwd) so it resolves no matter where the
|
|
9
|
+
// coding agent launches the bridge.
|
|
10
|
+
function defaultStorageRoot() {
|
|
11
|
+
return (
|
|
12
|
+
process.env.ACTIONS_JSON_STORAGE ||
|
|
13
|
+
path.join(os.homedir(), '.actions-json', 'storage')
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
|
|
18
|
+
|
|
19
|
+
// Recursively copy the scaffold, skipping the .gitkeep placeholders (they only
|
|
20
|
+
// exist to ship empty dirs inside the package/repo).
|
|
21
|
+
function copyScaffold(src, dst) {
|
|
22
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
23
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
24
|
+
if (entry.name === '.gitkeep') continue;
|
|
25
|
+
const s = path.join(src, entry.name);
|
|
26
|
+
const d = path.join(dst, entry.name);
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
copyScaffold(s, d);
|
|
29
|
+
} else {
|
|
30
|
+
fs.copyFileSync(s, d);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Ensure the storage root exists; scaffold it from the bundled template on
|
|
36
|
+
// first run. Returns the absolute path. Never overwrites existing storage.
|
|
37
|
+
function ensureStorageRoot(root) {
|
|
38
|
+
const target = root || defaultStorageRoot();
|
|
39
|
+
if (!fs.existsSync(target)) {
|
|
40
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
41
|
+
copyScaffold(SCAFFOLD_DIR, target);
|
|
42
|
+
// Recreate the empty scope dirs that .gitkeep stood in for.
|
|
43
|
+
for (const p of [
|
|
44
|
+
['scopes', 'private', 'sites'],
|
|
45
|
+
['scopes', 'public', 'sites'],
|
|
46
|
+
['scopes', 'shared'],
|
|
47
|
+
]) {
|
|
48
|
+
fs.mkdirSync(path.join(target, ...p), { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
process.stderr.write(`Created actions.json storage at ${target}\n`);
|
|
51
|
+
}
|
|
52
|
+
return path.resolve(target);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { ensureStorageRoot, defaultStorageRoot };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actions-json/bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.121",
|
|
4
4
|
"bridgeBinaryVersion": "0.1.119",
|
|
5
|
-
"description": "Run the actions.json MCP bridge with npx — no Rust toolchain required. Downloads the prebuilt actions-json-mcp binary
|
|
5
|
+
"description": "Run the actions.json MCP bridge with npx — no Rust toolchain required. Downloads the prebuilt actions-json-mcp binary, bundles the primitive dictionary, and scaffolds a storage workspace on first run.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"bin/",
|
|
18
18
|
"lib/",
|
|
19
19
|
"dictionary/",
|
|
20
|
+
"scaffold/",
|
|
20
21
|
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"engines": {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# actions.json storage scaffold
|
|
2
|
+
|
|
3
|
+
This is a starter `actions.json.storage` workspace. The `init` step copies it to
|
|
4
|
+
`.storage/` in your `actions.json` checkout, where it lives **inside the folder
|
|
5
|
+
but is not part of the code repo** (`.storage/` is gitignored).
|
|
6
|
+
|
|
7
|
+
Point the bridge at it with `--storage-root .storage`.
|
|
8
|
+
|
|
9
|
+
## Scopes
|
|
10
|
+
|
|
11
|
+
Storage is organized by visibility. Each scope is just a folder under `scopes/`;
|
|
12
|
+
the runtime discovers site maps under `scopes/<scope>/sites/<host>/`.
|
|
13
|
+
|
|
14
|
+
| Scope | What goes here | Git |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `private/` | Your owner-only browsing memory, observations, run logs, and unreviewed maps. | Local by default. Opt in: point it at your own **private** repo to sync across your machines and agents. |
|
|
17
|
+
| `public/` | Reviewed, redacted maps **you publish** openly. | Opt in: point it at your own public repo. |
|
|
18
|
+
| `shared/<name>/` | Maps shared with a specific collaborator, **and** maps you pull **from** a source. | Opt in: one git remote per source. |
|
|
19
|
+
|
|
20
|
+
`private` and `public` exist in the scaffold. Add `shared/<name>/` when you need
|
|
21
|
+
it.
|
|
22
|
+
|
|
23
|
+
## Opening a scope for sharing or syncing
|
|
24
|
+
|
|
25
|
+
The scaffold is local-only until you choose to version a scope. Each scope is an
|
|
26
|
+
ordinary folder, so you turn one into a git repo when you want to.
|
|
27
|
+
|
|
28
|
+
**Sync your private memory across machines** — back `scopes/private/` with your
|
|
29
|
+
own **private** repo so the same browsing memory follows your agent everywhere:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd .storage/scopes/private
|
|
33
|
+
git init && git add . && git commit -m "my private actions.json memory"
|
|
34
|
+
git remote add origin https://github.com/<you>/<your-private-storage>.git # private!
|
|
35
|
+
git push -u origin main
|
|
36
|
+
# on another machine: clone it into .storage/scopes/private instead of init
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This stays private — it is your repo, set to private. It only ever leaves your
|
|
40
|
+
machine if you point it at a remote, and `public`/`shared` promotion still
|
|
41
|
+
requires explicit review.
|
|
42
|
+
|
|
43
|
+
**Publish your public maps** — make `scopes/public/` your own public repo:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd .storage/scopes/public
|
|
47
|
+
git init && git add . && git commit -m "my public actions.json maps"
|
|
48
|
+
git remote add origin https://github.com/<you>/<your-public-storage>.git
|
|
49
|
+
git push -u origin main
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Pull the official map library** — vendor maps *from* a source into a shared
|
|
53
|
+
scope (the runtime already discovers maps under `scopes/shared/<name>/`):
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd .storage/scopes/shared
|
|
57
|
+
git clone https://github.com/yaniv256/actions.json.storage.public.git actions-json
|
|
58
|
+
# maps now resolve from scopes/shared/actions-json/sites/<host>/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Pulling from someone else's library uses the **shared** scope (inbound), not
|
|
62
|
+
`public` (which is for what *you* publish). Keep that boundary clear.
|
|
63
|
+
|
|
64
|
+
## Layout
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
storage.json Root manifest — which scopes are mounted
|
|
68
|
+
scopes/
|
|
69
|
+
private/
|
|
70
|
+
scope.json Private scope manifest
|
|
71
|
+
sites/<host>/ Per-site maps, observations, overlays (local; sync via a private repo)
|
|
72
|
+
public/
|
|
73
|
+
scope.json Public scope manifest
|
|
74
|
+
sites/<host>/ Reviewed, redacted maps you publish
|
|
75
|
+
shared/<name>/ Add per-collaborator or per-source as needed
|
|
76
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocol": "actions.json.storage.scope",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"scope": "private",
|
|
5
|
+
"parent": "actions.json.storage",
|
|
6
|
+
"owner": {
|
|
7
|
+
"type": "person",
|
|
8
|
+
"id": "you"
|
|
9
|
+
},
|
|
10
|
+
"visibility": "private",
|
|
11
|
+
"default_policy": {
|
|
12
|
+
"observations": "store_freely",
|
|
13
|
+
"runs": "store_freely",
|
|
14
|
+
"overlays": "store_freely",
|
|
15
|
+
"action_maps": "draft_until_reviewed"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocol": "actions.json.storage.scope",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"scope": "public",
|
|
5
|
+
"parent": "actions.json.storage",
|
|
6
|
+
"owner": {
|
|
7
|
+
"type": "person",
|
|
8
|
+
"id": "you"
|
|
9
|
+
},
|
|
10
|
+
"visibility": "public",
|
|
11
|
+
"default_policy": {
|
|
12
|
+
"observations": "do_not_store_raw_private_observations",
|
|
13
|
+
"reports": "reviewed_public_artifact",
|
|
14
|
+
"action_maps": "reviewed_and_redacted",
|
|
15
|
+
"promotion": "review_required"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocol": "actions.json.storage",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"owner": {
|
|
5
|
+
"type": "person",
|
|
6
|
+
"id": "you"
|
|
7
|
+
},
|
|
8
|
+
"visibility": "root-private",
|
|
9
|
+
"default_mount": "private",
|
|
10
|
+
"mounts": {
|
|
11
|
+
"private": {
|
|
12
|
+
"path": "scopes/private",
|
|
13
|
+
"mount_type": "local",
|
|
14
|
+
"visibility": "private",
|
|
15
|
+
"default": true,
|
|
16
|
+
"description": "Your owner-only browsing memory, observations, overlays, run logs, item indexes, and unreviewed action maps. Local by default; point it at your own private repo to sync the same memory across your machines and agents."
|
|
17
|
+
},
|
|
18
|
+
"public": {
|
|
19
|
+
"path": "scopes/public",
|
|
20
|
+
"mount_type": "local",
|
|
21
|
+
"visibility": "public",
|
|
22
|
+
"description": "Reviewed, redacted maps you publish openly. Point this at your own public repo when you want to share."
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"default_policy": {
|
|
26
|
+
"observations": "write_to_private_scope",
|
|
27
|
+
"item_indexes": "write_to_private_scope",
|
|
28
|
+
"runs": "write_to_private_scope",
|
|
29
|
+
"overlays": "write_to_private_scope",
|
|
30
|
+
"action_maps": "reviewed_change_in_scope",
|
|
31
|
+
"promotion": "review_required"
|
|
32
|
+
}
|
|
33
|
+
}
|