sublera-cli 0.0.0-stage → 1.3.0
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/CHANGELOG.md +172 -0
- package/LICENSE +21 -0
- package/README.md +585 -2
- package/SECURITY.md +78 -0
- package/THIRD_PARTY_NOTICES.md +37 -0
- package/dist/agent.d.ts +270 -0
- package/dist/agent.js +1867 -0
- package/dist/commands.d.ts +76 -0
- package/dist/commands.js +841 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.js +95 -0
- package/dist/engine/binaryManager.d.ts +67 -0
- package/dist/engine/binaryManager.js +590 -0
- package/dist/engine/gguf.d.ts +88 -0
- package/dist/engine/gguf.js +458 -0
- package/dist/engine/llamaRunner.d.ts +78 -0
- package/dist/engine/llamaRunner.js +282 -0
- package/dist/engine/modelManager.d.ts +63 -0
- package/dist/engine/modelManager.js +510 -0
- package/dist/engine/selfCheck.d.ts +34 -0
- package/dist/engine/selfCheck.js +108 -0
- package/dist/exitCodes.d.ts +20 -0
- package/dist/exitCodes.js +20 -0
- package/dist/hardware/gpuMonitor.d.ts +32 -0
- package/dist/hardware/gpuMonitor.js +378 -0
- package/dist/hardware/sleepGuard.d.ts +42 -0
- package/dist/hardware/sleepGuard.js +149 -0
- package/dist/hardware/types.d.ts +40 -0
- package/dist/hardware/types.js +2 -0
- package/dist/health.d.ts +17 -0
- package/dist/health.js +38 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +268 -0
- package/dist/logger.d.ts +53 -0
- package/dist/logger.js +201 -0
- package/dist/network/proxy.d.ts +58 -0
- package/dist/network/proxy.js +328 -0
- package/dist/network/streamProxy.d.ts +51 -0
- package/dist/network/streamProxy.js +286 -0
- package/dist/network/tunnelClient.d.ts +54 -0
- package/dist/network/tunnelClient.js +257 -0
- package/dist/settings.d.ts +53 -0
- package/dist/settings.js +171 -0
- package/dist/state.d.ts +52 -0
- package/dist/state.js +71 -0
- package/dist/storageCommand.d.ts +22 -0
- package/dist/storageCommand.js +81 -0
- package/dist/types.d.ts +222 -0
- package/dist/types.js +43 -0
- package/dist/ui/progress.d.ts +29 -0
- package/dist/ui/progress.js +82 -0
- package/dist/ui/terminalDashboard.d.ts +88 -0
- package/dist/ui/terminalDashboard.js +295 -0
- package/dist/util/env.d.ts +3 -0
- package/dist/util/env.js +6 -0
- package/dist/util/exec.d.ts +23 -0
- package/dist/util/exec.js +116 -0
- package/dist/util/format.d.ts +47 -0
- package/dist/util/format.js +125 -0
- package/dist/util/fs.d.ts +18 -0
- package/dist/util/fs.js +140 -0
- package/dist/util/http.d.ts +28 -0
- package/dist/util/http.js +128 -0
- package/dist/util/instanceLock.d.ts +3 -0
- package/dist/util/instanceLock.js +108 -0
- package/dist/util/open.d.ts +16 -0
- package/dist/util/open.js +65 -0
- package/dist/util/storage.d.ts +10 -0
- package/dist/util/storage.js +69 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.js +29 -0
- package/package.json +68 -4
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
Sublet CLI is MIT-licensed. It depends on the following packages; none of their
|
|
4
|
+
code is modified in this repository.
|
|
5
|
+
|
|
6
|
+
## Runtime dependencies
|
|
7
|
+
|
|
8
|
+
| Package | License | Use |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| `adm-zip` | MIT | Extract official llama.cpp Windows ZIP releases |
|
|
11
|
+
| `tar` | ISC | Extract official llama.cpp Linux/macOS tarballs |
|
|
12
|
+
| `ws` | MIT | Outbound WebSocket tunnel and reconnect handling |
|
|
13
|
+
| `undici` | MIT | HTTP(S) proxy support for downloads and API calls; loaded only when a proxy is set |
|
|
14
|
+
|
|
15
|
+
## Development dependencies
|
|
16
|
+
|
|
17
|
+
| Package | License |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `typescript` | Apache-2.0 |
|
|
20
|
+
| `tsx` | MIT |
|
|
21
|
+
| `@types/node` | MIT |
|
|
22
|
+
| `@types/ws` | MIT |
|
|
23
|
+
| `@types/tar` | MIT |
|
|
24
|
+
| `@types/adm-zip` | MIT |
|
|
25
|
+
|
|
26
|
+
## Downloaded at runtime, not bundled
|
|
27
|
+
|
|
28
|
+
- **llama.cpp / `llama-server`** — MIT. Downloaded from the official
|
|
29
|
+
`ggml-org/llama.cpp` GitHub releases and checked against the published digest
|
|
30
|
+
when available.
|
|
31
|
+
- **GGUF model weights** — each HuggingFace model has its own license. The CLI
|
|
32
|
+
does not bundle weights and does not grant rights to any model. Hosts are
|
|
33
|
+
responsible for following the model's license and acceptable-use terms.
|
|
34
|
+
- **Node.js** — MIT.
|
|
35
|
+
|
|
36
|
+
The Sublet marketplace server, wallet, and payment integrations are a separate
|
|
37
|
+
codebase and are not covered by this repository's license.
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { AgentConfig } from './config.js';
|
|
3
|
+
import type { Logger } from './logger.js';
|
|
4
|
+
import { type GpuOverride } from './hardware/gpuMonitor.js';
|
|
5
|
+
import { type InspectedModel } from './engine/gguf.js';
|
|
6
|
+
import { type DashboardState } from './ui/terminalDashboard.js';
|
|
7
|
+
import { type AgentHealth } from './health.js';
|
|
8
|
+
export type AgentOptions = {
|
|
9
|
+
config: AgentConfig;
|
|
10
|
+
logger: Logger;
|
|
11
|
+
simulation: boolean;
|
|
12
|
+
model?: string | null;
|
|
13
|
+
modelInfo?: InspectedModel | null;
|
|
14
|
+
publicMode?: boolean;
|
|
15
|
+
price?: number | null;
|
|
16
|
+
priceInUsd?: number | null;
|
|
17
|
+
priceOutUsd?: number | null;
|
|
18
|
+
/** Public mode: price per hour for the full GPU (default 0.5; 0 = no hourly rentals). Other modes send 0. */
|
|
19
|
+
priceHourUsd?: number | null;
|
|
20
|
+
context?: number;
|
|
21
|
+
slots?: number;
|
|
22
|
+
gpuOverride?: GpuOverride | null;
|
|
23
|
+
/** `sublera start <code>`: serve this request from the website. */
|
|
24
|
+
requestId?: string | null;
|
|
25
|
+
tokPerSec?: number | null;
|
|
26
|
+
autoInstall?: boolean;
|
|
27
|
+
requireChecksum?: boolean;
|
|
28
|
+
drainTimeoutMs?: number;
|
|
29
|
+
json?: boolean;
|
|
30
|
+
once?: boolean;
|
|
31
|
+
dashboard?: boolean;
|
|
32
|
+
/** Unit tests only: run this program as the engine instead of an installed llama-server. */
|
|
33
|
+
engine?: {
|
|
34
|
+
binaryPath: string;
|
|
35
|
+
baseArgs?: string[];
|
|
36
|
+
env?: NodeJS.ProcessEnv;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/** One request the server booked on this host. Several run side by side on the loaded model. */
|
|
40
|
+
type Booking = {
|
|
41
|
+
requestId: string;
|
|
42
|
+
model: string | null;
|
|
43
|
+
verified: boolean;
|
|
44
|
+
timerStartedAt: number | null;
|
|
45
|
+
timerEndsAt: number | null;
|
|
46
|
+
hours: number | null;
|
|
47
|
+
pricePerHourNanos: number | null;
|
|
48
|
+
minTokS: number | null;
|
|
49
|
+
guaranteedNanos: number | null;
|
|
50
|
+
/** A speed seat that shares the GPU with other renters and per-token buyers. */
|
|
51
|
+
shared: boolean;
|
|
52
|
+
/** The reserved speed of a seat; null means the full GPU. */
|
|
53
|
+
tokS: number | null;
|
|
54
|
+
/** llama-server slots and per-slot context the booking runs with; restored after a restart. */
|
|
55
|
+
slots: number;
|
|
56
|
+
context: number;
|
|
57
|
+
/** When a booking frame or a status poll last confirmed it. */
|
|
58
|
+
seenAt: number;
|
|
59
|
+
timer: NodeJS.Timeout | null;
|
|
60
|
+
};
|
|
61
|
+
export type BookingView = Readonly<Pick<Booking, 'requestId' | 'verified' | 'timerStartedAt' | 'timerEndsAt' | 'hours' | 'minTokS' | 'guaranteedNanos' | 'shared' | 'tokS'>>;
|
|
62
|
+
export declare class Agent extends EventEmitter {
|
|
63
|
+
private readonly options;
|
|
64
|
+
private readonly logger;
|
|
65
|
+
private readonly gpuMonitor;
|
|
66
|
+
private readonly sleepGuard;
|
|
67
|
+
private readonly dashboard;
|
|
68
|
+
private tunnel;
|
|
69
|
+
private runner;
|
|
70
|
+
private install;
|
|
71
|
+
private runnerModelPath;
|
|
72
|
+
private runnerContext;
|
|
73
|
+
/** The --parallel count the running llama-server was started with. */
|
|
74
|
+
private runnerSlotCount;
|
|
75
|
+
private gpu;
|
|
76
|
+
private model;
|
|
77
|
+
private cachedModels;
|
|
78
|
+
private me;
|
|
79
|
+
private meTimer;
|
|
80
|
+
private gpuTimer;
|
|
81
|
+
private activeJobs;
|
|
82
|
+
private stopped;
|
|
83
|
+
private readonly startup;
|
|
84
|
+
/** Aborts the download of a request the server stopped (released, cancelled, or taken back). */
|
|
85
|
+
private loadAbort;
|
|
86
|
+
/** A model download or engine start that replaces the runner: new inference waits. */
|
|
87
|
+
private loadingModel;
|
|
88
|
+
/** Any load frame in progress, including one that reuses the running model. */
|
|
89
|
+
private loadInFlight;
|
|
90
|
+
/** llama-server slots the last load asked for: more than one only for a shared booking. */
|
|
91
|
+
private bookingSlots;
|
|
92
|
+
/** Every booked request, keyed by requestId. */
|
|
93
|
+
private readonly bookings;
|
|
94
|
+
/**
|
|
95
|
+
* Bookings that ended in this session (end timer, reject, or dropped by the status poll) and
|
|
96
|
+
* when. Their earned share is already settled, so they are never added again.
|
|
97
|
+
*/
|
|
98
|
+
private readonly endedIds;
|
|
99
|
+
/** Server clock minus this machine's clock, from the last `/api/agent/me` answer. */
|
|
100
|
+
private serverOffset;
|
|
101
|
+
/** Requests the last status poll listed as live: claimed, loading, verifying or active. */
|
|
102
|
+
private liveRequestIds;
|
|
103
|
+
/** The id of `me.activeRequest` (the server's newest live request) in the last status answer. */
|
|
104
|
+
private serverNewestId;
|
|
105
|
+
private pending;
|
|
106
|
+
/** What the dashboard shows with no request: the public model, or the model loaded with --model. */
|
|
107
|
+
private startupJob;
|
|
108
|
+
private tokenEarnedNanos;
|
|
109
|
+
/** Earned share of bookings that ended or were stopped in this session. */
|
|
110
|
+
private settledEarnedNanos;
|
|
111
|
+
private settledGuaranteedNanos;
|
|
112
|
+
private meInitialWallet;
|
|
113
|
+
private lastSpeed;
|
|
114
|
+
private lastTtft;
|
|
115
|
+
private persisted;
|
|
116
|
+
/** True while the restore after a restart works on state.json. */
|
|
117
|
+
private restoring;
|
|
118
|
+
private stateWrite;
|
|
119
|
+
private online;
|
|
120
|
+
private onlineWaiters;
|
|
121
|
+
private keyHandler;
|
|
122
|
+
private heartbeatAt;
|
|
123
|
+
private bookingTimer;
|
|
124
|
+
private logLines;
|
|
125
|
+
/** The engine's answer to the self-check prompt right after the current model was loaded. */
|
|
126
|
+
private engineBaseline;
|
|
127
|
+
private selfCheckAbort;
|
|
128
|
+
private draining;
|
|
129
|
+
private runStarted;
|
|
130
|
+
private stopPromise;
|
|
131
|
+
private readonly messageTasks;
|
|
132
|
+
private healthTimer;
|
|
133
|
+
private healthWrite;
|
|
134
|
+
constructor(options: AgentOptions);
|
|
135
|
+
get dashboardState(): DashboardState;
|
|
136
|
+
/** Every booked request, soonest end first. */
|
|
137
|
+
get activeBookings(): BookingView[];
|
|
138
|
+
/** The booking for this request, or null when it is not (or no longer) booked here. */
|
|
139
|
+
booking(requestId: string): BookingView | null;
|
|
140
|
+
/**
|
|
141
|
+
* True while something other than `requestId` still needs this agent: public selling, another
|
|
142
|
+
* booking, another request being loaded, or another request the server lists as live. A seat on
|
|
143
|
+
* the loaded model never gets a load frame, so during its model check only the server's list shows it.
|
|
144
|
+
*/
|
|
145
|
+
servingOthers(requestId: string): boolean;
|
|
146
|
+
/** This machine's estimate of the server clock. */
|
|
147
|
+
private serverTime;
|
|
148
|
+
/** Remembers the server clock from a status answer, so ends are judged by server time even when this clock is off. */
|
|
149
|
+
private noteServerClock;
|
|
150
|
+
/** The loaded request that waits for its model check, or a loaded benchmark. Restarting llama-server would break it. */
|
|
151
|
+
private checkingRequest;
|
|
152
|
+
/** Keeps the machine awake for a booking (the same call for a booking frame and a status poll). */
|
|
153
|
+
private holdWakeLock;
|
|
154
|
+
private bookingView;
|
|
155
|
+
/** Bookings, a pending request, or a real load keep the machine awake. */
|
|
156
|
+
private get bookingWake();
|
|
157
|
+
private priceOutUsd;
|
|
158
|
+
private priceHourUsd;
|
|
159
|
+
get health(): AgentHealth;
|
|
160
|
+
private publishHealth;
|
|
161
|
+
/** Reject new work, finish in-flight inference up to a bounded grace period,
|
|
162
|
+
* then cancel leftovers and preserve booking state for server reconciliation. */
|
|
163
|
+
drain(timeoutMs?: number): Promise<void>;
|
|
164
|
+
waitForOnline(timeoutMs?: number): Promise<void>;
|
|
165
|
+
private markOnline;
|
|
166
|
+
/** After a crash or restart, reload the booked model and resume every booking saved in state.json. */
|
|
167
|
+
private restorePersistedBooking;
|
|
168
|
+
private restoreOwned;
|
|
169
|
+
/** Writes every booking to state.json (newest first), or removes the file when none is left. */
|
|
170
|
+
private persistBookings;
|
|
171
|
+
private sortedBookings;
|
|
172
|
+
/** Adds or updates a booking. A pending request with the same id becomes this booking. */
|
|
173
|
+
private upsertBooking;
|
|
174
|
+
private scheduleBookingEnd;
|
|
175
|
+
/** The end timer of one booking fired: remove only that booking. */
|
|
176
|
+
private finishBooking;
|
|
177
|
+
/**
|
|
178
|
+
* Removes one booking and books its earned share into the session total. A settled booking has
|
|
179
|
+
* ended: its id is remembered so a status answer built before the end cannot add it (and its
|
|
180
|
+
* earnings) a second time. `settle = false` only drops it (a restore that failed), so it is not remembered.
|
|
181
|
+
*/
|
|
182
|
+
private removeBooking;
|
|
183
|
+
private clearBookingTimers;
|
|
184
|
+
/** The part of a booking's guaranteed pay that the time so far has earned. */
|
|
185
|
+
private bookingShare;
|
|
186
|
+
private bookingJob;
|
|
187
|
+
private baseJob;
|
|
188
|
+
/**
|
|
189
|
+
* Rebuilds the dashboard's request view from the bookings. Earnings are the per-token
|
|
190
|
+
* earnings plus the time-proportional share of every booking, active or settled.
|
|
191
|
+
*/
|
|
192
|
+
private syncDashboard;
|
|
193
|
+
/** Removes state.json if this agent wrote it; `force` also removes the file a restore in progress is working on. */
|
|
194
|
+
private clearPersistedBooking;
|
|
195
|
+
run(): Promise<void>;
|
|
196
|
+
private runOwned;
|
|
197
|
+
private endpointFor;
|
|
198
|
+
/** Tells the server about a newly downloaded model, so the board can show it as ready on this host. */
|
|
199
|
+
private refreshCachedModels;
|
|
200
|
+
private prepareStartupModel;
|
|
201
|
+
private loadModel;
|
|
202
|
+
/**
|
|
203
|
+
* True while llama-server serves someone other than `owner`: an inference job, another
|
|
204
|
+
* booking, public selling, or another request whose model is loaded and in its model check
|
|
205
|
+
* (or a benchmark). A restart would cut them off, so it is not allowed then.
|
|
206
|
+
*/
|
|
207
|
+
private runnerBusy;
|
|
208
|
+
/** Decides whether loading `path` reuses, restarts, or must not touch the running llama-server. */
|
|
209
|
+
private runnerPlan;
|
|
210
|
+
/** Requests are served on the slots llama-server really runs with. */
|
|
211
|
+
private capacity;
|
|
212
|
+
private ensureRunner;
|
|
213
|
+
/**
|
|
214
|
+
* Asks the engine one short fixed question and compares the answer's token probabilities:
|
|
215
|
+
* twice in a row after a load, and against the load-time answer after a crash restart. It only
|
|
216
|
+
* warns; the server's model checks decide. It runs when the engine's prompt cache is empty and
|
|
217
|
+
* no buyer is waiting, and a buyer's job cancels it.
|
|
218
|
+
*/
|
|
219
|
+
private selfCheckEngine;
|
|
220
|
+
private runnerSlots;
|
|
221
|
+
private helloPayload;
|
|
222
|
+
private heartbeatPayload;
|
|
223
|
+
private handleMessage;
|
|
224
|
+
/**
|
|
225
|
+
* The server started a booking's clock. It may be for the request just loaded, or for a
|
|
226
|
+
* request that never had a load frame (a speed seat or hourly rental on the loaded model).
|
|
227
|
+
* Each booking keeps its own end timer; a model load in progress stays busy.
|
|
228
|
+
*/
|
|
229
|
+
private applyBooking;
|
|
230
|
+
private handleInfer;
|
|
231
|
+
/**
|
|
232
|
+
* Whether the dashboard counts a job that starts now as per-token income: only while no paid
|
|
233
|
+
* booking (speed seat or full GPU) is active. A renter's tokens are paid by the hour, and in
|
|
234
|
+
* public mode per-token buyers are served beside speed seats, but an `infer` frame does not say
|
|
235
|
+
* whose job it is. That is by design: the server must not reveal which jobs are hidden model
|
|
236
|
+
* checks. So while rentals run, per-token earnings are left out of the session total; the
|
|
237
|
+
* wallet on the website is exact.
|
|
238
|
+
*/
|
|
239
|
+
private earnsPerToken;
|
|
240
|
+
private estimateEarned;
|
|
241
|
+
/** The loaded model, when a load frame names it: the same SHA-256, or the same HuggingFace link when no hash is given. */
|
|
242
|
+
private loadedModelFor;
|
|
243
|
+
/** The slots llama-server should run with after a load that asks for `loadSlots`. */
|
|
244
|
+
private slotsAfterLoad;
|
|
245
|
+
private handleLoad;
|
|
246
|
+
private refreshMe;
|
|
247
|
+
/**
|
|
248
|
+
* Makes the bookings match the server's list of live requests: adds booked ones this agent
|
|
249
|
+
* missed (never one that already ended here or whose end has passed on the server's clock),
|
|
250
|
+
* updates timers, and drops bookings the server no longer lists. Also keeps the ids of every
|
|
251
|
+
* live request for servingOthers(). Returns the dropped ids.
|
|
252
|
+
*/
|
|
253
|
+
private reconcileBookings;
|
|
254
|
+
private setupKeyboard;
|
|
255
|
+
private handleKey;
|
|
256
|
+
/** The website page with this host's earnings, reliability, and current request. */
|
|
257
|
+
private hostPageUrl;
|
|
258
|
+
private openExternal;
|
|
259
|
+
private copyText;
|
|
260
|
+
private cleanupKeyboard;
|
|
261
|
+
private startGpuPolling;
|
|
262
|
+
private releaseWakeLockIfIdle;
|
|
263
|
+
private updateGpuDashboard;
|
|
264
|
+
private fail;
|
|
265
|
+
stop(preserveState?: boolean): Promise<void>;
|
|
266
|
+
private stopOwned;
|
|
267
|
+
/** Frees the wake lock, tunnel, llama-server and terminal. run() calls it again when startup finishes after stop(). */
|
|
268
|
+
private releaseResources;
|
|
269
|
+
}
|
|
270
|
+
export {};
|