groove-dev 0.8.2 → 0.8.3
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/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/cli/src/client.js +17 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/index.js +20 -8
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/client.js +17 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/index.js +20 -8
- package/packages/gui/package.json +1 -1
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
// GROOVE CLI — HTTP client for daemon communication
|
|
2
2
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import { existsSync, readFileSync } from 'fs';
|
|
5
|
+
import { resolve } from 'path';
|
|
6
|
+
|
|
7
|
+
function getBaseUrl() {
|
|
8
|
+
if (process.env.GROOVE_URL) return process.env.GROOVE_URL;
|
|
9
|
+
// Read actual port from daemon's port file (supports auto-port rotation)
|
|
10
|
+
try {
|
|
11
|
+
const portFile = resolve(process.cwd(), '.groove', 'daemon.port');
|
|
12
|
+
if (existsSync(portFile)) {
|
|
13
|
+
const port = readFileSync(portFile, 'utf8').trim();
|
|
14
|
+
if (port) return `http://localhost:${port}`;
|
|
15
|
+
}
|
|
16
|
+
} catch { /* fallback */ }
|
|
17
|
+
return 'http://localhost:31415';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const BASE_URL = getBaseUrl();
|
|
5
21
|
|
|
6
22
|
export async function apiCall(method, path, body) {
|
|
7
23
|
const url = `${BASE_URL}${path}`;
|
|
@@ -140,19 +140,29 @@ export class Daemon {
|
|
|
140
140
|
try { unlinkSync(this.pidFile); } catch { /* ignore */ }
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
//
|
|
144
|
-
const
|
|
143
|
+
// Auto-find an open port if the default is taken
|
|
144
|
+
const checkPort = (port) => new Promise((res) => {
|
|
145
145
|
const tester = createNetServer();
|
|
146
146
|
tester.once('error', () => res(false));
|
|
147
147
|
tester.once('listening', () => { tester.close(); res(true); });
|
|
148
|
-
tester.listen(
|
|
148
|
+
tester.listen(port, '127.0.0.1');
|
|
149
149
|
}).catch(() => false);
|
|
150
150
|
|
|
151
|
-
if (!
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
if (!(await checkPort(this.port))) {
|
|
152
|
+
const originalPort = this.port;
|
|
153
|
+
// Try next 10 ports
|
|
154
|
+
let found = false;
|
|
155
|
+
for (let i = 1; i <= 10; i++) {
|
|
156
|
+
if (await checkPort(this.port + i)) {
|
|
157
|
+
this.port = this.port + i;
|
|
158
|
+
found = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!found) {
|
|
163
|
+
console.error(`\n Ports ${originalPort}-${originalPort + 10} are all in use. Free one and try again.\n`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
// Restore persisted state
|
|
@@ -162,6 +172,8 @@ export class Daemon {
|
|
|
162
172
|
return new Promise((resolvePromise) => {
|
|
163
173
|
this.server.listen(this.port, '127.0.0.1', () => {
|
|
164
174
|
writeFileSync(this.pidFile, String(process.pid));
|
|
175
|
+
// Write actual port so CLI can find us (supports auto-port rotation)
|
|
176
|
+
writeFileSync(resolve(this.grooveDir, 'daemon.port'), String(this.port));
|
|
165
177
|
|
|
166
178
|
printWelcome(this.port);
|
|
167
179
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Open-source agent orchestration layer for AI coding tools. GUI dashboard, multi-agent coordination, zero cold-start (Journalist), infinite sessions (adaptive context rotation), AI Project Manager, Quick Launch. Works with Claude Code, Codex, Gemini CLI, Aider, Ollama.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
// GROOVE CLI — HTTP client for daemon communication
|
|
2
2
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import { existsSync, readFileSync } from 'fs';
|
|
5
|
+
import { resolve } from 'path';
|
|
6
|
+
|
|
7
|
+
function getBaseUrl() {
|
|
8
|
+
if (process.env.GROOVE_URL) return process.env.GROOVE_URL;
|
|
9
|
+
// Read actual port from daemon's port file (supports auto-port rotation)
|
|
10
|
+
try {
|
|
11
|
+
const portFile = resolve(process.cwd(), '.groove', 'daemon.port');
|
|
12
|
+
if (existsSync(portFile)) {
|
|
13
|
+
const port = readFileSync(portFile, 'utf8').trim();
|
|
14
|
+
if (port) return `http://localhost:${port}`;
|
|
15
|
+
}
|
|
16
|
+
} catch { /* fallback */ }
|
|
17
|
+
return 'http://localhost:31415';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const BASE_URL = getBaseUrl();
|
|
5
21
|
|
|
6
22
|
export async function apiCall(method, path, body) {
|
|
7
23
|
const url = `${BASE_URL}${path}`;
|
|
@@ -140,19 +140,29 @@ export class Daemon {
|
|
|
140
140
|
try { unlinkSync(this.pidFile); } catch { /* ignore */ }
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
//
|
|
144
|
-
const
|
|
143
|
+
// Auto-find an open port if the default is taken
|
|
144
|
+
const checkPort = (port) => new Promise((res) => {
|
|
145
145
|
const tester = createNetServer();
|
|
146
146
|
tester.once('error', () => res(false));
|
|
147
147
|
tester.once('listening', () => { tester.close(); res(true); });
|
|
148
|
-
tester.listen(
|
|
148
|
+
tester.listen(port, '127.0.0.1');
|
|
149
149
|
}).catch(() => false);
|
|
150
150
|
|
|
151
|
-
if (!
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
if (!(await checkPort(this.port))) {
|
|
152
|
+
const originalPort = this.port;
|
|
153
|
+
// Try next 10 ports
|
|
154
|
+
let found = false;
|
|
155
|
+
for (let i = 1; i <= 10; i++) {
|
|
156
|
+
if (await checkPort(this.port + i)) {
|
|
157
|
+
this.port = this.port + i;
|
|
158
|
+
found = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!found) {
|
|
163
|
+
console.error(`\n Ports ${originalPort}-${originalPort + 10} are all in use. Free one and try again.\n`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
// Restore persisted state
|
|
@@ -162,6 +172,8 @@ export class Daemon {
|
|
|
162
172
|
return new Promise((resolvePromise) => {
|
|
163
173
|
this.server.listen(this.port, '127.0.0.1', () => {
|
|
164
174
|
writeFileSync(this.pidFile, String(process.pid));
|
|
175
|
+
// Write actual port so CLI can find us (supports auto-port rotation)
|
|
176
|
+
writeFileSync(resolve(this.grooveDir, 'daemon.port'), String(this.port));
|
|
165
177
|
|
|
166
178
|
printWelcome(this.port);
|
|
167
179
|
|