tinker-agent 1.0.25 → 1.0.28
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 +49 -4
- package/package.json +1 -1
- package/run-tinker-agent.rb +97 -24
package/README.md
CHANGED
|
@@ -16,10 +16,55 @@ ENTRYPOINT ["/entrypoint.sh"]
|
|
|
16
16
|
CMD ["bash", "-c", "curl -fsSL https://raw.githubusercontent.com/RoM4iK/tinker-public/${TINKER_VERSION:-main}/setup-agent.rb | ruby"]
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
## Configuration (tinker.env.rb)
|
|
20
|
+
|
|
21
|
+
Agents are configured via a `tinker.env.rb` file in your project root. This Ruby file allows you to define configuration and secrets (using heredocs).
|
|
22
|
+
|
|
23
|
+
**Do not commit `tinker.env.rb` to git!** Add it to your `.gitignore`.
|
|
24
|
+
|
|
25
|
+
Example `tinker.env.rb`:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
{
|
|
29
|
+
project_id: 2,
|
|
30
|
+
rails_ws_url: "wss://tinkerai.win/cable",
|
|
31
|
+
rails_api_url: "https://tinker.tinkerai.win/api/v1",
|
|
32
|
+
|
|
33
|
+
# Git Identity
|
|
34
|
+
git: {
|
|
35
|
+
user_name: "Tinker Agent",
|
|
36
|
+
user_email: "agent@example.com"
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
# GitHub Auth (App or Token)
|
|
40
|
+
github: {
|
|
41
|
+
method: "app",
|
|
42
|
+
app_client_id: "Iv23liFDGt4FWGJSHAS",
|
|
43
|
+
app_installation_id: "102387777",
|
|
44
|
+
app_private_key_path: "/absolute/path/to/key.pem"
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
# Agent Specific Config
|
|
48
|
+
agents: {
|
|
49
|
+
worker: {
|
|
50
|
+
mcp_api_key: "...",
|
|
51
|
+
container_name: "tinker-worker"
|
|
52
|
+
},
|
|
53
|
+
planner: {
|
|
54
|
+
mcp_api_key: "...",
|
|
55
|
+
container_name: "tinker-planner"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
# Environment Variables Injection
|
|
60
|
+
# Simple strings or Heredocs supported
|
|
61
|
+
dot_env: <<~ENV
|
|
62
|
+
PORT=3200
|
|
63
|
+
DB_HOST=localhost
|
|
64
|
+
SECRET_KEY_BASE=very_secret
|
|
65
|
+
OPENAI_API_KEY=sk-...
|
|
66
|
+
ENV
|
|
67
|
+
}
|
|
23
68
|
```
|
|
24
69
|
|
|
25
70
|
## Environment Variables
|
package/package.json
CHANGED
package/run-tinker-agent.rb
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# - Docker
|
|
10
10
|
# - Ruby
|
|
11
11
|
# - Dockerfile.sandbox in project root
|
|
12
|
-
# - tinker.env.
|
|
12
|
+
# - tinker.env.rb in project root (gitignored)
|
|
13
13
|
|
|
14
14
|
require "json"
|
|
15
15
|
|
|
@@ -21,19 +21,55 @@ IMAGE_NAME = "tinker-sandbox"
|
|
|
21
21
|
AGENT_TYPES = AGENT_CONFIGS.keys.freeze
|
|
22
22
|
|
|
23
23
|
def load_config
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
# Support Ruby config for heredocs and comments (tinker.env.rb)
|
|
25
|
+
rb_config_file = File.join(Dir.pwd, "tinker.env.rb")
|
|
26
|
+
|
|
27
|
+
unless File.exist?(rb_config_file)
|
|
28
|
+
puts "❌ Error: tinker.env.rb not found in current directory"
|
|
28
29
|
puts ""
|
|
29
|
-
puts "Create
|
|
30
|
-
puts "
|
|
31
|
-
puts "
|
|
32
|
-
puts "
|
|
30
|
+
puts "Create tinker.env.rb:"
|
|
31
|
+
puts " {"
|
|
32
|
+
puts " project_id: 1,"
|
|
33
|
+
puts " rails_ws_url: '...',"
|
|
34
|
+
puts " # ..."
|
|
35
|
+
puts " # Paste your stripped .env content here:"
|
|
36
|
+
puts " dot_env: <<~ENV"
|
|
37
|
+
puts " STRIPE_KEY=sk_test_..."
|
|
38
|
+
puts " OPENAI_KEY=sk-..."
|
|
39
|
+
puts " ENV"
|
|
40
|
+
puts " }"
|
|
41
|
+
puts " echo 'tinker.env.rb' >> .gitignore"
|
|
33
42
|
exit 1
|
|
34
43
|
end
|
|
35
44
|
|
|
36
|
-
|
|
45
|
+
puts "⚙️ Loading configuration from tinker.env.rb"
|
|
46
|
+
config = eval(File.read(rb_config_file), binding, rb_config_file)
|
|
47
|
+
|
|
48
|
+
# Convert symbols to strings for easier handling before JSON normalization
|
|
49
|
+
config = config.transform_keys(&:to_s)
|
|
50
|
+
|
|
51
|
+
# Parse dot_env heredoc if present
|
|
52
|
+
if (dotenv = config["dot_env"])
|
|
53
|
+
config["env"] ||= {}
|
|
54
|
+
# Ensure env is string-keyed
|
|
55
|
+
config["env"] = config["env"].transform_keys(&:to_s)
|
|
56
|
+
|
|
57
|
+
dotenv.each_line do |line|
|
|
58
|
+
line = line.strip
|
|
59
|
+
next if line.empty? || line.start_with?('#')
|
|
60
|
+
k, v = line.split('=', 2)
|
|
61
|
+
next unless k && v
|
|
62
|
+
# Remove surrounding quotes and trailing comments (simple)
|
|
63
|
+
v = v.strip.gsub(/^['"]|['"]$/, '')
|
|
64
|
+
config["env"][k.strip] = v
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
config.delete("dot_env")
|
|
68
|
+
puts "🌿 Parsed dot_env into #{config['env'].size} environment variables"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Normalize symbols to strings for consistency via JSON round-trip
|
|
72
|
+
JSON.parse(JSON.generate(config))
|
|
37
73
|
end
|
|
38
74
|
|
|
39
75
|
def check_dockerfile!
|
|
@@ -97,6 +133,17 @@ def run_agent(agent_type, config)
|
|
|
97
133
|
"docker", "run", "-d",
|
|
98
134
|
"--name", container_name,
|
|
99
135
|
"--network=host",
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
# Inject custom environment variables from config
|
|
139
|
+
if (custom_env = config["env"])
|
|
140
|
+
custom_env.each do |k, v|
|
|
141
|
+
docker_cmd += ["-e", "#{k}=#{v}"]
|
|
142
|
+
end
|
|
143
|
+
puts "🌿 Injected #{custom_env.size} custom env vars from config"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
docker_cmd += [
|
|
100
147
|
# Mount Claude config
|
|
101
148
|
"-v", "#{ENV['HOME']}/.claude.json:/tmp/cfg/claude.json:ro",
|
|
102
149
|
"-v", "#{ENV['HOME']}/.claude:/tmp/cfg/claude_dir:ro",
|
|
@@ -117,7 +164,7 @@ def run_agent(agent_type, config)
|
|
|
117
164
|
|
|
118
165
|
unless File.exist?(key_path) && !File.directory?(key_path)
|
|
119
166
|
puts "❌ Error: GitHub App private key not found at: #{key_path}"
|
|
120
|
-
puts " Please check 'app_private_key_path' in tinker.env.
|
|
167
|
+
puts " Please check 'app_private_key_path' in tinker.env.rb"
|
|
121
168
|
exit 1
|
|
122
169
|
end
|
|
123
170
|
|
|
@@ -133,7 +180,7 @@ def run_agent(agent_type, config)
|
|
|
133
180
|
puts "🔑 Using GitHub token authentication"
|
|
134
181
|
else
|
|
135
182
|
puts "❌ Error: No GitHub authentication configured"
|
|
136
|
-
puts " Please configure 'github' in tinker.env.
|
|
183
|
+
puts " Please configure 'github' in tinker.env.rb"
|
|
137
184
|
exit 1
|
|
138
185
|
end
|
|
139
186
|
|
|
@@ -147,7 +194,15 @@ def run_agent(agent_type, config)
|
|
|
147
194
|
local_setup_script = File.join(File.dirname(__FILE__), "setup-agent.rb")
|
|
148
195
|
|
|
149
196
|
# Check for local agent-bridge binaries (for development)
|
|
150
|
-
|
|
197
|
+
# Priority:
|
|
198
|
+
# 1. Linux binary matching host arch (for proper container execution)
|
|
199
|
+
# 2. Legacy bin/agent-bridge if it's a binary (not script)
|
|
200
|
+
|
|
201
|
+
arch = `uname -m`.strip
|
|
202
|
+
linux_arch = (arch == "x86_64") ? "amd64" : "arm64"
|
|
203
|
+
linux_bridge = File.join(Dir.pwd, "tinker-public", "bin", "agent-bridge-linux-#{linux_arch}")
|
|
204
|
+
|
|
205
|
+
local_bridge_default = File.join(Dir.pwd, "bin", "agent-bridge")
|
|
151
206
|
local_tmux = File.join(File.dirname(__FILE__), "bin", "agent-bridge-tmux")
|
|
152
207
|
|
|
153
208
|
mounts = []
|
|
@@ -156,9 +211,18 @@ def run_agent(agent_type, config)
|
|
|
156
211
|
mounts += ["-v", "#{File.expand_path(local_setup_script)}:/tmp/setup-agent.rb:ro"]
|
|
157
212
|
end
|
|
158
213
|
|
|
159
|
-
if File.exist?(
|
|
160
|
-
puts "🔧 Using local
|
|
161
|
-
mounts += ["-v", "#{
|
|
214
|
+
if File.exist?(linux_bridge)
|
|
215
|
+
puts "🔧 Using local linux binary: #{linux_bridge}"
|
|
216
|
+
mounts += ["-v", "#{linux_bridge}:/tmp/agent-bridge:ro"]
|
|
217
|
+
elsif File.exist?(local_bridge_default)
|
|
218
|
+
# Check if it's a binary or script
|
|
219
|
+
is_script = File.read(local_bridge_default, 4) == "#!/b"
|
|
220
|
+
if is_script
|
|
221
|
+
puts "⚠️ bin/agent-bridge is a host wrapper script. Please run 'bin/build-bridge' to generate linux binaries."
|
|
222
|
+
else
|
|
223
|
+
puts "🔧 Using local agent-bridge binary"
|
|
224
|
+
mounts += ["-v", "#{local_bridge_default}:/tmp/agent-bridge:ro"]
|
|
225
|
+
end
|
|
162
226
|
end
|
|
163
227
|
|
|
164
228
|
if File.exist?(local_tmux)
|
|
@@ -193,15 +257,17 @@ def attach_to_agent(agent_type, config)
|
|
|
193
257
|
exit 1
|
|
194
258
|
end
|
|
195
259
|
|
|
260
|
+
agent_def = AGENT_CONFIGS[agent_type]
|
|
196
261
|
agent_config = config.dig("agents", agent_type) || {}
|
|
197
|
-
container_name = agent_config["container_name"] ||
|
|
262
|
+
container_name = agent_config["container_name"] || agent_def[:name]
|
|
198
263
|
|
|
199
264
|
running = `docker ps --filter name=^#{container_name}$ --format '{{.Names}}'`.strip
|
|
200
265
|
|
|
201
266
|
if running.empty?
|
|
202
|
-
puts "
|
|
203
|
-
|
|
204
|
-
|
|
267
|
+
puts "⚠️ #{agent_type} agent is not running. Auto-starting..."
|
|
268
|
+
build_docker_image
|
|
269
|
+
run_agent(agent_type, config)
|
|
270
|
+
sleep 3
|
|
205
271
|
end
|
|
206
272
|
|
|
207
273
|
puts "📎 Attaching to #{agent_type} agent..."
|
|
@@ -224,6 +290,14 @@ def attach_to_agent(agent_type, config)
|
|
|
224
290
|
|
|
225
291
|
puts " User: #{user}"
|
|
226
292
|
|
|
293
|
+
# Wait for tmux session to be ready
|
|
294
|
+
10.times do
|
|
295
|
+
if system("docker", "exec", "-u", user, container_name, "tmux", "has-session", "-t", "agent", err: File::NULL, out: File::NULL)
|
|
296
|
+
break
|
|
297
|
+
end
|
|
298
|
+
sleep 1
|
|
299
|
+
end
|
|
300
|
+
|
|
227
301
|
# Attach to agent session which has the status bar
|
|
228
302
|
# Must run as agent user since tmux server runs under that user
|
|
229
303
|
exec("docker", "exec", "-it", "-u", user, container_name, "tmux", "attach", "-t", "agent")
|
|
@@ -237,10 +311,9 @@ def show_usage
|
|
|
237
311
|
puts ""
|
|
238
312
|
puts "Setup:"
|
|
239
313
|
puts " 1. Create Dockerfile.sandbox (see https://github.com/RoM4iK/tinker-public/blob/main/README.md)"
|
|
240
|
-
puts " 2.
|
|
241
|
-
puts " 3.
|
|
242
|
-
puts " 4.
|
|
243
|
-
puts " 5. npx tinker-agent worker"
|
|
314
|
+
puts " 2. Create tinker.env.rb (see https://github.com/RoM4iK/tinker-public/blob/main/README.md)"
|
|
315
|
+
puts " 3. echo 'tinker.env.rb' >> .gitignore"
|
|
316
|
+
puts " 4. npx tinker-agent worker"
|
|
244
317
|
exit 1
|
|
245
318
|
end
|
|
246
319
|
|