groove-dev 0.27.217 → 0.27.220
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/.promote-remotes +1 -0
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +2 -1
- package/node_modules/@groove-dev/daemon/src/terminal-pty.js +29 -11
- package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +16 -2
- package/node_modules/@groove-dev/daemon/test/claude-code-provider.test.js +4 -4
- package/node_modules/@groove-dev/daemon/test/terminal-pty.test.js +80 -0
- package/node_modules/@groove-dev/daemon/test/tunnel-manager.test.js +11 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-BUmxCPjv.js +1055 -0
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/providers/claude-code.js +2 -1
- package/packages/daemon/src/terminal-pty.js +29 -11
- package/packages/daemon/src/tunnel-manager.js +16 -2
- package/packages/gui/dist/assets/index-BUmxCPjv.js +1055 -0
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-DDdFdSWx.js +0 -1099
- package/packages/gui/dist/assets/index-DDdFdSWx.js +0 -1099
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
8
8
|
<title>Groove GUI</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-BUmxCPjv.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-26L3JoZv.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/reactflow-DoBZjiHE.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-BYKpdS2W.js">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.220",
|
|
4
4
|
"description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -43,11 +43,12 @@ export class ClaudeCodeProvider extends Provider {
|
|
|
43
43
|
// FIRST model of a tier. Opus 5 stays first so auto-routing doesn't silently
|
|
44
44
|
// move heavy agents onto the Fable price tier (2× Opus per token) — Fable is
|
|
45
45
|
// an explicit user choice.
|
|
46
|
-
{ id: 'claude-opus-5', name: 'Claude Opus 5', tier: 'heavy', contextWindow: 1_000_000 },
|
|
46
|
+
{ id: 'claude-opus-5-5', name: 'Claude Opus 5.5', tier: 'heavy', contextWindow: 1_000_000 },
|
|
47
47
|
{ id: 'claude-fable-5-1', name: 'Claude Fable 5.1', tier: 'heavy', contextWindow: 1_000_000 },
|
|
48
48
|
{ id: 'claude-fable-5', name: 'Claude Fable 5', tier: 'heavy', contextWindow: 1_000_000 },
|
|
49
49
|
{ id: 'claude-opus-4-8', name: 'Claude Opus 4.8', tier: 'heavy', contextWindow: 1_000_000 },
|
|
50
50
|
{ id: 'claude-opus-4-6', name: 'Claude Opus 4.6', tier: 'heavy', contextWindow: 1_000_000 },
|
|
51
|
+
{ id: 'claude-sonnet-5', name: 'Claude Sonnet 5', tier: 'medium', contextWindow: 1_000_000 },
|
|
51
52
|
{ id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6', tier: 'medium', contextWindow: 200_000 },
|
|
52
53
|
{ id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5', tier: 'light', contextWindow: 200_000 },
|
|
53
54
|
];
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { spawn, execFileSync } from 'child_process';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
|
+
import { StringDecoder } from 'string_decoder';
|
|
7
8
|
|
|
8
9
|
// Python helper that creates a real PTY and relays I/O through stdin/stdout pipes.
|
|
9
10
|
// The shell sees a genuine TTY — prompts, colors, line editing, tab completion all work.
|
|
@@ -64,12 +65,22 @@ try:
|
|
|
64
65
|
bel_pos = stdin_buf.find(ESC_END)
|
|
65
66
|
if bel_pos == -1:
|
|
66
67
|
break
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
# Only OUR resize command lives on this channel — no real terminal
|
|
69
|
+
# sends OSC 7 as keyboard input. A malformed one used to raise
|
|
70
|
+
# inside this loop, escape it, and take the whole shell down; now
|
|
71
|
+
# it is simply dropped (forwarding it would feed the shell's line
|
|
72
|
+
# editor a garbage key chord).
|
|
73
|
+
raw = stdin_buf[:bel_pos+1]
|
|
72
74
|
stdin_buf = stdin_buf[bel_pos+1:]
|
|
75
|
+
try:
|
|
76
|
+
params = raw[4:-1].decode().split(';')
|
|
77
|
+
if len(params) == 2:
|
|
78
|
+
r, c = int(params[0]), int(params[1])
|
|
79
|
+
if 0 < r < 1000 and 0 < c < 1000:
|
|
80
|
+
fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack('HHHH', r, c, 0, 0))
|
|
81
|
+
os.kill(pid, signal.SIGWINCH)
|
|
82
|
+
except (ValueError, UnicodeDecodeError, OSError):
|
|
83
|
+
pass
|
|
73
84
|
if master in rlist:
|
|
74
85
|
try:
|
|
75
86
|
data = os.read(master, 4096)
|
|
@@ -128,16 +139,23 @@ export class TerminalManager {
|
|
|
128
139
|
const session = { proc, ws, id, label: options.label || '' };
|
|
129
140
|
this.sessions.set(id, session);
|
|
130
141
|
|
|
142
|
+
// The PTY relay hands us arbitrary 4096-byte slices, and a multi-byte UTF-8
|
|
143
|
+
// character (box drawing, emoji — TUI apps are full of them) can straddle a
|
|
144
|
+
// slice. Buffer.toString() on each slice independently turns every such
|
|
145
|
+
// character into U+FFFD garbage; a StringDecoder carries the partial byte
|
|
146
|
+
// sequence across chunks.
|
|
147
|
+
const outDecoder = new StringDecoder('utf8');
|
|
148
|
+
const errDecoder = new StringDecoder('utf8');
|
|
131
149
|
proc.stdout.on('data', (data) => {
|
|
132
|
-
if (ws.readyState
|
|
133
|
-
|
|
134
|
-
}
|
|
150
|
+
if (ws.readyState !== 1) return;
|
|
151
|
+
const text = outDecoder.write(data);
|
|
152
|
+
if (text) ws.send(JSON.stringify({ type: 'terminal:output', id, data: text }));
|
|
135
153
|
});
|
|
136
154
|
|
|
137
155
|
proc.stderr.on('data', (data) => {
|
|
138
|
-
if (ws.readyState
|
|
139
|
-
|
|
140
|
-
}
|
|
156
|
+
if (ws.readyState !== 1) return;
|
|
157
|
+
const text = errDecoder.write(data);
|
|
158
|
+
if (text) ws.send(JSON.stringify({ type: 'terminal:output', id, data: text }));
|
|
141
159
|
});
|
|
142
160
|
|
|
143
161
|
proc.on('exit', (code) => {
|
|
@@ -15,6 +15,20 @@ function getLocalVersion() {
|
|
|
15
15
|
} catch { return '0.0.0'; }
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// True only when `a` is strictly older than `b` (numeric x.y.z; any suffix such
|
|
19
|
+
// as "-local" is ignored). Auto-upgrade must never move a remote BACKWARDS: a
|
|
20
|
+
// box running a newer local build (promote-local.sh) than npm's latest would
|
|
21
|
+
// otherwise be "upgraded" down to the published release on every connect.
|
|
22
|
+
export function isOlderVersion(a, b) {
|
|
23
|
+
const parse = (v) => String(v || '').split('-')[0].split('.').map((n) => parseInt(n, 10) || 0);
|
|
24
|
+
const pa = parse(a), pb = parse(b);
|
|
25
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
26
|
+
const d = (pa[i] || 0) - (pb[i] || 0);
|
|
27
|
+
if (d !== 0) return d < 0;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
const REMOTE_PORT = 31415;
|
|
19
33
|
|
|
20
34
|
// Every remote `groove start` must run from the directory of the daemon's
|
|
@@ -665,13 +679,13 @@ export class TunnelManager {
|
|
|
665
679
|
}).trim();
|
|
666
680
|
} catch { return; }
|
|
667
681
|
|
|
668
|
-
if (!npmVer || npmVer
|
|
682
|
+
if (!npmVer || !isOlderVersion(remoteVer, npmVer)) {
|
|
669
683
|
const localVer = getLocalVersion();
|
|
670
684
|
this.daemon.broadcast({ type: 'tunnel.version-info', data: { id, localVersion: localVer, remoteVersion: remoteVer, match: remoteVer === localVer } });
|
|
671
685
|
return;
|
|
672
686
|
}
|
|
673
687
|
|
|
674
|
-
// Remote is behind npm — upgrade
|
|
688
|
+
// Remote is strictly behind npm — upgrade
|
|
675
689
|
this.daemon.broadcast({ type: 'tunnel.status', data: { id, step: 'upgrading', from: remoteVer, to: npmVer } });
|
|
676
690
|
|
|
677
691
|
const target = `${config.user}@${config.host}`;
|