@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 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 required. On first run this downloads the prebuilt
5
- `actions-json-mcp` binary for your platform from the GitHub release, caches it,
6
- and runs it. The primitive dictionary (browser-control tool catalog) is bundled,
7
- so you don't pass `--actions`.
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 --storage-root /path/to/.storage
12
+ npx @actions-json/bridge mcp
13
13
  ```
14
14
 
15
- Register it with a coding agent — for Claude Code:
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
- For Codex:
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
- All arguments after the binary pass straight through to `actions-json-mcp`. To
30
- use a custom primitive dictionary, pass your own `--actions <file>` and the
31
- bundled default is skipped. See
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 withDefaultActions(args) {
21
- const sub = args[0];
22
- if (!SUBCOMMANDS_NEEDING_ACTIONS.has(sub)) return args;
23
- if (args.includes('--actions')) return args;
24
- if (args.includes('--help') || args.includes('-h')) return args;
25
- // Insert right after the subcommand.
26
- return [args[0], '--actions', BUNDLED_ACTIONS, ...args.slice(1)];
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 = withDefaultActions(process.argv.slice(2));
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.120",
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 for your platform, bundles the primitive dictionary, and runs it.",
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
+ }