groove-dev 0.27.107 → 0.27.108
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/TRAINING_DATA.md +9 -0
- package/moe-training/client/envelope-builder.js +5 -0
- package/moe-training/client/scrubber.js +1 -1
- package/moe-training/client/step-classifier.js +22 -6
- package/moe-training/client/trajectory-capture.js +15 -4
- package/moe-training/shared/constants.js +2 -0
- package/moe-training/shared/envelope-schema.js +1 -1
- package/moe-training/test/client/envelope-builder.test.js +32 -0
- package/moe-training/test/client/scrubber.test.js +13 -0
- package/moe-training/test/client/step-classifier.test.js +96 -7
- package/moe-training/test/client/trajectory-capture.test.js +53 -6
- 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/api.js +29 -2
- package/node_modules/@groove-dev/daemon/src/process.js +5 -5
- package/node_modules/@groove-dev/gui/dist/assets/{index-DkAGIluW.js → index-CEgtSfbG.js} +1748 -1745
- package/node_modules/@groove-dev/gui/dist/assets/{index-QwgLRN8B.css → index-_3cJS_UG.css} +1 -1
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/src/components/layout/command-palette.jsx +2 -1
- package/node_modules/@groove-dev/gui/src/components/layout/status-bar.jsx +9 -3
- package/node_modules/@groove-dev/gui/src/components/settings/federation-panel.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/settings/federation-peers.jsx +14 -2
- package/node_modules/@groove-dev/gui/src/components/settings/quick-connect.jsx +9 -0
- package/node_modules/@groove-dev/gui/src/stores/groove.js +10 -0
- package/node_modules/@groove-dev/gui/src/views/federation.jsx +56 -15
- package/node_modules/moe-training/client/envelope-builder.js +5 -0
- package/node_modules/moe-training/client/scrubber.js +1 -1
- package/node_modules/moe-training/client/step-classifier.js +22 -6
- package/node_modules/moe-training/client/trajectory-capture.js +15 -4
- package/node_modules/moe-training/shared/constants.js +2 -0
- package/node_modules/moe-training/shared/envelope-schema.js +1 -1
- package/node_modules/moe-training/test/client/envelope-builder.test.js +32 -0
- package/node_modules/moe-training/test/client/scrubber.test.js +13 -0
- package/node_modules/moe-training/test/client/step-classifier.test.js +96 -7
- package/node_modules/moe-training/test/client/trajectory-capture.test.js +53 -6
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +29 -2
- package/packages/daemon/src/process.js +5 -5
- package/packages/gui/dist/assets/{index-DkAGIluW.js → index-CEgtSfbG.js} +1748 -1745
- package/packages/gui/dist/assets/{index-QwgLRN8B.css → index-_3cJS_UG.css} +1 -1
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/components/layout/command-palette.jsx +2 -1
- package/packages/gui/src/components/layout/status-bar.jsx +9 -3
- package/packages/gui/src/components/settings/federation-panel.jsx +2 -2
- package/packages/gui/src/components/settings/federation-peers.jsx +14 -2
- package/packages/gui/src/components/settings/quick-connect.jsx +9 -0
- package/packages/gui/src/stores/groove.js +10 -0
- package/packages/gui/src/views/federation.jsx +56 -15
- package/ssh/main.js +2253 -0
|
@@ -29,12 +29,17 @@ function makeCtx(overrides = {}) {
|
|
|
29
29
|
session_quality: overrides.quality ?? 80,
|
|
30
30
|
},
|
|
31
31
|
builder: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
_metadata: {},
|
|
33
|
+
updateMetadata(updates) { Object.assign(this._metadata, updates); },
|
|
34
|
+
buildSessionClose: function (outcome) {
|
|
35
|
+
return {
|
|
36
|
+
envelope_id: 'env_test_close',
|
|
37
|
+
session_id: 'sess_test_1',
|
|
38
|
+
type: 'SESSION_CLOSE',
|
|
39
|
+
metadata: { ...this._metadata },
|
|
40
|
+
outcome,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
38
43
|
},
|
|
39
44
|
};
|
|
40
45
|
}
|
|
@@ -439,6 +444,48 @@ describe('TrajectoryCapture — _computeQuality', () => {
|
|
|
439
444
|
});
|
|
440
445
|
});
|
|
441
446
|
|
|
447
|
+
describe('TrajectoryCapture — domain_tags in SESSION_CLOSE', () => {
|
|
448
|
+
it('domain_tags set on ctx.metadata flow into SESSION_CLOSE via updateMetadata', () => {
|
|
449
|
+
const tc = makeTc();
|
|
450
|
+
const captured = [];
|
|
451
|
+
tc._signAndTransmit = (_sid, envelope) => { captured.push(envelope); };
|
|
452
|
+
|
|
453
|
+
const ctx = makeCtx();
|
|
454
|
+
ctx.metadata.domain_tags = {
|
|
455
|
+
primary: { domain: 'react_frontend', confidence: 0.3 },
|
|
456
|
+
secondary: { domain: 'typescript_node', confidence: 0.25 },
|
|
457
|
+
tertiary: { domain: 'python', confidence: 0 },
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
ctx.builder.updateMetadata({
|
|
461
|
+
domain_tags: ctx.metadata.domain_tags,
|
|
462
|
+
session_quality: ctx.metadata.session_quality,
|
|
463
|
+
});
|
|
464
|
+
const close = ctx.builder.buildSessionClose({
|
|
465
|
+
status: 'SUCCESS', total_steps: 10, total_chunks: 1,
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
assert.ok(close.metadata, 'SESSION_CLOSE must have metadata');
|
|
469
|
+
assert.deepEqual(close.metadata.domain_tags, ctx.metadata.domain_tags);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('SESSION_CLOSE metadata is absent domain_tags when tagger returns null', () => {
|
|
473
|
+
const ctx = makeCtx();
|
|
474
|
+
ctx.metadata.domain_tags = null;
|
|
475
|
+
|
|
476
|
+
ctx.builder.updateMetadata({
|
|
477
|
+
domain_tags: null,
|
|
478
|
+
session_quality: ctx.metadata.session_quality,
|
|
479
|
+
});
|
|
480
|
+
const close = ctx.builder.buildSessionClose({
|
|
481
|
+
status: 'SUCCESS', total_steps: 5, total_chunks: 1,
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
assert.ok(close.metadata, 'SESSION_CLOSE must have metadata');
|
|
485
|
+
assert.equal(close.metadata.domain_tags, null);
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
|
|
442
489
|
describe('TrajectoryCapture — onParsedOutput', () => {
|
|
443
490
|
function makeEnabledTc() {
|
|
444
491
|
const tc = makeTc();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.108",
|
|
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)",
|
|
@@ -62,12 +62,12 @@ async function _executeApprovalRetry(daemon, approval) {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
if (rp.agentId) {
|
|
65
|
-
await daemon.processes.sendMessage(rp.agentId, `Your ${rp.type === 'integration_exec' ? 'integration action' : 'upload'} was approved and executed successfully. Result: ${resultText}
|
|
65
|
+
await daemon.processes.sendMessage(rp.agentId, `Your ${rp.type === 'integration_exec' ? 'integration action' : 'upload'} was approved and executed successfully. Result: ${resultText}`, 'system');
|
|
66
66
|
}
|
|
67
67
|
} catch (err) {
|
|
68
68
|
console.log(`[Groove] Auto-retry for approval ${approval.id} failed: ${err.message}`);
|
|
69
69
|
if (rp.agentId) {
|
|
70
|
-
daemon.processes.sendMessage(rp.agentId, `Your ${rp.type === 'integration_exec' ? 'integration action' : 'upload'} was approved but execution failed: ${err.message}
|
|
70
|
+
daemon.processes.sendMessage(rp.agentId, `Your ${rp.type === 'integration_exec' ? 'integration action' : 'upload'} was approved but execution failed: ${err.message}`, 'system').catch(() => {});
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -4211,6 +4211,33 @@ Keep responses concise. Help them think, don't lecture them about the system the
|
|
|
4211
4211
|
res.json(daemon.federation.getStatus());
|
|
4212
4212
|
});
|
|
4213
4213
|
|
|
4214
|
+
app.get('/api/federation/test', async (req, res) => {
|
|
4215
|
+
const target = req.query.target;
|
|
4216
|
+
if (!target) return res.status(400).json({ error: 'target required' });
|
|
4217
|
+
const host = target.split(':')[0];
|
|
4218
|
+
const privatePatterns = [
|
|
4219
|
+
/^127\./, /^10\./, /^192\.168\./, /^172\.(1[6-9]|2\d|3[01])\./,
|
|
4220
|
+
/^0\./, /^169\.254\./, /^localhost$/i, /^::1$/, /^\[::1\]$/,
|
|
4221
|
+
/^0\.0\.0\.0$/, /^fc/i, /^fd/i, /^fe80/i,
|
|
4222
|
+
];
|
|
4223
|
+
if (privatePatterns.some(p => p.test(host))) {
|
|
4224
|
+
return res.status(400).json({ error: 'Private/local addresses are not allowed' });
|
|
4225
|
+
}
|
|
4226
|
+
try {
|
|
4227
|
+
const controller = new AbortController();
|
|
4228
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
4229
|
+
const resp = await fetch(`http://${target}/api/health`, { signal: controller.signal });
|
|
4230
|
+
clearTimeout(timeout);
|
|
4231
|
+
if (resp.ok) {
|
|
4232
|
+
const data = await resp.json();
|
|
4233
|
+
return res.json({ reachable: true, version: data.version, peerId: data.daemonId, agents: data.agents });
|
|
4234
|
+
}
|
|
4235
|
+
res.json({ reachable: false });
|
|
4236
|
+
} catch {
|
|
4237
|
+
res.json({ reachable: false });
|
|
4238
|
+
}
|
|
4239
|
+
});
|
|
4240
|
+
|
|
4214
4241
|
// List peers
|
|
4215
4242
|
app.get('/api/federation/peers', (req, res) => {
|
|
4216
4243
|
res.json(daemon.federation.getPeers());
|
|
@@ -1434,7 +1434,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
1434
1434
|
if (existing && (existing.status === 'running' || existing.status === 'starting')) {
|
|
1435
1435
|
// Agent already active — reuse it instead of spawning a duplicate
|
|
1436
1436
|
if (config.prompt) {
|
|
1437
|
-
this.sendMessage(existing.id, config.prompt).catch((err) => {
|
|
1437
|
+
this.sendMessage(existing.id, config.prompt, 'planner').catch((err) => {
|
|
1438
1438
|
console.error(`[Groove] Phase 2 reuse message failed for ${existing.name}: ${err.message}`);
|
|
1439
1439
|
});
|
|
1440
1440
|
}
|
|
@@ -1527,7 +1527,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
1527
1527
|
const message = `Your teammate ${completedAgent.name} (${completedAgent.role}) just finished their work.${fileList}${result ? `\n\nTheir summary:\n${result.slice(0, 2000)}` : ''}\n\nPlease audit their changes: verify correctness, check for bugs, run tests if available, and report any issues.`;
|
|
1528
1528
|
|
|
1529
1529
|
// Send message to the QC agent via the instruct flow
|
|
1530
|
-
this.sendMessage(qc.id, message).catch((err) => {
|
|
1530
|
+
this.sendMessage(qc.id, message, 'system').catch((err) => {
|
|
1531
1531
|
console.error(`[Groove] QC auto-trigger failed: ${err.message}`);
|
|
1532
1532
|
});
|
|
1533
1533
|
|
|
@@ -1651,7 +1651,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
1651
1651
|
if (target.status === 'running') {
|
|
1652
1652
|
let sent = false;
|
|
1653
1653
|
if (this.hasAgentLoop(target.id)) {
|
|
1654
|
-
this.sendMessage(target.id, message).catch(() => {});
|
|
1654
|
+
this.sendMessage(target.id, message, 'agent').catch(() => {});
|
|
1655
1655
|
sent = true;
|
|
1656
1656
|
}
|
|
1657
1657
|
if (!sent && this.daemon.journalist) {
|
|
@@ -2189,7 +2189,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
2189
2189
|
* Send a message to a running agent loop.
|
|
2190
2190
|
* Returns true if the message was sent, false if the agent doesn't have an active loop.
|
|
2191
2191
|
*/
|
|
2192
|
-
async sendMessage(agentId, message) {
|
|
2192
|
+
async sendMessage(agentId, message, source = 'user') {
|
|
2193
2193
|
const handle = this.handles.get(agentId);
|
|
2194
2194
|
if (!handle?.loop) return false;
|
|
2195
2195
|
|
|
@@ -2200,7 +2200,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
2200
2200
|
const wrapped = agent ? wrapWithRoleReminder(agent.role, message) : message;
|
|
2201
2201
|
|
|
2202
2202
|
if (this.daemon.trajectoryCapture) {
|
|
2203
|
-
try { this.daemon.trajectoryCapture.onUserMessage(agentId, message); } catch (e) { /* fail silent */ }
|
|
2203
|
+
try { this.daemon.trajectoryCapture.onUserMessage(agentId, message, source); } catch (e) { /* fail silent */ }
|
|
2204
2204
|
}
|
|
2205
2205
|
|
|
2206
2206
|
loop.sendMessage(wrapped).catch(() => {});
|