@skaile/workspaces 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -0
- package/dist/{asset-feeds-2LQIGNUF.js → asset-feeds-6R2C2NHB.js} +7 -7
- package/dist/{asset-feeds-2LQIGNUF.js.map → asset-feeds-6R2C2NHB.js.map} +1 -1
- package/dist/asset-manager/index.js +5 -5
- package/dist/asset-manager/installer.js +4 -4
- package/dist/bridge/drivers/claude-sdk.js +8 -1
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +1 -1
- package/dist/bridge/drivers/continue.js +2 -2
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +3 -3
- package/dist/bridge/drivers/goose.js +2 -2
- package/dist/bridge/drivers/omp.js +1 -1
- package/dist/bridge/drivers/opencode.js +2 -2
- package/dist/bridge/drivers/qwen.js +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/{chunk-SN2RWSB3.js → chunk-2VM62DX7.js} +3 -3
- package/dist/{chunk-SN2RWSB3.js.map → chunk-2VM62DX7.js.map} +1 -1
- package/dist/{chunk-SIW5I47F.js → chunk-4RSCLQYX.js} +231 -33
- package/dist/chunk-4RSCLQYX.js.map +1 -0
- package/dist/{chunk-YHGJBGFU.js → chunk-5JAQVXPV.js} +2 -2
- package/dist/{chunk-YHGJBGFU.js.map → chunk-5JAQVXPV.js.map} +1 -1
- package/dist/{chunk-NGE6PALH.js → chunk-67AXL4OK.js} +3 -3
- package/dist/{chunk-NGE6PALH.js.map → chunk-67AXL4OK.js.map} +1 -1
- package/dist/{chunk-CPYXJJOD.js → chunk-BKE2E5AC.js} +6 -6
- package/dist/{chunk-CPYXJJOD.js.map → chunk-BKE2E5AC.js.map} +1 -1
- package/dist/{chunk-OEXA7BBK.js → chunk-CIFTUSBV.js} +2 -2
- package/dist/{chunk-OEXA7BBK.js.map → chunk-CIFTUSBV.js.map} +1 -1
- package/dist/{chunk-LO7QEIHT.js → chunk-DHN6VW4B.js} +4 -4
- package/dist/{chunk-LO7QEIHT.js.map → chunk-DHN6VW4B.js.map} +1 -1
- package/dist/{chunk-7WHBI3I6.js → chunk-DVIIYYD5.js} +3 -3
- package/dist/{chunk-7WHBI3I6.js.map → chunk-DVIIYYD5.js.map} +1 -1
- package/dist/{chunk-DTJNHYFE.js → chunk-E5VRPYUX.js} +9 -16
- package/dist/chunk-E5VRPYUX.js.map +1 -0
- package/dist/{chunk-NZJDQYNB.js → chunk-FM2BJYX4.js} +2 -2
- package/dist/{chunk-NZJDQYNB.js.map → chunk-FM2BJYX4.js.map} +1 -1
- package/dist/{chunk-AOWKMINN.js → chunk-JLSK6HR4.js} +5 -5
- package/dist/{chunk-AOWKMINN.js.map → chunk-JLSK6HR4.js.map} +1 -1
- package/dist/{chunk-7FLLPKX3.js → chunk-NSVAJWWQ.js} +3 -3
- package/dist/{chunk-7FLLPKX3.js.map → chunk-NSVAJWWQ.js.map} +1 -1
- package/dist/{chunk-MA7HSL5S.js → chunk-QLHOORR7.js} +2 -2
- package/dist/{chunk-MA7HSL5S.js.map → chunk-QLHOORR7.js.map} +1 -1
- package/dist/{chunk-P72K36PU.js → chunk-TV2OU2EZ.js} +4 -4
- package/dist/{chunk-P72K36PU.js.map → chunk-TV2OU2EZ.js.map} +1 -1
- package/dist/{chunk-2RQ3KLY3.js → chunk-UQ5JY2GQ.js} +10 -7
- package/dist/chunk-UQ5JY2GQ.js.map +1 -0
- package/dist/{chunk-MG4KFVGV.js → chunk-VSLSRDQZ.js} +3 -3
- package/dist/{chunk-MG4KFVGV.js.map → chunk-VSLSRDQZ.js.map} +1 -1
- package/dist/{chunk-BR7RPEHW.js → chunk-W6TLIJG3.js} +3 -3
- package/dist/{chunk-BR7RPEHW.js.map → chunk-W6TLIJG3.js.map} +1 -1
- package/dist/{chunk-GXHJDQ37.js → chunk-WQRDLR3K.js} +410 -48
- package/dist/chunk-WQRDLR3K.js.map +1 -0
- package/dist/{chunk-74UKG2LA.js → chunk-XT6AZWK3.js} +40 -5
- package/dist/chunk-XT6AZWK3.js.map +1 -0
- package/dist/cli/index.js +31 -31
- package/dist/connectors/config.js +4 -4
- package/dist/connectors/index.js +6 -6
- package/dist/connectors/rclone.js +1 -1
- package/dist/connectors/src/config.d.ts +30 -3
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/connectors/src/connector-manager.d.ts +56 -3
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/fleet-health-gate.d.ts +86 -0
- package/dist/connectors/src/fleet-health-gate.d.ts.map +1 -0
- package/dist/connectors/src/fleet-utils.d.ts +16 -0
- package/dist/connectors/src/fleet-utils.d.ts.map +1 -1
- package/dist/connectors/src/index.d.ts +9 -3
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/connectors/src/rclone-process-manager.d.ts +24 -0
- package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
- package/dist/connectors/src/rclone-token-refresh.d.ts +84 -0
- package/dist/connectors/src/rclone-token-refresh.d.ts.map +1 -0
- package/dist/core/index.js +3 -3
- package/dist/core/runtime-assets.js +2 -2
- package/dist/core/src/workspace-config.d.ts +20 -6
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +1 -1
- package/dist/deploy/index.js +3 -3
- package/dist/{ensure-sources-CRUZDVPG.js → ensure-sources-GYEQ65ET.js} +5 -5
- package/dist/{ensure-sources-CRUZDVPG.js.map → ensure-sources-GYEQ65ET.js.map} +1 -1
- package/dist/factory-assets/connectors/deploy.js +6 -6
- package/dist/factory-assets/connectors/devserver.js +6 -6
- package/dist/factory-assets/connectors/flow/adapter.js +6 -6
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
- package/dist/factory-assets/connectors/flow.js +6 -6
- package/dist/factory-assets/connectors/git.js +6 -6
- package/dist/factory-assets/connectors/gmail.js +6 -6
- package/dist/factory-assets/connectors/googledrive.js +6 -6
- package/dist/factory-assets/connectors/local.js +6 -6
- package/dist/factory-assets/connectors/mattermost.js +6 -6
- package/dist/factory-assets/connectors/memory.js +6 -6
- package/dist/factory-assets/connectors/minio.js +6 -6
- package/dist/factory-assets/connectors/postgres.js +6 -6
- package/dist/factory-assets/connectors/s3.js +6 -6
- package/dist/factory-assets/connectors/sharepoint/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/sharepoint.js +6 -6
- package/dist/factory-assets/connectors/sqlite.js +6 -6
- package/dist/factory-assets/connectors/static-server.js +6 -6
- package/dist/factory-assets/connectors/tunnel.js +6 -6
- package/dist/factory-assets/connectors/webdav/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/webdav.js +6 -6
- package/dist/factory-assets/connectors/xstate-store.js +6 -6
- package/dist/factory-assets/connectors/xstate.js +6 -6
- package/dist/{flows-W7L2576K.js → flows-TJUVSMRR.js} +3 -3
- package/dist/{flows-W7L2576K.js.map → flows-TJUVSMRR.js.map} +1 -1
- package/dist/library/index.js +3 -3
- package/dist/library/install.js +3 -3
- package/dist/{open-library-XZZXXVBP.js → open-library-GPZUB7N3.js} +6 -6
- package/dist/{open-library-XZZXXVBP.js.map → open-library-GPZUB7N3.js.map} +1 -1
- package/dist/{paths-RH5CIFX2.js → paths-R6WA7PKV.js} +6 -6
- package/dist/{paths-RH5CIFX2.js.map → paths-R6WA7PKV.js.map} +1 -1
- package/dist/{plugin-store-2UZGNS6M.js → plugin-store-TF7GECYJ.js} +5 -5
- package/dist/{plugin-store-2UZGNS6M.js.map → plugin-store-TF7GECYJ.js.map} +1 -1
- package/dist/runner/index.js +10 -10
- package/dist/runner/src/external-mcp.d.ts +45 -4
- package/dist/runner/src/external-mcp.d.ts.map +1 -1
- package/dist/runner/src/fleet-health-flag-dispatcher.d.ts +40 -0
- package/dist/runner/src/fleet-health-flag-dispatcher.d.ts.map +1 -0
- package/dist/runner/src/lifecycle-handler.d.ts +17 -0
- package/dist/runner/src/lifecycle-handler.d.ts.map +1 -0
- package/dist/runner/src/resources.d.ts.map +1 -1
- package/dist/runner/src/runner-capabilities.d.ts +1 -1
- package/dist/runner/src/runner-capabilities.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +5 -5
- package/dist/sdk/bridge.js +2 -2
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +10 -10
- package/dist/sdk/runner.js +10 -10
- package/dist/{setup-G5UATRCX.js → setup-YKL43RQJ.js} +7 -7
- package/dist/{setup-G5UATRCX.js.map → setup-YKL43RQJ.js.map} +1 -1
- package/dist/{store-client-TUC7VSOU.js → store-client-H7MHTZVU.js} +6 -6
- package/dist/{store-client-TUC7VSOU.js.map → store-client-H7MHTZVU.js.map} +1 -1
- package/dist/tui/index.js +10 -10
- package/dist/workspace-plugin/adapters/mcp.js +1 -1
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2RQ3KLY3.js.map +0 -1
- package/dist/chunk-74UKG2LA.js.map +0 -1
- package/dist/chunk-DTJNHYFE.js.map +0 -1
- package/dist/chunk-GXHJDQ37.js.map +0 -1
- package/dist/chunk-SIW5I47F.js.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { WorkspacePlugin } from './chunk-
|
|
1
|
+
import { WorkspacePlugin } from './chunk-QLHOORR7.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';
|
|
5
|
-
import { EventNormalizer } from './chunk-
|
|
5
|
+
import { EventNormalizer } from './chunk-NSVAJWWQ.js';
|
|
6
6
|
import { classifyClaudeSdkError } from './chunk-NGJ6E344.js';
|
|
7
|
-
import { createDriver } from './chunk-
|
|
7
|
+
import { createDriver } from './chunk-CIFTUSBV.js';
|
|
8
8
|
import { deployCatalogEntry, undeployCatalogEntry } from './chunk-LV2HPH3C.js';
|
|
9
|
-
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-
|
|
10
|
-
import { loadConnectorDeclarations, PreMintedSecretProvider, InMemorySecretProvider } from './chunk-
|
|
9
|
+
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools } from './chunk-WQRDLR3K.js';
|
|
10
|
+
import { loadConnectorDeclarations, PreMintedSecretProvider, InMemorySecretProvider } from './chunk-UQ5JY2GQ.js';
|
|
11
11
|
import { renderStimulusPrompt, buildOrchestratorPrompt } from './chunk-DEYYRFQU.js';
|
|
12
|
-
import { resolveSettings, resolveApiKey, providerEnvKey } from './chunk-
|
|
13
|
-
import { resolveRuntimeAssets } from './chunk-
|
|
14
|
-
import { resolveSkWorkspaceConfig, resolveAgentDir, stageMaterializedSkills, loadMcpServerDeclarations, COMPACTION_DEFAULTS, validateAssetRecipeAttr } from './chunk-
|
|
12
|
+
import { resolveSettings, resolveApiKey, providerEnvKey } from './chunk-DVIIYYD5.js';
|
|
13
|
+
import { resolveRuntimeAssets } from './chunk-2VM62DX7.js';
|
|
14
|
+
import { resolveSkWorkspaceConfig, resolveAgentDir, stageMaterializedSkills, loadMcpServerDeclarations, COMPACTION_DEFAULTS, validateAssetRecipeAttr } from './chunk-E5VRPYUX.js';
|
|
15
15
|
import { parseAssetRef } from './chunk-LFDZYCEO.js';
|
|
16
16
|
import { resolveDriverPaths } from './chunk-K5GBV4SA.js';
|
|
17
17
|
import { getLogStore, resolveLogStoreConfig, createLogStoreFromConfig, OnLogBridgeSink, WsLogSink, registerLogStore, resetLogStore, createLogger } from './chunk-JB35MVBN.js';
|
|
@@ -24,7 +24,7 @@ import path4, { join, resolve, relative, sep, isAbsolute, dirname, basename } fr
|
|
|
24
24
|
import { homedir } from 'os';
|
|
25
25
|
import * as z5 from 'zod';
|
|
26
26
|
import { z } from 'zod';
|
|
27
|
-
import fs4, { mkdir, writeFile, rename } from 'fs/promises';
|
|
27
|
+
import fs4, { mkdir, writeFile, rename, readFile } from 'fs/promises';
|
|
28
28
|
import { createHash, randomUUID } from 'crypto';
|
|
29
29
|
import { execFile, spawnSync } from 'child_process';
|
|
30
30
|
import { promisify } from 'util';
|
|
@@ -983,6 +983,17 @@ function warnUnresolvedRecipeMarkers(recipeLog, declId, resolvedCommand, resolve
|
|
|
983
983
|
var PASSTHROUGH_INPUT_ZOD = {
|
|
984
984
|
parse: (v) => v
|
|
985
985
|
};
|
|
986
|
+
function isMcpAuthError(err) {
|
|
987
|
+
if (!err || typeof err !== "object") return false;
|
|
988
|
+
const code = err.code ?? err.status;
|
|
989
|
+
if (code === 401 || code === "401") return true;
|
|
990
|
+
const message = err.message;
|
|
991
|
+
if (typeof message !== "string") return false;
|
|
992
|
+
return /\b401\b|invalid[_ ]token|invalid[_ ]grant/i.test(message);
|
|
993
|
+
}
|
|
994
|
+
function errMessage(err) {
|
|
995
|
+
return err instanceof Error ? err.message : String(err);
|
|
996
|
+
}
|
|
986
997
|
function buildTransport(decl, secrets) {
|
|
987
998
|
const transport = decl.transport ?? "stdio";
|
|
988
999
|
if (transport === "stdio") {
|
|
@@ -1029,10 +1040,14 @@ var ExternalMcpManager = class {
|
|
|
1029
1040
|
* @param connect Optional connector override (tests inject a fake client so
|
|
1030
1041
|
* no live subprocess is spawned). Defaults to the real SDK
|
|
1031
1042
|
* client + transport.
|
|
1043
|
+
* @param reauthorize Optional re-mint callback for `auth: backend` remote
|
|
1044
|
+
* servers. When present, a 401 from a tool call (or the
|
|
1045
|
+
* initial connect) triggers a re-mint + reconnect.
|
|
1032
1046
|
*/
|
|
1033
|
-
constructor(registry, secrets, sessionId, connect) {
|
|
1047
|
+
constructor(registry, secrets, sessionId, connect, reauthorize) {
|
|
1034
1048
|
this.registry = registry;
|
|
1035
1049
|
this.connect = connect ?? defaultMcpClientConnector(secrets);
|
|
1050
|
+
this.reauthorize = reauthorize;
|
|
1036
1051
|
this.log = createLogger({
|
|
1037
1052
|
kind: "mcp",
|
|
1038
1053
|
subkind: "runner-managed",
|
|
@@ -1043,6 +1058,7 @@ var ExternalMcpManager = class {
|
|
|
1043
1058
|
servers = [];
|
|
1044
1059
|
log;
|
|
1045
1060
|
connect;
|
|
1061
|
+
reauthorize;
|
|
1046
1062
|
/** True when at least one external server connected and registered tools. */
|
|
1047
1063
|
hasServers() {
|
|
1048
1064
|
return this.servers.length > 0;
|
|
@@ -1064,12 +1080,13 @@ var ExternalMcpManager = class {
|
|
|
1064
1080
|
}
|
|
1065
1081
|
}
|
|
1066
1082
|
async startServer(decl) {
|
|
1067
|
-
const client = await this.
|
|
1083
|
+
const client = await this.connectWithReauth(decl);
|
|
1084
|
+
const server = { id: decl.id, decl, client, toolNames: [] };
|
|
1068
1085
|
const toolNames = [];
|
|
1069
1086
|
try {
|
|
1070
1087
|
const { tools } = await client.listTools();
|
|
1071
1088
|
for (const tool of tools) {
|
|
1072
|
-
const cap = this.buildToolCapability(
|
|
1089
|
+
const cap = this.buildToolCapability(server, tool);
|
|
1073
1090
|
this.registry.register(cap, "agent");
|
|
1074
1091
|
toolNames.push(cap.name);
|
|
1075
1092
|
}
|
|
@@ -1081,7 +1098,8 @@ var ExternalMcpManager = class {
|
|
|
1081
1098
|
}
|
|
1082
1099
|
throw err;
|
|
1083
1100
|
}
|
|
1084
|
-
|
|
1101
|
+
server.toolNames = toolNames;
|
|
1102
|
+
this.servers.push(server);
|
|
1085
1103
|
this.log.info("MCP server registered (runner-managed)", {
|
|
1086
1104
|
id: decl.id,
|
|
1087
1105
|
transport: decl.transport ?? "stdio",
|
|
@@ -1089,14 +1107,72 @@ var ExternalMcpManager = class {
|
|
|
1089
1107
|
tools: toolNames
|
|
1090
1108
|
});
|
|
1091
1109
|
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Connect, re-minting once on an initial-connect 401: the provisioned bearer
|
|
1112
|
+
* may already be stale by the time the server is reached. Only retries for
|
|
1113
|
+
* `auth: backend` servers with a reauthorizer wired.
|
|
1114
|
+
*/
|
|
1115
|
+
async connectWithReauth(decl) {
|
|
1116
|
+
try {
|
|
1117
|
+
return await this.connect(decl);
|
|
1118
|
+
} catch (err) {
|
|
1119
|
+
if (isMcpAuthError(err) && this.reauthorize && decl.auth === "backend") {
|
|
1120
|
+
this.log.warn("MCP initial connect 401 \u2014 re-minting and retrying", { id: decl.id });
|
|
1121
|
+
if (await this.reauthorize(decl)) {
|
|
1122
|
+
return this.connect(decl);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
throw err;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Re-mint the bearer and reconnect one server in place after a 401. Concurrent
|
|
1130
|
+
* 401s for the same server share a single round-trip via `reauthInFlight`.
|
|
1131
|
+
* Returns `true` once `server.client` points at a freshly-authed connection.
|
|
1132
|
+
*/
|
|
1133
|
+
reauthAndReconnect(server) {
|
|
1134
|
+
server.reauthInFlight ??= this.doReauthAndReconnect(server).finally(() => {
|
|
1135
|
+
server.reauthInFlight = void 0;
|
|
1136
|
+
});
|
|
1137
|
+
return server.reauthInFlight;
|
|
1138
|
+
}
|
|
1139
|
+
async doReauthAndReconnect(server) {
|
|
1140
|
+
if (!this.reauthorize || server.decl.auth !== "backend") return false;
|
|
1141
|
+
let provisioned;
|
|
1142
|
+
try {
|
|
1143
|
+
provisioned = await this.reauthorize(server.decl);
|
|
1144
|
+
} catch (err) {
|
|
1145
|
+
this.log.warn("MCP re-mint failed after 401", { id: server.id, error: errMessage(err) });
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
if (!provisioned) return false;
|
|
1149
|
+
let next;
|
|
1150
|
+
try {
|
|
1151
|
+
next = await this.connect(server.decl);
|
|
1152
|
+
await next.listTools();
|
|
1153
|
+
} catch (err) {
|
|
1154
|
+
this.log.warn("MCP reconnect after 401 failed", { id: server.id, error: errMessage(err) });
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
const old = server.client;
|
|
1158
|
+
server.client = next;
|
|
1159
|
+
try {
|
|
1160
|
+
await old.close();
|
|
1161
|
+
} catch {
|
|
1162
|
+
}
|
|
1163
|
+
this.log.info("MCP server reconnected after 401 re-mint", { id: server.id });
|
|
1164
|
+
return true;
|
|
1165
|
+
}
|
|
1092
1166
|
/**
|
|
1093
1167
|
* Wrap a single MCP tool as a {@link DefinedCapability}. The capability name
|
|
1094
1168
|
* is `mcp__<server>__<tool>` (the naming claude-sdk wildcards and prompts
|
|
1095
|
-
* depend on). The handler proxies the call to the
|
|
1096
|
-
*
|
|
1097
|
-
* to the LLM
|
|
1169
|
+
* depend on). The handler proxies the call to the server's LIVE client (read
|
|
1170
|
+
* lazily so a 401 reconnect is transparent); a tool error (`isError`) is
|
|
1171
|
+
* rethrown so the capability dispatch path surfaces it to the LLM, and a 401
|
|
1172
|
+
* triggers a re-mint + reconnect followed by a single retry.
|
|
1098
1173
|
*/
|
|
1099
|
-
buildToolCapability(
|
|
1174
|
+
buildToolCapability(server, tool) {
|
|
1175
|
+
const serverId = server.id;
|
|
1100
1176
|
const name = `mcp__${serverId}__${tool.name}`;
|
|
1101
1177
|
const inputSchema = tool.inputSchema && typeof tool.inputSchema === "object" ? tool.inputSchema : { type: "object" };
|
|
1102
1178
|
return {
|
|
@@ -1111,10 +1187,18 @@ var ExternalMcpManager = class {
|
|
|
1111
1187
|
audience: ["llm"],
|
|
1112
1188
|
inputZod: PASSTHROUGH_INPUT_ZOD,
|
|
1113
1189
|
handler: async (input, ctx) => {
|
|
1114
|
-
const
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1190
|
+
const call = { name: tool.name, arguments: input ?? {} };
|
|
1191
|
+
let result;
|
|
1192
|
+
try {
|
|
1193
|
+
result = await server.client.callTool(call);
|
|
1194
|
+
} catch (err) {
|
|
1195
|
+
if (isMcpAuthError(err) && await this.reauthAndReconnect(server)) {
|
|
1196
|
+
ctx.log.info("mcp tool retried after 401 re-mint", { tool: name });
|
|
1197
|
+
result = await server.client.callTool(call);
|
|
1198
|
+
} else {
|
|
1199
|
+
throw err;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1118
1202
|
const content = result.content ?? [];
|
|
1119
1203
|
const text = content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n");
|
|
1120
1204
|
if (result.isError) {
|
|
@@ -1128,8 +1212,14 @@ var ExternalMcpManager = class {
|
|
|
1128
1212
|
/**
|
|
1129
1213
|
* Deregister every tool and close every client (kills the subprocesses).
|
|
1130
1214
|
* Best-effort: a failed close on one server does not prevent the rest.
|
|
1215
|
+
*
|
|
1216
|
+
* Drains any in-flight 401 reconnect first: a `doReauthAndReconnect` resolving
|
|
1217
|
+
* after teardown would set `server.client` to a freshly-connected client that
|
|
1218
|
+
* nothing then closes (leak). Awaiting `reauthInFlight` guarantees we close the
|
|
1219
|
+
* LATEST client.
|
|
1131
1220
|
*/
|
|
1132
1221
|
async dispose() {
|
|
1222
|
+
await Promise.allSettled(this.servers.map((s) => s.reauthInFlight).filter(Boolean));
|
|
1133
1223
|
for (const server of this.servers) {
|
|
1134
1224
|
for (const toolName of server.toolNames) {
|
|
1135
1225
|
this.registry.deregister(toolName);
|
|
@@ -1346,11 +1436,42 @@ async function startExternalMcpServers(capabilityRegistry, projectDir, secretPro
|
|
|
1346
1436
|
const externalMcpManager = new ExternalMcpManager(
|
|
1347
1437
|
capabilityRegistry,
|
|
1348
1438
|
secretProvider,
|
|
1349
|
-
sessionMeta?.sessionId
|
|
1439
|
+
sessionMeta?.sessionId,
|
|
1440
|
+
void 0,
|
|
1441
|
+
buildMcpReauthorizer(capabilityRegistry, secretProvider, sessionMeta?.sessionId)
|
|
1350
1442
|
);
|
|
1351
1443
|
await externalMcpManager.start(resolvedDecls);
|
|
1352
1444
|
return externalMcpManager;
|
|
1353
1445
|
}
|
|
1446
|
+
function mcpAuthSecretKey(id) {
|
|
1447
|
+
return `MCP__${id.replace(/[^A-Za-z0-9_]/g, "_")}__AUTH`;
|
|
1448
|
+
}
|
|
1449
|
+
function buildMcpReauthorizer(capabilityRegistry, secretProvider, sessionId) {
|
|
1450
|
+
const provider = secretProvider;
|
|
1451
|
+
const provision = provider?.provision?.bind(provider);
|
|
1452
|
+
if (!provision) return void 0;
|
|
1453
|
+
const log = createLogger({ kind: "mcp", subkind: "reauth", instance: sessionId ?? "no-session" });
|
|
1454
|
+
return async (decl) => {
|
|
1455
|
+
if (!decl.providerLinkId || decl.auth !== "backend") return false;
|
|
1456
|
+
let mint;
|
|
1457
|
+
try {
|
|
1458
|
+
mint = await capabilityRegistry.invokeRemote("host.refresh_credential", {
|
|
1459
|
+
kind: "mcp-server",
|
|
1460
|
+
id: decl.providerLinkId,
|
|
1461
|
+
reason: "retry-401"
|
|
1462
|
+
});
|
|
1463
|
+
} catch (err) {
|
|
1464
|
+
log.warn("MCP credential re-mint round-trip failed", {
|
|
1465
|
+
id: decl.id,
|
|
1466
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1467
|
+
});
|
|
1468
|
+
return false;
|
|
1469
|
+
}
|
|
1470
|
+
if (!mint?.ok || !mint.token) return false;
|
|
1471
|
+
provision({ [mcpAuthSecretKey(decl.id)]: `Bearer ${mint.token}` });
|
|
1472
|
+
return true;
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1354
1475
|
function wireExternalMcpServersForSdk(mcpServers, projectDir, secretProvider, sessionMeta) {
|
|
1355
1476
|
const mcpLog = createLogger({
|
|
1356
1477
|
kind: "mcp",
|
|
@@ -2719,6 +2840,57 @@ function rewriteFileChangedPath(event, cwd, mounts) {
|
|
|
2719
2840
|
return event;
|
|
2720
2841
|
}
|
|
2721
2842
|
|
|
2843
|
+
// runner/src/lifecycle-handler.ts
|
|
2844
|
+
function buildLifecycleHandler(deps) {
|
|
2845
|
+
const { getCompactionOrchestrator, getResourceManager, log } = deps;
|
|
2846
|
+
return async ({ phase }) => {
|
|
2847
|
+
switch (phase) {
|
|
2848
|
+
case "compact": {
|
|
2849
|
+
const orchestrator = getCompactionOrchestrator();
|
|
2850
|
+
if (orchestrator) await orchestrator.compact("manual");
|
|
2851
|
+
else log("[lifecycle] compact: no compaction orchestrator \u2014 skipped");
|
|
2852
|
+
break;
|
|
2853
|
+
}
|
|
2854
|
+
case "hibernate": {
|
|
2855
|
+
const manager = getResourceManager();
|
|
2856
|
+
if (manager) await manager.hibernateAll();
|
|
2857
|
+
else log("[lifecycle] hibernate: no resource manager \u2014 skipped");
|
|
2858
|
+
break;
|
|
2859
|
+
}
|
|
2860
|
+
case "close": {
|
|
2861
|
+
const manager = getResourceManager();
|
|
2862
|
+
if (manager) await manager.closeAll();
|
|
2863
|
+
else log("[lifecycle] close: no resource manager \u2014 skipped");
|
|
2864
|
+
break;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
return { ok: true };
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
function parseFleetHealthBody(body) {
|
|
2871
|
+
return body.trim().toLowerCase() === "healthy" ? "healthy" : "error";
|
|
2872
|
+
}
|
|
2873
|
+
async function dispatchFleetHealthFlag(dir, fileName, manager, log) {
|
|
2874
|
+
if (!manager) return;
|
|
2875
|
+
const connectorId = fileName;
|
|
2876
|
+
if (!connectorId || connectorId.startsWith(".")) return;
|
|
2877
|
+
let verdict;
|
|
2878
|
+
try {
|
|
2879
|
+
verdict = parseFleetHealthBody(await readFile(join(dir, connectorId), "utf8"));
|
|
2880
|
+
} catch {
|
|
2881
|
+
verdict = "error";
|
|
2882
|
+
}
|
|
2883
|
+
try {
|
|
2884
|
+
await manager.reportFleetHealth(connectorId, verdict);
|
|
2885
|
+
log.debug("fleet-health flag dispatched", { connectorId, verdict });
|
|
2886
|
+
} catch (err) {
|
|
2887
|
+
log.warn("fleet-health flag dispatch failed", {
|
|
2888
|
+
connectorId,
|
|
2889
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2722
2894
|
// runner/src/refresh-flag-dispatcher.ts
|
|
2723
2895
|
async function dispatchRefreshToExposedGitMounts(manager, log) {
|
|
2724
2896
|
if (!manager) return;
|
|
@@ -2807,7 +2979,7 @@ var setStateInput = z5.strictObject({
|
|
|
2807
2979
|
value: requiredUnknown
|
|
2808
2980
|
});
|
|
2809
2981
|
var lifecycleInput = z5.strictObject({
|
|
2810
|
-
|
|
2982
|
+
phase: z5.enum(["hibernate", "close", "compact"])
|
|
2811
2983
|
});
|
|
2812
2984
|
var VALID_LOG_STORE_LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
2813
2985
|
function buildRunnerCapabilities(handlers) {
|
|
@@ -2921,7 +3093,7 @@ function buildRunnerCapabilities(handlers) {
|
|
|
2921
3093
|
defineCapability({
|
|
2922
3094
|
name: "runner.lifecycle",
|
|
2923
3095
|
displayName: "Session lifecycle",
|
|
2924
|
-
description: "Transition the session lifecycle: hibernate
|
|
3096
|
+
description: "Transition the session lifecycle: hibernate (connectors persist state), close (connectors finalize), or compact conversation history.",
|
|
2925
3097
|
side: "agent",
|
|
2926
3098
|
origin: RUNNER_CAP_ORIGIN,
|
|
2927
3099
|
audience: ["runtime"],
|
|
@@ -3515,17 +3687,15 @@ async function startAgentServer(opts) {
|
|
|
3515
3687
|
const { skillsDir } = resolveDriverPaths({
|
|
3516
3688
|
driver: opts.driver ?? wsConfig.agent_config?.default?.driver ?? "claude-sdk"
|
|
3517
3689
|
});
|
|
3518
|
-
const
|
|
3519
|
-
const declared = strict ? (wsConfig.dependencies ?? []).flatMap((dep) => {
|
|
3690
|
+
const declared = (wsConfig.dependencies ?? []).flatMap((dep) => {
|
|
3520
3691
|
try {
|
|
3521
3692
|
const ref = parseAssetRef(dep);
|
|
3522
3693
|
return ref.kind === "skill" ? [ref.name] : [];
|
|
3523
3694
|
} catch {
|
|
3524
3695
|
return [];
|
|
3525
3696
|
}
|
|
3526
|
-
})
|
|
3697
|
+
});
|
|
3527
3698
|
const stagedSkills = stageMaterializedSkills(opts.projectDir, skillsDir, {
|
|
3528
|
-
strict,
|
|
3529
3699
|
declared
|
|
3530
3700
|
});
|
|
3531
3701
|
if (stagedSkills.length > 0) {
|
|
@@ -3842,6 +4012,25 @@ async function startAgentServer(opts) {
|
|
|
3842
4012
|
error: err instanceof Error ? err.message : String(err)
|
|
3843
4013
|
});
|
|
3844
4014
|
}
|
|
4015
|
+
const fleetHealthDir = join(opts.projectDir, ".skaile", "fleet-health");
|
|
4016
|
+
try {
|
|
4017
|
+
mkdirSync(fleetHealthDir, { recursive: true });
|
|
4018
|
+
} catch (err) {
|
|
4019
|
+
serverLog.warn("failed to pre-create fleet-health dir \u2014 platform health signal disabled", {
|
|
4020
|
+
error: err instanceof Error ? err.message : String(err)
|
|
4021
|
+
});
|
|
4022
|
+
}
|
|
4023
|
+
let fleetHealthWatcher = null;
|
|
4024
|
+
try {
|
|
4025
|
+
fleetHealthWatcher = watch(fleetHealthDir, (_event, fileName) => {
|
|
4026
|
+
if (!fileName) return;
|
|
4027
|
+
void dispatchFleetHealthFlag(fleetHealthDir, fileName.toString(), resourceManager, serverLog);
|
|
4028
|
+
});
|
|
4029
|
+
} catch (err) {
|
|
4030
|
+
serverLog.warn("fs.watch on fleet-health dir failed \u2014 platform health signal disabled", {
|
|
4031
|
+
error: err instanceof Error ? err.message : String(err)
|
|
4032
|
+
});
|
|
4033
|
+
}
|
|
3845
4034
|
async function cleanup() {
|
|
3846
4035
|
try {
|
|
3847
4036
|
await Promise.race([
|
|
@@ -3868,6 +4057,11 @@ async function startAgentServer(opts) {
|
|
|
3868
4057
|
} catch {
|
|
3869
4058
|
}
|
|
3870
4059
|
refreshFlagWatcher = null;
|
|
4060
|
+
try {
|
|
4061
|
+
fleetHealthWatcher?.close();
|
|
4062
|
+
} catch {
|
|
4063
|
+
}
|
|
4064
|
+
fleetHealthWatcher = null;
|
|
3871
4065
|
if (agentSession) {
|
|
3872
4066
|
try {
|
|
3873
4067
|
await agentSession.dispose();
|
|
@@ -3963,10 +4157,14 @@ async function startAgentServer(opts) {
|
|
|
3963
4157
|
});
|
|
3964
4158
|
},
|
|
3965
4159
|
log
|
|
4160
|
+
}),
|
|
4161
|
+
// setLogLevel left undefined (the cap self-falls-back to getLogStore);
|
|
4162
|
+
// setState remains a stub (not resource hot-plug).
|
|
4163
|
+
lifecycle: buildLifecycleHandler({
|
|
4164
|
+
getCompactionOrchestrator: () => compactionOrchestrator,
|
|
4165
|
+
getResourceManager: () => resourceManager,
|
|
4166
|
+
log
|
|
3966
4167
|
})
|
|
3967
|
-
// setLogLevel left undefined — the cap's built-in fallback calls
|
|
3968
|
-
// getLogStore()?.setLevel(...) directly. setState / lifecycle
|
|
3969
|
-
// remain stubs (not resource hot-plug; out of Sprint 2 scope).
|
|
3970
4168
|
});
|
|
3971
4169
|
for (const cap of runnerCaps) {
|
|
3972
4170
|
capabilityRegistry.register(cap, "agent");
|
|
@@ -4847,5 +5045,5 @@ function touchSession(state) {
|
|
|
4847
5045
|
}
|
|
4848
5046
|
|
|
4849
5047
|
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, builtinCapabilities, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, touchSession, writeClaudeCodeCredentialsFile };
|
|
4850
|
-
//# sourceMappingURL=chunk-
|
|
4851
|
-
//# sourceMappingURL=chunk-
|
|
5048
|
+
//# sourceMappingURL=chunk-4RSCLQYX.js.map
|
|
5049
|
+
//# sourceMappingURL=chunk-4RSCLQYX.js.map
|