@skaile/workspaces 0.38.0 → 0.40.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 +125 -0
- package/dist/{asset-feeds-W6JNAGNQ.js → asset-feeds-NOHUJ4XZ.js} +24 -6
- package/dist/asset-feeds-NOHUJ4XZ.js.map +1 -0
- package/dist/asset-manager/index.js +1 -1
- package/dist/{chunk-GL3MUJ5L.js → chunk-22Q5R7SM.js} +2 -2
- package/dist/{chunk-GL3MUJ5L.js.map → chunk-22Q5R7SM.js.map} +1 -1
- package/dist/{chunk-DQLRTCA2.js → chunk-3P7HBSSD.js} +43 -14
- package/dist/chunk-3P7HBSSD.js.map +1 -0
- package/dist/{chunk-6LW7Q53Z.js → chunk-6BEGKO2Q.js} +3 -3
- package/dist/{chunk-6LW7Q53Z.js.map → chunk-6BEGKO2Q.js.map} +1 -1
- package/dist/{chunk-KM6IWBDN.js → chunk-B5LHVPE2.js} +2 -2
- package/dist/{chunk-KM6IWBDN.js.map → chunk-B5LHVPE2.js.map} +1 -1
- package/dist/{chunk-A26MZ2GW.js → chunk-BGVQKQCP.js} +3 -3
- package/dist/{chunk-A26MZ2GW.js.map → chunk-BGVQKQCP.js.map} +1 -1
- package/dist/{chunk-P7CIT445.js → chunk-C5UK3JK7.js} +21 -14
- package/dist/chunk-C5UK3JK7.js.map +1 -0
- package/dist/{chunk-ZDKJHQY2.js → chunk-JXT46QFC.js} +2 -2
- package/dist/{chunk-ZDKJHQY2.js.map → chunk-JXT46QFC.js.map} +1 -1
- package/dist/{chunk-UAYAK7N4.js → chunk-O66LT7UI.js} +49 -3
- package/dist/chunk-O66LT7UI.js.map +1 -0
- package/dist/{chunk-OW32SQU3.js → chunk-RM2KAMGD.js} +243 -80
- package/dist/chunk-RM2KAMGD.js.map +1 -0
- package/dist/{chunk-O4PANZI2.js → chunk-XNMABEHH.js} +3 -3
- package/dist/{chunk-O4PANZI2.js.map → chunk-XNMABEHH.js.map} +1 -1
- package/dist/{chunk-6KKNROBU.js → chunk-XZNPKJXU.js} +4 -4
- package/dist/{chunk-6KKNROBU.js.map → chunk-XZNPKJXU.js.map} +1 -1
- package/dist/cli/index.js +30 -26
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/asset-feeds.d.ts +8 -5
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/manage.d.ts +6 -5
- package/dist/cli/src/commands/manage.d.ts.map +1 -1
- package/dist/cli/src/commands/source.d.ts +8 -0
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/connectors/index.js +2 -2
- package/dist/connectors/rclone.js +1 -1
- package/dist/connectors/src/connector-manager.d.ts +1 -1
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/connector-types.d.ts +5 -1
- package/dist/connectors/src/connector-types.d.ts.map +1 -1
- package/dist/connectors/src/rclone-process-manager.d.ts +9 -0
- package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
- package/dist/discovery/index.js +2 -2
- package/dist/{ensure-sources-AGORTKJC.js → ensure-sources-XITKRBLU.js} +5 -5
- package/dist/{ensure-sources-AGORTKJC.js.map → ensure-sources-XITKRBLU.js.map} +1 -1
- package/dist/factory-assets/connectors/deploy.js +2 -2
- package/dist/factory-assets/connectors/devserver.js +2 -2
- package/dist/factory-assets/connectors/flow/adapter.js +2 -2
- package/dist/factory-assets/connectors/flow/run-flow.js +3 -3
- package/dist/factory-assets/connectors/flow.js +2 -2
- package/dist/factory-assets/connectors/git/driver.d.ts +3 -0
- package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +2 -2
- package/dist/factory-assets/connectors/gmail.js +2 -2
- package/dist/factory-assets/connectors/googledrive.js +2 -2
- package/dist/factory-assets/connectors/local.js +2 -2
- package/dist/factory-assets/connectors/mattermost.js +2 -2
- package/dist/factory-assets/connectors/memory.js +2 -2
- package/dist/factory-assets/connectors/minio.js +2 -2
- package/dist/factory-assets/connectors/postgres/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/postgres.js +2 -2
- package/dist/factory-assets/connectors/s3.js +2 -2
- package/dist/factory-assets/connectors/sharepoint.js +2 -2
- package/dist/factory-assets/connectors/sqlite.js +2 -2
- package/dist/factory-assets/connectors/static-server.js +2 -2
- package/dist/factory-assets/connectors/tunnel.js +2 -2
- package/dist/factory-assets/connectors/webdav.js +2 -2
- package/dist/factory-assets/connectors/xstate-store.js +2 -2
- package/dist/factory-assets/connectors/xstate.js +2 -2
- package/dist/library/index.js +3 -3
- package/dist/library/src/remote/remote-catalog-source.d.ts +11 -1
- package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
- package/dist/{open-library-WTN7QLN7.js → open-library-5KJOZHG7.js} +6 -6
- package/dist/{open-library-WTN7QLN7.js.map → open-library-5KJOZHG7.js.map} +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/src/catalog-source.d.ts +52 -0
- package/dist/plugins/src/catalog-source.d.ts.map +1 -1
- package/dist/plugins/src/index.d.ts +1 -1
- package/dist/plugins/src/index.d.ts.map +1 -1
- package/dist/runner/index.js +4 -4
- package/dist/runner/src/ai-credential-refresh.d.ts +55 -23
- package/dist/runner/src/ai-credential-refresh.d.ts.map +1 -1
- package/dist/runner/src/ai-credential-retry.d.ts +79 -0
- package/dist/runner/src/ai-credential-retry.d.ts.map +1 -0
- package/dist/runner/src/credential-rotated.d.ts +33 -0
- package/dist/runner/src/credential-rotated.d.ts.map +1 -0
- package/dist/runner/src/resource-handler.d.ts +6 -0
- package/dist/runner/src/resource-handler.d.ts.map +1 -1
- package/dist/runner/src/runner-capabilities.d.ts +8 -0
- package/dist/runner/src/runner-capabilities.d.ts.map +1 -1
- package/dist/runner/src/serve-credentials.d.ts +14 -0
- package/dist/runner/src/serve-credentials.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-resource-handlers.d.ts +4 -1
- package/dist/runner/src/session-resource-handlers.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/index.js +4 -4
- package/dist/sdk/runner.js +4 -4
- package/dist/secrets/index.js +2 -2
- package/dist/tui/index.js +4 -4
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/asset-feeds-W6JNAGNQ.js.map +0 -1
- package/dist/chunk-DQLRTCA2.js.map +0 -1
- package/dist/chunk-OW32SQU3.js.map +0 -1
- package/dist/chunk-P7CIT445.js.map +0 -1
- package/dist/chunk-UAYAK7N4.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WorkspacePlugin } from './chunk-
|
|
1
|
+
import { WorkspacePlugin } from './chunk-22Q5R7SM.js';
|
|
2
2
|
import { WebSocketServerTransport } from './chunk-WQ7DE5UC.js';
|
|
3
3
|
import { assembleSystemPrompt, buildCapabilitiesPromptSection } from './chunk-W3UDISS2.js';
|
|
4
4
|
import { PROTOCOL_VERSION } from './chunk-TDSRLMDB.js';
|
|
@@ -6,7 +6,7 @@ import { EventNormalizer } from './chunk-5IXCNMMU.js';
|
|
|
6
6
|
import { classifyClaudeSdkError } from './chunk-GAH4YRCI.js';
|
|
7
7
|
import { createDriver } from './chunk-KM6DCR7A.js';
|
|
8
8
|
import { deployCatalogEntry, undeployCatalogEntry } from './chunk-LV2HPH3C.js';
|
|
9
|
-
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-
|
|
9
|
+
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-3P7HBSSD.js';
|
|
10
10
|
import { loadConnectorDeclarations, SecretProviderChain, PreMintedSecretProvider, InMemorySecretProvider, deriveSingleMaterializedConnectorDeclaration } from './chunk-WLWHOA3S.js';
|
|
11
11
|
import { renderStimulusPrompt, buildOrchestratorPrompt } from './chunk-DEYYRFQU.js';
|
|
12
12
|
import { resolveSettings, resolveApiKey, providerEnvKey } from './chunk-FBIQ4QPF.js';
|
|
@@ -19,7 +19,7 @@ import { __require } from './chunk-NSBPE2FW.js';
|
|
|
19
19
|
import pc from 'picocolors';
|
|
20
20
|
import { Marked } from 'marked';
|
|
21
21
|
import { markedTerminal } from 'marked-terminal';
|
|
22
|
-
import { readdirSync, existsSync, readFileSync, unlinkSync, mkdirSync, writeFileSync,
|
|
22
|
+
import { readdirSync, existsSync, readFileSync, statSync, rmSync, unlinkSync, mkdirSync, writeFileSync, watch, chmodSync, openSync, readSync, closeSync } from 'fs';
|
|
23
23
|
import path4, { join, resolve, relative, sep, isAbsolute, dirname, basename } from 'path';
|
|
24
24
|
import { homedir } from 'os';
|
|
25
25
|
import * as z5 from 'zod';
|
|
@@ -2400,6 +2400,12 @@ async function handleResourceRequest(command, manager, emit) {
|
|
|
2400
2400
|
function getMimeType(filename) {
|
|
2401
2401
|
return mime.getType(filename) ?? "application/octet-stream";
|
|
2402
2402
|
}
|
|
2403
|
+
var HTML_CLOSE_TAG_RE = /<\/html>/i;
|
|
2404
|
+
function stripStaleHtmlTail(content, contentType) {
|
|
2405
|
+
if (!contentType.toLowerCase().startsWith("text/html")) return content;
|
|
2406
|
+
const m = HTML_CLOSE_TAG_RE.exec(content);
|
|
2407
|
+
return m ? content.slice(0, m.index + m[0].length) : content;
|
|
2408
|
+
}
|
|
2403
2409
|
function isBinaryFile(filePath) {
|
|
2404
2410
|
try {
|
|
2405
2411
|
const fd = openSync(filePath, "r");
|
|
@@ -2415,7 +2421,7 @@ function isBinaryFile(filePath) {
|
|
|
2415
2421
|
}
|
|
2416
2422
|
}
|
|
2417
2423
|
function handleMountResourceRequest(command, manager, emit) {
|
|
2418
|
-
const { requestId, connectorId: mountId, operation, path: reqPath, content } = command;
|
|
2424
|
+
const { requestId, connectorId: mountId, operation, path: reqPath, options, content } = command;
|
|
2419
2425
|
try {
|
|
2420
2426
|
const entry = manager.get(mountId);
|
|
2421
2427
|
const mountPath = entry.handle.mountPath;
|
|
@@ -2430,22 +2436,30 @@ function handleMountResourceRequest(command, manager, emit) {
|
|
|
2430
2436
|
let data;
|
|
2431
2437
|
switch (operation) {
|
|
2432
2438
|
case "list": {
|
|
2433
|
-
const
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
const
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
}
|
|
2439
|
+
const recursive = Boolean(options?.recursive);
|
|
2440
|
+
const collected = [];
|
|
2441
|
+
const walk = (absDir, relDir) => {
|
|
2442
|
+
for (const e of readdirSync(absDir, { withFileTypes: true })) {
|
|
2443
|
+
if (e.name.startsWith(".")) continue;
|
|
2444
|
+
const entryRel = relDir ? `${relDir}/${e.name}` : e.name;
|
|
2445
|
+
const isDir = e.isDirectory();
|
|
2446
|
+
const result = {
|
|
2447
|
+
name: e.name,
|
|
2448
|
+
path: entryRel,
|
|
2449
|
+
type: isDir ? "directory" : "file"
|
|
2450
|
+
};
|
|
2451
|
+
if (!isDir) {
|
|
2452
|
+
try {
|
|
2453
|
+
result.size = statSync(join(absDir, e.name)).size;
|
|
2454
|
+
} catch {
|
|
2455
|
+
}
|
|
2445
2456
|
}
|
|
2457
|
+
collected.push(result);
|
|
2458
|
+
if (isDir && recursive) walk(join(absDir, e.name), entryRel);
|
|
2446
2459
|
}
|
|
2447
|
-
|
|
2448
|
-
|
|
2460
|
+
};
|
|
2461
|
+
walk(targetPath, reqPath ?? "");
|
|
2462
|
+
data = collected;
|
|
2449
2463
|
break;
|
|
2450
2464
|
}
|
|
2451
2465
|
case "read": {
|
|
@@ -2459,7 +2473,7 @@ function handleMountResourceRequest(command, manager, emit) {
|
|
|
2459
2473
|
};
|
|
2460
2474
|
} else {
|
|
2461
2475
|
data = {
|
|
2462
|
-
data: readFileSync(targetPath, "utf-8"),
|
|
2476
|
+
data: stripStaleHtmlTail(readFileSync(targetPath, "utf-8"), contentType),
|
|
2463
2477
|
contentType,
|
|
2464
2478
|
encoding: "utf-8"
|
|
2465
2479
|
};
|
|
@@ -2479,7 +2493,11 @@ function handleMountResourceRequest(command, manager, emit) {
|
|
|
2479
2493
|
break;
|
|
2480
2494
|
}
|
|
2481
2495
|
case "delete": {
|
|
2482
|
-
|
|
2496
|
+
if (statSync(targetPath).isDirectory()) {
|
|
2497
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
2498
|
+
} else {
|
|
2499
|
+
unlinkSync(targetPath);
|
|
2500
|
+
}
|
|
2483
2501
|
data = true;
|
|
2484
2502
|
break;
|
|
2485
2503
|
}
|
|
@@ -2497,9 +2515,46 @@ function handleMountResourceRequest(command, manager, emit) {
|
|
|
2497
2515
|
});
|
|
2498
2516
|
}
|
|
2499
2517
|
}
|
|
2518
|
+
var MINT_RETRY_MAX_ATTEMPTS = 3;
|
|
2519
|
+
var MINT_RETRY_BASE_DELAY_MS = 2e3;
|
|
2520
|
+
var MINT_RETRY_MAX_DELAY_MS = 5e3;
|
|
2521
|
+
function isTransientMintFailure(code) {
|
|
2522
|
+
return code === "backend-error";
|
|
2523
|
+
}
|
|
2524
|
+
function mintRetryDelayMs(retryNumber) {
|
|
2525
|
+
const delay = MINT_RETRY_BASE_DELAY_MS * 2 ** Math.max(0, retryNumber - 1);
|
|
2526
|
+
return Math.min(delay, MINT_RETRY_MAX_DELAY_MS);
|
|
2527
|
+
}
|
|
2528
|
+
async function retryTransientMint(attempt, deps) {
|
|
2529
|
+
const maxAttempts = deps.maxAttempts ?? MINT_RETRY_MAX_ATTEMPTS;
|
|
2530
|
+
let result = await attempt();
|
|
2531
|
+
for (let n = 1; n < maxAttempts; n++) {
|
|
2532
|
+
if (result.ok || !isTransientMintFailure(result.code)) return result;
|
|
2533
|
+
const nextDelayMs = mintRetryDelayMs(n);
|
|
2534
|
+
deps.onRetry?.({ attempt: n, nextDelayMs, code: result.code });
|
|
2535
|
+
await deps.sleep(nextDelayMs);
|
|
2536
|
+
result = await attempt();
|
|
2537
|
+
}
|
|
2538
|
+
return result;
|
|
2539
|
+
}
|
|
2540
|
+
function computeRejectedFingerprint(accessToken) {
|
|
2541
|
+
if (!accessToken) return void 0;
|
|
2542
|
+
return createHash("sha256").update(accessToken).digest("hex").slice(0, 16);
|
|
2543
|
+
}
|
|
2544
|
+
function buildRefreshCredentialInput(args) {
|
|
2545
|
+
const base = {
|
|
2546
|
+
kind: "ai-credentials",
|
|
2547
|
+
id: args.configId,
|
|
2548
|
+
reason: args.reason
|
|
2549
|
+
};
|
|
2550
|
+
if (args.reason !== "retry-401") return base;
|
|
2551
|
+
const rejectedFingerprint = computeRejectedFingerprint(args.rejectedToken);
|
|
2552
|
+
return rejectedFingerprint ? { ...base, rejectedFingerprint } : base;
|
|
2553
|
+
}
|
|
2500
2554
|
|
|
2501
2555
|
// runner/src/ai-credential-refresh.ts
|
|
2502
2556
|
var PROACTIVE_AI_REFRESH_MARGIN_MS = 5 * 60 * 1e3;
|
|
2557
|
+
var STALE_REARM_MS = 9 * 60 * 60 * 1e3;
|
|
2503
2558
|
function createAiCredentialRefreshScheduler(deps) {
|
|
2504
2559
|
const now = deps.now ?? (() => Date.now());
|
|
2505
2560
|
const setTimeoutImpl = deps.setTimeoutImpl ?? ((handler, ms) => {
|
|
@@ -2510,64 +2565,135 @@ function createAiCredentialRefreshScheduler(deps) {
|
|
|
2510
2565
|
clearTimeout(handle);
|
|
2511
2566
|
});
|
|
2512
2567
|
const marginMs = deps.marginMs ?? PROACTIVE_AI_REFRESH_MARGIN_MS;
|
|
2568
|
+
const logError = deps.logError ?? deps.log;
|
|
2513
2569
|
let timer = null;
|
|
2570
|
+
let transientRetryCount = 0;
|
|
2571
|
+
let lastSuccessAt = null;
|
|
2572
|
+
let isStatic = false;
|
|
2573
|
+
let inStaleGuard = false;
|
|
2514
2574
|
function cancel() {
|
|
2515
2575
|
if (timer !== null) {
|
|
2516
2576
|
clearTimeoutImpl(timer);
|
|
2517
2577
|
timer = null;
|
|
2518
2578
|
}
|
|
2519
2579
|
}
|
|
2580
|
+
function armTimer(handler, ms) {
|
|
2581
|
+
cancel();
|
|
2582
|
+
timer = setTimeoutImpl(handler, ms);
|
|
2583
|
+
timer.unref?.();
|
|
2584
|
+
}
|
|
2585
|
+
function isStale() {
|
|
2586
|
+
return lastSuccessAt !== null && now() - lastSuccessAt > STALE_REARM_MS;
|
|
2587
|
+
}
|
|
2520
2588
|
async function fire() {
|
|
2521
2589
|
timer = null;
|
|
2522
|
-
let
|
|
2590
|
+
let outcome;
|
|
2523
2591
|
try {
|
|
2524
|
-
|
|
2592
|
+
outcome = await deps.refresh();
|
|
2525
2593
|
} catch (err) {
|
|
2526
|
-
|
|
2527
|
-
`[ai-credential-refresh] refresh threw: ${err instanceof Error ? err.message : String(err)};
|
|
2594
|
+
logError(
|
|
2595
|
+
`[ai-credential-refresh] refresh threw: ${err instanceof Error ? err.message : String(err)}; treating as transient`
|
|
2528
2596
|
);
|
|
2597
|
+
outcome = { status: "transient" };
|
|
2598
|
+
}
|
|
2599
|
+
if (outcome.status === "ok") {
|
|
2600
|
+
schedule(outcome.expiresAt);
|
|
2529
2601
|
return;
|
|
2530
2602
|
}
|
|
2531
|
-
if (
|
|
2532
|
-
|
|
2533
|
-
|
|
2603
|
+
if (outcome.status === "terminal") {
|
|
2604
|
+
transientRetryCount = 0;
|
|
2605
|
+
inStaleGuard = false;
|
|
2606
|
+
logError(
|
|
2607
|
+
"[ai-credential-refresh] proactive refresh hit a terminal failure; not re-arming (reactive 401 path remains the safety net)"
|
|
2608
|
+
);
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
if (transientRetryCount < MINT_RETRY_MAX_ATTEMPTS - 1) {
|
|
2612
|
+
transientRetryCount += 1;
|
|
2613
|
+
inStaleGuard = false;
|
|
2614
|
+
const delayMs = mintRetryDelayMs(transientRetryCount);
|
|
2615
|
+
logError(
|
|
2616
|
+
`[ai-credential-refresh] proactive refresh transient failure; bounded retry ${transientRetryCount}/${MINT_RETRY_MAX_ATTEMPTS - 1} in ${Math.round(delayMs / 1e3)}s`
|
|
2534
2617
|
);
|
|
2618
|
+
armTimer(() => void fire(), delayMs);
|
|
2535
2619
|
return;
|
|
2536
2620
|
}
|
|
2537
|
-
|
|
2621
|
+
transientRetryCount = 0;
|
|
2622
|
+
inStaleGuard = true;
|
|
2623
|
+
logError(
|
|
2624
|
+
`[ai-credential-refresh] proactive refresh failed after ${MINT_RETRY_MAX_ATTEMPTS} attempts; reactive 401 path is the fallback, re-checking in ${Math.round(STALE_REARM_MS / 36e5)}h`
|
|
2625
|
+
);
|
|
2626
|
+
armTimer(() => void fire(), STALE_REARM_MS);
|
|
2538
2627
|
}
|
|
2539
2628
|
function schedule(expiresAtIso) {
|
|
2540
2629
|
cancel();
|
|
2630
|
+
inStaleGuard = false;
|
|
2541
2631
|
if (!expiresAtIso) {
|
|
2632
|
+
isStatic = true;
|
|
2633
|
+
transientRetryCount = 0;
|
|
2634
|
+
lastSuccessAt = now();
|
|
2542
2635
|
return;
|
|
2543
2636
|
}
|
|
2544
2637
|
const expiresAtMs = Date.parse(expiresAtIso);
|
|
2545
2638
|
if (!Number.isFinite(expiresAtMs)) return;
|
|
2639
|
+
isStatic = false;
|
|
2640
|
+
transientRetryCount = 0;
|
|
2641
|
+
lastSuccessAt = now();
|
|
2546
2642
|
const delayMs = expiresAtMs - now() - marginMs;
|
|
2547
2643
|
if (delayMs <= 0) {
|
|
2548
2644
|
deps.log(
|
|
2549
2645
|
`[ai-credential-refresh] token within ${marginMs / 1e3}s of expiry; refreshing now`
|
|
2550
2646
|
);
|
|
2551
|
-
|
|
2552
|
-
void fire();
|
|
2553
|
-
}, 0);
|
|
2647
|
+
armTimer(() => void fire(), 0);
|
|
2554
2648
|
} else {
|
|
2555
2649
|
deps.log(
|
|
2556
2650
|
`[ai-credential-refresh] scheduled in ${Math.round(delayMs / 1e3)}s (expiresAt=${expiresAtIso})`
|
|
2557
2651
|
);
|
|
2558
|
-
|
|
2559
|
-
void fire();
|
|
2560
|
-
}, delayMs);
|
|
2652
|
+
armTimer(() => void fire(), delayMs);
|
|
2561
2653
|
}
|
|
2562
|
-
|
|
2654
|
+
}
|
|
2655
|
+
function ensureArmed() {
|
|
2656
|
+
if (isStatic) return;
|
|
2657
|
+
if (timer !== null && !inStaleGuard && !isStale()) return;
|
|
2658
|
+
deps.log("[ai-credential-refresh] ensureArmed: reviving idle/stale schedule");
|
|
2659
|
+
transientRetryCount = 0;
|
|
2660
|
+
inStaleGuard = false;
|
|
2661
|
+
armTimer(() => void fire(), 0);
|
|
2563
2662
|
}
|
|
2564
2663
|
return {
|
|
2565
2664
|
schedule,
|
|
2665
|
+
ensureArmed,
|
|
2566
2666
|
cancel,
|
|
2567
2667
|
isPending: () => timer !== null
|
|
2568
2668
|
};
|
|
2569
2669
|
}
|
|
2570
2670
|
|
|
2671
|
+
// runner/src/credential-rotated.ts
|
|
2672
|
+
var AI_PROVIDER_CREDENTIAL_SUBKIND = "ai-provider-credential";
|
|
2673
|
+
function isCredentialRotatedSignal(msg) {
|
|
2674
|
+
if (!msg || typeof msg !== "object") return false;
|
|
2675
|
+
const m = msg;
|
|
2676
|
+
if (m.type !== "log_entry") return false;
|
|
2677
|
+
const entry = m.entry;
|
|
2678
|
+
if (!entry || typeof entry !== "object") return false;
|
|
2679
|
+
return entry.source?.subkind === AI_PROVIDER_CREDENTIAL_SUBKIND && entry.data?.credentialRotated === true;
|
|
2680
|
+
}
|
|
2681
|
+
async function handleCredentialRotatedSignal(deps) {
|
|
2682
|
+
deps.log("[serve] credentialRotated broadcast received; re-pulling ai-credentials");
|
|
2683
|
+
try {
|
|
2684
|
+
const result = await deps.repull();
|
|
2685
|
+
if (result.ok) {
|
|
2686
|
+
deps.log("[serve] credentialRotated: re-pulled fresh token and rewrote .credentials.json");
|
|
2687
|
+
} else {
|
|
2688
|
+
deps.logError(`[serve] credentialRotated: re-pull failed (code=${result.code})`);
|
|
2689
|
+
}
|
|
2690
|
+
} catch (err) {
|
|
2691
|
+
deps.logError(
|
|
2692
|
+
`[serve] credentialRotated: re-pull threw: ${err instanceof Error ? err.message : String(err)}`
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2571
2697
|
// runner/src/compaction/prompt.ts
|
|
2572
2698
|
var DEFAULT_COMPACTION_PROMPT = `You are being asked to compact this conversation into a structured summary.
|
|
2573
2699
|
This summary will replace the full conversation history when the session
|
|
@@ -2949,16 +3075,6 @@ function buildLifecycleHandler(deps) {
|
|
|
2949
3075
|
return { ok: true };
|
|
2950
3076
|
};
|
|
2951
3077
|
}
|
|
2952
|
-
function readResolvedConnectorSecret(instancePath, id) {
|
|
2953
|
-
if (!existsSync(instancePath)) return void 0;
|
|
2954
|
-
try {
|
|
2955
|
-
const parsed = JSON.parse(readFileSync(instancePath, "utf8"));
|
|
2956
|
-
const value = parsed.resolvedSecrets?.[`connector:${id}`];
|
|
2957
|
-
return typeof value === "string" ? value : void 0;
|
|
2958
|
-
} catch {
|
|
2959
|
-
return void 0;
|
|
2960
|
-
}
|
|
2961
|
-
}
|
|
2962
3078
|
function asDeclaration(declaration) {
|
|
2963
3079
|
if (declaration !== null && typeof declaration === "object" && typeof declaration.id === "string" && typeof declaration.driver === "string") {
|
|
2964
3080
|
return declaration;
|
|
@@ -2978,7 +3094,12 @@ function buildSessionResourceHandlers(deps) {
|
|
|
2978
3094
|
return { ok: false, code: "invalid_declaration", message: "declaration missing id/driver" };
|
|
2979
3095
|
}
|
|
2980
3096
|
if (input.preMintedToken) {
|
|
2981
|
-
|
|
3097
|
+
const ps = getPreMintedSecrets();
|
|
3098
|
+
if (ps) ps.set(kind, decl.id, toPreMinted(input.preMintedToken));
|
|
3099
|
+
else
|
|
3100
|
+
log(
|
|
3101
|
+
`[session-resource] preMintedToken provided but secret store not ready \u2014 ${kind}:${decl.id}`
|
|
3102
|
+
);
|
|
2982
3103
|
}
|
|
2983
3104
|
try {
|
|
2984
3105
|
await rm.connect(decl);
|
|
@@ -2994,7 +3115,7 @@ function buildSessionResourceHandlers(deps) {
|
|
|
2994
3115
|
log(`[session-resource] runner.add_${kind} connected ${decl.id}`);
|
|
2995
3116
|
return { ok: true, id: decl.id };
|
|
2996
3117
|
}
|
|
2997
|
-
async function attachConnectorInstance(name) {
|
|
3118
|
+
async function attachConnectorInstance(name, preMintedToken) {
|
|
2998
3119
|
if (!name) {
|
|
2999
3120
|
return { ok: false, code: "invalid_input", message: "name is required" };
|
|
3000
3121
|
}
|
|
@@ -3020,14 +3141,20 @@ function buildSessionResourceHandlers(deps) {
|
|
|
3020
3141
|
}
|
|
3021
3142
|
const rm = getResourceManager();
|
|
3022
3143
|
if (!rm) return { ok: false, code: "no_session", message: "session resources not ready" };
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3144
|
+
if (preMintedToken) {
|
|
3145
|
+
const ps = getPreMintedSecrets();
|
|
3146
|
+
if (ps) ps.set("connector", decl.id, toPreMinted(preMintedToken));
|
|
3147
|
+
else
|
|
3148
|
+
log(
|
|
3149
|
+
`[session-resource] preMintedToken provided but secret store not ready \u2014 connector:${decl.id}`
|
|
3150
|
+
);
|
|
3026
3151
|
}
|
|
3027
3152
|
try {
|
|
3028
3153
|
await rm.connect(decl);
|
|
3029
3154
|
} catch (err) {
|
|
3030
|
-
|
|
3155
|
+
if (preMintedToken) {
|
|
3156
|
+
getPreMintedSecrets()?.unset("connector", decl.id);
|
|
3157
|
+
}
|
|
3031
3158
|
const message = err instanceof Error ? err.message : String(err);
|
|
3032
3159
|
log(`[session-resource] runner.attach_instance connector failed for ${decl.id}: ${message}`);
|
|
3033
3160
|
return { ok: false, code: "connector_connect_failed", message };
|
|
@@ -3255,7 +3382,8 @@ var addMcpServerInputSchema = z5.strictObject({
|
|
|
3255
3382
|
});
|
|
3256
3383
|
var attachInstanceInputSchema = z5.strictObject({
|
|
3257
3384
|
kind: z5.string(),
|
|
3258
|
-
name: z5.string()
|
|
3385
|
+
name: z5.string(),
|
|
3386
|
+
preMintedToken: preMintedTokenSchema
|
|
3259
3387
|
});
|
|
3260
3388
|
var removeResourceInput = z5.strictObject({
|
|
3261
3389
|
id: z5.string()
|
|
@@ -3346,7 +3474,11 @@ function buildRunnerCapabilities(handlers) {
|
|
|
3346
3474
|
input: attachInstanceInputSchema,
|
|
3347
3475
|
handler: async (input) => {
|
|
3348
3476
|
if (!handlers.attachInstance) return notImplemented("runner.attach_instance");
|
|
3349
|
-
return handlers.attachInstance({
|
|
3477
|
+
return handlers.attachInstance({
|
|
3478
|
+
kind: input.kind,
|
|
3479
|
+
name: input.name,
|
|
3480
|
+
preMintedToken: input.preMintedToken
|
|
3481
|
+
});
|
|
3350
3482
|
}
|
|
3351
3483
|
}),
|
|
3352
3484
|
defineCapability({
|
|
@@ -3487,6 +3619,20 @@ function extractClaudeAiOauthExpiresAt(json) {
|
|
|
3487
3619
|
}
|
|
3488
3620
|
return null;
|
|
3489
3621
|
}
|
|
3622
|
+
function readCurrentClaudeAccessToken(home) {
|
|
3623
|
+
const credPath = join(home, ".claude", ".credentials.json");
|
|
3624
|
+
if (!existsSync(credPath)) return null;
|
|
3625
|
+
let parsed;
|
|
3626
|
+
try {
|
|
3627
|
+
parsed = JSON.parse(readFileSync(credPath, "utf-8"));
|
|
3628
|
+
} catch {
|
|
3629
|
+
return null;
|
|
3630
|
+
}
|
|
3631
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
3632
|
+
const obj = parsed;
|
|
3633
|
+
const raw = obj.claudeAiOauth?.accessToken ?? obj.accessToken;
|
|
3634
|
+
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
3635
|
+
}
|
|
3490
3636
|
|
|
3491
3637
|
// runner/src/session-stimulus.ts
|
|
3492
3638
|
var DEFAULT_COALESCE_MS = 50;
|
|
@@ -3760,6 +3906,10 @@ async function startAgentServer(opts) {
|
|
|
3760
3906
|
});
|
|
3761
3907
|
};
|
|
3762
3908
|
let aiProviderConfigId;
|
|
3909
|
+
const sleep = (ms) => new Promise((resolve3) => {
|
|
3910
|
+
const t = setTimeout(resolve3, ms);
|
|
3911
|
+
t.unref?.();
|
|
3912
|
+
});
|
|
3763
3913
|
async function mintAndPersistAiCredential(args) {
|
|
3764
3914
|
if (!transport.connected || aiProviderConfigId === void 0) {
|
|
3765
3915
|
return {
|
|
@@ -3770,22 +3920,19 @@ async function startAgentServer(opts) {
|
|
|
3770
3920
|
}
|
|
3771
3921
|
const targetConfigId = args.configId || aiProviderConfigId;
|
|
3772
3922
|
try {
|
|
3773
|
-
const
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
reason: args.reason
|
|
3923
|
+
const home = process.env.HOME || homedir();
|
|
3924
|
+
const refreshInput = buildRefreshCredentialInput({
|
|
3925
|
+
configId: targetConfigId,
|
|
3926
|
+
reason: args.reason,
|
|
3927
|
+
rejectedToken: args.reason === "retry-401" ? readCurrentClaudeAccessToken(home) : null
|
|
3777
3928
|
});
|
|
3929
|
+
const result = await capabilityRegistry.invokeRemote(
|
|
3930
|
+
"host.refresh_credential",
|
|
3931
|
+
refreshInput
|
|
3932
|
+
);
|
|
3778
3933
|
if (!result?.ok) {
|
|
3779
3934
|
return result ?? { ok: false, code: "backend-error", message: "no result from host" };
|
|
3780
3935
|
}
|
|
3781
|
-
const home = process.env.HOME ?? homedir();
|
|
3782
|
-
if (!home) {
|
|
3783
|
-
return {
|
|
3784
|
-
ok: false,
|
|
3785
|
-
code: "backend-error",
|
|
3786
|
-
message: "HOME env var unset; cannot rewrite credentials file"
|
|
3787
|
-
};
|
|
3788
|
-
}
|
|
3789
3936
|
await mergeAndRewriteCredentialsFile(home, result.token, result.expiresAt ?? null);
|
|
3790
3937
|
aiCredentialRefreshScheduler.schedule(result.expiresAt ?? null);
|
|
3791
3938
|
return result;
|
|
@@ -3797,22 +3944,27 @@ async function startAgentServer(opts) {
|
|
|
3797
3944
|
const aiCredentialRefreshScheduler = createAiCredentialRefreshScheduler({
|
|
3798
3945
|
refresh: async () => {
|
|
3799
3946
|
const result = await mintAndPersistAiCredential({ reason: "refresh" });
|
|
3800
|
-
if (
|
|
3801
|
-
|
|
3802
|
-
`[serve] proactive AI refresh failed (code=${result.code}); leaving reactive path as fallback`
|
|
3803
|
-
);
|
|
3804
|
-
return void 0;
|
|
3947
|
+
if (result.ok) {
|
|
3948
|
+
return { status: "ok", expiresAt: result.expiresAt ?? null };
|
|
3805
3949
|
}
|
|
3806
|
-
return result.
|
|
3950
|
+
return isTransientMintFailure(result.code) ? { status: "transient" } : { status: "terminal" };
|
|
3807
3951
|
},
|
|
3808
|
-
log
|
|
3952
|
+
log,
|
|
3953
|
+
// Scheduler/refresh failures must be visible in `skaile session logs` and
|
|
3954
|
+
// the debug panel, so route them through the error-level structured logger.
|
|
3955
|
+
logError: (line) => serverLog.error(line)
|
|
3809
3956
|
});
|
|
3810
3957
|
const onAuthError = async (args) => {
|
|
3811
3958
|
log("[serve] auth error: invoking host.refresh_credential capability");
|
|
3812
|
-
const result = await
|
|
3813
|
-
configId: args.configId,
|
|
3814
|
-
|
|
3815
|
-
|
|
3959
|
+
const result = await retryTransientMint(
|
|
3960
|
+
() => mintAndPersistAiCredential({ configId: args.configId, reason: "retry-401" }),
|
|
3961
|
+
{
|
|
3962
|
+
sleep,
|
|
3963
|
+
onRetry: ({ attempt, nextDelayMs, code }) => serverLog.error(
|
|
3964
|
+
`[serve] auth error: transient mint failure (code=${code}); retry ${attempt} in ${Math.round(nextDelayMs / 1e3)}s`
|
|
3965
|
+
)
|
|
3966
|
+
}
|
|
3967
|
+
);
|
|
3816
3968
|
if (!result.ok) {
|
|
3817
3969
|
log(`[serve] auth error: mint failed (code=${result.code}); surfacing`);
|
|
3818
3970
|
} else {
|
|
@@ -4440,7 +4592,7 @@ async function startAgentServer(opts) {
|
|
|
4440
4592
|
// connect path; everything else stays on the MCP attach path.
|
|
4441
4593
|
attachInstance: async (input) => {
|
|
4442
4594
|
if (input.kind === "connector") {
|
|
4443
|
-
return attachConnectorInstance(input.name);
|
|
4595
|
+
return attachConnectorInstance(input.name, input.preMintedToken);
|
|
4444
4596
|
}
|
|
4445
4597
|
return mcpHandlers.attachInstance ? mcpHandlers.attachInstance(input) : {
|
|
4446
4598
|
ok: false,
|
|
@@ -4699,6 +4851,9 @@ async function startAgentServer(opts) {
|
|
|
4699
4851
|
log(
|
|
4700
4852
|
`[serve] configure cfg keys=${Object.keys(cfg).join(",")} sharedState=${cfg.sharedState ? cfg.sharedState.length : "undefined"} resourceManager=${resourceManager ? "set" : "null"}`
|
|
4701
4853
|
);
|
|
4854
|
+
if (aiProviderConfigId) {
|
|
4855
|
+
aiCredentialRefreshScheduler.ensureArmed();
|
|
4856
|
+
}
|
|
4702
4857
|
let pendingResumeSessionId;
|
|
4703
4858
|
const cfgResumeSessionId = cfg.resumeSessionId;
|
|
4704
4859
|
const cfgExpectedSig = cfg.expectedCapabilitySignature;
|
|
@@ -5060,6 +5215,14 @@ async function startAgentServer(opts) {
|
|
|
5060
5215
|
}
|
|
5061
5216
|
async function handleCommand(cmd) {
|
|
5062
5217
|
const inbound = cmd;
|
|
5218
|
+
if (isCredentialRotatedSignal(cmd)) {
|
|
5219
|
+
await handleCredentialRotatedSignal({
|
|
5220
|
+
repull: () => mintAndPersistAiCredential({ reason: "refresh" }),
|
|
5221
|
+
log,
|
|
5222
|
+
logError: (line) => serverLog.error(line)
|
|
5223
|
+
});
|
|
5224
|
+
return;
|
|
5225
|
+
}
|
|
5063
5226
|
if (inbound.type === "capability_invoked") {
|
|
5064
5227
|
await dispatchRunnerCapabilityInvocation(
|
|
5065
5228
|
{ callId: inbound.callId ?? "", name: inbound.name ?? "", input: inbound.input },
|
|
@@ -5339,6 +5502,6 @@ function touchSession(state) {
|
|
|
5339
5502
|
return { ...state, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
5340
5503
|
}
|
|
5341
5504
|
|
|
5342
|
-
export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, builtinCapabilities, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, touchSession, writeClaudeCodeCredentialsFile };
|
|
5343
|
-
//# sourceMappingURL=chunk-
|
|
5344
|
-
//# sourceMappingURL=chunk-
|
|
5505
|
+
export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, builtinCapabilities, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, stripStaleHtmlTail, touchSession, writeClaudeCodeCredentialsFile };
|
|
5506
|
+
//# sourceMappingURL=chunk-RM2KAMGD.js.map
|
|
5507
|
+
//# sourceMappingURL=chunk-RM2KAMGD.js.map
|