@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
|
@@ -232,7 +232,8 @@ var RcloneProcessManager = class {
|
|
|
232
232
|
{ object, tries, event: "sync_status", phase: "error" }
|
|
233
233
|
);
|
|
234
234
|
config.onUploadStuck?.(object, tries);
|
|
235
|
-
}
|
|
235
|
+
},
|
|
236
|
+
onAuthError: config.onAuthError
|
|
236
237
|
};
|
|
237
238
|
const recentStderr = [];
|
|
238
239
|
const stderrTail = (line) => {
|
|
@@ -294,6 +295,7 @@ ${recentStderr.slice(-5).join("\n")}` : "";
|
|
|
294
295
|
port,
|
|
295
296
|
mountPoint: config.mountPoint,
|
|
296
297
|
cacheDir: config.cacheDir,
|
|
298
|
+
spawnConfig: config,
|
|
297
299
|
log: config.log,
|
|
298
300
|
rcloneLog,
|
|
299
301
|
recentStderr
|
|
@@ -356,6 +358,31 @@ ${recentStderr.slice(-5).join("\n")}` : "";
|
|
|
356
358
|
await unlink(entry.configPath).catch(() => {
|
|
357
359
|
});
|
|
358
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Apply a freshly-rendered rclone INI to a running mount by recycling the
|
|
363
|
+
* process: flush + stop the current rclone, then re-spawn at the same
|
|
364
|
+
* mountpoint/cacheDir with the new config. Returns the new handle.
|
|
365
|
+
*
|
|
366
|
+
* rclone holds the OAuth token in memory (baked into the config at spawn);
|
|
367
|
+
* there is no rc command to swap it on a live `onedrive` backend, so a
|
|
368
|
+
* recycle is the reliable way to apply a refreshed token. The vfs cache dir
|
|
369
|
+
* is reused, so the remount revalidates rather than re-downloads. During the
|
|
370
|
+
* brief unmount window the read-only mount-placeholder barrier underneath is
|
|
371
|
+
* exposed (writes fail with EROFS, not EIO) — see ConnectorManager's
|
|
372
|
+
* read-only-until-ready guarantee.
|
|
373
|
+
*/
|
|
374
|
+
async reconfigure(handle, rcloneConfig) {
|
|
375
|
+
const entry = HANDLES.get(handle.pid);
|
|
376
|
+
if (!entry) {
|
|
377
|
+
throw new Error(`rclone handle not found (pid=${handle.pid})`);
|
|
378
|
+
}
|
|
379
|
+
const nextConfig = { ...entry.spawnConfig, rcloneConfig };
|
|
380
|
+
entry.log.info("rclone reconfigure \u2014 recycling process to apply refreshed credential", {
|
|
381
|
+
pid: handle.pid
|
|
382
|
+
});
|
|
383
|
+
await this.stop(handle, { graceMs: 3e4 });
|
|
384
|
+
return this.spawn(nextConfig);
|
|
385
|
+
}
|
|
359
386
|
/**
|
|
360
387
|
* Force rclone to upload pending writes, then wait until the in-use
|
|
361
388
|
* counter reaches zero.
|
|
@@ -421,6 +448,7 @@ ${recentStderr.slice(-5).join("\n")}` : "";
|
|
|
421
448
|
};
|
|
422
449
|
var UPLOAD_FAIL_RE = /failed to upload.*?try #(\d+)/i;
|
|
423
450
|
var UPLOAD_OK_RE = /upload succeeded/i;
|
|
451
|
+
var AUTH_FAIL_RE = /invalid_client|couldn'?t fetch token|invalid_grant|InvalidAuthenticationToken/i;
|
|
424
452
|
function _routeRcloneLogLine(line, log, ctx) {
|
|
425
453
|
const trimmed = line.trim();
|
|
426
454
|
if (trimmed.length === 0) return;
|
|
@@ -432,7 +460,10 @@ function _routeRcloneLogLine(line, log, ctx) {
|
|
|
432
460
|
parsed = null;
|
|
433
461
|
}
|
|
434
462
|
if (!parsed) {
|
|
435
|
-
if (ctx)
|
|
463
|
+
if (ctx) {
|
|
464
|
+
_trackUploadFailure(trimmed, void 0, ctx);
|
|
465
|
+
if (AUTH_FAIL_RE.test(trimmed)) ctx.onAuthError?.();
|
|
466
|
+
}
|
|
436
467
|
log.info(trimmed);
|
|
437
468
|
return;
|
|
438
469
|
}
|
|
@@ -441,7 +472,11 @@ function _routeRcloneLogLine(line, log, ctx) {
|
|
|
441
472
|
const data = {};
|
|
442
473
|
if (parsed.object !== void 0) data.object = parsed.object;
|
|
443
474
|
if (parsed.source !== void 0) data.source = parsed.source;
|
|
444
|
-
if (ctx)
|
|
475
|
+
if (ctx) {
|
|
476
|
+
_trackUploadFailure(msg, parsed.object, ctx);
|
|
477
|
+
const errText = typeof parsed.error === "string" ? parsed.error : "";
|
|
478
|
+
if (AUTH_FAIL_RE.test(msg) || errText && AUTH_FAIL_RE.test(errText)) ctx.onAuthError?.();
|
|
479
|
+
}
|
|
445
480
|
switch (level) {
|
|
446
481
|
case "DEBUG":
|
|
447
482
|
log.debug(msg, data);
|
|
@@ -631,5 +666,5 @@ async function dirSize(dir) {
|
|
|
631
666
|
}
|
|
632
667
|
|
|
633
668
|
export { DEFAULT_UPLOAD_STUCK_THRESHOLD, DEFAULT_VFS_WRITE_BACK, PortPool, RcloneProcessManager, _buildRcloneArgs, _routeRcloneLogLine, awaitQuiescent, createFsWatcher, ensureDirMode };
|
|
634
|
-
//# sourceMappingURL=chunk-
|
|
635
|
-
//# sourceMappingURL=chunk-
|
|
669
|
+
//# sourceMappingURL=chunk-XT6AZWK3.js.map
|
|
670
|
+
//# sourceMappingURL=chunk-XT6AZWK3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../connectors/src/fs-utils.ts","../connectors/src/port-pool.ts","../connectors/src/watcher.ts","../connectors/src/rclone-process-manager.ts"],"names":[],"mappings":"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","file":"chunk-XT6AZWK3.js","sourcesContent":["/**\n * Shared filesystem helpers for connector infrastructure.\n *\n * @docLink packages/connectors/api-reference#fs-utils\n */\n\nimport { chmod, mkdir } from \"node:fs/promises\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * mkdir(recursive) + chmod 0o770 in one call. The post-mkdir `chmod` is the\n * load-bearing piece: `mkdir(mode:)` is ANDed with the process umask\n * (typically 022 → effective mode 0o750), which strips the group-write bit\n * that `fusermount3` requires on the rclone mountpoint and rclone needs on\n * its vfs cache directory. Explicit `chmod` is umask-immune.\n *\n * EPERM on `chmod` is swallowed: when a foreign uid pre-created the\n * directory (a stray uid-1000 process inside the container or a host-side\n * platform process writing through the project bind-mount), the runner\n * cannot chmod it. The platform's agent container entrypoint runs as root\n * and heals the subtree on the next restart — see\n * `platform/docker/agent/entrypoint.sh` `_skaile_heal_ownership`. A debug\n * line is emitted when a logger is supplied so the rare-but-real heal\n * trigger is observable in session logs without adding noise on the happy\n * path.\n *\n * The chmod is *idempotent* (the syscall always fires, but a no-op when\n * the mode is already 0o770), not a no-op — kernel behaviour for chmod is\n * \"set\", not \"set-if-different\".\n *\n * @param dir Absolute or relative path to ensure exists at mode 0o770.\n * @param log Optional logger. When provided, EPERM-on-chmod emits a\n * `debug`-level entry under whatever taxonomy the caller's logger uses.\n */\nexport async function ensureDirMode(dir: string, log?: Logger): Promise<void> {\n await mkdir(dir, { recursive: true });\n try {\n await chmod(dir, 0o770);\n } catch (err) {\n log?.debug(\"chmod 0770 skipped (EPERM — entrypoint heal expected)\", {\n path: dir,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n","/**\n * PortPool — allocates ports from a [min, max] range, checks OS for collisions.\n */\n\nimport { createConnection } from \"node:net\";\n\n/**\n * Allocates TCP ports from a `[min, max]` range with OS-level collision detection.\n * Used by service connector adapters (devserver, static-server) to assign local ports.\n * @docLink packages/connectors/api-reference#port-pool\n */\nexport class PortPool {\n private readonly min: number;\n private readonly max: number;\n private readonly inUse = new Set<number>();\n\n constructor(range: [number, number]) {\n this.min = range[0];\n this.max = range[1];\n }\n\n /** Allocate the next free port from the range. Checks OS for collisions. */\n async allocate(): Promise<number> {\n for (let port = this.min; port <= this.max; port++) {\n if (this.inUse.has(port)) continue;\n if (!(await PortPool.isPortFree(port))) {\n this.inUse.add(port);\n continue;\n }\n this.inUse.add(port);\n return port;\n }\n throw new Error(`No free port in range ${this.min}-${this.max}`);\n }\n\n /** Mark a port as in-use (for explicit port args or registered instances). */\n reserve(port: number): void {\n this.inUse.add(port);\n }\n\n /** Return a port to the pool. */\n release(port: number): void {\n this.inUse.delete(port);\n }\n\n /** Check if a port is currently tracked as in-use. */\n isInUse(port: number): boolean {\n return this.inUse.has(port);\n }\n\n /** Quick TCP connect test — returns true if nothing is listening. */\n static isPortFree(port: number, host = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ port, host });\n socket.once(\"connect\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.once(\"error\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.setTimeout(500, () => {\n socket.destroy();\n resolve(true);\n });\n });\n }\n}\n","/**\n * Shared filesystem watcher factory for mountable adapters.\n *\n * Uses chokidar for cross-platform, debounced file watching.\n *\n * Automatically reads .gitignore from the watched directory and merges\n * those patterns into chokidar's ignore list. This prevents scanning\n * large generated directories (node_modules, dist, .next, etc.) that\n * most projects already declare as ignored.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n// Static import so bun --compile bundles chokidar into the binary. A dynamic\n// `await import(\"chokidar\")` is not seen by the compiler's static analyzer\n// and fails at runtime inside the /$bunfs/ virtual filesystem.\nimport chokidar from \"chokidar\";\nimport type { ConnectorChangeEvent } from \"./connector-types.js\";\nimport type { WatchHandle, WatchOptions } from \"./shared-types.js\";\n\n/**\n * Convert a glob pattern to a matcher function.\n *\n * Chokidar 5 changed string matchers to exact equality (`===`) instead of\n * glob matching. We convert our patterns to functions so chokidar can still\n * filter correctly.\n */\nfunction globToMatcher(pattern: string): (path: string) => boolean {\n // Simple segment-name patterns: **/NAME/** or **/NAME\n // Match any path that contains /NAME/ or ends with /NAME\n const segmentMatch = pattern.match(/^\\*\\*\\/([^*/?]+)\\/\\*\\*$/);\n if (segmentMatch) {\n const name = segmentMatch[1];\n return (p: string) => p.includes(`/${name}/`) || p.endsWith(`/${name}`) || p === name;\n }\n\n // Dot-prefixed segment: **/.NAME or **/.NAME/**\n const dotSegment = pattern.match(/^\\*\\*\\/(\\.[\\w#]+)(?:\\/\\*\\*)?$/);\n if (dotSegment) {\n const name = dotSegment[1];\n return (p: string) => p.includes(`/${name}/`) || p.endsWith(`/${name}`) || p === name;\n }\n\n // Extension wildcard: **/*.EXT.* or **/*.EXT\n const extMatch = pattern.match(/^\\*\\*\\/\\*(\\.\\w+(?:\\.\\*)?)/);\n if (extMatch) {\n const suffix = extMatch[1];\n if (suffix.endsWith(\".*\")) {\n // e.g. **/*.tmp.* -> match any file with .tmp. in it\n const base = suffix.slice(0, -2);\n return (p: string) => p.includes(base);\n }\n return (p: string) => p.endsWith(suffix);\n }\n\n // Suffix wildcard: **/*SUFFIX (e.g. **/*~)\n const suffixMatch = pattern.match(/^\\*\\*\\/\\*(.+)$/);\n if (suffixMatch) {\n const sfx = suffixMatch[1];\n return (p: string) => p.endsWith(sfx);\n }\n\n // Fallback: convert simple globs to regex\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\?/g, \"[^/]\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \".*\");\n const re = new RegExp(`^${escaped}$`);\n return (p: string) => re.test(p);\n}\n\nconst DEFAULT_IGNORED: Array<string | ((path: string) => boolean)> = [\n (p: string) => p.includes(\"/.git/\") || p.endsWith(\"/.git\"),\n (p: string) => p.includes(\"/node_modules/\") || p.endsWith(\"/node_modules\"),\n (p: string) => p.includes(\"/.connectors/\") || p.endsWith(\"/.connectors\"),\n // Atomic-write tempfiles (Bun.write creates `<name>.tmp.<pid>.<ts>` then renames).\n // These vanish between readdir and fs.watch, causing EINVAL that crashes the process.\n (p: string) => /\\.tmp\\.\\d/.test(p),\n // Editor swap/backup files that also race with save operations.\n (p: string) => p.endsWith(\".swp\"),\n (p: string) => p.endsWith(\".swx\"),\n (p: string) => p.includes(\"/.#\"),\n (p: string) => p.endsWith(\"~\"),\n];\n/**\n * Default chokidar `awaitWriteFinish` stability threshold (ms). Exported so the\n * rclone process manager can reuse the same write-stabilization concept when\n * gating a flush on a quiescent mount.\n */\nexport const DEFAULT_DEBOUNCE_MS = 150;\n\n/**\n * Parse a .gitignore file into glob patterns suitable for chokidar's `ignored` option.\n * Handles comments, blank lines, directory patterns, and root-relative patterns.\n * Negation patterns (!) are skipped - chokidar cannot un-ignore.\n */\nfunction parseGitignore(rootDir: string): Array<(path: string) => boolean> {\n const gitignorePath = join(rootDir, \".gitignore\");\n if (!existsSync(gitignorePath)) return [];\n\n try {\n const content = readFileSync(gitignorePath, \"utf-8\");\n const matchers: Array<(path: string) => boolean> = [];\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\") || line.startsWith(\"!\")) continue;\n\n let pattern = line;\n\n // Strip leading / (root-relative -> convert to rootDir-relative)\n if (pattern.startsWith(\"/\")) {\n pattern = pattern.slice(1);\n } else if (!pattern.includes(\"/\")) {\n // Bare name like \"node_modules\" or \"*.log\" -> match anywhere\n pattern = `**/${pattern}`;\n }\n\n // Directory pattern (trailing /) -> ensure it matches contents too\n if (pattern.endsWith(\"/\")) {\n matchers.push(globToMatcher(`${pattern}**`));\n } else {\n matchers.push(globToMatcher(pattern));\n // Also match as directory (e.g. \"dist\" should match \"dist/\" and \"dist/**\")\n if (!pattern.includes(\"*\") && !pattern.includes(\".\")) {\n matchers.push(globToMatcher(`${pattern}/**`));\n }\n }\n }\n\n return matchers;\n } catch {\n return [];\n }\n}\n\ntype ChokidarAction = \"create\" | \"edit\" | \"delete\";\n\nconst CHOKIDAR_EVENT_MAP: Record<string, ChokidarAction> = {\n add: \"create\",\n change: \"edit\",\n unlink: \"delete\",\n addDir: \"create\",\n unlinkDir: \"delete\",\n};\n\n/**\n * Create a cross-platform filesystem watcher on `rootDir` using chokidar.\n * Auto-reads `.gitignore` from `rootDir` and merges those patterns into the ignore list.\n * @param rootDir - Absolute path to the directory to watch.\n * @param callback - Called with each `ConnectorChangeEvent` (create / edit / delete).\n * @param options - Debounce interval and additional ignore patterns.\n * @returns A `WatchHandle` — call `.close()` to stop watching.\n * @docLink packages/connectors/api-reference#create-fs-watcher\n */\nexport async function createFsWatcher(\n rootDir: string,\n callback: (event: ConnectorChangeEvent) => void,\n options?: WatchOptions,\n): Promise<WatchHandle> {\n const log = createLogger({ kind: \"connector\", subkind: \"watcher\", instance: rootDir });\n const gitignorePatterns = parseGitignore(rootDir);\n // Convert any remaining string patterns from options to matcher functions\n // (chokidar 5 treats strings as exact equality, not globs)\n const optionsIgnored = (options?.ignored ?? []).map((entry) =>\n typeof entry === \"string\" ? globToMatcher(entry) : entry,\n );\n const ignored = [...DEFAULT_IGNORED, ...gitignorePatterns, ...optionsIgnored];\n const debounceMs = options?.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n const watcher = chokidar.watch(rootDir, {\n ignoreInitial: true,\n ignored,\n awaitWriteFinish: { stabilityThreshold: debounceMs, pollInterval: 50 },\n usePolling: false,\n });\n\n // Swallow transient watch errors (EINVAL/ENOENT when a file vanishes between\n // readdir and fs.watch). Without this handler, chokidar rethrows and the\n // agent process dies.\n watcher.on(\"error\", (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.warn(\"watcher error (non-fatal)\", { message });\n });\n\n for (const [chokidarEvent, action] of Object.entries(CHOKIDAR_EVENT_MAP)) {\n (watcher as { on(event: string, fn: (fullPath: string) => void): void }).on(\n chokidarEvent,\n (fullPath: string) => {\n const rel = relative(rootDir, fullPath);\n if (!rel || rel.startsWith(\"..\")) return;\n // Normalize to forward slashes\n const normalizedPath = rel.split(\"\\\\\").join(\"/\");\n callback({ path: normalizedPath, action, source: \"filesystem\" });\n },\n );\n }\n\n return {\n close: () => watcher.close(),\n };\n}\n","/**\n * RcloneProcessManager — supervises an rclone FUSE subprocess per mount.\n *\n * Responsibilities:\n * - Spawn rclone with a per-mount config + cache dir, wait for the FUSE\n * mountpoint to appear, then return a handle.\n * - Pipe rclone's JSON-formatted log lines into the parent driver's\n * {@link Logger} via a child source `${driverName}+rclone`.\n * - Coordinate graceful stop (flush → SIGTERM → fusermount fallback).\n * - Expose `flush` (POST /vfs/refresh + poll /vfs/stats) and `status`\n * (process liveness + cache-dir size).\n *\n * Cross-link: see `workspaces/core/CLAUDE.md` § Logging for the\n * `createLogger` / `LogStore` contract, and\n * `_devlog/specs/2026-05-01-debug-logging-design.md` for the source taxonomy.\n */\n\nimport { type ChildProcess, spawn } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport type { Logger } from \"@skaile/workspaces/types\";\nimport { ensureDirMode } from \"./fs-utils.js\";\nimport { PortPool } from \"./port-pool.js\";\nimport { DEFAULT_DEBOUNCE_MS } from \"./watcher.js\";\n\n/** Module-level pool for rclone remote-control (rc) ports. */\nconst RCLONE_RC_PORTS = new PortPool([55000, 56000]);\n\n/** Default rclone `--vfs-write-back` delay; raised from 5s so a rapidly-rewritten file settles before upload (avoids mid-write \"sizes differ\" aborts). */\nexport const DEFAULT_VFS_WRITE_BACK = \"30s\";\n\n/** Consecutive failed upload retries for one object before a stuck-upload error is surfaced. */\nexport const DEFAULT_UPLOAD_STUCK_THRESHOLD = 3;\n\n/**\n * Stabilization gate defaults for {@link RcloneProcessManager.flush}. Before\n * forcing an upload we wait until the vfs cache dir has had no write for\n * `thresholdMs`, bounded by `timeoutMs` so close/hibernate never blocks\n * forever. `pollMs` reuses the watcher's write-stabilization debounce.\n */\nconst STABILIZE_THRESHOLD_MS = 1_500;\nconst STABILIZE_TIMEOUT_MS = 30_000;\nconst STABILIZE_POLL_MS = DEFAULT_DEBOUNCE_MS;\n\n/**\n * Spawn-time configuration for a single rclone FUSE mount.\n * @docLink packages/connectors/api-reference#rclone-spawn-config\n */\nexport interface RcloneSpawnConfig {\n /** Logical mount id; used as `instance` and as part of the rclone config filename. */\n mountId: string;\n /**\n * Driver name (e.g. \"sharepoint\", \"webdav\"); used to derive the rclone\n * subprocess child logger subkind: `${driverName}+rclone`.\n */\n driverName: string;\n /** Absolute path inside the container where rclone will FUSE-mount. Created if missing. */\n mountPoint: string;\n /** Absolute path inside the container for the vfs cache. Created if missing. */\n cacheDir: string;\n /** Full INI text for rclone.conf (one [remote] section, named `skaile-<mountId>`). */\n rcloneConfig: string;\n /** Remote spec, e.g. `skaile-foo:/Clients/KADK`. */\n remote: string;\n /** rclone --vfs-cache-mode value. */\n vfsCacheMode: \"minimal\" | \"writes\" | \"full\";\n /** Per-mount cache size cap. Default: '5G'. */\n cacheMaxSize?: string;\n /** Per-mount cache age cap. Default: '168h'. */\n cacheMaxAge?: string;\n /**\n * Skip rclone's post-transfer size + checksum verification by appending\n * `--ignore-size --ignore-checksum`. Default: false (verification on).\n *\n * Escape hatch for remotes that mutate uploaded bytes server-side (notably\n * SharePoint Online normalising LF→CRLF on text/html), which makes the\n * remote object a different size/hash than the local source. rclone reads\n * that as `corrupted on transfer`, deletes the upload, and retries forever,\n * so the file never durably lands. Enabling this trades integrity\n * verification for sync-ability and must only be set by drivers that have\n * confirmed the mutation is benign. Off-by-default; wired per-driver, never\n * globally.\n */\n ignoreSizeCheck?: boolean;\n /**\n * rclone `--vfs-write-back` delay (e.g. '30s', '1m'). Controls how long a\n * dirty file sits before rclone starts uploading it. Default:\n * {@link DEFAULT_VFS_WRITE_BACK}. Raise it when the agent rewrites files\n * faster than they upload, to avoid mid-write \"sizes differ\" aborts.\n */\n vfsWriteBack?: string;\n /**\n * Consecutive upload retries for one object before {@link onUploadStuck}\n * fires. Default: {@link DEFAULT_UPLOAD_STUCK_THRESHOLD}.\n */\n uploadStuckThreshold?: number;\n /**\n * Optional hook invoked once per object when its upload has failed\n * `uploadStuckThreshold` times in a row. spawn() always also logs an\n * error-level entry through the `${driverName}+rclone` child logger; this\n * hook lets callers surface the stranded file elsewhere (e.g. a sync event).\n */\n onUploadStuck?: (object: string, tries: number) => void;\n /**\n * Optional hook invoked when rclone reports an OAuth auth failure (notably\n * `invalid_client` / `couldn't fetch token`, the symptom of an expired\n * access token that rclone cannot self-refresh). Wired by the mount driver\n * to the reactive arm of its token-refresh controller. Fires per matching\n * log line; the controller dedupes via its in-flight guard + cooldown.\n */\n onAuthError?: () => void;\n /**\n * Parent driver Logger — already tagged\n * `{kind:\"mount\", subkind:<driver>, instance:<mountId>}` by ConnectorManager.\n * Used for manager-level events; rclone subprocess events go through the\n * derived `child({subkind: \\`${driverName}+rclone\\`})` logger.\n */\n log: Logger;\n}\n\n/**\n * Handle returned by `RcloneProcessManager.spawn()` once the FUSE mountpoint is confirmed.\n * @docLink packages/connectors/api-reference#rclone-handle\n */\nexport interface RcloneHandle {\n /** OS process id of the rclone subprocess. */\n pid: number;\n /** Confirmed FUSE mountpoint (echo of input). */\n mountPoint: string;\n /** Cache directory (echo of input). */\n cacheDir: string;\n /** The local rc API address rclone is bound to, e.g. '127.0.0.1:54321'. */\n rcAddr: string;\n}\n\ninterface InternalEntry {\n proc: ChildProcess;\n configPath: string;\n port: number;\n mountPoint: string;\n cacheDir: string;\n /** The full spawn config, retained so `reconfigure` can recycle the process. */\n spawnConfig: RcloneSpawnConfig;\n log: Logger;\n rcloneLog: Logger;\n /**\n * Last few stderr lines for diagnostic purposes (used in spawn-failure\n * messages).\n */\n recentStderr: string[];\n}\n\nconst HANDLES = new Map<number, InternalEntry>();\n\n/**\n * Manages rclone FUSE subprocesses for mount drivers. Stateless across instances —\n * the internal handle registry is module-scoped so a fresh `RcloneProcessManager`\n * can still find handles created by a previous instance.\n * @docLink packages/connectors/api-reference#rclone-process-manager\n */\nexport class RcloneProcessManager {\n /**\n * Spawn an rclone FUSE mount. Resolves once the mountpoint is confirmed\n * present in `/proc/self/mounts`. Throws on timeout, on early exit, or\n * if invariants are violated.\n */\n async spawn(config: RcloneSpawnConfig): Promise<RcloneHandle> {\n if (!path.isAbsolute(config.mountPoint)) {\n throw new Error(`mountPoint must be absolute: ${config.mountPoint}`);\n }\n if (!path.isAbsolute(config.cacheDir)) {\n throw new Error(`cacheDir must be absolute: ${config.cacheDir}`);\n }\n\n // Defence-in-depth: the per-connector driver already chmods these via\n // ensureDirMode, but direct callers that bypass the driver still need\n // mountPoint and cacheDir to be group-writable for fusermount3 / vfs.\n await ensureDirMode(config.mountPoint, config.log);\n await ensureDirMode(config.cacheDir, config.log);\n\n const configPath = path.join(\n tmpdir(),\n `rclone-${config.mountId}-${randomBytes(6).toString(\"hex\")}.conf`,\n );\n await writeFile(configPath, config.rcloneConfig, { mode: 0o600 });\n\n const port = await RCLONE_RC_PORTS.allocate();\n const rcAddr = `127.0.0.1:${port}`;\n const rcloneLog = config.log.child({ subkind: `${config.driverName}+rclone` });\n\n config.log.info(\"rclone spawn starting\", {\n mountPoint: config.mountPoint,\n remote: config.remote,\n vfsCacheMode: config.vfsCacheMode,\n });\n\n const args = _buildRcloneArgs(config, { configPath, rcAddr });\n\n const proc = spawn(\"rclone\", args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\n // Per-process tracker for the upload-stuck observability gate. When an\n // object's upload retry count crosses the threshold we log once at error\n // level (the stream otherwise stays at INFO and the failure is silent).\n const routeCtx: RcloneLogRouteContext = {\n stuckThreshold: config.uploadStuckThreshold ?? DEFAULT_UPLOAD_STUCK_THRESHOLD,\n alertedObjects: new Set<string>(),\n onUploadStuck: (object, tries) => {\n rcloneLog.error(\n \"rclone upload repeatedly failing — file may be stranded in this session's cache\",\n undefined,\n { object, tries, event: \"sync_status\", phase: \"error\" },\n );\n config.onUploadStuck?.(object, tries);\n },\n onAuthError: config.onAuthError,\n };\n\n const recentStderr: string[] = [];\n const stderrTail = (line: string) => {\n recentStderr.push(line);\n if (recentStderr.length > 20) recentStderr.shift();\n };\n\n const stdoutHandler = (line: string) => {\n _routeRcloneLogLine(line, rcloneLog, routeCtx);\n };\n const stderrHandler = (line: string) => {\n stderrTail(line);\n _routeRcloneLogLine(line, rcloneLog, routeCtx);\n };\n\n if (proc.stdout) attachLineSplitter(proc.stdout, stdoutHandler);\n if (proc.stderr) attachLineSplitter(proc.stderr, stderrHandler);\n\n let earlyExitCode: number | null = null;\n let earlyExitSignal: NodeJS.Signals | null = null;\n const earlyExit = new Promise<void>((resolve) => {\n proc.once(\"exit\", (code, signal) => {\n earlyExitCode = code;\n earlyExitSignal = signal;\n resolve();\n });\n });\n\n const mountReady = waitFor(\n async () => {\n if (earlyExitCode !== null || earlyExitSignal !== null) return false;\n return await isMountpoint(config.mountPoint);\n },\n { timeoutMs: 15_000, intervalMs: 100 },\n );\n\n const ready = await Promise.race([mountReady, earlyExit.then(() => false)]);\n\n if (!ready) {\n try {\n if (proc.exitCode === null && proc.signalCode === null) {\n proc.kill(\"SIGKILL\");\n }\n } catch {\n // ignore\n }\n await unlink(configPath).catch(() => {});\n RCLONE_RC_PORTS.release(port);\n const tail =\n recentStderr.length > 0 ? `\\nstderr tail:\\n${recentStderr.slice(-5).join(\"\\n\")}` : \"\";\n throw new Error(`rclone failed to mount ${config.remote} at ${config.mountPoint}${tail}`);\n }\n\n const pid = proc.pid;\n if (pid === undefined) {\n // Should never happen if mountReady resolved true, but defend anyway.\n proc.kill(\"SIGKILL\");\n await unlink(configPath).catch(() => {});\n RCLONE_RC_PORTS.release(port);\n throw new Error(\"rclone process has no pid after successful mount\");\n }\n\n const entry: InternalEntry = {\n proc,\n configPath,\n port,\n mountPoint: config.mountPoint,\n cacheDir: config.cacheDir,\n spawnConfig: config,\n log: config.log,\n rcloneLog,\n recentStderr,\n };\n HANDLES.set(pid, entry);\n\n proc.on(\"exit\", (code) => {\n // If the entry is still in the registry, this was unplanned.\n if (HANDLES.has(pid)) {\n config.log.warn(\"rclone exited unexpectedly\", { code, pid });\n }\n });\n\n config.log.info(\"rclone mountpoint confirmed\", { pid });\n\n return { pid, mountPoint: config.mountPoint, cacheDir: config.cacheDir, rcAddr };\n }\n\n /**\n * Stop an rclone subprocess. Attempts a flush first, then SIGTERM, then\n * SIGKILL + fusermount3 if `graceMs` elapses without the mountpoint\n * disappearing.\n *\n * `graceMs` bounds both the flush stabilization gate and the SIGTERM→SIGKILL\n * window — it is *not* a single total wall-clock cap: the flush also waits on\n * rclone's `/vfs/stats` drain (its own 60s ceiling) between the two.\n */\n async stop(handle: RcloneHandle, opts?: { graceMs?: number }): Promise<void> {\n const graceMs = opts?.graceMs ?? 30_000;\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n return;\n }\n\n try {\n // Bound the stabilization gate by graceMs so stop() doesn't silently add\n // the full default stabilize timeout on top of the caller's budget.\n await this.flush(handle, { stabilizeTimeoutMs: graceMs });\n } catch (err) {\n entry.log.warn(\"rclone flush before stop failed\", {\n pid: handle.pid,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n entry.log.info(\"rclone stop initiated\", { pid: handle.pid });\n\n // Remove FIRST so the exit handler doesn't fire the unplanned-exit warning.\n HANDLES.delete(handle.pid);\n\n try {\n entry.proc.kill(\"SIGTERM\");\n } catch {\n // ignore — process may already be gone\n }\n\n const unmounted = await waitFor(async () => !(await isMountpoint(entry.mountPoint)), {\n timeoutMs: graceMs,\n intervalMs: 200,\n });\n\n if (!unmounted) {\n try {\n entry.proc.kill(\"SIGKILL\");\n } catch {\n // ignore\n }\n await new Promise<void>((resolve) => {\n const fuse = spawn(\"fusermount3\", [\"-u\", entry.mountPoint], { stdio: \"ignore\" });\n fuse.once(\"exit\", () => resolve());\n fuse.once(\"error\", () => resolve());\n });\n entry.log.warn(\"rclone hard-killed\", { pid: handle.pid });\n }\n\n RCLONE_RC_PORTS.release(entry.port);\n await unlink(entry.configPath).catch(() => {});\n }\n\n /**\n * Apply a freshly-rendered rclone INI to a running mount by recycling the\n * process: flush + stop the current rclone, then re-spawn at the same\n * mountpoint/cacheDir with the new config. Returns the new handle.\n *\n * rclone holds the OAuth token in memory (baked into the config at spawn);\n * there is no rc command to swap it on a live `onedrive` backend, so a\n * recycle is the reliable way to apply a refreshed token. The vfs cache dir\n * is reused, so the remount revalidates rather than re-downloads. During the\n * brief unmount window the read-only mount-placeholder barrier underneath is\n * exposed (writes fail with EROFS, not EIO) — see ConnectorManager's\n * read-only-until-ready guarantee.\n */\n async reconfigure(handle: RcloneHandle, rcloneConfig: string): Promise<RcloneHandle> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n throw new Error(`rclone handle not found (pid=${handle.pid})`);\n }\n const nextConfig: RcloneSpawnConfig = { ...entry.spawnConfig, rcloneConfig };\n entry.log.info(\"rclone reconfigure — recycling process to apply refreshed credential\", {\n pid: handle.pid,\n });\n await this.stop(handle, { graceMs: 30_000 });\n return this.spawn(nextConfig);\n }\n\n /**\n * Force rclone to upload pending writes, then wait until the in-use\n * counter reaches zero.\n *\n * Before issuing the refresh it waits for the vfs cache dir to go quiescent\n * (no write for `stabilityThresholdMs`, bounded by `stabilizeTimeoutMs`) so a\n * close/hibernate-triggered flush doesn't snapshot a half-written file and\n * trigger rclone's mid-write \"sizes differ\" abort. Pass `stabilize: false`\n * to skip the gate.\n */\n async flush(\n handle: RcloneHandle,\n opts?: { stabilize?: boolean; stabilityThresholdMs?: number; stabilizeTimeoutMs?: number },\n ): Promise<void> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n throw new Error(`rclone handle not found (pid=${handle.pid})`);\n }\n\n if (opts?.stabilize !== false) {\n const thresholdMs = opts?.stabilityThresholdMs ?? STABILIZE_THRESHOLD_MS;\n const timeoutMs = opts?.stabilizeTimeoutMs ?? STABILIZE_TIMEOUT_MS;\n // Scan only the vfs content subtree (agent writes land here). The sibling\n // `vfsMeta/` tree is rclone housekeeping whose churn would never settle.\n const scanDir = await vfsContentDir(entry.cacheDir);\n const quiescent = await awaitQuiescent(scanDir, {\n thresholdMs,\n timeoutMs,\n pollMs: STABILIZE_POLL_MS,\n });\n if (!quiescent) {\n entry.log.warn(\"rclone cache did not stabilize before flush — proceeding anyway\", {\n pid: handle.pid,\n thresholdMs,\n timeoutMs,\n });\n }\n }\n\n const refreshRes = await fetch(`http://${handle.rcAddr}/vfs/refresh?recursive=true`, {\n method: \"POST\",\n });\n if (!refreshRes.ok) {\n const body = await refreshRes.text().catch(() => \"\");\n throw new Error(`rclone /vfs/refresh failed: ${refreshRes.status} ${body}`);\n }\n\n const ok = await waitFor(\n async () => {\n const r = await fetch(`http://${handle.rcAddr}/vfs/stats`, { method: \"GET\" });\n if (!r.ok) return false;\n const body = (await r.json()) as { inUse?: number; [k: string]: unknown };\n return body.inUse === 0;\n },\n { timeoutMs: 60_000, intervalMs: 500 },\n );\n if (!ok) {\n throw new Error(`rclone flush did not drain within 60s (pid=${handle.pid})`);\n }\n }\n\n /** Liveness + cache-dir size. */\n async status(handle: RcloneHandle): Promise<{ alive: boolean; cacheBytes: number }> {\n const entry = HANDLES.get(handle.pid);\n if (!entry) {\n return { alive: false, cacheBytes: 0 };\n }\n const alive = entry.proc.exitCode === null && entry.proc.signalCode === null;\n const cacheBytes = await dirSize(entry.cacheDir);\n return { alive, cacheBytes };\n }\n}\n\ninterface RcloneJsonLine {\n level?: string;\n msg?: string;\n source?: string;\n time?: string;\n object?: string;\n error?: unknown;\n}\n\n/**\n * Per-process state threaded through {@link _routeRcloneLogLine} so it can\n * detect a sustained upload failure (the same object failing to upload K times\n * in a row) and surface it exactly once, instead of letting rclone retry\n * silently at INFO level forever.\n */\nexport interface RcloneLogRouteContext {\n /** Consecutive retries for one object before {@link onUploadStuck} fires. */\n stuckThreshold?: number;\n /** Objects already alerted on, to fire once and not on every later retry. */\n alertedObjects?: Set<string>;\n /** Called the first time an object crosses {@link stuckThreshold}. */\n onUploadStuck?: (object: string, tries: number) => void;\n /** Called when a line matches an OAuth auth-failure pattern. */\n onAuthError?: () => void;\n}\n\n/** rclone's vfs write-back failure line: \"... failed to upload try #3, will retry ...\". */\nconst UPLOAD_FAIL_RE = /failed to upload.*?try #(\\d+)/i;\n/** rclone's vfs write-back success line, used to reset the per-object alert. */\nconst UPLOAD_OK_RE = /upload succeeded/i;\n/**\n * OAuth token-level failures rclone emits when the access token is expired and\n * it cannot self-refresh (the Skaile-managed-Entra `client_secret`-stripped\n * case). `invalid_client` / `couldn't fetch token` is the confirmed prod\n * symptom; the rest cover the equivalent MSAL/refresh-grant token failures.\n * Bare HTTP `401` is intentionally excluded — rclone retries many transient\n * 401s internally without needing a token refresh; only these token-level\n * failures mean rclone is stuck.\n */\nconst AUTH_FAIL_RE =\n /invalid_client|couldn'?t fetch token|invalid_grant|InvalidAuthenticationToken/i;\n\n/**\n * @internal\n * Route a single rclone log line (JSON or raw) to the appropriate Logger\n * call. Exported for tests; not part of the public API. When `ctx` is\n * supplied, also tracks consecutive upload failures per object and invokes\n * `ctx.onUploadStuck` once the retry count for an object reaches the threshold.\n */\nexport function _routeRcloneLogLine(line: string, log: Logger, ctx?: RcloneLogRouteContext): void {\n const trimmed = line.trim();\n if (trimmed.length === 0) return;\n\n let parsed: RcloneJsonLine | null = null;\n try {\n const candidate = JSON.parse(trimmed);\n if (candidate && typeof candidate === \"object\") parsed = candidate as RcloneJsonLine;\n } catch {\n parsed = null;\n }\n\n if (!parsed) {\n if (ctx) {\n _trackUploadFailure(trimmed, undefined, ctx);\n if (AUTH_FAIL_RE.test(trimmed)) ctx.onAuthError?.();\n }\n log.info(trimmed);\n return;\n }\n\n const level = (parsed.level ?? \"INFO\").toUpperCase();\n const msg = parsed.msg ?? \"\";\n const data: Record<string, unknown> = {};\n if (parsed.object !== undefined) data.object = parsed.object;\n if (parsed.source !== undefined) data.source = parsed.source;\n\n if (ctx) {\n _trackUploadFailure(msg, parsed.object, ctx);\n const errText = typeof parsed.error === \"string\" ? parsed.error : \"\";\n if (AUTH_FAIL_RE.test(msg) || (errText && AUTH_FAIL_RE.test(errText))) ctx.onAuthError?.();\n }\n\n switch (level) {\n case \"DEBUG\":\n log.debug(msg, data);\n break;\n case \"INFO\":\n case \"NOTICE\":\n log.info(msg, data);\n break;\n case \"WARNING\":\n log.warn(msg, data);\n break;\n case \"ERROR\":\n case \"CRITICAL\":\n case \"EMERGENCY\":\n case \"ALERT\":\n log.error(msg, parsed.error, data);\n break;\n default:\n log.info(msg, data);\n break;\n }\n}\n\n/**\n * @internal\n * Inspect one rclone message for an upload retry / success and update the\n * per-object alert state in `ctx`. Fires `onUploadStuck` once when an object's\n * retry count first reaches the threshold; a later success clears the alert so\n * a fresh failure run can re-trigger.\n */\nfunction _trackUploadFailure(\n msg: string,\n object: string | undefined,\n ctx: RcloneLogRouteContext,\n): void {\n const failMatch = UPLOAD_FAIL_RE.exec(msg);\n if (failMatch) {\n const tries = Number(failMatch[1]);\n const key = object ?? extractObjectFromMsg(msg) ?? \"(unknown)\";\n const threshold = ctx.stuckThreshold ?? DEFAULT_UPLOAD_STUCK_THRESHOLD;\n if (!ctx.alertedObjects) ctx.alertedObjects = new Set<string>();\n const alerted = ctx.alertedObjects;\n if (tries >= threshold && !alerted.has(key)) {\n alerted.add(key);\n ctx.onUploadStuck?.(key, tries);\n }\n return;\n }\n if (UPLOAD_OK_RE.test(msg)) {\n const key = object ?? extractObjectFromMsg(msg);\n if (key) ctx.alertedObjects?.delete(key);\n }\n}\n\n/** Best-effort path extraction from a free-text rclone message. */\nfunction extractObjectFromMsg(msg: string): string | undefined {\n const m = /(?:^|\\s)([^\\s:]+\\/[^\\s:]+):/.exec(msg);\n return m?.[1];\n}\n\n/**\n * @internal\n * Build the `rclone mount` argv from a spawn config. Extracted from spawn() so\n * the flag wiring (notably `--vfs-write-back` and the conditional\n * `--ignore-size --ignore-checksum`) is unit-testable without actually\n * launching rclone. Exported for tests; not part of the public API.\n */\nexport function _buildRcloneArgs(\n config: RcloneSpawnConfig,\n io: { configPath: string; rcAddr: string },\n): string[] {\n const args = [\n \"mount\",\n config.remote,\n config.mountPoint,\n \"--config\",\n io.configPath,\n \"--cache-dir\",\n config.cacheDir,\n \"--vfs-cache-mode\",\n config.vfsCacheMode,\n \"--vfs-cache-max-size\",\n config.cacheMaxSize ?? \"5G\",\n \"--vfs-cache-max-age\",\n config.cacheMaxAge ?? \"168h\",\n \"--vfs-write-back\",\n config.vfsWriteBack ?? DEFAULT_VFS_WRITE_BACK,\n \"--vfs-cache-poll-interval\",\n \"60s\",\n \"--rc\",\n \"--rc-addr\",\n io.rcAddr,\n \"--log-level\",\n \"INFO\",\n \"--use-json-log\",\n \"--allow-other\",\n ];\n\n // Remotes that rewrite bytes on upload (SharePoint LF→CRLF) make the\n // post-transfer size/hash check fail and rclone rolls the upload back\n // forever. Both flags are needed: a byte change shifts size AND checksum.\n if (config.ignoreSizeCheck) {\n args.push(\"--ignore-size\", \"--ignore-checksum\");\n }\n\n return args;\n}\n\n/**\n * Poll `dir` until its newest file mtime is at least `thresholdMs` in the past\n * (no write for that long), or `timeoutMs` elapses. Returns true if it went\n * quiescent, false on timeout. An empty/missing dir counts as quiescent.\n */\nexport async function awaitQuiescent(\n dir: string,\n opts: { thresholdMs: number; timeoutMs: number; pollMs: number },\n): Promise<boolean> {\n const deadline = Date.now() + opts.timeoutMs;\n for (;;) {\n const newest = await newestMtimeMs(dir);\n if (newest === null || Date.now() - newest >= opts.thresholdMs) return true;\n if (Date.now() >= deadline) return false;\n await sleep(opts.pollMs);\n }\n}\n\n/**\n * Resolve the rclone vfs content subtree (`<cacheDir>/vfs`) where cached file\n * data — and therefore agent writes — land, falling back to `cacheDir` itself\n * if that subtree doesn't exist yet. Keeps the stabilization gate off rclone's\n * `vfsMeta/` housekeeping tree.\n */\nasync function vfsContentDir(cacheDir: string): Promise<string> {\n const vfs = path.join(cacheDir, \"vfs\");\n try {\n return (await stat(vfs)).isDirectory() ? vfs : cacheDir;\n } catch {\n return cacheDir;\n }\n}\n\n/**\n * Recursively find the most recent file mtime (ms) under `dir`. Returns null if\n * the dir is missing or contains no files. Symlinks are skipped — rclone's\n * cache holds only regular files and dirs.\n */\nasync function newestMtimeMs(dir: string): Promise<number | null> {\n let newest: number | null = null;\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const e of entries) {\n const full = path.join(dir, String(e.name));\n if (e.isDirectory()) {\n const sub = await newestMtimeMs(full);\n if (sub !== null && (newest === null || sub > newest)) newest = sub;\n } else if (e.isFile()) {\n try {\n const s = await stat(full);\n if (newest === null || s.mtimeMs > newest) newest = s.mtimeMs;\n } catch {\n // ignore — file vanished between readdir and stat\n }\n }\n }\n } catch {\n return null;\n }\n return newest;\n}\n\n/** Returns true if `mountPoint` appears as a mount in /proc/self/mounts. */\nasync function isMountpoint(mountPoint: string): Promise<boolean> {\n try {\n const resolved = path.resolve(mountPoint);\n const text = await readFile(\"/proc/self/mounts\", \"utf8\");\n for (const raw of text.split(\"\\n\")) {\n if (raw.length === 0) continue;\n const fields = raw.split(/\\s+/);\n const mp = fields[1];\n if (!mp) continue;\n // /proc/self/mounts encodes spaces as \\040; cheap decode.\n const decoded = mp.replace(/\\\\040/g, \" \");\n if (decoded === resolved) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Poll `check` every `intervalMs` until it returns true or `timeoutMs`\n * elapses. Returns true on success, false on timeout.\n */\nasync function waitFor(\n check: () => Promise<boolean>,\n opts: { timeoutMs: number; intervalMs: number },\n): Promise<boolean> {\n const deadline = Date.now() + opts.timeoutMs;\n while (Date.now() < deadline) {\n if (await check()) return true;\n await sleep(opts.intervalMs);\n }\n return await check();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/** Wire a Readable to a per-line callback, buffering partial chunks. */\nfunction attachLineSplitter(stream: Readable, onLine: (line: string) => void): void {\n let buffer = \"\";\n stream.setEncoding(\"utf8\");\n stream.on(\"data\", (chunk: string) => {\n buffer += chunk;\n let idx = buffer.indexOf(\"\\n\");\n while (idx >= 0) {\n const line = buffer.slice(0, idx);\n buffer = buffer.slice(idx + 1);\n if (line.length > 0) onLine(line);\n idx = buffer.indexOf(\"\\n\");\n }\n });\n stream.on(\"end\", () => {\n if (buffer.length > 0) {\n onLine(buffer);\n buffer = \"\";\n }\n });\n}\n\n/** Recursively sum file sizes under `dir`. Returns 0 if dir does not exist. */\nasync function dirSize(dir: string): Promise<number> {\n let total = 0;\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const e of entries) {\n const full = path.join(dir, String(e.name));\n if (e.isDirectory()) {\n total += await dirSize(full);\n } else if (e.isFile()) {\n try {\n const s = await stat(full);\n total += s.size;\n } catch {\n // ignore\n }\n }\n }\n } catch {\n return 0;\n }\n return total;\n}\n"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-
|
|
2
|
+
import { openCatalogSource, openLibraryManager, createFullRegistry, openLibrary } from '../chunk-5JAQVXPV.js';
|
|
3
3
|
import { logErr, S, logOk, logInfo, colorRef, logWarn, kindColorPad, kindColor, formatRelativeTime, fitWidth } from '../chunk-GYPA2Q7F.js';
|
|
4
|
-
import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-
|
|
5
|
-
import { AI_RESOURCES, aiResourceRoots } from '../chunk-
|
|
4
|
+
import { getStoreConfig, storeFetch, saveStoreTokens, clearStoreTokens, isStoreAuthenticated } from '../chunk-VSLSRDQZ.js';
|
|
5
|
+
import { AI_RESOURCES, aiResourceRoots } from '../chunk-W6TLIJG3.js';
|
|
6
6
|
import { LocalSecretsProvider } from '../chunk-6LW7Q53Z.js';
|
|
7
7
|
import { resolveLibraryDir, LocalCatalogSource, skaileHomeDir } from '../chunk-PWXN2KHV.js';
|
|
8
8
|
import '../chunk-7MANNJ3U.js';
|
|
9
9
|
import '../chunk-N74UQJPN.js';
|
|
10
10
|
import '../chunk-R7FOF242.js';
|
|
11
11
|
import '../chunk-ZDKJHQY2.js';
|
|
12
|
-
import { runFlow, resumeFlow } from '../chunk-
|
|
12
|
+
import { runFlow, resumeFlow } from '../chunk-JLSK6HR4.js';
|
|
13
13
|
import '../chunk-4R6DROGN.js';
|
|
14
14
|
import { validateFlowVersions, parseSkillFrontmatter } from '../chunk-GXC3TYMQ.js';
|
|
15
|
-
import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-
|
|
16
|
-
import { buildClaudePluginFiles } from '../chunk-
|
|
15
|
+
import { runAgentChat, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, compileComposition, MarkdownStreamer, resolveMixin } from '../chunk-4RSCLQYX.js';
|
|
16
|
+
import { buildClaudePluginFiles } from '../chunk-QLHOORR7.js';
|
|
17
17
|
import '../chunk-X5YPJV4N.js';
|
|
18
18
|
import '../chunk-O7SG5PC2.js';
|
|
19
19
|
import '../chunk-7QBNJTTQ.js';
|
|
@@ -22,25 +22,25 @@ import '../chunk-WQ7DE5UC.js';
|
|
|
22
22
|
import '../chunk-32NA4TVC.js';
|
|
23
23
|
import '../chunk-W3UDISS2.js';
|
|
24
24
|
import '../chunk-TDSRLMDB.js';
|
|
25
|
-
import '../chunk-
|
|
25
|
+
import '../chunk-NSVAJWWQ.js';
|
|
26
26
|
import '../chunk-RRVQAE5D.js';
|
|
27
27
|
import '../chunk-BMQKMOQY.js';
|
|
28
28
|
import '../chunk-NGJ6E344.js';
|
|
29
|
-
import '../chunk-
|
|
29
|
+
import '../chunk-CIFTUSBV.js';
|
|
30
30
|
import '../chunk-LV2HPH3C.js';
|
|
31
|
-
import '../chunk-
|
|
31
|
+
import '../chunk-WQRDLR3K.js';
|
|
32
32
|
import '../chunk-OVRSNIKJ.js';
|
|
33
|
-
import '../chunk-
|
|
34
|
-
import '../chunk-
|
|
33
|
+
import '../chunk-UQ5JY2GQ.js';
|
|
34
|
+
import '../chunk-XT6AZWK3.js';
|
|
35
35
|
import '../chunk-6E6PKKAD.js';
|
|
36
36
|
import { loadFlow, loadAllFlows } from '../chunk-X46FY45B.js';
|
|
37
37
|
import '../chunk-DEYYRFQU.js';
|
|
38
38
|
import '../chunk-IFGTRL2I.js';
|
|
39
|
-
import { AssetManager } from '../chunk-
|
|
40
|
-
import '../chunk-
|
|
41
|
-
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-
|
|
42
|
-
import '../chunk-
|
|
43
|
-
import { resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-
|
|
39
|
+
import { AssetManager } from '../chunk-BKE2E5AC.js';
|
|
40
|
+
import '../chunk-DHN6VW4B.js';
|
|
41
|
+
import { readLock, resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, portableSpawn, portableSpawnSync, WorkspaceYamlEditor } from '../chunk-DVIIYYD5.js';
|
|
42
|
+
import '../chunk-2VM62DX7.js';
|
|
43
|
+
import { resolveAgentDir, findWorkspaceRoot, workspaceConfigFilename, resolveSkWorkspaceConfig } from '../chunk-E5VRPYUX.js';
|
|
44
44
|
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest } from '../chunk-H5YXL4KI.js';
|
|
45
45
|
import { parseFrontmatter } from '../chunk-4AGIEU7V.js';
|
|
46
46
|
import { ASSET_KINDS, parseAssetRef, isValidAssetName, ASSET_NAME_HINT, assetRefToStr } from '../chunk-LFDZYCEO.js';
|
|
@@ -321,7 +321,7 @@ function printLocalEntries(entries) {
|
|
|
321
321
|
}
|
|
322
322
|
async function searchStore(query, kind, opts) {
|
|
323
323
|
try {
|
|
324
|
-
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-
|
|
324
|
+
const { getStoreConfig: getStoreConfig2, storeFetch: storeFetch2 } = await import('../store-client-H7MHTZVU.js');
|
|
325
325
|
const config = getStoreConfig2();
|
|
326
326
|
const params = {};
|
|
327
327
|
if (query) params.q = query;
|
|
@@ -509,7 +509,7 @@ function makeCatalogCommand() {
|
|
|
509
509
|
return catalog;
|
|
510
510
|
}
|
|
511
511
|
async function runLocalCatalogTest(projectDir) {
|
|
512
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
512
|
+
const { resolveCatalogSource } = await import('../open-library-GPZUB7N3.js');
|
|
513
513
|
let resolved;
|
|
514
514
|
try {
|
|
515
515
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -1499,7 +1499,7 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
1499
1499
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
1500
1500
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
1501
1501
|
if (config.plugins && config.plugins.length > 0) {
|
|
1502
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
1502
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-TF7GECYJ.js');
|
|
1503
1503
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
1504
1504
|
for (const f of result.failed) logWarn(f.error);
|
|
1505
1505
|
}
|
|
@@ -2991,7 +2991,7 @@ function actOnHeader(row, action3) {
|
|
|
2991
2991
|
return false;
|
|
2992
2992
|
}
|
|
2993
2993
|
async function loadAssets() {
|
|
2994
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
2994
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-6R2C2NHB.js');
|
|
2995
2995
|
const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
2996
2996
|
if (notes.length > 0) {
|
|
2997
2997
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -3075,7 +3075,7 @@ function reconcileCollapsedSets(rows) {
|
|
|
3075
3075
|
async function loadSourcesAndLibraries() {
|
|
3076
3076
|
try {
|
|
3077
3077
|
const [{ openLibraryManager: openLibraryManager2 }, { skaileHomeDir: skaileHomeDir2 }] = await Promise.all([
|
|
3078
|
-
import('../open-library-
|
|
3078
|
+
import('../open-library-GPZUB7N3.js'),
|
|
3079
3079
|
import('../library/index.js')
|
|
3080
3080
|
]);
|
|
3081
3081
|
const { manager, library, close } = await openLibraryManager2();
|
|
@@ -3877,7 +3877,7 @@ function action2(fn) {
|
|
|
3877
3877
|
};
|
|
3878
3878
|
}
|
|
3879
3879
|
async function reconcileAndReport(projectDir, plugins) {
|
|
3880
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
3880
|
+
const { reconcilePlugins } = await import('../plugin-store-TF7GECYJ.js');
|
|
3881
3881
|
if (plugins.length === 0) {
|
|
3882
3882
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
3883
3883
|
return;
|
|
@@ -3893,7 +3893,7 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
3893
3893
|
async function runInstall2(spec, opts) {
|
|
3894
3894
|
const projectDir = path12__default.resolve(opts.projectDir);
|
|
3895
3895
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
3896
|
-
const { specName } = await import('../plugin-store-
|
|
3896
|
+
const { specName } = await import('../plugin-store-TF7GECYJ.js');
|
|
3897
3897
|
const yamlPath = path12__default.join(projectDir, "skaile.yaml");
|
|
3898
3898
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
3899
3899
|
const replaced = editor.addPlugin(spec, specName);
|
|
@@ -3905,7 +3905,7 @@ async function runInstall2(spec, opts) {
|
|
|
3905
3905
|
async function runRemove(name, opts) {
|
|
3906
3906
|
const projectDir = path12__default.resolve(opts.projectDir);
|
|
3907
3907
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
3908
|
-
const { specName } = await import('../plugin-store-
|
|
3908
|
+
const { specName } = await import('../plugin-store-TF7GECYJ.js');
|
|
3909
3909
|
const yamlPath = path12__default.join(projectDir, "skaile.yaml");
|
|
3910
3910
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
3911
3911
|
const removed = editor.removePlugin(name, specName);
|
|
@@ -3933,7 +3933,7 @@ async function runList(opts) {
|
|
|
3933
3933
|
const registry = createPluginRegistry();
|
|
3934
3934
|
if (declared.length > 0) {
|
|
3935
3935
|
try {
|
|
3936
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
3936
|
+
const { loadPlugins } = await import('../plugin-store-TF7GECYJ.js');
|
|
3937
3937
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
3938
3938
|
for (const f of result.failed) logWarn(f.error);
|
|
3939
3939
|
} catch (err) {
|
|
@@ -4165,7 +4165,7 @@ async function runRefInstall(ref, opts) {
|
|
|
4165
4165
|
const spinner5 = p5.spinner();
|
|
4166
4166
|
spinner5.start(`Installing ${ref}`);
|
|
4167
4167
|
try {
|
|
4168
|
-
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-
|
|
4168
|
+
const { openCatalogSource: openCatalogSource2, openLibrary: openLibrary2 } = await import('../open-library-GPZUB7N3.js');
|
|
4169
4169
|
const catalog = await openCatalogSource2({ projectDir: path12__default.resolve(opts.projectDir) });
|
|
4170
4170
|
if (!supportsInstallManifest(catalog)) {
|
|
4171
4171
|
throw new Error(
|
|
@@ -4197,7 +4197,7 @@ async function runRefInstall(ref, opts) {
|
|
|
4197
4197
|
async function runYamlInstall(opts) {
|
|
4198
4198
|
const projectDir = path12__default.resolve(opts.projectDir);
|
|
4199
4199
|
try {
|
|
4200
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
4200
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GYEQ65ET.js');
|
|
4201
4201
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
4202
4202
|
if (hydrate.cloned.length > 0) {
|
|
4203
4203
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -4634,7 +4634,7 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
4634
4634
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
4635
4635
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
4636
4636
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
4637
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
4637
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-TF7GECYJ.js');
|
|
4638
4638
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
4639
4639
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
4640
4640
|
if (result.loaded.length > 0) {
|
|
@@ -4655,7 +4655,7 @@ async function runCompileTest(opts) {
|
|
|
4655
4655
|
const { unlinkSync, existsSync: existsSync12 } = await import('fs');
|
|
4656
4656
|
const { spawn } = await import('child_process');
|
|
4657
4657
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
4658
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
4658
|
+
const { MONOREPO_ROOT } = await import('../paths-R6WA7PKV.js');
|
|
4659
4659
|
if (MONOREPO_ROOT === null) {
|
|
4660
4660
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
4661
4661
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
@@ -6728,7 +6728,7 @@ async function bootstrapUserConfig() {
|
|
|
6728
6728
|
}
|
|
6729
6729
|
async function hydrateInitSources(resolved, created) {
|
|
6730
6730
|
try {
|
|
6731
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
6731
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-GYEQ65ET.js');
|
|
6732
6732
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
6733
6733
|
for (const n of hydrate.cloned) created.push(`~/.skaile/sources/${n}/`);
|
|
6734
6734
|
if (hydrate.failed.length > 0) {
|
|
@@ -6756,7 +6756,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
6756
6756
|
console.log();
|
|
6757
6757
|
}
|
|
6758
6758
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
6759
|
-
const { cmdSetup } = await import('../setup-
|
|
6759
|
+
const { cmdSetup } = await import('../setup-YKL43RQJ.js');
|
|
6760
6760
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
6761
6761
|
});
|
|
6762
6762
|
program.addCommand(makeInstallCommand());
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { LegacyAuthGrammarError, MountTokenMediatorError, createCliSecretProviderChain, createForgeSecretProviderChain, loadConnectorDeclarations, resolveAuth, resolveAuthRef, resolveBackendAuthFor, resolveMountCredentialString } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
1
|
+
export { LegacyAuthGrammarError, MountTokenMediatorError, createCliSecretProviderChain, createForgeSecretProviderChain, loadConnectorDeclarations, resolveAuth, resolveAuthRef, resolveBackendAuthFor, resolveMountCredential, resolveMountCredentialString } from '../chunk-UQ5JY2GQ.js';
|
|
2
|
+
import '../chunk-DVIIYYD5.js';
|
|
3
|
+
import '../chunk-2VM62DX7.js';
|
|
4
|
+
import '../chunk-E5VRPYUX.js';
|
|
5
5
|
import '../chunk-H5YXL4KI.js';
|
|
6
6
|
import '../chunk-4AGIEU7V.js';
|
|
7
7
|
import '../chunk-LFDZYCEO.js';
|
package/dist/connectors/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { AbstractConnector, BUILTIN_CONNECTOR_CATALOG, ConnectorFieldMissingError, ConnectorManager, ConnectorStartupError, FlowAdapter, LogBuffer, ManagedGitconfigCollisionError, NOT_READY_SENTINEL, RoMountPlaceholderBarrier, atomicReplaceCredential, buildConnectorPromptSection, buildSdkConnectorTools, createWorktree, defaultMountPlaceholderBarrier, defaultSpawn, ensureFleetMounted, findGitRoot, findMissingPackages, getConnector, installNpmPackages, isFleetManaged, isPackageResolvable, listConnectors, listWorktrees, registerBuiltinConnectors, removeMountBlock, renderCredentialHelperScript, tryGetConnector, worktreeRegistry, writeHelperScript, writeMountBlock } from '../chunk-
|
|
1
|
+
export { AbstractConnector, BUILTIN_CONNECTOR_CATALOG, ConnectorFieldMissingError, ConnectorManager, ConnectorStartupError, DEFAULT_REACTIVE_COOLDOWN_MS, FleetHealthGate, FlowAdapter, LogBuffer, ManagedGitconfigCollisionError, NOT_READY_SENTINEL, PROACTIVE_RCLONE_REFRESH_MARGIN_MS, RoMountPlaceholderBarrier, atomicReplaceCredential, buildConnectorPromptSection, buildSdkConnectorTools, createRcloneTokenRefresh, createWorktree, defaultMountPlaceholderBarrier, defaultSpawn, ensureFleetMounted, findGitRoot, findMissingPackages, getConnector, installNpmPackages, isFleetManaged, isPackageResolvable, listConnectors, listWorktrees, probeFleetHealth, registerBuiltinConnectors, removeMountBlock, renderCredentialHelperScript, tryGetConnector, worktreeRegistry, writeHelperScript, writeMountBlock } from '../chunk-WQRDLR3K.js';
|
|
2
2
|
export { renderGoogleDriveConfig, renderOneDriveConfig, renderWebDAVConfig } from '../chunk-OVRSNIKJ.js';
|
|
3
|
-
export { EnvSecretProvider, ForgeSecretProvider, InMemorySecretProvider, LegacyAuthGrammarError, LockedSecretProvider, MountTokenMediatorError, OAuthRequiredError, PreMintedSecretProvider, SecretProviderChain, createCliSecretProviderChain, createForgeSecretProviderChain, loadConnectorDeclarations, resolveAuth, resolveAuthRef, resolveBackendAuthFor, resolveMountCredentialString } from '../chunk-
|
|
4
|
-
export { PortPool, RcloneProcessManager, createFsWatcher, ensureDirMode } from '../chunk-
|
|
3
|
+
export { EnvSecretProvider, ForgeSecretProvider, InMemorySecretProvider, LegacyAuthGrammarError, LockedSecretProvider, MountTokenMediatorError, OAuthRequiredError, PreMintedSecretProvider, SecretProviderChain, createCliSecretProviderChain, createForgeSecretProviderChain, loadConnectorDeclarations, resolveAuth, resolveAuthRef, resolveBackendAuthFor, resolveMountCredential, resolveMountCredentialString } from '../chunk-UQ5JY2GQ.js';
|
|
4
|
+
export { PortPool, RcloneProcessManager, createFsWatcher, ensureDirMode } from '../chunk-XT6AZWK3.js';
|
|
5
5
|
import '../chunk-6E6PKKAD.js';
|
|
6
6
|
import '../chunk-X46FY45B.js';
|
|
7
7
|
import '../chunk-DEYYRFQU.js';
|
|
8
8
|
import '../chunk-IFGTRL2I.js';
|
|
9
|
-
import '../chunk-
|
|
10
|
-
import '../chunk-
|
|
11
|
-
import '../chunk-
|
|
9
|
+
import '../chunk-DVIIYYD5.js';
|
|
10
|
+
import '../chunk-2VM62DX7.js';
|
|
11
|
+
import '../chunk-E5VRPYUX.js';
|
|
12
12
|
import '../chunk-H5YXL4KI.js';
|
|
13
13
|
import '../chunk-4AGIEU7V.js';
|
|
14
14
|
import '../chunk-LFDZYCEO.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_UPLOAD_STUCK_THRESHOLD, DEFAULT_VFS_WRITE_BACK, RcloneProcessManager, _buildRcloneArgs, _routeRcloneLogLine, awaitQuiescent } from '../chunk-
|
|
1
|
+
export { DEFAULT_UPLOAD_STUCK_THRESHOLD, DEFAULT_VFS_WRITE_BACK, RcloneProcessManager, _buildRcloneArgs, _routeRcloneLogLine, awaitQuiescent } from '../chunk-XT6AZWK3.js';
|
|
2
2
|
import '../chunk-JB35MVBN.js';
|
|
3
3
|
import '../chunk-NSBPE2FW.js';
|
|
4
4
|
//# sourceMappingURL=rclone.js.map
|
|
@@ -154,9 +154,10 @@ export declare class MountTokenMediatorError extends Error {
|
|
|
154
154
|
* legacy `resolveAuth` secrets/env path and NEVER touches the
|
|
155
155
|
* mediator.
|
|
156
156
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
157
|
+
* For `auth: backend` the mediator also surfaces the access token's expiry,
|
|
158
|
+
* which the rclone drivers use to arm a proactive refresh tick (the
|
|
159
|
+
* client_secret is stripped from Skaile-managed Entra blobs, so rclone cannot
|
|
160
|
+
* self-refresh) — see {@link resolveMountCredential}.
|
|
160
161
|
*
|
|
161
162
|
* @param declaration - The connector declaration (supplies `auth` + `id`).
|
|
162
163
|
* @param secrets - Secrets chain for the legacy `env:`/inline path.
|
|
@@ -166,4 +167,30 @@ export declare class MountTokenMediatorError extends Error {
|
|
|
166
167
|
* @docLink packages/connectors/api-reference#resolve-mount-credential-string
|
|
167
168
|
*/
|
|
168
169
|
export declare function resolveMountCredentialString(declaration: ConnectorDeclaration, secrets: import("./secrets.js").SecretProvider | undefined, tokenMediator: TokenMediator | undefined): Promise<string | undefined>;
|
|
170
|
+
/**
|
|
171
|
+
* The credential string an rclone mount driver feeds into `parseAuthBlob` /
|
|
172
|
+
* `parseAuth`, paired with the access token's ISO expiry (`null` for static
|
|
173
|
+
* credentials / the legacy env path).
|
|
174
|
+
*/
|
|
175
|
+
export interface ResolvedMountCredential {
|
|
176
|
+
/** The credential string, or `undefined` when no auth is declared. */
|
|
177
|
+
token: string | undefined;
|
|
178
|
+
/** ISO-8601 expiry of the access token, or `null` if unknown / static. */
|
|
179
|
+
expiresAt: string | null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Resolve a mount credential together with its expiry. The richer companion of
|
|
183
|
+
* {@link resolveMountCredentialString}: rclone drivers use the returned
|
|
184
|
+
* `expiresAt` to arm a proactive token-refresh tick, and re-call this with
|
|
185
|
+
* `reason: 'refresh'` (or `'retry-401'` on the reactive path) to re-mint.
|
|
186
|
+
*
|
|
187
|
+
* Branches on `declaration.auth` exactly like `resolveMountCredentialString`:
|
|
188
|
+
* `backend` mints through the mediator (and fails closed on refusal / empty
|
|
189
|
+
* token); everything else resolves through the legacy `resolveAuth` secrets
|
|
190
|
+
* path with a `null` expiry and never touches the mediator.
|
|
191
|
+
*
|
|
192
|
+
* @throws {MountTokenMediatorError} when the mediator refuses an `auth: backend` mint.
|
|
193
|
+
* @docLink packages/connectors/api-reference#resolve-mount-credential
|
|
194
|
+
*/
|
|
195
|
+
export declare function resolveMountCredential(declaration: ConnectorDeclaration, secrets: import("./secrets.js").SecretProvider | undefined, tokenMediator: TokenMediator | undefined, reason?: "initial" | "refresh" | "retry-401"): Promise<ResolvedMountCredential>;
|
|
169
196
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../connectors/src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAYpF;AAyBD,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAA6C,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9F;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,mBAAmB,EAClC,cAAc,GAAE,cAAc,EAAO,GACpC,mBAAmB,CAErB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,mBAAmB,CAMrB;AAED;;;;;;;GAOG;AAEH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE,OAAO,cAAc,EAAE,cAAc,GAC9C,MAAM,GAAG,SAAS,CAQpB;AAID;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,aAAa,CAAC;IACpB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAY3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,GAAG,WAAW,EAC3B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,cAAc,EAAE,cAAc,GAAG,SAAS,GACvD,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,YAAY,GAAG,SAAS,CAa1B;AAID;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,EAAE,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACnE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAE3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,EAAE,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,EACzD,WAAW,EAAE,MAAM;CAOtB;AAED
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../connectors/src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAYpF;AAyBD,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAA6C,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9F;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,mBAAmB,EAClC,cAAc,GAAE,cAAc,EAAO,GACpC,mBAAmB,CAErB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,mBAAmB,CAMrB;AAED;;;;;;;GAOG;AAEH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE,OAAO,cAAc,EAAE,cAAc,GAC9C,MAAM,GAAG,SAAS,CAQpB;AAID;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,aAAa,CAAC;IACpB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAY3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,GAAG,WAAW,EAC3B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,cAAc,EAAE,cAAc,GAAG,SAAS,GACvD,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,YAAY,GAAG,SAAS,CAa1B;AAID;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,EAAE,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACnE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAE3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,EAAE,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,EACzD,WAAW,EAAE,MAAM;CAOtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,oBAAoB,EACjC,OAAO,EAAE,OAAO,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1D,aAAa,EAAE,aAAa,GAAG,SAAS,GACvC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7B;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,oBAAoB,EACjC,OAAO,EAAE,OAAO,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1D,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,MAAM,GAAE,SAAS,GAAG,SAAS,GAAG,WAAuB,GACtD,OAAO,CAAC,uBAAuB,CAAC,CAyBlC"}
|