bitpull 0.1.19 → 0.1.20
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/bitpull.cjs +29 -8
- package/package.json +1 -1
package/bitpull.cjs
CHANGED
|
@@ -18538,7 +18538,7 @@ async function heartbeat(ctx) {
|
|
|
18538
18538
|
boxKey: ctx.config.boxKeys.publicKey,
|
|
18539
18539
|
...ctx.groups ? { groupStates: ctx.groups.reports() } : {},
|
|
18540
18540
|
// Development runs have no version number.
|
|
18541
|
-
...true ? { agentVersion: "0.1.
|
|
18541
|
+
...true ? { agentVersion: "0.1.20" } : {}
|
|
18542
18542
|
});
|
|
18543
18543
|
}
|
|
18544
18544
|
async function startGroup(ctx, modelId) {
|
|
@@ -19289,9 +19289,9 @@ async function executeJob(ctx, job, sandbox, signal, keyWaitMs = KEY_WAIT_MS) {
|
|
|
19289
19289
|
const safe = containerJobFrom(job, secret, ctx.config.lending);
|
|
19290
19290
|
outcome = sandbox ? await runContainer(safe, sandbox, signal) : { ok: false, usage: {}, error: "no_sandbox" };
|
|
19291
19291
|
} else {
|
|
19292
|
-
const limit = await aiLimitReached(ctx.config.lending.aiLimits);
|
|
19292
|
+
const limit = job.own ? null : await aiLimitReached(ctx.config.lending.aiLimits);
|
|
19293
19293
|
outcome = limit ? { ok: false, usage: {}, error: `lender_limit_reached: ${limit}` } : await runAiTask(spec, job.timeoutSec, ctx.config.ollamaUrl, signal);
|
|
19294
|
-
if (outcome.ok) await recordAiUsage((outcome.usage.promptTokens ?? 0) + (outcome.usage.completionTokens ?? 0)).catch(() => void 0);
|
|
19294
|
+
if (outcome.ok && !job.own) await recordAiUsage((outcome.usage.promptTokens ?? 0) + (outcome.usage.completionTokens ?? 0)).catch(() => void 0);
|
|
19295
19295
|
}
|
|
19296
19296
|
} catch (err) {
|
|
19297
19297
|
const message = err.message;
|
|
@@ -19611,7 +19611,7 @@ async function doctor(cfg) {
|
|
|
19611
19611
|
}
|
|
19612
19612
|
|
|
19613
19613
|
// apps/agent/src/control.ts
|
|
19614
|
-
var APP_VERSION = true ? "0.1.
|
|
19614
|
+
var APP_VERSION = true ? "0.1.20" : "dev";
|
|
19615
19615
|
var UPDATE_MANIFEST = "https://github.com/SamuealPK/bitpull-releases/releases/latest/download/latest.json";
|
|
19616
19616
|
var inDesktopApp = () => /bitpull-agent(\.exe)?$/i.test(process.execPath);
|
|
19617
19617
|
function newerVersion(a, b) {
|
|
@@ -30906,6 +30906,7 @@ var DATA = 2;
|
|
|
30906
30906
|
var CLOSE = 3;
|
|
30907
30907
|
var CHUNK = 64 * 1024;
|
|
30908
30908
|
var PAUSE_BYTES = 4 * 1024 * 1024;
|
|
30909
|
+
var KEEPALIVE_MS = 25e3;
|
|
30909
30910
|
var TunnelCipher = class {
|
|
30910
30911
|
constructor(groupKey, hostSalt, workerSalt, role) {
|
|
30911
30912
|
this.role = role;
|
|
@@ -30998,6 +30999,13 @@ async function startTunnel(o) {
|
|
|
30998
30999
|
ws = socket;
|
|
30999
31000
|
cipher = null;
|
|
31000
31001
|
const mySalt = (0, import_node_crypto8.randomBytes)(32);
|
|
31002
|
+
let answered = true;
|
|
31003
|
+
const keepalive = setInterval(() => {
|
|
31004
|
+
if (!answered) return socket.terminate();
|
|
31005
|
+
answered = false;
|
|
31006
|
+
if (socket.readyState === socket.OPEN) socket.ping();
|
|
31007
|
+
}, o.keepaliveMs ?? KEEPALIVE_MS);
|
|
31008
|
+
socket.on("pong", () => answered = true);
|
|
31001
31009
|
socket.on("message", (data, isBinary2) => {
|
|
31002
31010
|
try {
|
|
31003
31011
|
const buf = data;
|
|
@@ -31019,6 +31027,7 @@ async function startTunnel(o) {
|
|
|
31019
31027
|
}
|
|
31020
31028
|
});
|
|
31021
31029
|
socket.on("close", () => {
|
|
31030
|
+
clearInterval(keepalive);
|
|
31022
31031
|
o.onStatus?.(false);
|
|
31023
31032
|
cipher = null;
|
|
31024
31033
|
closeAll();
|
|
@@ -31130,14 +31139,15 @@ var freePort = () => new Promise((resolve, reject) => {
|
|
|
31130
31139
|
s.close(() => resolve(port));
|
|
31131
31140
|
});
|
|
31132
31141
|
});
|
|
31142
|
+
var engineReason = (tail) => tail.trim().split("\n").filter((l) => !/^\s*\d+\s+\S+\s+0x/.test(l)).pop() ?? "";
|
|
31133
31143
|
function startEngine(exe, args, onExit) {
|
|
31134
31144
|
const dir = (0, import_node_path17.dirname)(exe);
|
|
31135
31145
|
const env = { ...process.env, LD_LIBRARY_PATH: dir, DYLD_LIBRARY_PATH: dir, LLAMA_CACHE: (0, import_node_path17.join)(bitpullHome(), "group-cache") };
|
|
31136
31146
|
const child = (0, import_node_child_process8.spawn)(exe, args, { cwd: dir, windowsHide: true, stdio: ["ignore", "ignore", "pipe"], env });
|
|
31137
31147
|
let tail = "";
|
|
31138
|
-
child.stderr?.on("data", (d) => tail = (tail + d.toString()).slice(-
|
|
31148
|
+
child.stderr?.on("data", (d) => tail = (tail + d.toString()).slice(-4e3));
|
|
31139
31149
|
child.on("error", (err) => onExit(err.message));
|
|
31140
|
-
child.on("close", (code) => onExit(`engine stopped (${code}): ${tail
|
|
31150
|
+
child.on("close", (code) => onExit(`engine stopped (${code}): ${engineReason(tail)}`));
|
|
31141
31151
|
return child;
|
|
31142
31152
|
}
|
|
31143
31153
|
var RETRY_MS = 6e4;
|
|
@@ -31189,6 +31199,12 @@ var GroupManager = class {
|
|
|
31189
31199
|
this.failures.set(id, (this.failures.get(id) ?? 0) + 1);
|
|
31190
31200
|
this.set(id, "error", err.message ?? String(err));
|
|
31191
31201
|
}
|
|
31202
|
+
/** A tunnel fell: the engine lost its connection for good, so it starts again as soon as it can. */
|
|
31203
|
+
reconnect(id) {
|
|
31204
|
+
this.running.get(id)?.stop();
|
|
31205
|
+
this.running.delete(id);
|
|
31206
|
+
this.set(id, "waiting");
|
|
31207
|
+
}
|
|
31192
31208
|
async start(o) {
|
|
31193
31209
|
const stops = [];
|
|
31194
31210
|
const entry = { order: o, stop: () => stops.forEach((s) => s()) };
|
|
@@ -31221,11 +31237,15 @@ var GroupManager = class {
|
|
|
31221
31237
|
const file = await ensureModel(model, (p) => this.set(o.id, "downloading", `${p}%`));
|
|
31222
31238
|
if (!alive()) return;
|
|
31223
31239
|
this.set(o.id, "waiting");
|
|
31224
|
-
|
|
31240
|
+
let started = false;
|
|
31241
|
+
const tunnels = await Promise.all(
|
|
31242
|
+
o.workers.map((workerId) => startTunnel({ ...common, workerId, role: "host", onStatus: (c) => !c && started && alive() && this.reconnect(o.id) }))
|
|
31243
|
+
);
|
|
31225
31244
|
for (const t of tunnels) stops.push(t.stop);
|
|
31226
31245
|
while (alive() && !tunnels.every((t) => t.connected())) await new Promise((r) => setTimeout(r, 1e3));
|
|
31227
31246
|
if (!alive()) return;
|
|
31228
31247
|
this.set(o.id, "loading");
|
|
31248
|
+
started = true;
|
|
31229
31249
|
const port = await freePort();
|
|
31230
31250
|
const apiKey = (0, import_node_crypto9.randomBytes)(24).toString("hex");
|
|
31231
31251
|
const exe = await findExe(dir, exeName("llama-server"));
|
|
@@ -31241,6 +31261,7 @@ var GroupManager = class {
|
|
|
31241
31261
|
if (!alive()) return;
|
|
31242
31262
|
entry.url = url;
|
|
31243
31263
|
entry.apiKey = apiKey;
|
|
31264
|
+
this.failures.delete(o.id);
|
|
31244
31265
|
this.set(o.id, "ready");
|
|
31245
31266
|
} catch (err) {
|
|
31246
31267
|
if (alive()) this.fail(o.id, err);
|
|
@@ -31450,7 +31471,7 @@ function openBrowser(url) {
|
|
|
31450
31471
|
const args = (0, import_node_os13.platform)() === "win32" ? ["/c", "start", "", url] : [url];
|
|
31451
31472
|
(0, import_node_child_process9.spawn)(cmd, args, { stdio: "ignore", detached: true }).unref();
|
|
31452
31473
|
}
|
|
31453
|
-
var agentVersion = () => true ? "0.1.
|
|
31474
|
+
var agentVersion = () => true ? "0.1.20" : "dev";
|
|
31454
31475
|
var dashboardUrl = (cfg) => `http://127.0.0.1:${cfg.controlPort}/#token=${cfg.controlToken}`;
|
|
31455
31476
|
var AppNotRunning = class extends Error {
|
|
31456
31477
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bitpull",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "BitPull (bitpull.cloud): share signed, AI-readable code, computing power and open AI models with AI tools through MCP. CLI and MCP server.",
|
|
5
5
|
"mcpName": "io.github.SamuealPK/bitpull",
|
|
6
6
|
"bin": {
|