@skaile/workspaces 0.32.0 → 0.34.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 +103 -0
- package/dist/{asset-feeds-2LQIGNUF.js → asset-feeds-6R2C2NHB.js} +7 -7
- package/dist/{asset-feeds-2LQIGNUF.js.map → asset-feeds-6R2C2NHB.js.map} +1 -1
- package/dist/asset-manager/index.js +5 -5
- package/dist/asset-manager/installer.js +4 -4
- package/dist/bridge/drivers/claude-sdk.js +8 -1
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +1 -1
- package/dist/bridge/drivers/continue.js +2 -2
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +3 -3
- package/dist/bridge/drivers/goose.js +2 -2
- package/dist/bridge/drivers/omp.js +1 -1
- package/dist/bridge/drivers/opencode.js +2 -2
- package/dist/bridge/drivers/qwen.js +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/{chunk-SN2RWSB3.js → chunk-2VM62DX7.js} +3 -3
- package/dist/{chunk-SN2RWSB3.js.map → chunk-2VM62DX7.js.map} +1 -1
- package/dist/{chunk-SIW5I47F.js → chunk-4RSCLQYX.js} +231 -33
- package/dist/chunk-4RSCLQYX.js.map +1 -0
- package/dist/{chunk-YHGJBGFU.js → chunk-5JAQVXPV.js} +2 -2
- package/dist/{chunk-YHGJBGFU.js.map → chunk-5JAQVXPV.js.map} +1 -1
- package/dist/{chunk-NGE6PALH.js → chunk-67AXL4OK.js} +3 -3
- package/dist/{chunk-NGE6PALH.js.map → chunk-67AXL4OK.js.map} +1 -1
- package/dist/{chunk-CPYXJJOD.js → chunk-BKE2E5AC.js} +6 -6
- package/dist/{chunk-CPYXJJOD.js.map → chunk-BKE2E5AC.js.map} +1 -1
- package/dist/{chunk-OEXA7BBK.js → chunk-CIFTUSBV.js} +2 -2
- package/dist/{chunk-OEXA7BBK.js.map → chunk-CIFTUSBV.js.map} +1 -1
- package/dist/{chunk-LO7QEIHT.js → chunk-DHN6VW4B.js} +4 -4
- package/dist/{chunk-LO7QEIHT.js.map → chunk-DHN6VW4B.js.map} +1 -1
- package/dist/{chunk-7WHBI3I6.js → chunk-DVIIYYD5.js} +3 -3
- package/dist/{chunk-7WHBI3I6.js.map → chunk-DVIIYYD5.js.map} +1 -1
- package/dist/{chunk-DTJNHYFE.js → chunk-E5VRPYUX.js} +9 -16
- package/dist/chunk-E5VRPYUX.js.map +1 -0
- package/dist/{chunk-NZJDQYNB.js → chunk-FM2BJYX4.js} +2 -2
- package/dist/{chunk-NZJDQYNB.js.map → chunk-FM2BJYX4.js.map} +1 -1
- package/dist/{chunk-AOWKMINN.js → chunk-JLSK6HR4.js} +5 -5
- package/dist/{chunk-AOWKMINN.js.map → chunk-JLSK6HR4.js.map} +1 -1
- package/dist/{chunk-7FLLPKX3.js → chunk-NSVAJWWQ.js} +3 -3
- package/dist/{chunk-7FLLPKX3.js.map → chunk-NSVAJWWQ.js.map} +1 -1
- package/dist/{chunk-MA7HSL5S.js → chunk-QLHOORR7.js} +2 -2
- package/dist/{chunk-MA7HSL5S.js.map → chunk-QLHOORR7.js.map} +1 -1
- package/dist/{chunk-P72K36PU.js → chunk-TV2OU2EZ.js} +4 -4
- package/dist/{chunk-P72K36PU.js.map → chunk-TV2OU2EZ.js.map} +1 -1
- package/dist/{chunk-2RQ3KLY3.js → chunk-UQ5JY2GQ.js} +10 -7
- package/dist/chunk-UQ5JY2GQ.js.map +1 -0
- package/dist/{chunk-MG4KFVGV.js → chunk-VSLSRDQZ.js} +3 -3
- package/dist/{chunk-MG4KFVGV.js.map → chunk-VSLSRDQZ.js.map} +1 -1
- package/dist/{chunk-BR7RPEHW.js → chunk-W6TLIJG3.js} +3 -3
- package/dist/{chunk-BR7RPEHW.js.map → chunk-W6TLIJG3.js.map} +1 -1
- package/dist/{chunk-GXHJDQ37.js → chunk-WQRDLR3K.js} +410 -48
- package/dist/chunk-WQRDLR3K.js.map +1 -0
- package/dist/{chunk-74UKG2LA.js → chunk-XT6AZWK3.js} +40 -5
- package/dist/chunk-XT6AZWK3.js.map +1 -0
- package/dist/cli/index.js +31 -31
- package/dist/connectors/config.js +4 -4
- package/dist/connectors/index.js +6 -6
- package/dist/connectors/rclone.js +1 -1
- package/dist/connectors/src/config.d.ts +30 -3
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/connectors/src/connector-manager.d.ts +56 -3
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/fleet-health-gate.d.ts +86 -0
- package/dist/connectors/src/fleet-health-gate.d.ts.map +1 -0
- package/dist/connectors/src/fleet-utils.d.ts +16 -0
- package/dist/connectors/src/fleet-utils.d.ts.map +1 -1
- package/dist/connectors/src/index.d.ts +9 -3
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/connectors/src/rclone-process-manager.d.ts +24 -0
- package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
- package/dist/connectors/src/rclone-token-refresh.d.ts +84 -0
- package/dist/connectors/src/rclone-token-refresh.d.ts.map +1 -0
- package/dist/core/index.js +3 -3
- package/dist/core/runtime-assets.js +2 -2
- package/dist/core/src/workspace-config.d.ts +20 -6
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +1 -1
- package/dist/deploy/index.js +3 -3
- package/dist/{ensure-sources-CRUZDVPG.js → ensure-sources-GYEQ65ET.js} +5 -5
- package/dist/{ensure-sources-CRUZDVPG.js.map → ensure-sources-GYEQ65ET.js.map} +1 -1
- package/dist/factory-assets/connectors/deploy.js +6 -6
- package/dist/factory-assets/connectors/devserver.js +6 -6
- package/dist/factory-assets/connectors/flow/adapter.js +6 -6
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
- package/dist/factory-assets/connectors/flow.js +6 -6
- package/dist/factory-assets/connectors/git.js +6 -6
- package/dist/factory-assets/connectors/gmail.js +6 -6
- package/dist/factory-assets/connectors/googledrive.js +6 -6
- package/dist/factory-assets/connectors/local.js +6 -6
- package/dist/factory-assets/connectors/mattermost.js +6 -6
- package/dist/factory-assets/connectors/memory.js +6 -6
- package/dist/factory-assets/connectors/minio.js +6 -6
- package/dist/factory-assets/connectors/postgres.js +6 -6
- package/dist/factory-assets/connectors/s3.js +6 -6
- package/dist/factory-assets/connectors/sharepoint/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/sharepoint.js +6 -6
- package/dist/factory-assets/connectors/sqlite.js +6 -6
- package/dist/factory-assets/connectors/static-server.js +6 -6
- package/dist/factory-assets/connectors/tunnel.js +6 -6
- package/dist/factory-assets/connectors/webdav/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/webdav.js +6 -6
- package/dist/factory-assets/connectors/xstate-store.js +6 -6
- package/dist/factory-assets/connectors/xstate.js +6 -6
- package/dist/{flows-W7L2576K.js → flows-TJUVSMRR.js} +3 -3
- package/dist/{flows-W7L2576K.js.map → flows-TJUVSMRR.js.map} +1 -1
- package/dist/library/index.js +3 -3
- package/dist/library/install.js +3 -3
- package/dist/{open-library-XZZXXVBP.js → open-library-GPZUB7N3.js} +6 -6
- package/dist/{open-library-XZZXXVBP.js.map → open-library-GPZUB7N3.js.map} +1 -1
- package/dist/{paths-RH5CIFX2.js → paths-R6WA7PKV.js} +6 -6
- package/dist/{paths-RH5CIFX2.js.map → paths-R6WA7PKV.js.map} +1 -1
- package/dist/{plugin-store-2UZGNS6M.js → plugin-store-TF7GECYJ.js} +5 -5
- package/dist/{plugin-store-2UZGNS6M.js.map → plugin-store-TF7GECYJ.js.map} +1 -1
- package/dist/runner/index.js +10 -10
- package/dist/runner/src/external-mcp.d.ts +45 -4
- package/dist/runner/src/external-mcp.d.ts.map +1 -1
- package/dist/runner/src/fleet-health-flag-dispatcher.d.ts +40 -0
- package/dist/runner/src/fleet-health-flag-dispatcher.d.ts.map +1 -0
- package/dist/runner/src/lifecycle-handler.d.ts +17 -0
- package/dist/runner/src/lifecycle-handler.d.ts.map +1 -0
- package/dist/runner/src/resources.d.ts.map +1 -1
- package/dist/runner/src/runner-capabilities.d.ts +1 -1
- package/dist/runner/src/runner-capabilities.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +5 -5
- package/dist/sdk/bridge.js +2 -2
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +10 -10
- package/dist/sdk/runner.js +10 -10
- package/dist/{setup-G5UATRCX.js → setup-YKL43RQJ.js} +7 -7
- package/dist/{setup-G5UATRCX.js.map → setup-YKL43RQJ.js.map} +1 -1
- package/dist/{store-client-TUC7VSOU.js → store-client-H7MHTZVU.js} +6 -6
- package/dist/{store-client-TUC7VSOU.js.map → store-client-H7MHTZVU.js.map} +1 -1
- package/dist/tui/index.js +10 -10
- package/dist/workspace-plugin/adapters/mcp.js +1 -1
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2RQ3KLY3.js.map +0 -1
- package/dist/chunk-74UKG2LA.js.map +0 -1
- package/dist/chunk-DTJNHYFE.js.map +0 -1
- package/dist/chunk-GXHJDQ37.js.map +0 -1
- package/dist/chunk-SIW5I47F.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { renderGoogleDriveConfig, renderOneDriveConfig, renderWebDAVConfig } from './chunk-OVRSNIKJ.js';
|
|
2
|
-
import { resolveAuthRef, resolveAuth, resolveMountCredentialString } from './chunk-
|
|
3
|
-
import { PortPool, createFsWatcher, RcloneProcessManager, ensureDirMode } from './chunk-
|
|
2
|
+
import { resolveAuthRef, resolveAuth, resolveMountCredentialString, resolveMountCredential } from './chunk-UQ5JY2GQ.js';
|
|
3
|
+
import { PortPool, createFsWatcher, RcloneProcessManager, ensureDirMode } from './chunk-XT6AZWK3.js';
|
|
4
4
|
import { pluginRegistry } from './chunk-6E6PKKAD.js';
|
|
5
5
|
import { computeFlowStateFromSnapshots } from './chunk-X46FY45B.js';
|
|
6
6
|
import { renderStimulusPrompt } from './chunk-DEYYRFQU.js';
|
|
7
7
|
import { computeStimulus } from './chunk-IFGTRL2I.js';
|
|
8
|
-
import { portableSpawn } from './chunk-
|
|
8
|
+
import { portableSpawn } from './chunk-DVIIYYD5.js';
|
|
9
9
|
import { createLogger } from './chunk-JB35MVBN.js';
|
|
10
10
|
import { existsSync, mkdirSync, renameSync, writeFileSync, readFileSync, cpSync, statSync, createReadStream, readdirSync, openSync, writeSync, closeSync, chmodSync } from 'fs';
|
|
11
11
|
import path, { join, dirname, resolve, sep } from 'path';
|
|
@@ -3459,7 +3459,7 @@ var SharePointConnector = class extends AbstractConnector {
|
|
|
3459
3459
|
});
|
|
3460
3460
|
await ensureFleetMounted(targetDir, this.log);
|
|
3461
3461
|
const fleetState = {
|
|
3462
|
-
|
|
3462
|
+
handleRef: { current: null },
|
|
3463
3463
|
fleetManaged: true
|
|
3464
3464
|
};
|
|
3465
3465
|
return this.makeHandle(declaration, fleetState, targetDir);
|
|
@@ -3475,10 +3475,8 @@ var SharePointConnector = class extends AbstractConnector {
|
|
|
3475
3475
|
);
|
|
3476
3476
|
}
|
|
3477
3477
|
const basePath = String(opts?.basePath ?? "").replace(/^\/+|\/+$/g, "");
|
|
3478
|
-
const
|
|
3479
|
-
|
|
3480
|
-
this.log
|
|
3481
|
-
);
|
|
3478
|
+
const cred = await resolveMountCredential(declaration, secrets, tokenMediator, "initial");
|
|
3479
|
+
const auth = parseAuthBlob2(cred.token, this.log);
|
|
3482
3480
|
if (!auth.accessToken) {
|
|
3483
3481
|
throw new Error(
|
|
3484
3482
|
"SharePoint connector: no access token resolved. Use 'auth: backend' (platform) or 'auth: env:SHAREPOINT_TOKEN' (standalone)."
|
|
@@ -3497,16 +3495,29 @@ var SharePointConnector = class extends AbstractConnector {
|
|
|
3497
3495
|
vfsCacheMode,
|
|
3498
3496
|
hasRefresh: auth.refreshToken !== null
|
|
3499
3497
|
});
|
|
3500
|
-
const
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3498
|
+
const renderConfig = (rawToken) => {
|
|
3499
|
+
const a = parseAuthBlob2(rawToken, this.log);
|
|
3500
|
+
return renderOneDriveConfig({
|
|
3501
|
+
remoteName,
|
|
3502
|
+
accessToken: a.accessToken,
|
|
3503
|
+
refreshToken: a.refreshToken,
|
|
3504
|
+
expiresAtMs: a.expiresAtMs,
|
|
3505
|
+
tenantId: a.tenantId,
|
|
3506
|
+
clientId: a.clientId,
|
|
3507
|
+
clientSecret: a.clientSecret,
|
|
3508
|
+
driveId
|
|
3509
|
+
});
|
|
3510
|
+
};
|
|
3511
|
+
const handleRef = { current: null };
|
|
3512
|
+
const refresh = declaration.auth === "backend" && tokenMediator ? createRcloneTokenRefresh({
|
|
3513
|
+
connectorId: declaration.id,
|
|
3514
|
+
tokenMediator,
|
|
3515
|
+
renderConfig,
|
|
3516
|
+
rclone: this.rclone,
|
|
3517
|
+
handleRef,
|
|
3518
|
+
log: (line) => this.log.info(line)
|
|
3519
|
+
}) : void 0;
|
|
3520
|
+
const rcloneConfig = renderConfig(cred.token ?? "");
|
|
3510
3521
|
await ensureDirMode(base, this.log);
|
|
3511
3522
|
await ensureDirMode(cacheDir, this.log);
|
|
3512
3523
|
await ensureDirMode(targetDir, this.log);
|
|
@@ -3532,20 +3543,24 @@ var SharePointConnector = class extends AbstractConnector {
|
|
|
3532
3543
|
...cacheMaxAge !== void 0 ? { cacheMaxAge } : {},
|
|
3533
3544
|
...vfsWriteBack !== void 0 ? { vfsWriteBack } : {},
|
|
3534
3545
|
...ignoreSizeCheck ? { ignoreSizeCheck: true } : {},
|
|
3546
|
+
...refresh ? { onAuthError: () => refresh.onAuthError() } : {},
|
|
3535
3547
|
log: this.log
|
|
3536
3548
|
});
|
|
3537
3549
|
this.log.info("mount ready", { pid: rcloneHandle.pid });
|
|
3538
|
-
|
|
3550
|
+
handleRef.current = rcloneHandle;
|
|
3551
|
+
refresh?.schedule(cred.expiresAt);
|
|
3552
|
+
const state = { handleRef, refresh };
|
|
3539
3553
|
return this.makeHandle(declaration, state, targetDir);
|
|
3540
3554
|
}
|
|
3541
3555
|
async disconnect(handle) {
|
|
3542
3556
|
const s = handle.state;
|
|
3543
|
-
|
|
3544
|
-
|
|
3557
|
+
s.refresh?.cancel();
|
|
3558
|
+
if (s.fleetManaged || !s.handleRef.current) return;
|
|
3559
|
+
await this.rclone.stop(s.handleRef.current, { graceMs: 3e4 });
|
|
3545
3560
|
}
|
|
3546
3561
|
async _sync(handle, options) {
|
|
3547
3562
|
const s = handle.state;
|
|
3548
|
-
if (s.fleetManaged || !s.
|
|
3563
|
+
if (s.fleetManaged || !s.handleRef.current) {
|
|
3549
3564
|
options?.onSyncStatus?.({
|
|
3550
3565
|
phase: "initial_sync_complete",
|
|
3551
3566
|
totalFiles: 0,
|
|
@@ -3555,7 +3570,7 @@ var SharePointConnector = class extends AbstractConnector {
|
|
|
3555
3570
|
});
|
|
3556
3571
|
return { filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 };
|
|
3557
3572
|
}
|
|
3558
|
-
await this.rclone.flush(s.
|
|
3573
|
+
await this.rclone.flush(s.handleRef.current);
|
|
3559
3574
|
options?.onSyncStatus?.({
|
|
3560
3575
|
phase: "initial_sync_complete",
|
|
3561
3576
|
totalFiles: 0,
|
|
@@ -4405,7 +4420,7 @@ var WebDAVConnector = class extends AbstractConnector {
|
|
|
4405
4420
|
});
|
|
4406
4421
|
await ensureFleetMounted(targetDir, this.log);
|
|
4407
4422
|
const fleetState = {
|
|
4408
|
-
|
|
4423
|
+
handleRef: { current: null },
|
|
4409
4424
|
fleetManaged: true
|
|
4410
4425
|
};
|
|
4411
4426
|
return this.makeHandle(declaration, fleetState, targetDir);
|
|
@@ -4423,8 +4438,8 @@ var WebDAVConnector = class extends AbstractConnector {
|
|
|
4423
4438
|
const vendor = vendorRaw;
|
|
4424
4439
|
const basePath = String(opts?.basePath ?? "").replace(/^\/+|\/+$/g, "");
|
|
4425
4440
|
const remotePath = basePath.length > 0 ? `/${basePath}` : "/";
|
|
4426
|
-
const
|
|
4427
|
-
const
|
|
4441
|
+
const cred = await resolveMountCredential(declaration, secrets, tokenMediator, "initial");
|
|
4442
|
+
const auth = parseAuth(cred.token);
|
|
4428
4443
|
const remoteName = `skaile-${declaration.id}`;
|
|
4429
4444
|
const remote = `${remoteName}:${remotePath}`;
|
|
4430
4445
|
const base = cacheBase3();
|
|
@@ -4438,14 +4453,28 @@ var WebDAVConnector = class extends AbstractConnector {
|
|
|
4438
4453
|
vfsCacheMode,
|
|
4439
4454
|
authKind: auth.bearerToken ? "bearer" : auth.username ? "basic" : "anonymous"
|
|
4440
4455
|
});
|
|
4441
|
-
const
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4456
|
+
const renderConfig = async (rawToken) => {
|
|
4457
|
+
const a = parseAuth(rawToken);
|
|
4458
|
+
const obscured = a.password ? await this.obscure(a.password) : null;
|
|
4459
|
+
return renderWebDAVConfig({
|
|
4460
|
+
remoteName,
|
|
4461
|
+
url,
|
|
4462
|
+
vendor,
|
|
4463
|
+
username: a.username,
|
|
4464
|
+
obscuredPassword: obscured,
|
|
4465
|
+
bearerToken: a.bearerToken
|
|
4466
|
+
});
|
|
4467
|
+
};
|
|
4468
|
+
const handleRef = { current: null };
|
|
4469
|
+
const refresh = declaration.auth === "backend" && tokenMediator ? createRcloneTokenRefresh({
|
|
4470
|
+
connectorId: declaration.id,
|
|
4471
|
+
tokenMediator,
|
|
4472
|
+
renderConfig,
|
|
4473
|
+
rclone: this.rclone,
|
|
4474
|
+
handleRef,
|
|
4475
|
+
log: (line) => this.log.info(line)
|
|
4476
|
+
}) : void 0;
|
|
4477
|
+
const rcloneConfig = await renderConfig(cred.token ?? "");
|
|
4449
4478
|
await ensureDirMode(base, this.log);
|
|
4450
4479
|
await ensureDirMode(cacheDir, this.log);
|
|
4451
4480
|
await ensureDirMode(targetDir, this.log);
|
|
@@ -4463,20 +4492,24 @@ var WebDAVConnector = class extends AbstractConnector {
|
|
|
4463
4492
|
...cacheMaxSize !== void 0 ? { cacheMaxSize } : {},
|
|
4464
4493
|
...cacheMaxAge !== void 0 ? { cacheMaxAge } : {},
|
|
4465
4494
|
...vfsWriteBack !== void 0 ? { vfsWriteBack } : {},
|
|
4495
|
+
...refresh ? { onAuthError: () => refresh.onAuthError() } : {},
|
|
4466
4496
|
log: this.log
|
|
4467
4497
|
});
|
|
4468
4498
|
this.log.info("mount ready", { pid: rcloneHandle.pid });
|
|
4469
|
-
|
|
4499
|
+
handleRef.current = rcloneHandle;
|
|
4500
|
+
refresh?.schedule(cred.expiresAt);
|
|
4501
|
+
const state = { handleRef, refresh };
|
|
4470
4502
|
return this.makeHandle(declaration, state, targetDir);
|
|
4471
4503
|
}
|
|
4472
4504
|
async disconnect(handle) {
|
|
4473
4505
|
const s = handle.state;
|
|
4474
|
-
|
|
4475
|
-
|
|
4506
|
+
s.refresh?.cancel();
|
|
4507
|
+
if (s.fleetManaged || !s.handleRef.current) return;
|
|
4508
|
+
await this.rclone.stop(s.handleRef.current, { graceMs: 3e4 });
|
|
4476
4509
|
}
|
|
4477
4510
|
async _sync(handle, options) {
|
|
4478
4511
|
const s = handle.state;
|
|
4479
|
-
if (s.fleetManaged || !s.
|
|
4512
|
+
if (s.fleetManaged || !s.handleRef.current) {
|
|
4480
4513
|
options?.onSyncStatus?.({
|
|
4481
4514
|
phase: "initial_sync_complete",
|
|
4482
4515
|
totalFiles: 0,
|
|
@@ -4486,7 +4519,7 @@ var WebDAVConnector = class extends AbstractConnector {
|
|
|
4486
4519
|
});
|
|
4487
4520
|
return { filesWritten: 0, filesDeleted: 0, bytesTransferred: 0 };
|
|
4488
4521
|
}
|
|
4489
|
-
await this.rclone.flush(s.
|
|
4522
|
+
await this.rclone.flush(s.handleRef.current);
|
|
4490
4523
|
options?.onSyncStatus?.({
|
|
4491
4524
|
phase: "initial_sync_complete",
|
|
4492
4525
|
totalFiles: 0,
|
|
@@ -5240,6 +5273,115 @@ var ConnectorStartupError = class extends Error {
|
|
|
5240
5273
|
this.failedReadWrite = failedReadWrite;
|
|
5241
5274
|
}
|
|
5242
5275
|
};
|
|
5276
|
+
|
|
5277
|
+
// connectors/src/fleet-health-gate.ts
|
|
5278
|
+
var FleetHealthGate = class {
|
|
5279
|
+
constructor(target, barrier, log, opts) {
|
|
5280
|
+
this.target = target;
|
|
5281
|
+
this.barrier = barrier;
|
|
5282
|
+
this.log = log;
|
|
5283
|
+
this.unhealthyThreshold = Math.max(1, opts?.unhealthyThreshold ?? 2);
|
|
5284
|
+
this.healthyThreshold = Math.max(1, opts?.healthyThreshold ?? 2);
|
|
5285
|
+
}
|
|
5286
|
+
target;
|
|
5287
|
+
barrier;
|
|
5288
|
+
log;
|
|
5289
|
+
unhealthyThreshold;
|
|
5290
|
+
healthyThreshold;
|
|
5291
|
+
/** True while the read-only barrier is established over the target. */
|
|
5292
|
+
gated = false;
|
|
5293
|
+
/**
|
|
5294
|
+
* The gate state that the most recently *enqueued* transition will settle on.
|
|
5295
|
+
* Hysteresis is measured against this, not `gated`, so that verdicts arriving
|
|
5296
|
+
* while a (slow, async) establish/remove is still in flight are counted toward
|
|
5297
|
+
* the post-transition state rather than the stale pre-transition one. Without
|
|
5298
|
+
* this, fast healthy verdicts arriving during a slow `establish()` could meet
|
|
5299
|
+
* `healthyThreshold` before the gate finished tripping, ungating it on the
|
|
5300
|
+
* first healthy verdict afterwards and defeating the threshold.
|
|
5301
|
+
*/
|
|
5302
|
+
pendingGated = false;
|
|
5303
|
+
/** Consecutive same-verdict run length, signed by the *current* run's verdict. */
|
|
5304
|
+
unhealthyRun = 0;
|
|
5305
|
+
healthyRun = 0;
|
|
5306
|
+
/** Serialises establish/remove so overlapping observe() calls can't race. */
|
|
5307
|
+
transition = Promise.resolve();
|
|
5308
|
+
/** True while the read-only barrier is established (test/observability hook). */
|
|
5309
|
+
get isGated() {
|
|
5310
|
+
return this.gated;
|
|
5311
|
+
}
|
|
5312
|
+
/**
|
|
5313
|
+
* Feed one health verdict. Applies hysteresis, then establishes or removes the
|
|
5314
|
+
* barrier on a state change. Resolves once the (possibly no-op) transition is
|
|
5315
|
+
* applied. Never throws — a failed establish is treated as gated (fail-closed).
|
|
5316
|
+
*/
|
|
5317
|
+
observe(verdict) {
|
|
5318
|
+
if (verdict === "healthy") {
|
|
5319
|
+
this.healthyRun += 1;
|
|
5320
|
+
this.unhealthyRun = 0;
|
|
5321
|
+
if (this.pendingGated && this.healthyRun >= this.healthyThreshold) {
|
|
5322
|
+
this.pendingGated = false;
|
|
5323
|
+
this.healthyRun = 0;
|
|
5324
|
+
return this.enqueue(() => this.ungate());
|
|
5325
|
+
}
|
|
5326
|
+
} else {
|
|
5327
|
+
this.unhealthyRun += 1;
|
|
5328
|
+
this.healthyRun = 0;
|
|
5329
|
+
if (!this.pendingGated && this.unhealthyRun >= this.unhealthyThreshold) {
|
|
5330
|
+
this.pendingGated = true;
|
|
5331
|
+
this.unhealthyRun = 0;
|
|
5332
|
+
return this.enqueue(() => this.gate());
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
return this.transition;
|
|
5336
|
+
}
|
|
5337
|
+
/**
|
|
5338
|
+
* Tear the gate down. If currently gated, removes the barrier so a leftover
|
|
5339
|
+
* read-only tmpfs is not leaked. Call only after the connector above the target
|
|
5340
|
+
* is disconnected (top-down, no leaked mount).
|
|
5341
|
+
*/
|
|
5342
|
+
dispose() {
|
|
5343
|
+
if (!this.gated) return this.transition;
|
|
5344
|
+
return this.enqueue(() => this.ungate());
|
|
5345
|
+
}
|
|
5346
|
+
enqueue(step) {
|
|
5347
|
+
this.transition = this.transition.then(step, step);
|
|
5348
|
+
return this.transition;
|
|
5349
|
+
}
|
|
5350
|
+
async gate() {
|
|
5351
|
+
if (this.gated) {
|
|
5352
|
+
this.pendingGated = true;
|
|
5353
|
+
return;
|
|
5354
|
+
}
|
|
5355
|
+
try {
|
|
5356
|
+
await this.barrier.establish(this.target, this.log);
|
|
5357
|
+
this.gated = true;
|
|
5358
|
+
this.log?.warn("fleet mount unhealthy \u2014 gated read-only", { target: this.target });
|
|
5359
|
+
} catch (err) {
|
|
5360
|
+
this.gated = true;
|
|
5361
|
+
this.log?.error(
|
|
5362
|
+
"fleet read-only gate establish threw \u2014 treating as gated (fail-closed)",
|
|
5363
|
+
err,
|
|
5364
|
+
{
|
|
5365
|
+
target: this.target
|
|
5366
|
+
}
|
|
5367
|
+
);
|
|
5368
|
+
}
|
|
5369
|
+
}
|
|
5370
|
+
async ungate() {
|
|
5371
|
+
if (!this.gated) return;
|
|
5372
|
+
try {
|
|
5373
|
+
await this.barrier.remove(this.target, this.log);
|
|
5374
|
+
} catch (err) {
|
|
5375
|
+
this.pendingGated = true;
|
|
5376
|
+
this.log?.error("fleet read-only gate remove failed \u2014 staying gated", err, {
|
|
5377
|
+
target: this.target
|
|
5378
|
+
});
|
|
5379
|
+
return;
|
|
5380
|
+
}
|
|
5381
|
+
this.gated = false;
|
|
5382
|
+
this.log?.info("fleet mount recovered \u2014 gate lifted, writable again", { target: this.target });
|
|
5383
|
+
}
|
|
5384
|
+
};
|
|
5243
5385
|
function isFleetManaged(connectorId) {
|
|
5244
5386
|
const raw = process.env.SKAILE_FLEET_MANAGED_MOUNTS ?? "";
|
|
5245
5387
|
if (raw.length === 0) return false;
|
|
@@ -5268,6 +5410,16 @@ async function ensureFleetMounted(dir, log, options) {
|
|
|
5268
5410
|
`fleet mount ${dir} not ready after ${timeoutMs}ms \u2014 check SKAILE_FLEET_MANAGED_MOUNTS env var and host bind: ${lastErr instanceof Error ? lastErr.message : String(lastErr)}`
|
|
5269
5411
|
);
|
|
5270
5412
|
}
|
|
5413
|
+
async function probeFleetHealth(dir) {
|
|
5414
|
+
try {
|
|
5415
|
+
const st = await stat(dir);
|
|
5416
|
+
if (!st.isDirectory()) return "error";
|
|
5417
|
+
await readdir(dir);
|
|
5418
|
+
return "healthy";
|
|
5419
|
+
} catch {
|
|
5420
|
+
return "error";
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5271
5423
|
var NOT_READY_SENTINEL = ".skaile-workspace-not-ready";
|
|
5272
5424
|
var SENTINEL_BODY = [
|
|
5273
5425
|
"This workspace is backed by a remote mount that is not live yet.",
|
|
@@ -5394,6 +5546,12 @@ var defaultMountPlaceholderBarrier = new RoMountPlaceholderBarrier();
|
|
|
5394
5546
|
|
|
5395
5547
|
// connectors/src/connector-manager.ts
|
|
5396
5548
|
var KNOWN_PREFIXES = ["env:", "forge:", "op:", "kp:", "oauth:"];
|
|
5549
|
+
var DEFAULT_FLEET_HEALTH_POLL_MS = 5e3;
|
|
5550
|
+
function parseFleetHealthPollMs(raw = process.env.SKAILE_FLEET_HEALTH_POLL_MS) {
|
|
5551
|
+
if (raw === void 0) return DEFAULT_FLEET_HEALTH_POLL_MS;
|
|
5552
|
+
const n = Number(raw);
|
|
5553
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_FLEET_HEALTH_POLL_MS;
|
|
5554
|
+
}
|
|
5397
5555
|
function hasKnownPrefix(ref) {
|
|
5398
5556
|
return KNOWN_PREFIXES.some((p) => ref.startsWith(p));
|
|
5399
5557
|
}
|
|
@@ -5494,6 +5652,7 @@ var ConnectorManager = class {
|
|
|
5494
5652
|
this.tokenMediator = opts.tokenMediator;
|
|
5495
5653
|
this.preMintedSecrets = opts.preMintedSecrets;
|
|
5496
5654
|
this.placeholderBarrier = opts.placeholderBarrier ?? defaultMountPlaceholderBarrier;
|
|
5655
|
+
this.fleetHealthPollMs = opts.fleetHealthPollMs ?? parseFleetHealthPollMs();
|
|
5497
5656
|
const secrets = opts.secrets;
|
|
5498
5657
|
if (secrets && typeof secrets === "object" && "prepareRef" in secrets) {
|
|
5499
5658
|
this.chain = secrets;
|
|
@@ -5522,6 +5681,10 @@ var ConnectorManager = class {
|
|
|
5522
5681
|
disposeController = new AbortController();
|
|
5523
5682
|
/** Tracks the background task driving deferred (rclone-backed) mounts. */
|
|
5524
5683
|
deferredConnect;
|
|
5684
|
+
/** Periodic local fleet-health probe; runs only while a fleet gate is active. */
|
|
5685
|
+
fleetHealthTimer;
|
|
5686
|
+
/** Local fleet-health poll interval (ms). 0 disables the local probe. */
|
|
5687
|
+
fleetHealthPollMs;
|
|
5525
5688
|
// ── Private helpers ──────────────────────────────────────────────────────────
|
|
5526
5689
|
/**
|
|
5527
5690
|
* Wrap the user-supplied `TokenMediator` so `reason: 'initial'` calls for an
|
|
@@ -5793,7 +5956,9 @@ var ConnectorManager = class {
|
|
|
5793
5956
|
connector,
|
|
5794
5957
|
handle,
|
|
5795
5958
|
declaration: decl,
|
|
5796
|
-
placeholderTarget: previous?.placeholderTarget
|
|
5959
|
+
placeholderTarget: previous?.placeholderTarget,
|
|
5960
|
+
fleetHealthGate: previous?.fleetHealthGate,
|
|
5961
|
+
fleetHealthTarget: previous?.fleetHealthTarget
|
|
5797
5962
|
});
|
|
5798
5963
|
this.opts.onStatusChange?.({
|
|
5799
5964
|
type: "connector_status",
|
|
@@ -5829,16 +5994,25 @@ var ConnectorManager = class {
|
|
|
5829
5994
|
* prompt before the background mount completes.
|
|
5830
5995
|
*
|
|
5831
5996
|
* Before exposing the target, a read-only barrier is established so the agent
|
|
5832
|
-
* cannot write a phantom workspace into a not-yet-mounted remote.
|
|
5833
|
-
*
|
|
5834
|
-
*
|
|
5997
|
+
* cannot write a phantom workspace into a not-yet-mounted remote.
|
|
5998
|
+
*
|
|
5999
|
+
* Fleet-managed mounts skip the *static* boot-time barrier (the host already
|
|
6000
|
+
* bound the live share at the target — a static barrier would shadow real
|
|
6001
|
+
* content) but instead get a *dynamic* health gate: while the host fleet rclone
|
|
6002
|
+
* is healthy the target stays writable exactly as before; when it wedges, the
|
|
6003
|
+
* gate establishes the same read-only barrier until the mount recovers.
|
|
5835
6004
|
*/
|
|
5836
6005
|
async preRegisterDeferred(decl, connector) {
|
|
5837
6006
|
const mountTarget = this.resolveMountTarget(decl);
|
|
5838
6007
|
if (!existsSync(mountTarget)) mkdirSync(mountTarget, { recursive: true });
|
|
5839
6008
|
const fleetManaged = isFleetManaged(decl.id);
|
|
5840
6009
|
let placeholderTarget;
|
|
5841
|
-
|
|
6010
|
+
let fleetHealthGate;
|
|
6011
|
+
let fleetHealthTarget;
|
|
6012
|
+
if (fleetManaged) {
|
|
6013
|
+
fleetHealthGate = new FleetHealthGate(mountTarget, this.placeholderBarrier, this.mgrLog);
|
|
6014
|
+
fleetHealthTarget = mountTarget;
|
|
6015
|
+
} else {
|
|
5842
6016
|
try {
|
|
5843
6017
|
await this.placeholderBarrier.establish(mountTarget, this.mgrLog);
|
|
5844
6018
|
placeholderTarget = mountTarget;
|
|
@@ -5857,7 +6031,58 @@ var ConnectorManager = class {
|
|
|
5857
6031
|
// returns cleanly instead of dereferencing null state.
|
|
5858
6032
|
state: {}
|
|
5859
6033
|
};
|
|
5860
|
-
this.active.set(decl.id, {
|
|
6034
|
+
this.active.set(decl.id, {
|
|
6035
|
+
connector,
|
|
6036
|
+
handle,
|
|
6037
|
+
declaration: decl,
|
|
6038
|
+
placeholderTarget,
|
|
6039
|
+
fleetHealthGate,
|
|
6040
|
+
fleetHealthTarget
|
|
6041
|
+
});
|
|
6042
|
+
if (fleetHealthGate) this.ensureFleetHealthPoll();
|
|
6043
|
+
}
|
|
6044
|
+
/**
|
|
6045
|
+
* Start the periodic local fleet-health probe if it is not already running and
|
|
6046
|
+
* the poll interval is enabled. Each tick `stat`+`readdir`s every fleet target
|
|
6047
|
+
* and feeds the verdict to its gate (hysteresis lives in the gate). The probe
|
|
6048
|
+
* only catches directly-detectable failures (EIO / dead bind); silent
|
|
6049
|
+
* degradation is covered by the platform signal via `reportFleetHealth`.
|
|
6050
|
+
*/
|
|
6051
|
+
ensureFleetHealthPoll() {
|
|
6052
|
+
if (this.fleetHealthTimer || this.fleetHealthPollMs <= 0 || this.disposed) return;
|
|
6053
|
+
this.fleetHealthTimer = setInterval(() => {
|
|
6054
|
+
void this.runFleetHealthProbe();
|
|
6055
|
+
}, this.fleetHealthPollMs);
|
|
6056
|
+
this.fleetHealthTimer.unref?.();
|
|
6057
|
+
}
|
|
6058
|
+
async runFleetHealthProbe() {
|
|
6059
|
+
if (this.disposed) return;
|
|
6060
|
+
const gates = [...this.active.values()].filter(
|
|
6061
|
+
(e) => e.fleetHealthGate != null && e.fleetHealthTarget != null
|
|
6062
|
+
);
|
|
6063
|
+
await Promise.all(
|
|
6064
|
+
gates.map(async (e) => {
|
|
6065
|
+
if (e.fleetHealthGate.isGated) return;
|
|
6066
|
+
const verdict = await probeFleetHealth(e.fleetHealthTarget);
|
|
6067
|
+
await e.fleetHealthGate.observe(verdict).catch(() => {
|
|
6068
|
+
});
|
|
6069
|
+
})
|
|
6070
|
+
);
|
|
6071
|
+
}
|
|
6072
|
+
/**
|
|
6073
|
+
* Feed an externally-derived fleet-health verdict for a connector into its gate.
|
|
6074
|
+
*
|
|
6075
|
+
* This is the consume side of the platform fleet-health signal: the host fleet
|
|
6076
|
+
* health poll knows `core/stats.errors` and can detect a *silently-empty-but-
|
|
6077
|
+
* writable* degraded mount that the local probe cannot. The runner watches the
|
|
6078
|
+
* `<workspace>/.skaile/fleet-health/<connectorId>` flag and forwards its verdict
|
|
6079
|
+
* here. Unknown / non-fleet ids are ignored.
|
|
6080
|
+
*/
|
|
6081
|
+
async reportFleetHealth(connectorId, verdict) {
|
|
6082
|
+
const entry = this.active.get(connectorId);
|
|
6083
|
+
if (!entry?.fleetHealthGate) return;
|
|
6084
|
+
await entry.fleetHealthGate.observe(verdict).catch(() => {
|
|
6085
|
+
});
|
|
5861
6086
|
}
|
|
5862
6087
|
/** Drive all deferred mounts concurrently; resolves when every one settles. */
|
|
5863
6088
|
async connectDeferred(deferred) {
|
|
@@ -5904,6 +6129,10 @@ var ConnectorManager = class {
|
|
|
5904
6129
|
this.mgrLog.info("disconnectAll start", { count: this.active.size });
|
|
5905
6130
|
this.disposed = true;
|
|
5906
6131
|
this.disposeController.abort();
|
|
6132
|
+
if (this.fleetHealthTimer) {
|
|
6133
|
+
clearInterval(this.fleetHealthTimer);
|
|
6134
|
+
this.fleetHealthTimer = void 0;
|
|
6135
|
+
}
|
|
5907
6136
|
if (this.deferredConnect) {
|
|
5908
6137
|
try {
|
|
5909
6138
|
await this.deferredConnect;
|
|
@@ -5921,6 +6150,8 @@ var ConnectorManager = class {
|
|
|
5921
6150
|
await this.placeholderBarrier.remove(entry.placeholderTarget, this.mgrLog).catch(() => {
|
|
5922
6151
|
});
|
|
5923
6152
|
}
|
|
6153
|
+
if (entry.fleetHealthGate) await entry.fleetHealthGate.dispose().catch(() => {
|
|
6154
|
+
});
|
|
5924
6155
|
this.opts.onStatusChange?.({
|
|
5925
6156
|
type: "connector_status",
|
|
5926
6157
|
connectorId: id,
|
|
@@ -6011,6 +6242,8 @@ var ConnectorManager = class {
|
|
|
6011
6242
|
await this.placeholderBarrier.remove(entry.placeholderTarget, this.mgrLog).catch(() => {
|
|
6012
6243
|
});
|
|
6013
6244
|
}
|
|
6245
|
+
if (entry.fleetHealthGate) await entry.fleetHealthGate.dispose().catch(() => {
|
|
6246
|
+
});
|
|
6014
6247
|
this.active.delete(id);
|
|
6015
6248
|
this.opts.onStatusChange?.({
|
|
6016
6249
|
type: "connector_status",
|
|
@@ -6982,6 +7215,135 @@ function isPackageResolvable(pkg, projectDir) {
|
|
|
6982
7215
|
function findMissingPackages(packages, projectDir) {
|
|
6983
7216
|
return packages.filter((p) => !isPackageResolvable(p, projectDir));
|
|
6984
7217
|
}
|
|
7218
|
+
|
|
7219
|
+
// connectors/src/rclone-token-refresh.ts
|
|
7220
|
+
var PROACTIVE_RCLONE_REFRESH_MARGIN_MS = 5 * 60 * 1e3;
|
|
7221
|
+
var DEFAULT_REACTIVE_COOLDOWN_MS = 30 * 1e3;
|
|
7222
|
+
var MAX_TIMER_MS = 2147483647;
|
|
7223
|
+
function createRcloneTokenRefresh(deps) {
|
|
7224
|
+
const now2 = deps.now ?? (() => Date.now());
|
|
7225
|
+
const setTimeoutImpl = deps.setTimeoutImpl ?? ((handler, ms) => setTimeout(handler, ms));
|
|
7226
|
+
const clearTimeoutImpl = deps.clearTimeoutImpl ?? ((handle) => {
|
|
7227
|
+
clearTimeout(handle);
|
|
7228
|
+
});
|
|
7229
|
+
const marginMs = deps.marginMs ?? PROACTIVE_RCLONE_REFRESH_MARGIN_MS;
|
|
7230
|
+
const reactiveCooldownMs = deps.reactiveCooldownMs ?? DEFAULT_REACTIVE_COOLDOWN_MS;
|
|
7231
|
+
let timer = null;
|
|
7232
|
+
let refreshing = false;
|
|
7233
|
+
let disposed = false;
|
|
7234
|
+
let lastRefreshAt = Number.NEGATIVE_INFINITY;
|
|
7235
|
+
function clearTimer() {
|
|
7236
|
+
if (timer !== null) {
|
|
7237
|
+
clearTimeoutImpl(timer);
|
|
7238
|
+
timer = null;
|
|
7239
|
+
}
|
|
7240
|
+
}
|
|
7241
|
+
function cancel() {
|
|
7242
|
+
disposed = true;
|
|
7243
|
+
clearTimer();
|
|
7244
|
+
}
|
|
7245
|
+
async function fire(reason) {
|
|
7246
|
+
if (refreshing || disposed) return;
|
|
7247
|
+
refreshing = true;
|
|
7248
|
+
try {
|
|
7249
|
+
let result;
|
|
7250
|
+
try {
|
|
7251
|
+
result = await deps.tokenMediator({ connectorId: deps.connectorId, reason });
|
|
7252
|
+
} catch (err) {
|
|
7253
|
+
deps.log(
|
|
7254
|
+
`[rclone-token-refresh] mediator threw: ${err instanceof Error ? err.message : String(err)}; reactive auth-error path remains as safety net`
|
|
7255
|
+
);
|
|
7256
|
+
return;
|
|
7257
|
+
}
|
|
7258
|
+
if (disposed) return;
|
|
7259
|
+
if (!result.ok) {
|
|
7260
|
+
deps.log(
|
|
7261
|
+
`[rclone-token-refresh] mediator refused (${result.code}: ${result.message}); reactive auth-error path remains as safety net`
|
|
7262
|
+
);
|
|
7263
|
+
return;
|
|
7264
|
+
}
|
|
7265
|
+
if (!result.token) {
|
|
7266
|
+
deps.log(
|
|
7267
|
+
"[rclone-token-refresh] mediator returned an empty token; reactive auth-error path remains as safety net"
|
|
7268
|
+
);
|
|
7269
|
+
return;
|
|
7270
|
+
}
|
|
7271
|
+
const handle = deps.handleRef.current;
|
|
7272
|
+
if (!handle) {
|
|
7273
|
+
deps.log("[rclone-token-refresh] no live rclone handle to recycle; skipping refresh");
|
|
7274
|
+
return;
|
|
7275
|
+
}
|
|
7276
|
+
const rcloneConfig = await deps.renderConfig(result.token);
|
|
7277
|
+
if (disposed) return;
|
|
7278
|
+
let next;
|
|
7279
|
+
try {
|
|
7280
|
+
next = await deps.rclone.reconfigure(handle, rcloneConfig);
|
|
7281
|
+
} catch (err) {
|
|
7282
|
+
deps.log(
|
|
7283
|
+
`[rclone-token-refresh] reconfigure failed: ${err instanceof Error ? err.message : String(err)}; reactive auth-error path remains as safety net`
|
|
7284
|
+
);
|
|
7285
|
+
return;
|
|
7286
|
+
}
|
|
7287
|
+
if (disposed) {
|
|
7288
|
+
deps.log("[rclone-token-refresh] disposed mid-recycle; stopping freshly-spawned process");
|
|
7289
|
+
try {
|
|
7290
|
+
await deps.rclone.stop(next);
|
|
7291
|
+
} catch {
|
|
7292
|
+
}
|
|
7293
|
+
return;
|
|
7294
|
+
}
|
|
7295
|
+
deps.handleRef.current = next;
|
|
7296
|
+
lastRefreshAt = now2();
|
|
7297
|
+
deps.log(
|
|
7298
|
+
`[rclone-token-refresh] recycled mount with refreshed token (reason=${reason}, expiresAt=${result.expiresAt ?? "none"})`
|
|
7299
|
+
);
|
|
7300
|
+
schedule(result.expiresAt);
|
|
7301
|
+
} finally {
|
|
7302
|
+
refreshing = false;
|
|
7303
|
+
}
|
|
7304
|
+
}
|
|
7305
|
+
function armTimer(fireAtMs) {
|
|
7306
|
+
const delayMs = Math.min(Math.max(0, fireAtMs - now2()), MAX_TIMER_MS);
|
|
7307
|
+
timer = setTimeoutImpl(() => {
|
|
7308
|
+
timer = null;
|
|
7309
|
+
if (now2() < fireAtMs) armTimer(fireAtMs);
|
|
7310
|
+
else void fire("refresh");
|
|
7311
|
+
}, delayMs);
|
|
7312
|
+
timer.unref?.();
|
|
7313
|
+
}
|
|
7314
|
+
function schedule(expiresAtIso) {
|
|
7315
|
+
clearTimer();
|
|
7316
|
+
if (disposed || !expiresAtIso) return;
|
|
7317
|
+
const expiresAtMs = Date.parse(expiresAtIso);
|
|
7318
|
+
if (!Number.isFinite(expiresAtMs)) return;
|
|
7319
|
+
const fireAtMs = expiresAtMs - marginMs;
|
|
7320
|
+
if (fireAtMs - now2() <= 0) {
|
|
7321
|
+
deps.log(`[rclone-token-refresh] token within ${marginMs / 1e3}s of expiry; refreshing now`);
|
|
7322
|
+
} else {
|
|
7323
|
+
deps.log(
|
|
7324
|
+
`[rclone-token-refresh] scheduled in ${Math.round((fireAtMs - now2()) / 1e3)}s (expiresAt=${expiresAtIso})`
|
|
7325
|
+
);
|
|
7326
|
+
}
|
|
7327
|
+
armTimer(fireAtMs);
|
|
7328
|
+
}
|
|
7329
|
+
function onAuthError() {
|
|
7330
|
+
if (refreshing || disposed) return;
|
|
7331
|
+
if (now2() - lastRefreshAt < reactiveCooldownMs) {
|
|
7332
|
+
deps.log(
|
|
7333
|
+
"[rclone-token-refresh] auth-error within refresh cooldown; suppressing reactive refresh"
|
|
7334
|
+
);
|
|
7335
|
+
return;
|
|
7336
|
+
}
|
|
7337
|
+
clearTimer();
|
|
7338
|
+
void fire("retry-401");
|
|
7339
|
+
}
|
|
7340
|
+
return {
|
|
7341
|
+
schedule,
|
|
7342
|
+
onAuthError,
|
|
7343
|
+
cancel,
|
|
7344
|
+
isPending: () => timer !== null
|
|
7345
|
+
};
|
|
7346
|
+
}
|
|
6985
7347
|
var WorktreeRegistryImpl = class {
|
|
6986
7348
|
entries = /* @__PURE__ */ new Map();
|
|
6987
7349
|
register(path2, owner) {
|
|
@@ -8002,6 +8364,6 @@ function createConnector() {
|
|
|
8002
8364
|
return new FlowAdapter();
|
|
8003
8365
|
}
|
|
8004
8366
|
|
|
8005
|
-
export { AbstractConnector, BUILTIN_CONNECTOR_CATALOG, ConnectorFieldMissingError, ConnectorManager, ConnectorStartupError, DeployConnector, DevServerConnector, FlowAdapter, GitConnector, GmailConnector, GoogleDriveConnector, LocalConnector, LogBuffer, ManagedGitconfigCollisionError, MattermostConnector, MemoryConnector, MinIOConnector, NOT_READY_SENTINEL, PostgresConnector, RoMountPlaceholderBarrier, S3Connector, SQLiteConnector, SharePointConnector, StaticServerConnector, TunnelConnector, WebDAVConnector, XStateConnector, XStateStoreConnector, __test, atomicReplaceCredential, buildConnectorPromptSection, buildSdkConnectorTools, createConnector, createConnector10, createConnector11, createConnector12, createConnector13, createConnector14, createConnector15, createConnector16, createConnector17, createConnector18, createConnector19, createConnector2, createConnector3, createConnector4, createConnector5, createConnector6, createConnector7, createConnector8, createConnector9, createWorktree, defaultMountPlaceholderBarrier, defaultSpawn, ensureFleetMounted, findGitRoot, findMissingPackages, getConnector, installNpmPackages, isFleetManaged, isPackageResolvable, listConnectors, listWorktrees, registerBuiltinConnectors, removeMountBlock, renderCredentialHelperScript, tryGetConnector, worktreeRegistry, writeHelperScript, writeMountBlock };
|
|
8006
|
-
//# sourceMappingURL=chunk-
|
|
8007
|
-
//# sourceMappingURL=chunk-
|
|
8367
|
+
export { AbstractConnector, BUILTIN_CONNECTOR_CATALOG, ConnectorFieldMissingError, ConnectorManager, ConnectorStartupError, DEFAULT_REACTIVE_COOLDOWN_MS, DeployConnector, DevServerConnector, FleetHealthGate, FlowAdapter, GitConnector, GmailConnector, GoogleDriveConnector, LocalConnector, LogBuffer, ManagedGitconfigCollisionError, MattermostConnector, MemoryConnector, MinIOConnector, NOT_READY_SENTINEL, PROACTIVE_RCLONE_REFRESH_MARGIN_MS, PostgresConnector, RoMountPlaceholderBarrier, S3Connector, SQLiteConnector, SharePointConnector, StaticServerConnector, TunnelConnector, WebDAVConnector, XStateConnector, XStateStoreConnector, __test, atomicReplaceCredential, buildConnectorPromptSection, buildSdkConnectorTools, createConnector, createConnector10, createConnector11, createConnector12, createConnector13, createConnector14, createConnector15, createConnector16, createConnector17, createConnector18, createConnector19, createConnector2, createConnector3, createConnector4, createConnector5, createConnector6, createConnector7, createConnector8, createConnector9, createRcloneTokenRefresh, createWorktree, defaultMountPlaceholderBarrier, defaultSpawn, ensureFleetMounted, findGitRoot, findMissingPackages, getConnector, installNpmPackages, isFleetManaged, isPackageResolvable, listConnectors, listWorktrees, probeFleetHealth, registerBuiltinConnectors, removeMountBlock, renderCredentialHelperScript, tryGetConnector, worktreeRegistry, writeHelperScript, writeMountBlock };
|
|
8368
|
+
//# sourceMappingURL=chunk-WQRDLR3K.js.map
|
|
8369
|
+
//# sourceMappingURL=chunk-WQRDLR3K.js.map
|