@virtengine/openfleet 0.25.0 → 0.26.1
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/.env.example +7 -3
- package/cli.mjs +62 -0
- package/package.json +6 -2
- package/publish.mjs +85 -1
- package/telegram-bot.mjs +1 -1
package/.env.example
CHANGED
|
@@ -735,11 +735,15 @@ COMPLEXITY_ROUTING_ENABLED=true
|
|
|
735
735
|
# COMPLEXITY_ROUTING_CODEX_LOW_REASONING=low
|
|
736
736
|
# COMPLEXITY_ROUTING_CODEX_MEDIUM_MODEL=gpt-5.2-codex
|
|
737
737
|
# COMPLEXITY_ROUTING_CODEX_MEDIUM_VARIANT=DEFAULT
|
|
738
|
+
# COMPLEXITY_ROUTING_CODEX_MEDIUM_REASONING=medium
|
|
738
739
|
# COMPLEXITY_ROUTING_CODEX_HIGH_MODEL=gpt-5.1-codex-max
|
|
739
740
|
# COMPLEXITY_ROUTING_CODEX_HIGH_VARIANT=GPT51_CODEX_MAX
|
|
740
|
-
#
|
|
741
|
-
#
|
|
742
|
-
#
|
|
741
|
+
# COMPLEXITY_ROUTING_CODEX_HIGH_REASONING=high
|
|
742
|
+
# COMPLEXITY_ROUTING_COPILOT_LOW_MODEL=claude-haiku-4.5
|
|
743
|
+
# COMPLEXITY_ROUTING_COPILOT_MEDIUM_MODEL=claude-sonnet-4.5
|
|
744
|
+
# COMPLEXITY_ROUTING_COPILOT_MEDIUM_REASONING=medium
|
|
745
|
+
# COMPLEXITY_ROUTING_COPILOT_HIGH_MODEL=claude-opus-4.6
|
|
746
|
+
# COMPLEXITY_ROUTING_COPILOT_HIGH_REASONING=high
|
|
743
747
|
|
|
744
748
|
# ─── Shared Cloud Workspaces ────────────────────────────────────────────────
|
|
745
749
|
# Registry file for shared workspace leasing (default: .cache/openfleet/shared-workspaces.json)
|
package/cli.mjs
CHANGED
|
@@ -689,6 +689,68 @@ async function main() {
|
|
|
689
689
|
console.log("\n Setup complete! Starting openfleet...\n");
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
+
// ── Handle --echo-logs: tail the active monitor's log instead of spawning a new instance ──
|
|
693
|
+
if (args.includes("--echo-logs")) {
|
|
694
|
+
// Search for the monitor PID file in common cache locations
|
|
695
|
+
const candidatePidFiles = [
|
|
696
|
+
process.env.CODEX_MONITOR_DIR
|
|
697
|
+
? resolve(process.env.CODEX_MONITOR_DIR, ".cache", "openfleet.pid")
|
|
698
|
+
: null,
|
|
699
|
+
resolve(__dirname, "..", ".cache", "openfleet.pid"),
|
|
700
|
+
resolve(process.cwd(), ".cache", "openfleet.pid"),
|
|
701
|
+
].filter(Boolean);
|
|
702
|
+
|
|
703
|
+
let activePidFile = null;
|
|
704
|
+
for (const f of candidatePidFiles) {
|
|
705
|
+
if (existsSync(f)) {
|
|
706
|
+
activePidFile = f;
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (activePidFile) {
|
|
712
|
+
try {
|
|
713
|
+
const pidData = JSON.parse(readFileSync(activePidFile, "utf8"));
|
|
714
|
+
const monitorPid = Number(pidData.pid);
|
|
715
|
+
const monitorPath = (pidData.argv || [])[1] || "";
|
|
716
|
+
|
|
717
|
+
let isAlive = false;
|
|
718
|
+
try {
|
|
719
|
+
process.kill(monitorPid, 0);
|
|
720
|
+
isAlive = true;
|
|
721
|
+
} catch {}
|
|
722
|
+
|
|
723
|
+
if (isAlive && monitorPath) {
|
|
724
|
+
const logDir = resolve(dirname(monitorPath), "logs");
|
|
725
|
+
const daemonLog = resolve(logDir, "daemon.log");
|
|
726
|
+
const monitorLog = resolve(logDir, "monitor.log");
|
|
727
|
+
const logFile = existsSync(daemonLog) ? daemonLog : monitorLog;
|
|
728
|
+
|
|
729
|
+
if (existsSync(logFile)) {
|
|
730
|
+
console.log(
|
|
731
|
+
`\n Tailing logs for active openfleet (PID ${monitorPid}):\n ${logFile}\n`,
|
|
732
|
+
);
|
|
733
|
+
await new Promise((res) => {
|
|
734
|
+
const tail = spawn("tail", ["-f", "-n", "200", logFile], {
|
|
735
|
+
stdio: "inherit",
|
|
736
|
+
});
|
|
737
|
+
tail.on("exit", res);
|
|
738
|
+
process.on("SIGINT", () => {
|
|
739
|
+
tail.kill();
|
|
740
|
+
res();
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
process.exit(0);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
} catch {
|
|
747
|
+
// best-effort — fall through to normal start
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// No active monitor found — start normally; echoLogs will be picked up by config.mjs
|
|
752
|
+
}
|
|
753
|
+
|
|
692
754
|
// Fork monitor as a child process — enables self-restart on source changes.
|
|
693
755
|
// When monitor exits with code 75, cli re-forks with a fresh ESM module cache.
|
|
694
756
|
await runMonitor();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@virtengine/openfleet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.1",
|
|
4
4
|
"description": "AI-powered orchestrator supervisor — manages AI agent executors with failover, auto-restarts on failure, analyzes crashes with Codex SDK, creates PRs via Vibe-Kanban API, and sends Telegram notifications. Supports N executors with weighted distribution, multi-repo projects, and auto-setup.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache 2.0",
|
|
@@ -92,7 +92,11 @@
|
|
|
92
92
|
"prepush:check": "npm run syntax:check && npm test",
|
|
93
93
|
"prepublishOnly": "node prepublish-check.mjs",
|
|
94
94
|
"publish:env": "node publish.mjs",
|
|
95
|
-
"publish:dry-run": "node publish.mjs --dry-run"
|
|
95
|
+
"publish:dry-run": "node publish.mjs --dry-run",
|
|
96
|
+
"publish:minor": "node publish.mjs --bump minor",
|
|
97
|
+
"publish:major": "node publish.mjs --bump major",
|
|
98
|
+
"publish:minor:dry": "node publish.mjs --bump minor --dry-run",
|
|
99
|
+
"publish:major:dry": "node publish.mjs --bump major --dry-run"
|
|
96
100
|
},
|
|
97
101
|
"files": [
|
|
98
102
|
".env.example",
|
package/publish.mjs
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
//
|
|
3
|
+
// Usage:
|
|
4
|
+
// node publish.mjs # publish at current version
|
|
5
|
+
// node publish.mjs --bump minor # 0.25.0 → 0.25.1 (patch digit)
|
|
6
|
+
// node publish.mjs --bump major # 0.25.0 → 0.26.0 (minor digit)
|
|
7
|
+
// node publish.mjs --bump minor --dry-run
|
|
8
|
+
//
|
|
9
|
+
// Terminology matches the openfleet convention (not semver):
|
|
10
|
+
// minor = last digit (semver patch)
|
|
11
|
+
// major = middle digit (semver minor)
|
|
2
12
|
|
|
3
13
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
5
15
|
import { tmpdir } from "node:os";
|
|
6
16
|
import { join, resolve } from "node:path";
|
|
7
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -64,8 +74,82 @@ function runCheck(label, command, args, env) {
|
|
|
64
74
|
|
|
65
75
|
const NPM_BIN = "npm";
|
|
66
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Bump the version in package.json and sync package-lock.json.
|
|
79
|
+
* type: "minor" → patch digit (0.25.0 → 0.25.1)
|
|
80
|
+
* "major" → middle digit (0.25.0 → 0.26.0)
|
|
81
|
+
* Returns the new version string.
|
|
82
|
+
*/
|
|
83
|
+
function bumpVersion(type, dryRun) {
|
|
84
|
+
const pkgPath = resolve(SCRIPT_DIR, "package.json");
|
|
85
|
+
const lockPath = resolve(SCRIPT_DIR, "package-lock.json");
|
|
86
|
+
|
|
87
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
88
|
+
const [maj, mid, pat] = pkg.version.split(".").map(Number);
|
|
89
|
+
|
|
90
|
+
let newVersion;
|
|
91
|
+
if (type === "minor") {
|
|
92
|
+
// minor = patch digit (last number)
|
|
93
|
+
newVersion = `${maj}.${mid}.${pat + 1}`;
|
|
94
|
+
} else if (type === "major") {
|
|
95
|
+
// major = middle digit, reset patch
|
|
96
|
+
newVersion = `${maj}.${mid + 1}.0`;
|
|
97
|
+
} else {
|
|
98
|
+
console.error(
|
|
99
|
+
`[publish] Unknown bump type "${type}". Use "minor" (0.25.0→0.25.1) or "major" (0.25.0→0.26.0).`,
|
|
100
|
+
);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log(`[publish] Bumping version: ${pkg.version} → ${newVersion}`);
|
|
105
|
+
|
|
106
|
+
if (!dryRun) {
|
|
107
|
+
pkg.version = newVersion;
|
|
108
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
109
|
+
|
|
110
|
+
// Update package-lock.json in-place
|
|
111
|
+
try {
|
|
112
|
+
const lock = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
113
|
+
lock.version = newVersion;
|
|
114
|
+
if (lock.packages?.[""] != null) {
|
|
115
|
+
lock.packages[""].version = newVersion;
|
|
116
|
+
}
|
|
117
|
+
writeFileSync(lockPath, JSON.stringify(lock, null, 2) + "\n", "utf8");
|
|
118
|
+
console.log(
|
|
119
|
+
`[publish] package.json + package-lock.json updated to ${newVersion}`,
|
|
120
|
+
);
|
|
121
|
+
} catch {
|
|
122
|
+
console.warn(
|
|
123
|
+
"[publish] Could not update package-lock.json — regenerating...",
|
|
124
|
+
);
|
|
125
|
+
spawnSync(NPM_BIN, ["install", "--package-lock-only", "--ignore-scripts"], {
|
|
126
|
+
stdio: "inherit",
|
|
127
|
+
cwd: SCRIPT_DIR,
|
|
128
|
+
shell: true,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
console.log(
|
|
133
|
+
`[publish] dry-run: would write version ${newVersion} to package.json & package-lock.json`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return newVersion;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function getBumpArg() {
|
|
141
|
+
const idx = process.argv.indexOf("--bump");
|
|
142
|
+
if (idx !== -1 && process.argv[idx + 1]) return process.argv[idx + 1];
|
|
143
|
+
const flag = process.argv.find((a) => a.startsWith("--bump="));
|
|
144
|
+
if (flag) return flag.slice(7);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
67
148
|
function main() {
|
|
149
|
+
const bumpType = getBumpArg();
|
|
68
150
|
const dryRun = hasArg("--dry-run");
|
|
151
|
+
if (bumpType) bumpVersion(bumpType, dryRun);
|
|
152
|
+
|
|
69
153
|
const tag = process.env.NPM_PUBLISH_TAG || "latest";
|
|
70
154
|
const otp = process.env.NPM_OTP || "";
|
|
71
155
|
const access = process.env.NPM_PUBLISH_ACCESS || "public";
|
package/telegram-bot.mjs
CHANGED
|
@@ -2614,7 +2614,7 @@ async function clearWebAppMenuButton() {
|
|
|
2614
2614
|
}
|
|
2615
2615
|
}
|
|
2616
2616
|
|
|
2617
|
-
const MENU_BUTTON_REFRESH_MS =
|
|
2617
|
+
const MENU_BUTTON_REFRESH_MS = 60 * 1000; // 1 minute — re-sync after tunnel URL rotates
|
|
2618
2618
|
|
|
2619
2619
|
async function refreshMenuButton() {
|
|
2620
2620
|
const { uiUrl: currentUiUrl, webAppUrl: currentUrl } = syncUiUrlsFromServer();
|