indieclaw-agent 2.0.0 → 2.1.0

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.
Files changed (3) hide show
  1. package/index.js +36 -44
  2. package/install.sh +63 -22
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -143,12 +143,14 @@ try {
143
143
  }
144
144
 
145
145
  // --- OpenClaw Detection ---
146
- function detectOpenClaw() {
146
+ const OPENCLAW_PORTS = [18789, 8080, 11434, 1234, 8000];
147
+
148
+ function tryOpenClawPort(port) {
147
149
  return new Promise((resolve) => {
148
150
  const req = http.request(
149
151
  {
150
152
  hostname: '127.0.0.1',
151
- port: 18789,
153
+ port,
152
154
  path: '/v1/models',
153
155
  method: 'GET',
154
156
  timeout: 2000,
@@ -160,30 +162,44 @@ function detectOpenClaw() {
160
162
  try {
161
163
  const json = JSON.parse(body);
162
164
  const models = (json.data || []).map((m) => m.id);
163
- resolve({ available: true, models });
165
+ if (models.length > 0) {
166
+ resolve({ available: true, models, port });
167
+ } else {
168
+ resolve({ available: false, models: [], port });
169
+ }
164
170
  } catch {
165
- resolve({ available: false, models: [] });
171
+ resolve({ available: false, models: [], port });
166
172
  }
167
173
  });
168
174
  }
169
175
  );
170
176
  req.on('timeout', () => {
171
177
  req.destroy();
172
- resolve({ available: false, models: [] });
178
+ resolve({ available: false, models: [], port });
173
179
  });
174
180
  req.on('error', () => {
175
- resolve({ available: false, models: [] });
181
+ resolve({ available: false, models: [], port });
176
182
  });
177
183
  req.end();
178
184
  });
179
185
  }
180
186
 
187
+ async function detectOpenClaw() {
188
+ // Try all common ports in parallel
189
+ const results = await Promise.all(OPENCLAW_PORTS.map(tryOpenClawPort));
190
+ const found = results.find((r) => r.available);
191
+ if (found) {
192
+ return { available: true, models: found.models, port: found.port };
193
+ }
194
+ return { available: false, models: [], port: null };
195
+ }
196
+
181
197
  // Run detection on startup
182
198
  detectOpenClaw().then((oc) => {
183
199
  if (oc.available) {
184
- console.log(` [OpenClaw] Detected! Models: ${oc.models.join(', ')}`);
200
+ console.log(` [OpenClaw] Detected on port ${oc.port}! Models: ${oc.models.join(', ')}`);
185
201
  } else {
186
- console.log(' [OpenClaw] Not detected on port 18789');
202
+ console.log(` [OpenClaw] Not detected on ports ${OPENCLAW_PORTS.join(', ')}`);
187
203
  }
188
204
  });
189
205
 
@@ -1190,42 +1206,18 @@ function handleCronHistory(ws, { id }) {
1190
1206
  }
1191
1207
 
1192
1208
  // --- Agent List (OpenClaw Models) ---
1193
- function handleAgentList(ws, { id }) {
1194
- const req = http.request(
1195
- {
1196
- hostname: '127.0.0.1',
1197
- port: 18789,
1198
- path: '/v1/models',
1199
- method: 'GET',
1200
- timeout: 2000,
1201
- },
1202
- (res) => {
1203
- let body = '';
1204
- res.on('data', (chunk) => (body += chunk));
1205
- res.on('end', () => {
1206
- try {
1207
- const json = JSON.parse(body);
1208
- const models = (json.data || []).map((m) => ({
1209
- id: m.id,
1210
- name: m.id,
1211
- status: 'running',
1212
- port: 18789,
1213
- }));
1214
- reply(ws, id, models);
1215
- } catch {
1216
- reply(ws, id, []);
1217
- }
1218
- });
1219
- }
1220
- );
1221
- req.on('timeout', () => {
1222
- req.destroy();
1223
- reply(ws, id, []);
1224
- });
1225
- req.on('error', () => {
1226
- reply(ws, id, []);
1227
- });
1228
- req.end();
1209
+ async function handleAgentList(ws, { id }) {
1210
+ const oc = await detectOpenClaw();
1211
+ if (oc.available) {
1212
+ const models = oc.models.map((modelId) => ({
1213
+ id: modelId,
1214
+ name: modelId,
1215
+ status: 'running',
1216
+ port: oc.port,
1217
+ }));
1218
+ return reply(ws, id, models);
1219
+ }
1220
+ reply(ws, id, []);
1229
1221
  }
1230
1222
 
1231
1223
  // --- Agent Logs ---
package/install.sh CHANGED
@@ -23,7 +23,7 @@ else
23
23
  fi
24
24
 
25
25
  # Step 1: Check/Install Node.js
26
- echo -e "${YELLOW}[1/4]${NC} Checking Node.js..."
26
+ echo -e "${YELLOW}[1/5]${NC} Checking Node.js..."
27
27
  if command -v node &> /dev/null; then
28
28
  NODE_VERSION=$(node -v)
29
29
  echo -e " ${GREEN}✓${NC} Node.js ${NODE_VERSION} found"
@@ -46,12 +46,13 @@ else
46
46
  fi
47
47
 
48
48
  # Step 2: Install indieclaw-agent
49
- echo -e "${YELLOW}[2/4]${NC} Installing indieclaw-agent..."
50
- $SUDO npm install -g indieclaw-agent 2>/dev/null || npm install -g indieclaw-agent
51
- echo -e " ${GREEN}✓${NC} indieclaw-agent installed"
49
+ echo -e "${YELLOW}[2/5]${NC} Installing indieclaw-agent..."
50
+ $SUDO npm install -g indieclaw-agent@latest 2>/dev/null || npm install -g indieclaw-agent@latest
51
+ AGENT_VERSION=$(node -e "try{console.log(require(require('child_process').execSync('which indieclaw-agent',{encoding:'utf8'}).trim().replace(/indieclaw-agent$/,'')+'../lib/node_modules/indieclaw-agent/package.json').version)}catch{console.log('2.0.0')}" 2>/dev/null || echo "2.0.0")
52
+ echo -e " ${GREEN}✓${NC} indieclaw-agent v${AGENT_VERSION} installed"
52
53
 
53
54
  # Step 3: Create systemd service
54
- echo -e "${YELLOW}[3/4]${NC} Setting up background service..."
55
+ echo -e "${YELLOW}[3/5]${NC} Setting up background service..."
55
56
  AGENT_PATH=$(which indieclaw-agent)
56
57
  CURRENT_USER=$(whoami)
57
58
 
@@ -74,32 +75,72 @@ EOF
74
75
 
75
76
  $SUDO systemctl daemon-reload
76
77
  $SUDO systemctl enable indieclaw-agent
77
- $SUDO systemctl start indieclaw-agent
78
+ $SUDO systemctl restart indieclaw-agent
78
79
  echo -e " ${GREEN}✓${NC} Service created and started"
79
80
 
80
- # Step 4: Wait for token to be generated
81
+ # Step 4: Wait for token and detect IP
82
+ echo -e "${YELLOW}[4/5]${NC} Detecting configuration..."
81
83
  sleep 2
82
84
 
83
- # Show token
84
- echo ""
85
- echo -e "${CYAN}═══════════════════════════════════════${NC}"
86
- echo ""
85
+ PORT=3100
86
+ HOSTNAME=$(hostname)
87
87
 
88
+ # Get token
88
89
  if [ -f "$HOME/.indieclaw-token" ]; then
89
90
  TOKEN=$(cat "$HOME/.indieclaw-token")
90
- echo -e " ${GREEN}${BOLD}Setup complete!${NC}"
91
- echo ""
92
- echo -e " Your auth token:"
93
- echo ""
94
- echo -e " ${BOLD}${CYAN}${TOKEN}${NC}"
95
- echo ""
96
- echo -e " Copy this token into the IndieClaw app."
97
- echo -e " Port: ${BOLD}3100${NC}"
98
91
  else
99
- echo -e " ${GREEN}${BOLD}Setup complete!${NC}"
92
+ echo -e " ${YELLOW}⚠${NC} Token file not found yet. Check: cat ~/.indieclaw-token"
93
+ TOKEN=""
94
+ fi
95
+
96
+ # Detect IP (same logic as agent: try tailscale first, fallback to network)
97
+ MACHINE_IP=""
98
+ if command -v tailscale &> /dev/null; then
99
+ MACHINE_IP=$(tailscale ip -4 2>/dev/null || true)
100
+ fi
101
+ if [ -z "$MACHINE_IP" ]; then
102
+ MACHINE_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || ip route get 1 2>/dev/null | awk '{print $7; exit}' || echo "")
103
+ fi
104
+ if [ -z "$MACHINE_IP" ]; then
105
+ MACHINE_IP="YOUR_SERVER_IP"
106
+ fi
107
+
108
+ echo -e " ${GREEN}✓${NC} IP: ${MACHINE_IP}"
109
+
110
+ # Step 5: Check OpenClaw
111
+ echo -e "${YELLOW}[5/5]${NC} Checking OpenClaw..."
112
+ OPENCLAW_STATUS="not detected"
113
+ if curl -s --max-time 2 http://127.0.0.1:18789/v1/models > /dev/null 2>&1; then
114
+ OPENCLAW_STATUS="detected on port 18789"
115
+ echo -e " ${GREEN}✓${NC} OpenClaw detected on port 18789"
116
+ else
117
+ echo -e " ${YELLOW}—${NC} OpenClaw not detected on port 18789 (optional, for AI features)"
118
+ fi
119
+
120
+ # Build deep link
121
+ DEEP_LINK="indieclaw://connect?host=${MACHINE_IP}&port=${PORT}&token=${TOKEN}&name=${HOSTNAME}&tls=0"
122
+
123
+ # Show results
124
+ echo ""
125
+ echo -e "${CYAN}╔═══════════════════════════════════════╗${NC}"
126
+ echo -e "${CYAN}║ ${BOLD}IndieClaw Agent v${AGENT_VERSION}${NC}${CYAN} ║${NC}"
127
+ echo -e "${CYAN}╠═══════════════════════════════════════╣${NC}"
128
+ echo -e "${CYAN}║${NC} Port: ${BOLD}${PORT}${NC}"
129
+ echo -e "${CYAN}║${NC} IP: ${BOLD}${MACHINE_IP}${NC}"
130
+ echo -e "${CYAN}║${NC} OpenClaw: ${BOLD}${OPENCLAW_STATUS}${NC}"
131
+ echo -e "${CYAN}╚═══════════════════════════════════════╝${NC}"
132
+ echo ""
133
+
134
+ if [ -n "$TOKEN" ]; then
135
+ echo -e " ${BOLD}Auth Token:${NC}"
136
+ echo -e " ${CYAN}${TOKEN}${NC}"
137
+ echo ""
138
+ echo -e " ${BOLD}Deep Link (paste in phone browser):${NC}"
139
+ echo -e " ${CYAN}${DEEP_LINK}${NC}"
100
140
  echo ""
101
- echo -e " Run this to see your token:"
102
- echo -e " ${BOLD}cat ~/.indieclaw-token${NC}"
141
+ echo -e " ${BOLD}Or scan QR code:${NC}"
142
+ echo -e " Run: ${BOLD}indieclaw-agent${NC} interactively to see QR code"
143
+ echo -e " Or: ${BOLD}sudo journalctl -u indieclaw-agent --no-pager | head -50${NC}"
103
144
  fi
104
145
 
105
146
  echo ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indieclaw-agent",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Manage your server from your phone. Agent for the IndieClaw mobile app.",
5
5
  "main": "index.js",
6
6
  "bin": {