golem-bridge 1.0.1
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/LICENSE +21 -0
- package/README.md +31 -0
- package/cli.js +128 -0
- package/package.json +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nickils
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Golem
|
|
2
|
+
|
|
3
|
+
`golem-bridge` connects an AI coding agent to a live Roblox Studio session
|
|
4
|
+
running the Golem plugin.
|
|
5
|
+
|
|
6
|
+
This repo holds the npm package (the AI side). The Studio plugin itself is
|
|
7
|
+
distributed through the Roblox Creator Store, not from here.
|
|
8
|
+
|
|
9
|
+
## How it connects
|
|
10
|
+
|
|
11
|
+
The plugin shows one line in Studio (popup on first run, also in Settings):
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Connect to my Roblox Studio, Run: npx golem-bridge connect <channelId>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The user sends that line to their AI. It downloads this package, which asks
|
|
18
|
+
the plugin for its two connection files and stores them under `./.golem/`:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npx golem-bridge connect <channelId>
|
|
22
|
+
python3 ./.golem/golem.py ping
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`ping` should return `"ok": true` plus the open place name. Then the agent
|
|
26
|
+
reads `./.golem/golem.md` for the full tool reference.
|
|
27
|
+
|
|
28
|
+
## Files
|
|
29
|
+
|
|
30
|
+
- `cli.js` - source of the `golem-bridge` package
|
|
31
|
+
- `package.json` - npm manifest
|
package/cli.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// golem-bridge: pulls golem.py and golem.md from the Golem Studio plugin
|
|
5
|
+
// over Firebase and writes them to ./.golem/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
|
|
10
|
+
const DB_URL = "https://roblox-golem-default-rtdb.firebaseio.com";
|
|
11
|
+
const POLL_INTERVAL_MS = 2000;
|
|
12
|
+
const POLL_ATTEMPTS = 45;
|
|
13
|
+
|
|
14
|
+
function usage() {
|
|
15
|
+
console.error("Usage: golem-bridge connect <channelId>");
|
|
16
|
+
console.error(" <channelId> is shown in the Golem plugin widget inside Roblox Studio.");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function postJson(url, body) {
|
|
21
|
+
const res = await fetch(url, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/json" },
|
|
24
|
+
body: JSON.stringify(body),
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
throw new Error(`POST ${url} failed: HTTP ${res.status}`);
|
|
28
|
+
}
|
|
29
|
+
return res.json();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function getJson(url) {
|
|
33
|
+
const res = await fetch(url);
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new Error(`GET ${url} failed: HTTP ${res.status}`);
|
|
36
|
+
}
|
|
37
|
+
const text = await res.text();
|
|
38
|
+
return text === "null" ? null : JSON.parse(text);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function sleep(ms) {
|
|
42
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function fetchSetupResult(channelId) {
|
|
46
|
+
const cmdId = `setup${Date.now()}${Math.floor(Math.random() * 1e6)}`;
|
|
47
|
+
await postJson(`${DB_URL}/channels/${channelId}/cmd.json`, {
|
|
48
|
+
id: cmdId,
|
|
49
|
+
op: "setup",
|
|
50
|
+
ts: Math.floor(Date.now() / 1000),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt++) {
|
|
54
|
+
await sleep(POLL_INTERVAL_MS);
|
|
55
|
+
let keys;
|
|
56
|
+
try {
|
|
57
|
+
keys = await getJson(`${DB_URL}/channels/${channelId}/res.json?shallow=true`);
|
|
58
|
+
} catch {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (!keys) continue;
|
|
62
|
+
for (const key of Object.keys(keys).sort()) {
|
|
63
|
+
let entry;
|
|
64
|
+
try {
|
|
65
|
+
entry = await getJson(`${DB_URL}/channels/${channelId}/res/${key}.json`);
|
|
66
|
+
} catch {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (entry && entry.id === cmdId) {
|
|
70
|
+
return entry;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function connect(channelId) {
|
|
78
|
+
if (!channelId || channelId.length < 8) {
|
|
79
|
+
usage();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(`Contacting Golem plugin on channel ${channelId} ...`);
|
|
83
|
+
const entry = await fetchSetupResult(channelId);
|
|
84
|
+
|
|
85
|
+
if (!entry) {
|
|
86
|
+
console.error("No response from the Studio plugin. Is Roblox Studio open with Golem running?");
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
if (!entry.ok) {
|
|
90
|
+
console.error(`Setup failed: ${entry.error || "unknown error"}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let result = entry.result;
|
|
95
|
+
if (entry.resultEncoded) {
|
|
96
|
+
result = JSON.parse(result);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const dir = path.join(process.cwd(), ".golem");
|
|
100
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
101
|
+
|
|
102
|
+
const pyPath = path.join(dir, "golem.py");
|
|
103
|
+
const mdPath = path.join(dir, "golem.md");
|
|
104
|
+
fs.writeFileSync(pyPath, result.source);
|
|
105
|
+
fs.writeFileSync(mdPath, result.prompt);
|
|
106
|
+
|
|
107
|
+
console.log("");
|
|
108
|
+
console.log(result.instructions || "Connected.");
|
|
109
|
+
console.log("");
|
|
110
|
+
console.log(`Wrote ${path.relative(process.cwd(), pyPath)} and ${path.relative(process.cwd(), mdPath)}`);
|
|
111
|
+
console.log(`Next: read ${path.relative(process.cwd(), mdPath)}, then run:`);
|
|
112
|
+
console.log(` python3 ${path.relative(process.cwd(), pyPath)} ping`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function main() {
|
|
116
|
+
const [cmd, arg] = process.argv.slice(2);
|
|
117
|
+
if (cmd !== "connect") {
|
|
118
|
+
usage();
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
await connect(arg);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(`golem-bridge error: ${err.message}`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "golem-bridge",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Connects an AI coding agent to a running Roblox Studio session via the Golem plugin.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"golem-bridge": "./cli.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "commonjs",
|
|
9
|
+
"files": ["cli.js", "README.md"],
|
|
10
|
+
"keywords": ["roblox", "roblox-studio", "ai", "cli"],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/nickils/Golem.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/nickils/Golem#readme",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/nickils/Golem/issues"
|
|
22
|
+
}
|
|
23
|
+
}
|