@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.
Files changed (146) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/dist/{asset-feeds-2LQIGNUF.js → asset-feeds-6R2C2NHB.js} +7 -7
  3. package/dist/{asset-feeds-2LQIGNUF.js.map → asset-feeds-6R2C2NHB.js.map} +1 -1
  4. package/dist/asset-manager/index.js +5 -5
  5. package/dist/asset-manager/installer.js +4 -4
  6. package/dist/bridge/drivers/claude-sdk.js +8 -1
  7. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  8. package/dist/bridge/drivers/codex.js +1 -1
  9. package/dist/bridge/drivers/continue.js +2 -2
  10. package/dist/bridge/drivers/echo.js +1 -1
  11. package/dist/bridge/drivers/gemini.js +3 -3
  12. package/dist/bridge/drivers/goose.js +2 -2
  13. package/dist/bridge/drivers/omp.js +1 -1
  14. package/dist/bridge/drivers/opencode.js +2 -2
  15. package/dist/bridge/drivers/qwen.js +3 -3
  16. package/dist/bridge/index.js +2 -2
  17. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  18. package/dist/{chunk-SN2RWSB3.js → chunk-2VM62DX7.js} +3 -3
  19. package/dist/{chunk-SN2RWSB3.js.map → chunk-2VM62DX7.js.map} +1 -1
  20. package/dist/{chunk-SIW5I47F.js → chunk-4RSCLQYX.js} +231 -33
  21. package/dist/chunk-4RSCLQYX.js.map +1 -0
  22. package/dist/{chunk-YHGJBGFU.js → chunk-5JAQVXPV.js} +2 -2
  23. package/dist/{chunk-YHGJBGFU.js.map → chunk-5JAQVXPV.js.map} +1 -1
  24. package/dist/{chunk-NGE6PALH.js → chunk-67AXL4OK.js} +3 -3
  25. package/dist/{chunk-NGE6PALH.js.map → chunk-67AXL4OK.js.map} +1 -1
  26. package/dist/{chunk-CPYXJJOD.js → chunk-BKE2E5AC.js} +6 -6
  27. package/dist/{chunk-CPYXJJOD.js.map → chunk-BKE2E5AC.js.map} +1 -1
  28. package/dist/{chunk-OEXA7BBK.js → chunk-CIFTUSBV.js} +2 -2
  29. package/dist/{chunk-OEXA7BBK.js.map → chunk-CIFTUSBV.js.map} +1 -1
  30. package/dist/{chunk-LO7QEIHT.js → chunk-DHN6VW4B.js} +4 -4
  31. package/dist/{chunk-LO7QEIHT.js.map → chunk-DHN6VW4B.js.map} +1 -1
  32. package/dist/{chunk-7WHBI3I6.js → chunk-DVIIYYD5.js} +3 -3
  33. package/dist/{chunk-7WHBI3I6.js.map → chunk-DVIIYYD5.js.map} +1 -1
  34. package/dist/{chunk-DTJNHYFE.js → chunk-E5VRPYUX.js} +9 -16
  35. package/dist/chunk-E5VRPYUX.js.map +1 -0
  36. package/dist/{chunk-NZJDQYNB.js → chunk-FM2BJYX4.js} +2 -2
  37. package/dist/{chunk-NZJDQYNB.js.map → chunk-FM2BJYX4.js.map} +1 -1
  38. package/dist/{chunk-AOWKMINN.js → chunk-JLSK6HR4.js} +5 -5
  39. package/dist/{chunk-AOWKMINN.js.map → chunk-JLSK6HR4.js.map} +1 -1
  40. package/dist/{chunk-7FLLPKX3.js → chunk-NSVAJWWQ.js} +3 -3
  41. package/dist/{chunk-7FLLPKX3.js.map → chunk-NSVAJWWQ.js.map} +1 -1
  42. package/dist/{chunk-MA7HSL5S.js → chunk-QLHOORR7.js} +2 -2
  43. package/dist/{chunk-MA7HSL5S.js.map → chunk-QLHOORR7.js.map} +1 -1
  44. package/dist/{chunk-P72K36PU.js → chunk-TV2OU2EZ.js} +4 -4
  45. package/dist/{chunk-P72K36PU.js.map → chunk-TV2OU2EZ.js.map} +1 -1
  46. package/dist/{chunk-2RQ3KLY3.js → chunk-UQ5JY2GQ.js} +10 -7
  47. package/dist/chunk-UQ5JY2GQ.js.map +1 -0
  48. package/dist/{chunk-MG4KFVGV.js → chunk-VSLSRDQZ.js} +3 -3
  49. package/dist/{chunk-MG4KFVGV.js.map → chunk-VSLSRDQZ.js.map} +1 -1
  50. package/dist/{chunk-BR7RPEHW.js → chunk-W6TLIJG3.js} +3 -3
  51. package/dist/{chunk-BR7RPEHW.js.map → chunk-W6TLIJG3.js.map} +1 -1
  52. package/dist/{chunk-GXHJDQ37.js → chunk-WQRDLR3K.js} +410 -48
  53. package/dist/chunk-WQRDLR3K.js.map +1 -0
  54. package/dist/{chunk-74UKG2LA.js → chunk-XT6AZWK3.js} +40 -5
  55. package/dist/chunk-XT6AZWK3.js.map +1 -0
  56. package/dist/cli/index.js +31 -31
  57. package/dist/connectors/config.js +4 -4
  58. package/dist/connectors/index.js +6 -6
  59. package/dist/connectors/rclone.js +1 -1
  60. package/dist/connectors/src/config.d.ts +30 -3
  61. package/dist/connectors/src/config.d.ts.map +1 -1
  62. package/dist/connectors/src/connector-manager.d.ts +56 -3
  63. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  64. package/dist/connectors/src/fleet-health-gate.d.ts +86 -0
  65. package/dist/connectors/src/fleet-health-gate.d.ts.map +1 -0
  66. package/dist/connectors/src/fleet-utils.d.ts +16 -0
  67. package/dist/connectors/src/fleet-utils.d.ts.map +1 -1
  68. package/dist/connectors/src/index.d.ts +9 -3
  69. package/dist/connectors/src/index.d.ts.map +1 -1
  70. package/dist/connectors/src/rclone-process-manager.d.ts +24 -0
  71. package/dist/connectors/src/rclone-process-manager.d.ts.map +1 -1
  72. package/dist/connectors/src/rclone-token-refresh.d.ts +84 -0
  73. package/dist/connectors/src/rclone-token-refresh.d.ts.map +1 -0
  74. package/dist/core/index.js +3 -3
  75. package/dist/core/runtime-assets.js +2 -2
  76. package/dist/core/src/workspace-config.d.ts +20 -6
  77. package/dist/core/src/workspace-config.d.ts.map +1 -1
  78. package/dist/core/workspace-config.js +1 -1
  79. package/dist/deploy/index.js +3 -3
  80. package/dist/{ensure-sources-CRUZDVPG.js → ensure-sources-GYEQ65ET.js} +5 -5
  81. package/dist/{ensure-sources-CRUZDVPG.js.map → ensure-sources-GYEQ65ET.js.map} +1 -1
  82. package/dist/factory-assets/connectors/deploy.js +6 -6
  83. package/dist/factory-assets/connectors/devserver.js +6 -6
  84. package/dist/factory-assets/connectors/flow/adapter.js +6 -6
  85. package/dist/factory-assets/connectors/flow/engine.js +3 -3
  86. package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
  87. package/dist/factory-assets/connectors/flow.js +6 -6
  88. package/dist/factory-assets/connectors/git.js +6 -6
  89. package/dist/factory-assets/connectors/gmail.js +6 -6
  90. package/dist/factory-assets/connectors/googledrive.js +6 -6
  91. package/dist/factory-assets/connectors/local.js +6 -6
  92. package/dist/factory-assets/connectors/mattermost.js +6 -6
  93. package/dist/factory-assets/connectors/memory.js +6 -6
  94. package/dist/factory-assets/connectors/minio.js +6 -6
  95. package/dist/factory-assets/connectors/postgres.js +6 -6
  96. package/dist/factory-assets/connectors/s3.js +6 -6
  97. package/dist/factory-assets/connectors/sharepoint/driver.d.ts.map +1 -1
  98. package/dist/factory-assets/connectors/sharepoint.js +6 -6
  99. package/dist/factory-assets/connectors/sqlite.js +6 -6
  100. package/dist/factory-assets/connectors/static-server.js +6 -6
  101. package/dist/factory-assets/connectors/tunnel.js +6 -6
  102. package/dist/factory-assets/connectors/webdav/driver.d.ts.map +1 -1
  103. package/dist/factory-assets/connectors/webdav.js +6 -6
  104. package/dist/factory-assets/connectors/xstate-store.js +6 -6
  105. package/dist/factory-assets/connectors/xstate.js +6 -6
  106. package/dist/{flows-W7L2576K.js → flows-TJUVSMRR.js} +3 -3
  107. package/dist/{flows-W7L2576K.js.map → flows-TJUVSMRR.js.map} +1 -1
  108. package/dist/library/index.js +3 -3
  109. package/dist/library/install.js +3 -3
  110. package/dist/{open-library-XZZXXVBP.js → open-library-GPZUB7N3.js} +6 -6
  111. package/dist/{open-library-XZZXXVBP.js.map → open-library-GPZUB7N3.js.map} +1 -1
  112. package/dist/{paths-RH5CIFX2.js → paths-R6WA7PKV.js} +6 -6
  113. package/dist/{paths-RH5CIFX2.js.map → paths-R6WA7PKV.js.map} +1 -1
  114. package/dist/{plugin-store-2UZGNS6M.js → plugin-store-TF7GECYJ.js} +5 -5
  115. package/dist/{plugin-store-2UZGNS6M.js.map → plugin-store-TF7GECYJ.js.map} +1 -1
  116. package/dist/runner/index.js +10 -10
  117. package/dist/runner/src/external-mcp.d.ts +45 -4
  118. package/dist/runner/src/external-mcp.d.ts.map +1 -1
  119. package/dist/runner/src/fleet-health-flag-dispatcher.d.ts +40 -0
  120. package/dist/runner/src/fleet-health-flag-dispatcher.d.ts.map +1 -0
  121. package/dist/runner/src/lifecycle-handler.d.ts +17 -0
  122. package/dist/runner/src/lifecycle-handler.d.ts.map +1 -0
  123. package/dist/runner/src/resources.d.ts.map +1 -1
  124. package/dist/runner/src/runner-capabilities.d.ts +1 -1
  125. package/dist/runner/src/runner-capabilities.d.ts.map +1 -1
  126. package/dist/runner/src/serve.d.ts.map +1 -1
  127. package/dist/sdk/asset-manager.js +5 -5
  128. package/dist/sdk/bridge.js +2 -2
  129. package/dist/sdk/core.js +3 -3
  130. package/dist/sdk/flow.js +3 -3
  131. package/dist/sdk/index.js +10 -10
  132. package/dist/sdk/runner.js +10 -10
  133. package/dist/{setup-G5UATRCX.js → setup-YKL43RQJ.js} +7 -7
  134. package/dist/{setup-G5UATRCX.js.map → setup-YKL43RQJ.js.map} +1 -1
  135. package/dist/{store-client-TUC7VSOU.js → store-client-H7MHTZVU.js} +6 -6
  136. package/dist/{store-client-TUC7VSOU.js.map → store-client-H7MHTZVU.js.map} +1 -1
  137. package/dist/tui/index.js +10 -10
  138. package/dist/workspace-plugin/adapters/mcp.js +1 -1
  139. package/dist/workspace-plugin/adapters/omp.js +3 -3
  140. package/dist/workspace-plugin/index.js +1 -1
  141. package/package.json +1 -1
  142. package/dist/chunk-2RQ3KLY3.js.map +0 -1
  143. package/dist/chunk-74UKG2LA.js.map +0 -1
  144. package/dist/chunk-DTJNHYFE.js.map +0 -1
  145. package/dist/chunk-GXHJDQ37.js.map +0 -1
  146. package/dist/chunk-SIW5I47F.js.map +0 -1
@@ -1,17 +1,17 @@
1
- import { WorkspacePlugin } from './chunk-MA7HSL5S.js';
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-7FLLPKX3.js';
5
+ import { EventNormalizer } from './chunk-NSVAJWWQ.js';
6
6
  import { classifyClaudeSdkError } from './chunk-NGJ6E344.js';
7
- import { createDriver } from './chunk-OEXA7BBK.js';
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-GXHJDQ37.js';
10
- import { loadConnectorDeclarations, PreMintedSecretProvider, InMemorySecretProvider } from './chunk-2RQ3KLY3.js';
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-7WHBI3I6.js';
13
- import { resolveRuntimeAssets } from './chunk-SN2RWSB3.js';
14
- import { resolveSkWorkspaceConfig, resolveAgentDir, stageMaterializedSkills, loadMcpServerDeclarations, COMPACTION_DEFAULTS, validateAssetRecipeAttr } from './chunk-DTJNHYFE.js';
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.connect(decl);
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(decl.id, tool, client);
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
- this.servers.push({ id: decl.id, client, toolNames });
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 live MCP client; a tool
1096
- * error (`isError`) is rethrown so the capability dispatch path surfaces it
1097
- * to the LLM as a tool failure.
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(serverId, tool, client) {
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 result = await client.callTool({
1115
- name: tool.name,
1116
- arguments: input ?? {}
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
- action: z5.enum(["hibernate", "close", "shutdown"])
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 to disk, close the active flow, or shut down the runner.",
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 strict = process.env.SKAILE_STRICT_YAML === "true";
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-SIW5I47F.js.map
4851
- //# sourceMappingURL=chunk-SIW5I47F.js.map
5048
+ //# sourceMappingURL=chunk-4RSCLQYX.js.map
5049
+ //# sourceMappingURL=chunk-4RSCLQYX.js.map