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.
Files changed (72) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/LICENSE +21 -0
  3. package/README.md +585 -2
  4. package/SECURITY.md +78 -0
  5. package/THIRD_PARTY_NOTICES.md +37 -0
  6. package/dist/agent.d.ts +270 -0
  7. package/dist/agent.js +1867 -0
  8. package/dist/commands.d.ts +76 -0
  9. package/dist/commands.js +841 -0
  10. package/dist/config.d.ts +27 -0
  11. package/dist/config.js +95 -0
  12. package/dist/engine/binaryManager.d.ts +67 -0
  13. package/dist/engine/binaryManager.js +590 -0
  14. package/dist/engine/gguf.d.ts +88 -0
  15. package/dist/engine/gguf.js +458 -0
  16. package/dist/engine/llamaRunner.d.ts +78 -0
  17. package/dist/engine/llamaRunner.js +282 -0
  18. package/dist/engine/modelManager.d.ts +63 -0
  19. package/dist/engine/modelManager.js +510 -0
  20. package/dist/engine/selfCheck.d.ts +34 -0
  21. package/dist/engine/selfCheck.js +108 -0
  22. package/dist/exitCodes.d.ts +20 -0
  23. package/dist/exitCodes.js +20 -0
  24. package/dist/hardware/gpuMonitor.d.ts +32 -0
  25. package/dist/hardware/gpuMonitor.js +378 -0
  26. package/dist/hardware/sleepGuard.d.ts +42 -0
  27. package/dist/hardware/sleepGuard.js +149 -0
  28. package/dist/hardware/types.d.ts +40 -0
  29. package/dist/hardware/types.js +2 -0
  30. package/dist/health.d.ts +17 -0
  31. package/dist/health.js +38 -0
  32. package/dist/index.d.ts +11 -0
  33. package/dist/index.js +268 -0
  34. package/dist/logger.d.ts +53 -0
  35. package/dist/logger.js +201 -0
  36. package/dist/network/proxy.d.ts +58 -0
  37. package/dist/network/proxy.js +328 -0
  38. package/dist/network/streamProxy.d.ts +51 -0
  39. package/dist/network/streamProxy.js +286 -0
  40. package/dist/network/tunnelClient.d.ts +54 -0
  41. package/dist/network/tunnelClient.js +257 -0
  42. package/dist/settings.d.ts +53 -0
  43. package/dist/settings.js +171 -0
  44. package/dist/state.d.ts +52 -0
  45. package/dist/state.js +71 -0
  46. package/dist/storageCommand.d.ts +22 -0
  47. package/dist/storageCommand.js +81 -0
  48. package/dist/types.d.ts +222 -0
  49. package/dist/types.js +43 -0
  50. package/dist/ui/progress.d.ts +29 -0
  51. package/dist/ui/progress.js +82 -0
  52. package/dist/ui/terminalDashboard.d.ts +88 -0
  53. package/dist/ui/terminalDashboard.js +295 -0
  54. package/dist/util/env.d.ts +3 -0
  55. package/dist/util/env.js +6 -0
  56. package/dist/util/exec.d.ts +23 -0
  57. package/dist/util/exec.js +116 -0
  58. package/dist/util/format.d.ts +47 -0
  59. package/dist/util/format.js +125 -0
  60. package/dist/util/fs.d.ts +18 -0
  61. package/dist/util/fs.js +140 -0
  62. package/dist/util/http.d.ts +28 -0
  63. package/dist/util/http.js +128 -0
  64. package/dist/util/instanceLock.d.ts +3 -0
  65. package/dist/util/instanceLock.js +108 -0
  66. package/dist/util/open.d.ts +16 -0
  67. package/dist/util/open.js +65 -0
  68. package/dist/util/storage.d.ts +10 -0
  69. package/dist/util/storage.js +69 -0
  70. package/dist/version.d.ts +15 -0
  71. package/dist/version.js +29 -0
  72. package/package.json +68 -4
@@ -0,0 +1,27 @@
1
+ export type AgentConfig = {
2
+ server: string;
3
+ token: string;
4
+ wsPath: string;
5
+ updatedAt: number;
6
+ tokenLabel?: string;
7
+ };
8
+ export declare function subletHome(env?: NodeJS.ProcessEnv): string;
9
+ export declare function configPath(env?: NodeJS.ProcessEnv): string;
10
+ export declare function binDir(env?: NodeJS.ProcessEnv): string;
11
+ export declare function modelsDir(env?: NodeJS.ProcessEnv): string;
12
+ export declare function logsDir(env?: NodeJS.ProcessEnv): string;
13
+ export declare function cacheDir(env?: NodeJS.ProcessEnv): string;
14
+ /** The OpenAI-compatible base URL that buyers use for this host's public market. */
15
+ export declare function hostEndpoint(server: string, username: string | null | undefined): string;
16
+ /** True for this machine's own addresses: localhost, 127.0.0.0/8, 0.0.0.0 and [::1]. */
17
+ export declare function isLoopbackHost(hostname: string): boolean;
18
+ /**
19
+ * A server URL in one canonical form. Plain http is allowed only for this machine, because the host key travels in
20
+ * every request; SUBLERA_ALLOW_HTTP=1 allows it elsewhere, for a test server on a trusted LAN.
21
+ */
22
+ export declare function normalizeServer(raw: string, env?: NodeJS.ProcessEnv): string;
23
+ export declare function apiUrl(server: string, path: string): string;
24
+ export declare function wsUrl(server: string, token: string, wsPath?: string, mode?: 'query' | 'header'): string;
25
+ export declare function maskToken(token: string | null | undefined): string;
26
+ export declare function hostKeyFromToken(token: string): boolean;
27
+ export declare function displayNameForHome(home: string): string;
package/dist/config.js ADDED
@@ -0,0 +1,95 @@
1
+ import { homedir } from 'node:os';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { brandEnv } from './util/env.js';
4
+ export function subletHome(env = process.env) {
5
+ const home = brandEnv(env, 'SUBLET_HOME');
6
+ // Keep the existing default so old/new binaries share credentials and ownership.
7
+ return resolve(home && home.trim() ? home : join(homedir(), '.sublet'));
8
+ }
9
+ export function configPath(env = process.env) {
10
+ return join(subletHome(env), 'config.json');
11
+ }
12
+ export function binDir(env = process.env) {
13
+ return join(subletHome(env), 'bin');
14
+ }
15
+ export function modelsDir(env = process.env) {
16
+ return join(subletHome(env), 'models');
17
+ }
18
+ export function logsDir(env = process.env) {
19
+ return join(subletHome(env), 'logs');
20
+ }
21
+ export function cacheDir(env = process.env) {
22
+ return join(subletHome(env), 'cache');
23
+ }
24
+ /** The OpenAI-compatible base URL that buyers use for this host's public market. */
25
+ export function hostEndpoint(server, username) {
26
+ return `${server.replace(/\/+$/, '')}/h/${username || 'USERNAME'}/v1`;
27
+ }
28
+ /** True for this machine's own addresses: localhost, 127.0.0.0/8, 0.0.0.0 and [::1]. */
29
+ export function isLoopbackHost(hostname) {
30
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, '');
31
+ return host === 'localhost' || host === '0.0.0.0' || host === '::1' || /^127(?:\.\d{1,3}){3}$/.test(host);
32
+ }
33
+ /**
34
+ * A server URL in one canonical form. Plain http is allowed only for this machine, because the host key travels in
35
+ * every request; SUBLERA_ALLOW_HTTP=1 allows it elsewhere, for a test server on a trusted LAN.
36
+ */
37
+ export function normalizeServer(raw, env = process.env) {
38
+ let value = raw.trim();
39
+ if (!value)
40
+ throw new Error('Server URL is empty');
41
+ if (!/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
42
+ const local = /^(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$)/i.test(value);
43
+ value = `${local ? 'http' : 'https'}://${value}`;
44
+ }
45
+ const url = new URL(value);
46
+ if (url.protocol !== 'http:' && url.protocol !== 'https:')
47
+ throw new Error('Server must be an http(s) URL');
48
+ if (url.protocol === 'http:' && !isLoopbackHost(url.hostname) && brandEnv(env, 'SUBLET_ALLOW_HTTP') !== '1') {
49
+ throw new Error('Server must use https:// (the host key would be sent unencrypted). For a test server on a trusted network, set SUBLERA_ALLOW_HTTP=1');
50
+ }
51
+ if (url.username || url.password)
52
+ throw new Error('Server URL must not contain credentials; use --key or SUBLET_KEY');
53
+ if (url.search || url.hash)
54
+ throw new Error('Server URL must not contain a query or fragment');
55
+ const path = url.pathname.replace(/\/+$/, '');
56
+ return `${url.origin}${path === '/' ? '' : path}`;
57
+ }
58
+ export function apiUrl(server, path) {
59
+ return `${normalizeServer(server)}${path.startsWith('/') ? path : `/${path}`}`;
60
+ }
61
+ export function wsUrl(server, token, wsPath = '/tunnel', mode = 'query') {
62
+ const base = new URL(normalizeServer(server));
63
+ base.protocol = base.protocol === 'https:' ? 'wss:' : 'ws:';
64
+ const path = wsPath.trim() || '/tunnel';
65
+ if (/^wss?:\/\//i.test(path)) {
66
+ const full = new URL(path);
67
+ if (full.origin !== base.origin)
68
+ throw new Error('Tunnel URL must use the same server origin; refusing to forward the host key');
69
+ if (full.username || full.password || full.hash)
70
+ throw new Error('Tunnel URL must not contain credentials or a fragment');
71
+ if (mode === 'query')
72
+ full.searchParams.set('token', token);
73
+ return full.toString();
74
+ }
75
+ base.pathname = `${base.pathname.replace(/\/+$/, '')}${path.startsWith('/') ? path : `/${path}`}`;
76
+ base.search = '';
77
+ if (mode === 'query')
78
+ base.searchParams.set('token', token);
79
+ return base.toString();
80
+ }
81
+ export function maskToken(token) {
82
+ if (!token)
83
+ return 'not set';
84
+ if (token.length <= 10)
85
+ return `${token.slice(0, 3)}...`;
86
+ return `${token.slice(0, 7)}...${token.slice(-4)}`;
87
+ }
88
+ export function hostKeyFromToken(token) {
89
+ return /^(sh_|sk-)[A-Za-z0-9_-]{6,}$/.test(token.trim());
90
+ }
91
+ export function displayNameForHome(home) {
92
+ const parent = dirname(home);
93
+ return parent === home ? home : `${parent}${home.startsWith('/') || home.includes('\\') ? '\\' : '/'}${home}`;
94
+ }
95
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,67 @@
1
+ import { type HttpError } from '../util/http.js';
2
+ import type { Logger } from '../logger.js';
3
+ import type { GpuSnapshot, GpuVendor } from '../hardware/types.js';
4
+ export type LlamaVariant = 'cuda' | 'vulkan' | 'metal' | 'cpu';
5
+ export type LlamaInstall = {
6
+ path: string;
7
+ version: string;
8
+ variant: LlamaVariant;
9
+ sha256: string | null;
10
+ binarySha256?: string | null;
11
+ verified: boolean;
12
+ source: 'env' | 'path' | 'manifest' | 'download';
13
+ dir?: string;
14
+ };
15
+ export type ReleaseAsset = {
16
+ name: string;
17
+ browser_download_url: string;
18
+ size?: number;
19
+ digest?: string | null;
20
+ };
21
+ export type ReleaseInfo = {
22
+ tag_name: string;
23
+ name?: string;
24
+ published_at?: string;
25
+ assets: ReleaseAsset[];
26
+ };
27
+ export type InstallOptions = {
28
+ platform?: NodeJS.Platform;
29
+ arch?: string;
30
+ env?: NodeJS.ProcessEnv;
31
+ home?: string;
32
+ gpu?: GpuSnapshot | null;
33
+ logger?: Logger;
34
+ fetchImpl?: typeof fetch;
35
+ showProgress?: boolean;
36
+ stream?: NodeJS.WriteStream;
37
+ requireChecksum?: boolean;
38
+ release?: ReleaseInfo;
39
+ version?: string;
40
+ };
41
+ export type EnsureResult = {
42
+ found: true;
43
+ install: LlamaInstall;
44
+ } | {
45
+ found: false;
46
+ reason: string;
47
+ install?: undefined;
48
+ };
49
+ export declare function variantFor(platform: NodeJS.Platform, arch: string, vendor: GpuVendor | null | undefined): LlamaVariant;
50
+ export declare function pickReleaseAsset(release: ReleaseInfo, platform: NodeJS.Platform, arch: string, variant: LlamaVariant): {
51
+ main: ReleaseAsset | null;
52
+ companions: ReleaseAsset[];
53
+ };
54
+ export declare function extractArchive(archive: string, destination: string): Promise<void>;
55
+ export declare function findExistingLlama(options?: InstallOptions): Promise<LlamaInstall | null>;
56
+ export declare function ensureLlamaServer(options?: InstallOptions & {
57
+ fix?: boolean;
58
+ simulation?: boolean;
59
+ }): Promise<EnsureResult>;
60
+ export declare function installLlamaServer(options?: InstallOptions): Promise<LlamaInstall>;
61
+ export declare function binaryStatus(options?: InstallOptions): Promise<{
62
+ install: LlamaInstall | null;
63
+ manifestPath: string;
64
+ }>;
65
+ export declare function verifyInstalledBinary(install: LlamaInstall): Promise<boolean>;
66
+ export declare function isHttpError(error: unknown): error is HttpError;
67
+ export declare function readReleaseForTest(): Promise<ReleaseInfo>;