fluxy-bot 0.5.44 → 0.5.46
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/bin/cli.js +22 -0
- package/package.json +7 -1
- package/supervisor/index.ts +37 -1
- package/worker/prompts/fluxy-system-prompt.txt +22 -0
package/bin/cli.js
CHANGED
|
@@ -242,6 +242,10 @@ function finalMessage(tunnelUrl, relayUrl) {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
function writeVersionFile(version) {
|
|
246
|
+
try { fs.writeFileSync(path.join(DATA_DIR, 'VERSION'), version); } catch {}
|
|
247
|
+
}
|
|
248
|
+
|
|
245
249
|
// ── Steps ──
|
|
246
250
|
|
|
247
251
|
function createConfig() {
|
|
@@ -401,6 +405,7 @@ async function init() {
|
|
|
401
405
|
banner();
|
|
402
406
|
|
|
403
407
|
createConfig();
|
|
408
|
+
writeVersionFile(pkg.version);
|
|
404
409
|
|
|
405
410
|
const isLinux = os.platform() === 'linux';
|
|
406
411
|
const hasSystemd = isLinux && (() => { try { execSync('systemctl --version', { stdio: 'ignore' }); return true; } catch { return false; } })();
|
|
@@ -720,6 +725,14 @@ async function update() {
|
|
|
720
725
|
}
|
|
721
726
|
stepper.advance();
|
|
722
727
|
|
|
728
|
+
// Read release notes and write version before cleanup
|
|
729
|
+
let releaseNotes = '';
|
|
730
|
+
try {
|
|
731
|
+
const newPkg = JSON.parse(fs.readFileSync(path.join(extracted, 'package.json'), 'utf-8'));
|
|
732
|
+
releaseNotes = newPkg.releaseNotes || '';
|
|
733
|
+
} catch {}
|
|
734
|
+
writeVersionFile(latest.version);
|
|
735
|
+
|
|
723
736
|
// Clean up
|
|
724
737
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
725
738
|
|
|
@@ -736,6 +749,15 @@ async function update() {
|
|
|
736
749
|
|
|
737
750
|
console.log(`\n ${c.blue}${c.bold}✔ Updated to v${latest.version}${c.reset}\n`);
|
|
738
751
|
|
|
752
|
+
if (releaseNotes) {
|
|
753
|
+
console.log(` ${c.bold}${c.white}What's new:${c.reset}`);
|
|
754
|
+
const notes = Array.isArray(releaseNotes) ? releaseNotes : [releaseNotes];
|
|
755
|
+
notes.forEach((note, i) => {
|
|
756
|
+
console.log(` ${c.dim}${i + 1}.${c.reset} ${note}`);
|
|
757
|
+
});
|
|
758
|
+
console.log('');
|
|
759
|
+
}
|
|
760
|
+
|
|
739
761
|
if (daemonWasRunning) {
|
|
740
762
|
if (isServiceActive()) {
|
|
741
763
|
console.log(` ${c.blue}✔${c.reset} Daemon restarted with new version.\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fluxy-bot",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.46",
|
|
4
|
+
"releaseNotes": [
|
|
5
|
+
"Worker and backend now survive systemd environments",
|
|
6
|
+
"Daemon auto-installs on Linux during init/start",
|
|
7
|
+
"Update flow stops daemon before applying files",
|
|
8
|
+
"Status command detects daemon state"
|
|
9
|
+
],
|
|
4
10
|
"description": "Self-hosted, self-evolving AI agent with its own dashboard.",
|
|
5
11
|
"type": "module",
|
|
6
12
|
"license": "MIT",
|
package/supervisor/index.ts
CHANGED
|
@@ -16,7 +16,8 @@ import { startFluxyAgentQuery, stopFluxyAgentQuery, type RecentMessage } from '.
|
|
|
16
16
|
import { ensureFileDirs, saveAttachment, type SavedFile } from './file-saver.js';
|
|
17
17
|
import { startViteDevServers, stopViteDevServers } from './vite-dev.js';
|
|
18
18
|
import { startScheduler, stopScheduler } from './scheduler.js';
|
|
19
|
-
import { execSync } from 'child_process';
|
|
19
|
+
import { execSync, spawn as cpSpawn } from 'child_process';
|
|
20
|
+
import os from 'os';
|
|
20
21
|
|
|
21
22
|
const DIST_FLUXY = path.join(PKG_DIR, 'dist-fluxy');
|
|
22
23
|
|
|
@@ -534,6 +535,11 @@ export async function startSupervisor() {
|
|
|
534
535
|
resetBackendRestarts();
|
|
535
536
|
stopBackend().then(() => spawnBackend(backendPort));
|
|
536
537
|
}
|
|
538
|
+
// Run deferred update if agent requested one
|
|
539
|
+
if (pendingUpdate) {
|
|
540
|
+
pendingUpdate = false;
|
|
541
|
+
runDeferredUpdate();
|
|
542
|
+
}
|
|
537
543
|
return; // don't forward bot:done to client
|
|
538
544
|
}
|
|
539
545
|
|
|
@@ -656,6 +662,26 @@ export async function startSupervisor() {
|
|
|
656
662
|
// Track whether an agent query is active — file watcher defers to bot:done during turns
|
|
657
663
|
let agentQueryActive = false;
|
|
658
664
|
let pendingBackendRestart = false; // Set when file watcher fires during agent turn
|
|
665
|
+
let pendingUpdate = false; // Set when .update file is created during agent turn
|
|
666
|
+
|
|
667
|
+
// Run fluxy update in a separate systemd scope so it survives daemon stop/restart
|
|
668
|
+
function runDeferredUpdate() {
|
|
669
|
+
const cliPath = path.join(PKG_DIR, 'bin', 'cli.js');
|
|
670
|
+
log.info('Deferred update triggered — running fluxy update via systemd-run...');
|
|
671
|
+
try {
|
|
672
|
+
const child = cpSpawn('sudo', [
|
|
673
|
+
'systemd-run', '--quiet',
|
|
674
|
+
'--unit=fluxy-update',
|
|
675
|
+
'--setenv=HOME=' + os.homedir(),
|
|
676
|
+
'--setenv=FLUXY_NODE_PATH=' + process.execPath,
|
|
677
|
+
'--setenv=FLUXY_REAL_HOME=' + os.homedir(),
|
|
678
|
+
process.execPath, cliPath, 'update',
|
|
679
|
+
], { detached: true, stdio: 'ignore' });
|
|
680
|
+
child.unref();
|
|
681
|
+
} catch (err) {
|
|
682
|
+
log.error(`Deferred update failed: ${err instanceof Error ? err.message : err}`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
659
685
|
|
|
660
686
|
// Spawn worker + backend
|
|
661
687
|
spawnWorker(workerPort);
|
|
@@ -712,6 +738,16 @@ export async function startSupervisor() {
|
|
|
712
738
|
try { fs.unlinkSync(path.join(workspaceDir, '.restart')); } catch {}
|
|
713
739
|
scheduleBackendRestart('.restart trigger');
|
|
714
740
|
}
|
|
741
|
+
if (filename === '.update') {
|
|
742
|
+
// Consume the trigger file
|
|
743
|
+
try { fs.unlinkSync(path.join(workspaceDir, '.update')); } catch {}
|
|
744
|
+
if (agentQueryActive) {
|
|
745
|
+
pendingUpdate = true;
|
|
746
|
+
log.info('Update requested — deferring until agent turn ends');
|
|
747
|
+
} else {
|
|
748
|
+
runDeferredUpdate();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
715
751
|
});
|
|
716
752
|
|
|
717
753
|
// Tunnel
|
|
@@ -152,6 +152,28 @@ If a `<CRON_TASK_DETAIL>` block follows the CRON tag, it contains the full instr
|
|
|
152
152
|
|
|
153
153
|
Notify your human only if importance is 7+ — otherwise log results silently.
|
|
154
154
|
|
|
155
|
+
## Self-Update
|
|
156
|
+
|
|
157
|
+
**Check version:** `cat ~/.fluxy/VERSION` (current) vs `npm view fluxy-bot version` (latest).
|
|
158
|
+
|
|
159
|
+
**To update:** Create the trigger file `touch ~/.fluxy/workspace/.update` — the supervisor runs the update after your turn ends. You will
|
|
160
|
+
NOT die. Finish your turn normally.
|
|
161
|
+
|
|
162
|
+
**On PULSE:** Occasionally check for updates (not every pulse — once every few hours). If a new version exists:
|
|
163
|
+
1. Read release notes: `npm view fluxy-bot releaseNotes --json`
|
|
164
|
+
2. `touch ~/.fluxy/workspace/.update`
|
|
165
|
+
3. Save to daily notes: "Updated from vX to vY" + notable changes
|
|
166
|
+
4. Only <Message> the user if release notes contain something important (new feature, breaking change). Skip routine fixes.
|
|
167
|
+
|
|
168
|
+
**When user asks to update:**
|
|
169
|
+
1. Check version, if already latest say so
|
|
170
|
+
2. Otherwise read release notes, `touch ~/.fluxy/workspace/.update`
|
|
171
|
+
3. ALWAYS send a <Message>:
|
|
172
|
+
"Updated to vX.Y.Z! Here's what's new:
|
|
173
|
+
1. ...
|
|
174
|
+
2. ...
|
|
175
|
+
3. ..."
|
|
176
|
+
|
|
155
177
|
## Task Files — `tasks/`
|
|
156
178
|
|
|
157
179
|
Complex cron tasks can have detailed instruction files in `tasks/{cron-id}.md`. The supervisor automatically injects the file content into your context when the cron fires.
|