nextclaw 0.18.2 → 0.18.4

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 (107) hide show
  1. package/dist/cli/app/index.js +409 -123
  2. package/package.json +15 -15
  3. package/ui-dist/assets/api-DnPN4SyA.js +15 -0
  4. package/ui-dist/assets/app-manager-provider-M7TngYxx.js +1 -0
  5. package/ui-dist/assets/app-navigation.config-B5YIdRju.js +1 -0
  6. package/ui-dist/assets/{book-open-BE8M56IM.js → book-open-B4mOKdz8.js} +1 -1
  7. package/ui-dist/assets/channels-list-page-Cm-Bbu6u.js +8 -0
  8. package/ui-dist/assets/chat-C0ZNZtS3.js +58 -0
  9. package/ui-dist/assets/chat-page-CGHNhXaw.js +1 -0
  10. package/ui-dist/assets/chunk-JZWAC4HX-BJer-fqD.js +3 -0
  11. package/ui-dist/assets/config-split-page-B3PRA_AV.js +1 -0
  12. package/ui-dist/assets/{createLucideIcon-CCiTGX8L.js → createLucideIcon-C_GFKVuW.js} +1 -1
  13. package/ui-dist/assets/desktop-update-config-Dfh-3uma.js +1 -0
  14. package/ui-dist/assets/{dialog-BghZFPch.js → dialog-D-I7ONHQ.js} +1 -1
  15. package/ui-dist/assets/{dist-Dd9cr-kz.js → dist-DreLBS93.js} +1 -1
  16. package/ui-dist/assets/doc-browser-CoKIUCJj.js +1 -0
  17. package/ui-dist/assets/doc-browser-CwgI7ipB.js +1 -0
  18. package/ui-dist/assets/doc-browser-DYKpRqe-.js +1 -0
  19. package/ui-dist/assets/doc-browser-context-Dib9sS83.js +1 -0
  20. package/ui-dist/assets/{es2015-CEAreese.js → es2015-DMSUl3fm.js} +1 -1
  21. package/ui-dist/assets/{external-link-qsnCMhw1.js → external-link-DP2IJ7AM.js} +1 -1
  22. package/ui-dist/assets/folder-BPwc278w.js +1 -0
  23. package/ui-dist/assets/{hash-0zjWsNl-.js → hash-CvcvtMBq.js} +1 -1
  24. package/ui-dist/assets/i18n-BnNAQpVM.js +1 -0
  25. package/ui-dist/assets/index-Bc6c1kIx.js +2 -0
  26. package/ui-dist/assets/index-mRmSAB-e.css +1 -0
  27. package/ui-dist/assets/{key-round-BLe9D8ND.js → key-round-BQXmPSxD.js} +1 -1
  28. package/ui-dist/assets/loader-circle-C6gg2m2a.js +1 -0
  29. package/ui-dist/assets/{LogoBadge-DP8Ye7wJ.js → logo-badge-uB4SwANR.js} +1 -1
  30. package/ui-dist/assets/{logos-_v5b2SdG.js → logos-BcELLmYh.js} +1 -1
  31. package/ui-dist/assets/marketplace-page-BCrS-jH6.js +49 -0
  32. package/ui-dist/assets/marketplace-page-DVrlpB68.js +1 -0
  33. package/ui-dist/assets/mcp-marketplace-page-CjrxT6wI.js +40 -0
  34. package/ui-dist/assets/mcp-marketplace-page-pQ_A38fH.js +1 -0
  35. package/ui-dist/assets/message-square-CLVODA23.js +1 -0
  36. package/ui-dist/assets/model-config-D4myteLK.js +1 -0
  37. package/ui-dist/assets/notice-card-DX_NEZTQ.js +1 -0
  38. package/ui-dist/assets/play-DeNVUA5C.js +1 -0
  39. package/ui-dist/assets/plus-BptLViq1.js +1 -0
  40. package/ui-dist/assets/popover-Dm_NQ3Cs.js +1 -0
  41. package/ui-dist/assets/provider-scoped-model-input-BLHImwI5.js +1 -0
  42. package/ui-dist/assets/providers-list-DsBFslNi.js +1 -0
  43. package/ui-dist/assets/refresh-ccw-CeG203yU.js +1 -0
  44. package/ui-dist/assets/remote-CQQykOYe.js +1 -0
  45. package/ui-dist/assets/rotate-cw-F7aThvYj.js +1 -0
  46. package/ui-dist/assets/runtime-config-page-Bz9r68Rf.js +1 -0
  47. package/ui-dist/assets/{save-D4bObrmH.js → save-7ztImRj7.js} +1 -1
  48. package/ui-dist/assets/search-DZSNKEGp.js +1 -0
  49. package/ui-dist/assets/search-config-C-6KpgRQ.js +1 -0
  50. package/ui-dist/assets/secrets-config-MiMElvpm.js +3 -0
  51. package/ui-dist/assets/{select-BILPf7zs.js → select-RgeHgn_-.js} +1 -1
  52. package/ui-dist/assets/sessions-config-page-0KNW9QC_.js +2 -0
  53. package/ui-dist/assets/{setting-row-BATDgg4r.js → setting-row-vwm4XKv2.js} +1 -1
  54. package/ui-dist/assets/settings-DjvNMJde.js +1 -0
  55. package/ui-dist/assets/skeleton-5Mg6vZHN.js +1 -0
  56. package/ui-dist/assets/sparkles-CyDTgTM4.js +1 -0
  57. package/ui-dist/assets/status-dot-aQU9Mia4.js +1 -0
  58. package/ui-dist/assets/{tabs-custom-Bx3cNhD-.js → tabs-custom-C4P7g4vR.js} +1 -1
  59. package/ui-dist/assets/{tag-chip-zUaDE2-H.js → tag-chip-DGqz3TON.js} +1 -1
  60. package/ui-dist/assets/theme-provider-CUppbOyN.js +1 -0
  61. package/ui-dist/assets/tooltip-DQlSKhZ_.js +1 -0
  62. package/ui-dist/assets/{trash-2-CQUgYyRn.js → trash-2-C1cdqL6V.js} +1 -1
  63. package/ui-dist/assets/use-config-CrsavfWZ.js +1 -0
  64. package/ui-dist/assets/{useConfirmDialog-patAnl1g.js → use-confirm-dialog-D1AnLFlc.js} +1 -1
  65. package/ui-dist/assets/use-infinite-scroll-loader-DZhv-rmv.js +1 -0
  66. package/ui-dist/assets/use-viewport-layout-CytJAPWM.js +1 -0
  67. package/ui-dist/assets/x-BjMO7v8q.js +1 -0
  68. package/ui-dist/index.html +39 -22
  69. package/ui-dist/assets/ChannelsList-SQ7Oxotv.js +0 -8
  70. package/ui-dist/assets/DocBrowser-BCO2k6XD.js +0 -1
  71. package/ui-dist/assets/DocBrowser-rDOjI3ga.js +0 -1
  72. package/ui-dist/assets/DocBrowserContext-BUq3Wo8O.js +0 -1
  73. package/ui-dist/assets/ModelConfig-C77Ae9ru.js +0 -1
  74. package/ui-dist/assets/ProviderScopedModelInput-CEnK61uo.js +0 -1
  75. package/ui-dist/assets/ProvidersList-BCupBayq.js +0 -1
  76. package/ui-dist/assets/RuntimeConfig-Ad-CAcmy.js +0 -1
  77. package/ui-dist/assets/SearchConfig-BfCz4wJ4.js +0 -1
  78. package/ui-dist/assets/SecretsConfig-DjmBIhyy.js +0 -3
  79. package/ui-dist/assets/SessionsConfig-CvjxU40H.js +0 -2
  80. package/ui-dist/assets/chat-page-JKC6ln-y.js +0 -58
  81. package/ui-dist/assets/chat-session-display-YcRMrAMa.js +0 -1
  82. package/ui-dist/assets/chunk-JZWAC4HX-erTUn3b8.js +0 -3
  83. package/ui-dist/assets/client-CszWMVKi.js +0 -7
  84. package/ui-dist/assets/config-split-page-BAGSzUR3.js +0 -1
  85. package/ui-dist/assets/desktop-DfkLlkG2.js +0 -1
  86. package/ui-dist/assets/desktop-update-config-BXeGlqHD.js +0 -1
  87. package/ui-dist/assets/dist-ZwoAXs46.js +0 -9
  88. package/ui-dist/assets/download-D7LOizcW.js +0 -1
  89. package/ui-dist/assets/i18n-DvzXOGQX.js +0 -1
  90. package/ui-dist/assets/index-DvVTC9FF.css +0 -1
  91. package/ui-dist/assets/index-lr6rQUSd.js +0 -2
  92. package/ui-dist/assets/loader-circle-wj7kARHv.js +0 -1
  93. package/ui-dist/assets/marketplace-page-CAAk1Khc.js +0 -1
  94. package/ui-dist/assets/marketplace-page-CfCiq90S.js +0 -49
  95. package/ui-dist/assets/mcp-marketplace-page-D0Pp9Hs-.js +0 -40
  96. package/ui-dist/assets/play-o6NmwGTi.js +0 -1
  97. package/ui-dist/assets/plus-I9pBS4Fl.js +0 -1
  98. package/ui-dist/assets/refresh-cw-MNqgR3LZ.js +0 -1
  99. package/ui-dist/assets/remote-C9fXm4V5.js +0 -1
  100. package/ui-dist/assets/search-DxmL3IWE.js +0 -1
  101. package/ui-dist/assets/security-config-BUm6FFfl.js +0 -1
  102. package/ui-dist/assets/skeleton-COKMAnJy.js +0 -1
  103. package/ui-dist/assets/switch-CBOzecWS.js +0 -1
  104. package/ui-dist/assets/use-infinite-scroll-loader-B5V2Klve.js +0 -1
  105. package/ui-dist/assets/useMutation-__AYv-Pz.js +0 -1
  106. package/ui-dist/assets/x-BHUGQIUv.js +0 -1
  107. /package/ui-dist/assets/{config-hints-DSQQbeOA.js → config-hints-CPNzbMEp.js} +0 -0
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
3
  import * as NextclawCore from "@nextclaw/core";
4
- import { APP_NAME, APP_TAGLINE, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, ChannelManager, CommandRegistry, ConfigSchema, ContextBuilder, CronService, CronTool, DEFAULT_WORKSPACE_DIR, DEFAULT_WORKSPACE_PATH, DisposableStore, EditFileTool, ExecTool, ExtensionToolAdapter, FileLogSink, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, MemoryGetTool, MemorySearchTool, MessageBus, MessageTool, ProviderManager, ReadFileTool, RequestedSkillsMetadataReader, SessionManager, SessionsHistoryTool, SessionsListTool, SkillsLoader, Tool, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool, buildConfigSchema, buildMinimalSystemExecutionPrompt, buildReloadPlan, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createExternalCommandEnv, createGlobalTypedEventBus, createTypedEventKey, createTypingStopControlMessage, diffConfigPaths, expandHome, findEffectiveAgentProfile, getAppLogger, getConfigPath, getDataDir, getDataPath, getLoggingRuntime, getLogsPath, getPackageVersion, getWorkspacePath, hasSecretRef, loadConfig, normalizeInlineSecretRefs, parseAgentScopedSessionKey, parseThinkingLevel, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveAppLogPath, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveLocalUiBaseUrl, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, toDisposable, updateAgentProfile } from "@nextclaw/core";
4
+ import { APP_NAME, APP_TAGLINE, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, ChannelManager, CommandRegistry, ConfigSchema, ContextBuilder, CronService, CronTool, DEFAULT_WORKSPACE_DIR, DEFAULT_WORKSPACE_PATH, DisposableStore, EditFileTool, ExecTool, ExtensionToolAdapter, FileLogSink, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, MemoryGetTool, MemorySearchTool, MessageBus, MessageTool, ProviderManager, ReadFileTool, RequestedSkillsMetadataReader, SessionManager, SessionsHistoryTool, SessionsListTool, SkillsLoader, Tool, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool, buildConfigSchema, buildMinimalSystemExecutionPrompt, buildReloadPlan, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createExternalCommandEnv, createGlobalTypedEventBus, createTypedEventKey, createTypingStopControlMessage, diffConfigPaths, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getLoggingRuntime, getLogsPath, getPackageVersion, getWorkspacePath, hasSecretRef, loadConfig, normalizeInlineSecretRefs, parseAgentScopedSessionKey, parseThinkingLevel, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveAppLogPath, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveLocalUiBaseUrl, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, toDisposable, updateAgentProfile } from "@nextclaw/core";
5
5
  import { Command } from "commander";
6
6
  import fs, { appendFileSync, closeSync, constants, cpSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, relative, resolve, win32 } from "node:path";
8
8
  import { homedir, hostname, platform } from "node:os";
9
9
  import { ensureUiBridgeSecret, startUiServer } from "@nextclaw/server";
10
- import { addPluginLoadPath, buildPluginStatusReport, disablePluginInConfig, discoverPluginStatusReport, enablePluginInConfig, getPackageManifestExtensions, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadOpenClawPluginsProgressively, loadPluginManifest, mergePluginConfigView, recordPluginInstall, resolvePluginChannelMessageToolHints, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, startPluginChannelGateways, stopPluginChannelGateways, toPluginConfigView, toPluginConfigView as toPluginConfigView$1, uninstallPlugin } from "@nextclaw/openclaw-compat";
10
+ import { addPluginLoadPath, buildPluginStatusReport, disablePluginInConfig, discoverPluginStatusReport, enablePluginInConfig, getPackageManifestExtensions, getPluginChannelBindings, getPluginUiMetadataFromRegistry, installPluginFromNpmSpec, installPluginFromPath, loadOpenClawPlugins, loadPluginManifest, mergePluginConfigView, recordPluginInstall, resolvePluginChannelMessageToolHints, resolveUninstallDirectoryTargets, setPluginRuntimeBridge, stopPluginChannelGateways, toPluginConfigView, toPluginConfigView as toPluginConfigView$1, uninstallPlugin } from "@nextclaw/openclaw-compat";
11
11
  import { fileURLToPath } from "node:url";
12
- import { spawn, spawnSync } from "node:child_process";
12
+ import { fork, spawn, spawnSync } from "node:child_process";
13
13
  import { createServer, isIP } from "node:net";
14
14
  import { BUILTIN_CHANNEL_PLUGIN_IDS, builtinProviderIds, listBuiltinProviders } from "@nextclaw/runtime";
15
15
  import { createInterface } from "node:readline";
@@ -5220,11 +5220,31 @@ async function waitForExit(pid, timeoutMs) {
5220
5220
  }
5221
5221
  return !isProcessRunning(pid);
5222
5222
  }
5223
- function resolveUiStaticDir() {
5223
+ function findNearestPackageManifest(startDir, expectedName) {
5224
+ let current = resolve(startDir);
5225
+ while (current.length > 0) {
5226
+ const pkgPath = join(current, "package.json");
5227
+ if (existsSync(pkgPath)) try {
5228
+ const raw = readFileSync(pkgPath, "utf-8");
5229
+ const parsed = JSON.parse(raw);
5230
+ if (!expectedName || parsed.name === expectedName) return {
5231
+ rootDir: current,
5232
+ version: typeof parsed.version === "string" ? parsed.version : void 0
5233
+ };
5234
+ } catch {}
5235
+ const parent = resolve(current, "..");
5236
+ if (parent === current) break;
5237
+ current = parent;
5238
+ }
5239
+ return null;
5240
+ }
5241
+ function resolveUiStaticDir(importMetaUrl = import.meta.url) {
5224
5242
  if (process.env.NEXTCLAW_DISABLE_STATIC_UI === "1") return null;
5225
5243
  const envDir = process.env.NEXTCLAW_UI_STATIC_DIR;
5226
5244
  if (envDir) return existsSync(join(envDir, "index.html")) ? envDir : null;
5227
- const bundledDir = join(resolve(resolve(fileURLToPath(new URL(".", import.meta.url))), "..", "..", "..", ".."), "ui-dist");
5245
+ const pkgRoot = findNearestPackageManifest(resolve(fileURLToPath(new URL(".", importMetaUrl))), "nextclaw")?.rootDir;
5246
+ if (!pkgRoot) return null;
5247
+ const bundledDir = join(pkgRoot, "ui-dist");
5228
5248
  return existsSync(join(bundledDir, "index.html")) ? bundledDir : null;
5229
5249
  }
5230
5250
  function openBrowser(url) {
@@ -5246,7 +5266,7 @@ function openBrowser(url) {
5246
5266
  command = "xdg-open";
5247
5267
  args = [url];
5248
5268
  }
5249
- if (!which(command)) return false;
5269
+ if (!findExecutableOnPath(command)) return false;
5250
5270
  try {
5251
5271
  spawn(command, args, {
5252
5272
  stdio: "ignore",
@@ -5260,7 +5280,7 @@ function openBrowser(url) {
5260
5280
  }
5261
5281
  function normalizePathEntries(rawPath, platform) {
5262
5282
  const delimiter = platform === "win32" ? ";" : ":";
5263
- return rawPath.split(delimiter).map((entry) => entry.trim().replace(/^"+|"+$/g, "")).filter((entry) => entry.length > 0);
5283
+ return rawPath.split(delimiter).map((entry) => entry.trim().replace(/^"+|"+$/g, "")).filter(Boolean);
5264
5284
  }
5265
5285
  function normalizeWindowsPathExt(rawPathExt) {
5266
5286
  const source = rawPathExt && rawPathExt.trim().length > 0 ? rawPathExt : ".COM;.EXE;.BAT;.CMD";
@@ -5274,8 +5294,7 @@ function normalizeWindowsPathExt(rawPathExt) {
5274
5294
  return [...unique];
5275
5295
  }
5276
5296
  function hasFileExtension(binary) {
5277
- const lastSlash = Math.max(binary.lastIndexOf("/"), binary.lastIndexOf("\\"));
5278
- return binary.lastIndexOf(".") > lastSlash;
5297
+ return binary.lastIndexOf(".") > Math.max(binary.lastIndexOf("/"), binary.lastIndexOf("\\"));
5279
5298
  }
5280
5299
  function findExecutableOnPath(binary, env = process.env, platform = process.platform) {
5281
5300
  const target = binary.trim();
@@ -5285,41 +5304,20 @@ function findExecutableOnPath(binary, env = process.env, platform = process.plat
5285
5304
  if (!rawPath.trim()) return null;
5286
5305
  const entries = normalizePathEntries(rawPath, platform);
5287
5306
  if (entries.length === 0) return null;
5288
- const checkCandidates = (candidate) => existsSync(candidate) ? candidate : null;
5289
5307
  for (const dir of entries) {
5290
- const direct = checkCandidates(join(dir, target));
5291
- if (direct) return direct;
5308
+ const direct = join(dir, target);
5309
+ if (existsSync(direct)) return direct;
5292
5310
  if (platform !== "win32" || hasFileExtension(target)) continue;
5293
5311
  for (const ext of normalizeWindowsPathExt(env.PATHEXT)) {
5294
- const withExt = checkCandidates(join(dir, `${target}${ext}`));
5295
- if (withExt) return withExt;
5312
+ const withExt = join(dir, `${target}${ext}`);
5313
+ if (existsSync(withExt)) return withExt;
5296
5314
  }
5297
5315
  }
5298
5316
  return null;
5299
5317
  }
5300
- function which(binary) {
5301
- return findExecutableOnPath(binary) !== null;
5302
- }
5303
- function resolveVersionFromPackageTree(startDir, expectedName) {
5304
- let current = resolve(startDir);
5305
- while (current.length > 0) {
5306
- const pkgPath = join(current, "package.json");
5307
- if (existsSync(pkgPath)) try {
5308
- const raw = readFileSync(pkgPath, "utf-8");
5309
- const parsed = JSON.parse(raw);
5310
- const version = typeof parsed.version === "string" ? parsed.version : null;
5311
- const matchesExpectedName = !expectedName || parsed.name === expectedName;
5312
- if (version && matchesExpectedName) return version;
5313
- } catch {}
5314
- const parent = resolve(current, "..");
5315
- if (parent === current) break;
5316
- current = parent;
5317
- }
5318
- return null;
5319
- }
5320
5318
  function getPackageVersion$1() {
5321
5319
  const cliDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
5322
- return resolveVersionFromPackageTree(cliDir, "nextclaw") ?? resolveVersionFromPackageTree(cliDir) ?? getPackageVersion();
5320
+ return findNearestPackageManifest(cliDir, "nextclaw")?.version ?? findNearestPackageManifest(cliDir)?.version ?? getPackageVersion();
5323
5321
  }
5324
5322
  function printAgentResponse(response) {
5325
5323
  console.log("\n" + response + "\n");
@@ -6026,23 +6024,9 @@ function toExtensionRegistry(pluginRegistry) {
6026
6024
  }
6027
6025
  //#endregion
6028
6026
  //#region src/cli/commands/plugin/plugin-registry-loader.ts
6029
- function createPluginLogger() {
6030
- return getAppLogger("plugin.registry_loader");
6031
- }
6032
6027
  function withDevFirstPartyPluginPaths(config) {
6033
6028
  return resolveDevPluginLoadingContext(config, resolveDevFirstPartyPluginDir(process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR));
6034
6029
  }
6035
- async function loadPluginRegistryProgressively(config, workspaceDir, options = {}) {
6036
- const { configWithDevPluginOverrides, excludedRoots } = withDevFirstPartyPluginPaths(config);
6037
- return await loadOpenClawPluginsProgressively({
6038
- config: configWithDevPluginOverrides,
6039
- workspaceDir,
6040
- excludeRoots: excludedRoots,
6041
- ...buildReservedPluginLoadOptions(),
6042
- onPluginProcessed: options.onPluginProcessed,
6043
- logger: createPluginLogger()
6044
- });
6045
- }
6046
6030
  function discoverPluginRegistryStatus(config, workspaceDir) {
6047
6031
  const { configWithDevPluginOverrides } = withDevFirstPartyPluginPaths(config);
6048
6032
  return discoverPluginStatusReport({
@@ -8554,6 +8538,7 @@ function buildLegacyAssistantMessages(message, timestamp) {
8554
8538
  name: toolInvocation.toolName,
8555
8539
  tool_call_id: toolInvocation.toolCallId,
8556
8540
  content: typeof toolInvocation.result === "string" ? toolInvocation.result : JSON.stringify(toolInvocation.result ?? null),
8541
+ ...toolInvocation.resultContentItems ? { ncp_tool_result_content_items: structuredClone(toolInvocation.resultContentItems) } : {},
8557
8542
  timestamp,
8558
8543
  ncp_message_id: message.id
8559
8544
  });
@@ -9432,8 +9417,9 @@ function buildGenericMessage(params) {
9432
9417
  parts: contentToParts(params.message.content)
9433
9418
  };
9434
9419
  }
9435
- function attachToolResult(target, toolCallId, result, toolName) {
9420
+ function attachToolResult(target, toolCallId, result, toolName, resultContentItems) {
9436
9421
  const normalizedResult = normalizeToolResultPayload(result);
9422
+ const normalizedContentItems = Array.isArray(resultContentItems) ? structuredClone(resultContentItems) : void 0;
9437
9423
  target.parts = target.parts.map((part) => {
9438
9424
  if (part.type !== "tool-invocation" || part.toolCallId !== toolCallId) return part;
9439
9425
  if (part.state === "result" && Object.prototype.hasOwnProperty.call(part, "result")) return {
@@ -9444,7 +9430,8 @@ function attachToolResult(target, toolCallId, result, toolName) {
9444
9430
  ...part,
9445
9431
  toolName: toolName ?? part.toolName,
9446
9432
  state: "result",
9447
- result: normalizedResult
9433
+ result: normalizedResult,
9434
+ ...normalizedContentItems ? { resultContentItems: normalizedContentItems } : {}
9448
9435
  };
9449
9436
  });
9450
9437
  }
@@ -9458,7 +9445,7 @@ function toNcpMessages(sessionId, messages) {
9458
9445
  if (toolCallId) {
9459
9446
  const assistantIndex = assistantIndexByToolCallId.get(toolCallId);
9460
9447
  if (assistantIndex !== void 0) {
9461
- attachToolResult(ncpMessages[assistantIndex], toolCallId, structuredClone(message.content), normalizeString(message.name) ?? void 0);
9448
+ attachToolResult(ncpMessages[assistantIndex], toolCallId, structuredClone(message.content), normalizeString(message.name) ?? void 0, message.ncp_tool_result_content_items);
9462
9449
  return;
9463
9450
  }
9464
9451
  }
@@ -13973,19 +13960,6 @@ var ManagedServiceCommandService = class {
13973
13960
  };
13974
13961
  //#endregion
13975
13962
  //#region src/cli/shared/services/gateway/service-startup-support.ts
13976
- const pluginGatewayLogger = {
13977
- info: (message) => console.log(`[plugins] ${message}`),
13978
- warn: (message) => console.warn(`[plugins] ${message}`),
13979
- error: (message) => console.error(`[plugins] ${message}`),
13980
- debug: (message) => console.debug(`[plugins] ${message}`)
13981
- };
13982
- function logPluginGatewayDiagnostics(diagnostics) {
13983
- for (const diag of diagnostics) {
13984
- const text = `${diag.pluginId ? `${diag.pluginId}: ` : ""}${diag.message}`;
13985
- if (diag.level === "error") console.error(`[plugins] ${text}`);
13986
- else console.warn(`[plugins] ${text}`);
13987
- }
13988
- }
13989
13963
  async function startGatewaySupportServices(params) {
13990
13964
  if (params.cronJobs > 0) console.log(`✓ Cron: ${params.cronJobs} scheduled jobs`);
13991
13965
  console.log("✓ Heartbeat: every 30m");
@@ -15396,14 +15370,10 @@ var NextclawApp = class {
15396
15370
  await measureStartupAsync("service.deferred_startup.recover_durable_state", async () => await this.ncpAgentRuntime.recoverDurableState());
15397
15371
  };
15398
15372
  warmDerivedCapabilities = async () => {
15399
- const runtimeWarmupTask = this.kernelReady ? measureStartupAsync("service.deferred_startup.warm_ncp_capabilities", async () => await this.ncpAgentRuntime.warmDerivedCapabilities()).catch((error) => {
15400
- console.warn(`UI NCP derived capability warmup failed: ${error instanceof Error ? error.message : String(error)}`);
15401
- }) : Promise.resolve();
15402
15373
  if (this.params.hydrateCapabilities) await measureStartupAsync("service.deferred_startup.hydrate_capabilities", this.params.hydrateCapabilities);
15403
15374
  await measureStartupAsync("service.deferred_startup.start_plugin_gateways", this.params.startPluginGateways);
15404
15375
  await measureStartupAsync("service.deferred_startup.start_channels", this.params.startChannels);
15405
15376
  await measureStartupAsync("service.deferred_startup.wake_restart_sentinel", this.params.wakeFromRestartSentinel);
15406
- await runtimeWarmupTask;
15407
15377
  };
15408
15378
  handleKernelStartupError(error) {
15409
15379
  this.params.bootstrapStatus.markNcpAgentError(error instanceof Error ? error.message : String(error));
@@ -15905,58 +15875,57 @@ function countEnabledPlugins(config, workspaceDir) {
15905
15875
  return discoverPluginRegistryStatus(config, workspaceDir).plugins.filter((plugin) => plugin.enabled).length;
15906
15876
  }
15907
15877
  async function hydrateServiceCapabilities(params) {
15908
- await waitForUiShellGraceWindow(params.uiStartup);
15909
- const nextConfig = resolveConfigSecrets(loadConfig(), { configPath: params.gateway.runtimeConfigPath });
15878
+ const { bootstrapStatus, extensionHost, gateway, getLiveUiNcpAgent, state, uiStartup } = params;
15879
+ await waitForUiShellGraceWindow(uiStartup);
15880
+ const nextConfig = resolveConfigSecrets(loadConfig(), { configPath: gateway.runtimeConfigPath });
15910
15881
  const nextWorkspace = getWorkspacePath(nextConfig.agents.defaults.workspace);
15911
15882
  const totalPluginCount = countEnabledPlugins(nextConfig, nextWorkspace);
15912
15883
  let loadedPluginCount = 0;
15913
- params.bootstrapStatus.markPluginHydrationRunning({ totalPluginCount });
15914
- params.bootstrapStatus.markChannelsPending();
15884
+ bootstrapStatus.markPluginHydrationRunning({ totalPluginCount });
15885
+ bootstrapStatus.markChannelsPending();
15915
15886
  try {
15916
- const nextPluginRegistry = await loadPluginRegistryProgressively(nextConfig, nextWorkspace, { onPluginProcessed: ({ loadedPluginCount: nextCount }) => {
15917
- loadedPluginCount = nextCount;
15918
- params.bootstrapStatus.markPluginHydrationProgress({
15919
- loadedPluginCount: nextCount,
15920
- totalPluginCount
15921
- });
15922
- } });
15887
+ const nextPluginRegistry = extensionHost.createProxyPluginRegistry(await extensionHost.load({
15888
+ config: nextConfig,
15889
+ workspaceDir: nextWorkspace
15890
+ }));
15891
+ loadedPluginCount = loadedPluginCount || nextPluginRegistry.plugins.filter((plugin) => plugin.status === "loaded").length;
15923
15892
  logPluginDiagnostics(nextPluginRegistry);
15924
15893
  const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
15925
15894
  const nextPluginChannelBindings = getPluginChannelBindings(nextPluginRegistry);
15926
15895
  const nextPluginUiMetadata = getPluginUiMetadataFromRegistry(nextPluginRegistry);
15927
15896
  const shouldRebuildChannels = shouldRestartChannelsForPluginReload({
15928
15897
  changedPaths: [],
15929
- currentPluginChannelBindings: params.state.pluginChannelBindings,
15898
+ currentPluginChannelBindings: state.pluginChannelBindings,
15930
15899
  nextPluginChannelBindings,
15931
- currentExtensionChannels: params.state.extensionRegistry.channels,
15900
+ currentExtensionChannels: state.extensionRegistry.channels,
15932
15901
  nextExtensionChannels: nextExtensionRegistry.channels
15933
15902
  });
15934
- applyGatewayCapabilityState(params.gateway, {
15903
+ applyGatewayCapabilityState(gateway, {
15935
15904
  pluginRegistry: nextPluginRegistry,
15936
15905
  extensionRegistry: nextExtensionRegistry,
15937
15906
  pluginChannelBindings: nextPluginChannelBindings
15938
15907
  });
15939
- params.state.pluginRegistry = nextPluginRegistry;
15940
- params.state.extensionRegistry = nextExtensionRegistry;
15941
- params.state.pluginChannelBindings = nextPluginChannelBindings;
15942
- params.state.pluginUiMetadata = nextPluginUiMetadata;
15943
- params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(nextExtensionRegistry);
15944
- if (shouldRebuildChannels) await params.gateway.reloader.rebuildChannels(nextConfig, { start: false });
15945
- params.uiStartup?.publish({
15908
+ state.pluginRegistry = nextPluginRegistry;
15909
+ state.extensionRegistry = nextExtensionRegistry;
15910
+ state.pluginChannelBindings = nextPluginChannelBindings;
15911
+ state.pluginUiMetadata = nextPluginUiMetadata;
15912
+ getLiveUiNcpAgent()?.applyExtensionRegistry?.(nextExtensionRegistry);
15913
+ if (shouldRebuildChannels) await gateway.reloader.rebuildChannels(nextConfig, { start: false });
15914
+ uiStartup?.publish({
15946
15915
  type: "config.updated",
15947
15916
  payload: { path: "channels" }
15948
15917
  });
15949
- params.uiStartup?.publish({
15918
+ uiStartup?.publish({
15950
15919
  type: "config.updated",
15951
15920
  payload: { path: "plugins" }
15952
15921
  });
15953
- params.bootstrapStatus.markPluginHydrationReady({
15922
+ bootstrapStatus.markPluginHydrationReady({
15954
15923
  loadedPluginCount: loadedPluginCount || totalPluginCount,
15955
15924
  totalPluginCount
15956
15925
  });
15957
15926
  } catch (error) {
15958
15927
  const message = error instanceof Error ? error.message : String(error);
15959
- params.bootstrapStatus.markPluginHydrationError(message);
15928
+ bootstrapStatus.markPluginHydrationError(message);
15960
15929
  throw error;
15961
15930
  }
15962
15931
  }
@@ -16051,7 +16020,10 @@ function resolvePluginRuntimeAttachments(ctx) {
16051
16020
  //#region src/cli/shared/services/plugin/service-plugin-reload.service.ts
16052
16021
  async function reloadServicePlugins(params) {
16053
16022
  const nextWorkspace = getWorkspacePath(params.nextConfig.agents.defaults.workspace);
16054
- const nextPluginRegistry = loadPluginRegistry(params.nextConfig, nextWorkspace);
16023
+ const nextPluginRegistry = params.extensionHost.createProxyPluginRegistry(await params.extensionHost.load({
16024
+ config: params.nextConfig,
16025
+ workspaceDir: nextWorkspace
16026
+ }));
16055
16027
  const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
16056
16028
  const nextPluginChannelBindings = getPluginChannelBindings(nextPluginRegistry);
16057
16029
  const shouldRestartChannels = shouldRestartChannelsForPluginReload({
@@ -16062,22 +16034,14 @@ async function reloadServicePlugins(params) {
16062
16034
  nextExtensionChannels: nextExtensionRegistry.channels
16063
16035
  });
16064
16036
  logPluginDiagnostics(nextPluginRegistry);
16065
- let pluginGatewayHandles = params.pluginGatewayHandles;
16066
16037
  if (shouldRestartChannels) {
16067
- await stopPluginChannelGateways(pluginGatewayHandles);
16068
- const startedPluginGateways = await startPluginChannelGateways({
16069
- registry: nextPluginRegistry,
16070
- config: params.nextConfig,
16071
- logger: params.pluginGatewayLogger
16072
- });
16073
- pluginGatewayHandles = startedPluginGateways.handles;
16074
- params.logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
16038
+ await params.extensionHost.stopPluginGateways();
16039
+ await params.extensionHost.startPluginGateways(params.nextConfig);
16075
16040
  }
16076
16041
  return {
16077
16042
  pluginRegistry: nextPluginRegistry,
16078
16043
  extensionRegistry: nextExtensionRegistry,
16079
16044
  pluginChannelBindings: nextPluginChannelBindings,
16080
- pluginGatewayHandles,
16081
16045
  restartChannels: shouldRestartChannels
16082
16046
  };
16083
16047
  }
@@ -16102,22 +16066,20 @@ function createGatewayRuntimeState(gateway) {
16102
16066
  };
16103
16067
  }
16104
16068
  function applyGatewayRuntimeCapabilityState(params) {
16105
- applyGatewayCapabilityState(params.gateway, params.next);
16106
- params.state.pluginRegistry = params.next.pluginRegistry;
16107
- params.state.extensionRegistry = params.next.extensionRegistry;
16108
- params.state.pluginChannelBindings = params.next.pluginChannelBindings;
16069
+ const { gateway, next, state } = params;
16070
+ applyGatewayCapabilityState(gateway, next);
16071
+ state.pluginRegistry = next.pluginRegistry;
16072
+ state.extensionRegistry = next.extensionRegistry;
16073
+ state.pluginChannelBindings = next.pluginChannelBindings;
16109
16074
  }
16110
16075
  function configureGatewayPluginRuntime(params) {
16111
16076
  params.gateway.reloader.setReloadPlugins(async ({ config: nextConfig, changedPaths }) => {
16112
16077
  const result = await reloadServicePlugins({
16113
16078
  nextConfig,
16114
16079
  changedPaths,
16115
- pluginRegistry: params.state.pluginRegistry,
16116
16080
  extensionRegistry: params.state.extensionRegistry,
16117
16081
  pluginChannelBindings: params.state.pluginChannelBindings,
16118
- pluginGatewayHandles: params.state.pluginGatewayHandles,
16119
- pluginGatewayLogger,
16120
- logPluginGatewayDiagnostics
16082
+ extensionHost: params.extensionHost
16121
16083
  });
16122
16084
  applyGatewayRuntimeCapabilityState({
16123
16085
  gateway: params.gateway,
@@ -16129,7 +16091,6 @@ function configureGatewayPluginRuntime(params) {
16129
16091
  }
16130
16092
  });
16131
16093
  params.state.pluginUiMetadata = getPluginUiMetadataFromRegistry(result.pluginRegistry);
16132
- params.state.pluginGatewayHandles = result.pluginGatewayHandles;
16133
16094
  params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(result.extensionRegistry);
16134
16095
  if (result.restartChannels) console.log("Config reload: plugin channel gateways restarted.");
16135
16096
  return { restartChannels: result.restartChannels };
@@ -16156,17 +16117,12 @@ function createDeferredGatewayStartupHooks(params) {
16156
16117
  gateway: params.gateway,
16157
16118
  state: params.state,
16158
16119
  bootstrapStatus: params.bootstrapStatus,
16159
- getLiveUiNcpAgent: params.getLiveUiNcpAgent
16120
+ getLiveUiNcpAgent: params.getLiveUiNcpAgent,
16121
+ extensionHost: params.extensionHost
16160
16122
  });
16161
16123
  },
16162
16124
  startPluginGateways: async () => {
16163
- const startedPluginGateways = await startPluginChannelGateways({
16164
- registry: params.state.pluginRegistry,
16165
- config: resolveConfigSecrets$2(loadConfig$2(), { configPath: params.gateway.runtimeConfigPath }),
16166
- logger: pluginGatewayLogger
16167
- });
16168
- params.state.pluginGatewayHandles = startedPluginGateways.handles;
16169
- logPluginGatewayDiagnostics(startedPluginGateways.diagnostics);
16125
+ await params.extensionHost.startPluginGateways(resolveConfigSecrets$2(loadConfig$2(), { configPath: params.gateway.runtimeConfigPath }));
16170
16126
  },
16171
16127
  startChannels: async () => {
16172
16128
  await params.gateway.reloader.getChannels().startAll();
@@ -16201,6 +16157,326 @@ async function cleanupGatewayRuntime(params) {
16201
16157
  setPluginRuntimeBridge(null);
16202
16158
  }
16203
16159
  //#endregion
16160
+ //#region src/cli/shared/services/extension-host-proxy-registry.service.ts
16161
+ function normalizeSchema(schema) {
16162
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) return {
16163
+ type: "object",
16164
+ properties: {},
16165
+ additionalProperties: true
16166
+ };
16167
+ return schema;
16168
+ }
16169
+ function stringifyToolResult(value) {
16170
+ if (typeof value === "string") return value;
16171
+ if (value === void 0 || value === null) return "";
16172
+ try {
16173
+ return JSON.stringify(value, null, 2);
16174
+ } catch {
16175
+ return String(value);
16176
+ }
16177
+ }
16178
+ function pickPreview(params) {
16179
+ const { alias, descriptor } = params;
16180
+ const byName = descriptor.previews.find((preview) => preview.name === alias);
16181
+ if (byName) return byName;
16182
+ if (descriptor.previews.length === 1) return descriptor.previews[0] ?? null;
16183
+ if (descriptor.previews.length === descriptor.names.length) {
16184
+ const index = descriptor.names.indexOf(alias);
16185
+ if (index >= 0 && index < descriptor.previews.length) return descriptor.previews[index] ?? null;
16186
+ }
16187
+ return null;
16188
+ }
16189
+ var ExtensionHostProxyRuntime = class {
16190
+ constructor(params) {
16191
+ this.params = params;
16192
+ }
16193
+ run = (input, options) => this.params.client.runRuntimeStream({
16194
+ kind: this.params.kind,
16195
+ entry: this.params.entry,
16196
+ runtimeParams: this.params.runtimeParams,
16197
+ input,
16198
+ signal: options?.signal
16199
+ });
16200
+ };
16201
+ var ExtensionHostProxyRegistryService = class {
16202
+ constructor(client) {
16203
+ this.client = client;
16204
+ }
16205
+ createPluginRegistry = (snapshot) => ({
16206
+ plugins: snapshot.plugins,
16207
+ diagnostics: snapshot.diagnostics,
16208
+ tools: snapshot.tools.map((descriptor) => ({
16209
+ pluginId: descriptor.pluginId,
16210
+ source: descriptor.source,
16211
+ names: descriptor.names,
16212
+ optional: descriptor.optional,
16213
+ factory: (context) => this.createProxyTools(descriptor, context)
16214
+ })),
16215
+ channels: snapshot.channels.map((descriptor) => ({
16216
+ pluginId: descriptor.pluginId,
16217
+ source: descriptor.source,
16218
+ channel: {
16219
+ id: descriptor.channel.id,
16220
+ ...descriptor.channel.meta ? { meta: descriptor.channel.meta } : {},
16221
+ ...descriptor.channel.capabilities ? { capabilities: descriptor.channel.capabilities } : {},
16222
+ ...descriptor.channel.configSchema ? { configSchema: descriptor.channel.configSchema } : {},
16223
+ outbound: this.createChannelOutbound(descriptor)
16224
+ }
16225
+ })),
16226
+ providers: snapshot.providers.map((descriptor) => ({
16227
+ pluginId: descriptor.pluginId,
16228
+ source: descriptor.source,
16229
+ provider: descriptor.provider
16230
+ })),
16231
+ ncpAgentRuntimes: snapshot.ncpAgentRuntimes.map((descriptor) => ({
16232
+ pluginId: descriptor.pluginId,
16233
+ source: descriptor.source,
16234
+ kind: descriptor.kind,
16235
+ label: descriptor.label,
16236
+ createRuntime: (runtimeParams) => new ExtensionHostProxyRuntime({
16237
+ client: this.client,
16238
+ kind: descriptor.kind,
16239
+ runtimeParams
16240
+ }),
16241
+ createRuntimeForEntry: descriptor.supportsEntryRuntime ? ({ entry, runtimeParams }) => new ExtensionHostProxyRuntime({
16242
+ client: this.client,
16243
+ kind: descriptor.kind,
16244
+ entry,
16245
+ runtimeParams
16246
+ }) : void 0,
16247
+ describeSessionType: async (describeParams) => await this.client.describeRuntime({
16248
+ kind: descriptor.kind,
16249
+ describeParams
16250
+ }),
16251
+ describeSessionTypeForEntry: descriptor.supportsEntryDescription ? async ({ entry, describeParams }) => await this.client.describeRuntime({
16252
+ kind: descriptor.kind,
16253
+ entry,
16254
+ describeParams
16255
+ }) : void 0
16256
+ })),
16257
+ resolvedTools: snapshot.tools.flatMap((descriptor) => descriptor.previews.map((preview) => this.createProxyTool(descriptor, preview.name, {}, preview)))
16258
+ });
16259
+ createChannelOutbound = (descriptor) => ({
16260
+ ...descriptor.channel.hasOutboundText ? { sendText: async (ctx) => await this.client.sendChannelOutbound({
16261
+ pluginId: descriptor.pluginId,
16262
+ channelId: descriptor.channel.id,
16263
+ kind: "text",
16264
+ cfg: ctx.cfg,
16265
+ to: ctx.to,
16266
+ text: ctx.text,
16267
+ accountId: ctx.accountId
16268
+ }) } : {},
16269
+ ...descriptor.channel.hasOutboundPayload ? { sendPayload: async (ctx) => await this.client.sendChannelOutbound({
16270
+ pluginId: descriptor.pluginId,
16271
+ channelId: descriptor.channel.id,
16272
+ kind: "payload",
16273
+ cfg: ctx.cfg,
16274
+ to: ctx.to,
16275
+ text: ctx.text,
16276
+ payload: ctx.payload,
16277
+ accountId: ctx.accountId
16278
+ }) } : {}
16279
+ });
16280
+ createProxyTools = (descriptor, context) => descriptor.names.map((alias) => {
16281
+ const preview = pickPreview({
16282
+ descriptor,
16283
+ alias
16284
+ });
16285
+ return this.createProxyTool(descriptor, alias, context, preview ?? void 0);
16286
+ });
16287
+ createProxyTool = (descriptor, alias, context, preview) => ({
16288
+ name: preview?.name ?? alias,
16289
+ ...preview?.label ? { label: preview.label } : {},
16290
+ description: preview?.description ?? `Extension tool '${alias}' from ${descriptor.pluginId}`,
16291
+ parameters: normalizeSchema(preview?.parameters),
16292
+ execute: async (toolCallIdOrParams, maybeParams) => {
16293
+ const hasToolCallId = typeof toolCallIdOrParams === "string";
16294
+ const params = hasToolCallId ? maybeParams ?? {} : toolCallIdOrParams;
16295
+ const toolCallId = hasToolCallId ? toolCallIdOrParams : void 0;
16296
+ return stringifyToolResult(await this.client.executeTool({
16297
+ registrationId: descriptor.registrationId,
16298
+ alias,
16299
+ context,
16300
+ params,
16301
+ toolCallId
16302
+ }));
16303
+ }
16304
+ });
16305
+ };
16306
+ //#endregion
16307
+ //#region src/cli/shared/services/extension-host-client.service.ts
16308
+ function resolveChildEntryPath() {
16309
+ const sourcePath = fileURLToPath(new URL("./extension-host-child.service.ts", import.meta.url));
16310
+ if (existsSync(sourcePath)) return sourcePath;
16311
+ return fileURLToPath(new URL("./extension-host-child.service.js", import.meta.url));
16312
+ }
16313
+ var ExtensionHostClient = class {
16314
+ child = null;
16315
+ nextRequestId = 1;
16316
+ nextStreamId = 1;
16317
+ pending = /* @__PURE__ */ new Map();
16318
+ runtimeStreams = /* @__PURE__ */ new Map();
16319
+ proxyRegistry = new ExtensionHostProxyRegistryService(this);
16320
+ constructor(params = {}) {
16321
+ this.params = params;
16322
+ }
16323
+ load = async (request) => await this.request("load", request);
16324
+ startPluginGateways = async (config) => {
16325
+ await this.request("channel.startGateways", { config });
16326
+ };
16327
+ stopPluginGateways = async () => {
16328
+ await this.request("channel.stopGateways", void 0);
16329
+ };
16330
+ executeTool = async (request) => await this.request("tool.execute", request);
16331
+ sendChannelOutbound = async (request) => await this.request("channel.outbound", request);
16332
+ describeRuntime = async (request) => await this.request("runtime.describe", request);
16333
+ createProxyPluginRegistry = (snapshot) => this.proxyRegistry.createPluginRegistry(snapshot);
16334
+ runRuntimeStream = async function* (params) {
16335
+ const { entry, input, kind, runtimeParams, signal } = params;
16336
+ const streamId = `runtime-${this.nextStreamId++}`;
16337
+ const state = {
16338
+ queue: [],
16339
+ wake: null,
16340
+ onMetadata: runtimeParams.setSessionMetadata,
16341
+ applyStateBatch: async (events) => {
16342
+ await runtimeParams.stateManager.dispatchBatch(events);
16343
+ }
16344
+ };
16345
+ this.runtimeStreams.set(streamId, state);
16346
+ const abortListener = () => {
16347
+ this.request("runtime.abort", {
16348
+ streamId,
16349
+ reason: typeof signal?.reason === "string" ? signal.reason : void 0
16350
+ }).catch(() => void 0);
16351
+ };
16352
+ signal?.addEventListener("abort", abortListener, { once: true });
16353
+ await this.request("runtime.run", {
16354
+ streamId,
16355
+ kind,
16356
+ entry,
16357
+ runtimeParams: {
16358
+ sessionId: runtimeParams.sessionId,
16359
+ agentId: runtimeParams.agentId,
16360
+ sessionMetadata: runtimeParams.sessionMetadata,
16361
+ ...runtimeParams.resolveTools ? { resolvedTools: Array.from(runtimeParams.resolveTools(input) ?? []) } : {}
16362
+ },
16363
+ input
16364
+ });
16365
+ try {
16366
+ while (true) {
16367
+ const next = await this.nextRuntimeStreamItem(state);
16368
+ if (next === null) return;
16369
+ if (next instanceof Error) throw next;
16370
+ yield next;
16371
+ }
16372
+ } finally {
16373
+ signal?.removeEventListener("abort", abortListener);
16374
+ this.runtimeStreams.delete(streamId);
16375
+ }
16376
+ };
16377
+ dispose = async () => {
16378
+ await this.stopPluginGateways().catch(() => void 0);
16379
+ this.child?.kill();
16380
+ this.child = null;
16381
+ this.rejectAll(/* @__PURE__ */ new Error("Extension host disposed"));
16382
+ };
16383
+ request = async (method, payload) => {
16384
+ const child = this.ensureChild();
16385
+ const id = this.nextRequestId++;
16386
+ const promise = new Promise((resolve, reject) => {
16387
+ this.pending.set(id, {
16388
+ resolve: (value) => resolve(value),
16389
+ reject
16390
+ });
16391
+ });
16392
+ child.send?.({
16393
+ type: "request",
16394
+ id,
16395
+ method,
16396
+ payload
16397
+ });
16398
+ return await promise;
16399
+ };
16400
+ ensureChild = () => {
16401
+ if (this.child) return this.child;
16402
+ const child = fork(resolveChildEntryPath(), [], {
16403
+ env: process.env,
16404
+ execArgv: process.execArgv,
16405
+ stdio: [
16406
+ "ignore",
16407
+ "inherit",
16408
+ "inherit",
16409
+ "ipc"
16410
+ ]
16411
+ });
16412
+ child.on("message", (message) => this.handleMessage(message));
16413
+ child.on("exit", (code, signal) => {
16414
+ this.child = null;
16415
+ this.rejectAll(/* @__PURE__ */ new Error(`Extension host exited: code=${code ?? "null"} signal=${signal ?? "null"}`));
16416
+ });
16417
+ child.on("error", (error) => {
16418
+ this.rejectAll(error);
16419
+ });
16420
+ this.child = child;
16421
+ return child;
16422
+ };
16423
+ handleMessage = (message) => {
16424
+ if (message.type === "response") {
16425
+ const pending = this.pending.get(message.id);
16426
+ if (!pending) return;
16427
+ this.pending.delete(message.id);
16428
+ if (message.ok) {
16429
+ pending.resolve(message.payload);
16430
+ return;
16431
+ }
16432
+ pending.reject(new Error(message.error));
16433
+ return;
16434
+ }
16435
+ if (message.type !== "event") return;
16436
+ if (message.event === "load.progress") {
16437
+ this.params.onProgress?.(message.payload);
16438
+ return;
16439
+ }
16440
+ if (message.event === "runtime.state.dispatchBatch") {
16441
+ this.runtimeStreams.get(message.payload.streamId)?.applyStateBatch(message.payload.events);
16442
+ return;
16443
+ }
16444
+ const state = this.runtimeStreams.get(message.payload.streamId);
16445
+ if (!state) return;
16446
+ if (message.event === "runtime.event") {
16447
+ this.pushRuntimeStreamItem(state, message.payload.event);
16448
+ return;
16449
+ }
16450
+ if (message.event === "runtime.metadata") {
16451
+ state.onMetadata(message.payload.metadata);
16452
+ return;
16453
+ }
16454
+ if (message.event === "runtime.error") {
16455
+ this.pushRuntimeStreamItem(state, new Error(message.payload.error));
16456
+ return;
16457
+ }
16458
+ if (message.event === "runtime.done") this.pushRuntimeStreamItem(state, null);
16459
+ };
16460
+ pushRuntimeStreamItem = (state, item) => {
16461
+ state.queue.push(item);
16462
+ state.wake?.();
16463
+ state.wake = null;
16464
+ };
16465
+ nextRuntimeStreamItem = async (state) => {
16466
+ const queued = state.queue.shift();
16467
+ if (queued !== void 0) return queued;
16468
+ await new Promise((resolve) => {
16469
+ state.wake = resolve;
16470
+ });
16471
+ return state.queue.shift() ?? null;
16472
+ };
16473
+ rejectAll = (error) => {
16474
+ for (const pending of this.pending.values()) pending.reject(error);
16475
+ this.pending.clear();
16476
+ for (const state of this.runtimeStreams.values()) this.pushRuntimeStreamItem(state, error);
16477
+ };
16478
+ };
16479
+ //#endregion
16204
16480
  //#region src/cli/shared/services/runtime/runtime-command.service.ts
16205
16481
  const { getApiBase, getConfigPath: getConfigPath$1, getProvider, getProviderName, getWorkspacePath: getWorkspacePath$1, loadConfig: loadConfig$1, LiteLLMProvider, MessageBus: MessageBus$1, resolveConfigSecrets: resolveConfigSecrets$1, SessionManager: SessionManager$1, parseAgentScopedSessionKey: parseAgentScopedSessionKey$1 } = NextclawCore;
16206
16482
  function createSkillsLoader(workspace) {
@@ -16237,6 +16513,12 @@ var RuntimeCommandService = class {
16237
16513
  };
16238
16514
  let runtimeState = null;
16239
16515
  const bootstrapStatus = createBootstrapStatus(shellContext.config.remote.enabled);
16516
+ const extensionHost = new ExtensionHostClient({ onProgress: ({ loadedPluginCount, totalPluginCount }) => {
16517
+ bootstrapStatus.markPluginHydrationProgress({
16518
+ loadedPluginCount,
16519
+ totalPluginCount
16520
+ });
16521
+ } });
16240
16522
  const ncpSessionRealtimeBridge = createServiceNcpSessionRealtimeBridge({ sessionManager: shellContext.sessionManager });
16241
16523
  const marketplaceInstaller = new ServiceMarketplaceInstaller({
16242
16524
  applyLiveConfigReload,
@@ -16303,7 +16585,8 @@ var RuntimeCommandService = class {
16303
16585
  configureGatewayPluginRuntime({
16304
16586
  gateway,
16305
16587
  state: gatewayRuntimeState,
16306
- getLiveUiNcpAgent: () => this.liveUiNcpAgent
16588
+ getLiveUiNcpAgent: () => this.liveUiNcpAgent,
16589
+ extensionHost
16307
16590
  });
16308
16591
  console.log("✓ Capability hydration: scheduled in background");
16309
16592
  await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
@@ -16329,6 +16612,7 @@ var RuntimeCommandService = class {
16329
16612
  setLiveUiNcpAgent: (ncpAgent) => {
16330
16613
  this.liveUiNcpAgent = ncpAgent;
16331
16614
  },
16615
+ extensionHost,
16332
16616
  wakeFromRestartSentinel: async () => await this.wakeFromRestartSentinel({
16333
16617
  bus: gateway.bus,
16334
16618
  sessionManager: gateway.sessionManager
@@ -16365,6 +16649,8 @@ var RuntimeCommandService = class {
16365
16649
  uiStartup,
16366
16650
  remoteModule: gateway.remoteModule,
16367
16651
  runtimeState
16652
+ }).finally(async () => {
16653
+ await extensionHost.dispose();
16368
16654
  })
16369
16655
  });
16370
16656
  logStartupTrace("service.start_gateway.end");
@@ -18216,7 +18502,7 @@ var WorkspaceManager = class {
18216
18502
  return this.exitWithError(`Bridge source not found. Try reinstalling ${APP_NAME}.`);
18217
18503
  };
18218
18504
  assertCommandAvailable = (command) => {
18219
- if (which(command)) return;
18505
+ if (findExecutableOnPath(command)) return;
18220
18506
  this.exitWithError(`${command} not found. Please install Node.js >= 18.`);
18221
18507
  };
18222
18508
  runBridgeCommand = (cwd, args, step) => {