nextclaw 0.8.61 → 0.9.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/dist/cli/index.js +358 -67
- package/package.json +4 -4
- package/ui-dist/assets/ChannelsList-BWQYaOuz.js +1 -0
- package/ui-dist/assets/ChatPage-DsIuF-TC.js +32 -0
- package/ui-dist/assets/DocBrowser-D4pXQDKt.js +1 -0
- package/ui-dist/assets/MarketplacePage-Cj1HGbGe.js +49 -0
- package/ui-dist/assets/ModelConfig-C2f3h7yq.js +1 -0
- package/ui-dist/assets/{ProvidersList-D3hfY5U7.js → ProvidersList-DUdQEMNV.js} +1 -1
- package/ui-dist/assets/RuntimeConfig-BnR60m9J.js +1 -0
- package/ui-dist/assets/{SecretsConfig-BFDeNvwV.js → SecretsConfig-CXV017VN.js} +2 -2
- package/ui-dist/assets/SessionsConfig-DsgHhuYe.js +2 -0
- package/ui-dist/assets/{card-BREZdIEb.js → card-B7d3Z9Y7.js} +1 -1
- package/ui-dist/assets/index-Dp6x_DHf.js +2 -0
- package/ui-dist/assets/index-DsQL2mtx.css +1 -0
- package/ui-dist/assets/{label-CzMB2yjV.js → label-Dlq0AZXx.js} +1 -1
- package/ui-dist/assets/{logos-vVtRUuoo.js → logos-CSTJsbua.js} +1 -1
- package/ui-dist/assets/{page-layout-B07kdurB.js → page-layout-DeBYaT_B.js} +1 -1
- package/ui-dist/assets/provider-models-y4mUDcGF.js +1 -0
- package/ui-dist/assets/{switch-Cr6cemeT.js → switch-DwDE9PLr.js} +1 -1
- package/ui-dist/assets/{tabs-custom-BzcvgsvR.js → tabs-custom-DqY_ht59.js} +1 -1
- package/ui-dist/assets/useConfig-BiM-oO9i.js +6 -0
- package/ui-dist/assets/{useConfirmDialog-Dc5WHCUf.js → useConfirmDialog-BEFIWczY.js} +2 -2
- package/ui-dist/assets/{vendor-Dh04PGww.js → vendor-Ylg6Wdt_.js} +84 -69
- package/ui-dist/index.html +3 -3
- package/dist/chunk-4I7WMYPU.js +0 -2289
- package/dist/chunk-HXRBJNWA.js +0 -2324
- package/dist/chunk-PIG2O4DT.js +0 -2095
- package/dist/chunk-RTVGGPPW.js +0 -2307
- package/dist/chunk-X77K7Y4T.js +0 -2316
- package/dist/chunk-XAY6UDOR.js +0 -2282
- package/dist/chunk-Z2YDZBBE.js +0 -2325
- package/ui-dist/assets/ChannelsList-B6N0kXyK.js +0 -1
- package/ui-dist/assets/ChatPage-DsDFvVQX.js +0 -32
- package/ui-dist/assets/CronConfig-Cbz6V8MU.js +0 -1
- package/ui-dist/assets/DocBrowser-hQzP4Iai.js +0 -1
- package/ui-dist/assets/MarketplacePage-DMoWoU1y.js +0 -49
- package/ui-dist/assets/ModelConfig-BXjF-qbA.js +0 -1
- package/ui-dist/assets/RuntimeConfig-DJ7qIejp.js +0 -1
- package/ui-dist/assets/SessionsConfig-CJF7lPkX.js +0 -2
- package/ui-dist/assets/index-C5cdRzpO.css +0 -1
- package/ui-dist/assets/index-uTbQ-MAY.js +0 -2
- package/ui-dist/assets/useConfig-B4Y6cGwc.js +0 -6
package/dist/cli/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
getWorkspacePath as getWorkspacePath6,
|
|
15
15
|
expandHome as expandHome2,
|
|
16
16
|
MessageBus as MessageBus2,
|
|
17
|
-
AgentLoop
|
|
17
|
+
AgentLoop,
|
|
18
18
|
ProviderManager as ProviderManager2,
|
|
19
19
|
resolveConfigSecrets as resolveConfigSecrets3,
|
|
20
20
|
APP_NAME as APP_NAME4,
|
|
@@ -598,6 +598,7 @@ function loadPluginRegistry(config2, workspaceDir) {
|
|
|
598
598
|
],
|
|
599
599
|
reservedChannelIds: [],
|
|
600
600
|
reservedProviderIds: PROVIDERS.map((provider) => provider.name),
|
|
601
|
+
reservedEngineKinds: ["native"],
|
|
601
602
|
logger: {
|
|
602
603
|
info: (message) => console.log(message),
|
|
603
604
|
warn: (message) => console.warn(message),
|
|
@@ -620,6 +621,12 @@ function toExtensionRegistry(pluginRegistry) {
|
|
|
620
621
|
channel: channel.channel,
|
|
621
622
|
source: channel.source
|
|
622
623
|
})),
|
|
624
|
+
engines: pluginRegistry.engines.map((engine) => ({
|
|
625
|
+
extensionId: engine.pluginId,
|
|
626
|
+
kind: engine.kind,
|
|
627
|
+
factory: engine.factory,
|
|
628
|
+
source: engine.source
|
|
629
|
+
})),
|
|
623
630
|
diagnostics: pluginRegistry.diagnostics.map((diag) => ({
|
|
624
631
|
level: diag.level,
|
|
625
632
|
message: diag.message,
|
|
@@ -685,7 +692,8 @@ var PluginCommands = class {
|
|
|
685
692
|
config: config2,
|
|
686
693
|
workspaceDir,
|
|
687
694
|
reservedChannelIds: [],
|
|
688
|
-
reservedProviderIds: PROVIDERS.map((provider) => provider.name)
|
|
695
|
+
reservedProviderIds: PROVIDERS.map((provider) => provider.name),
|
|
696
|
+
reservedEngineKinds: ["native"]
|
|
689
697
|
});
|
|
690
698
|
const list = opts.enabled ? report.plugins.filter((plugin) => plugin.status === "loaded") : report.plugins;
|
|
691
699
|
if (opts.json) {
|
|
@@ -729,6 +737,9 @@ var PluginCommands = class {
|
|
|
729
737
|
if (plugin.providerIds.length > 0) {
|
|
730
738
|
console.log(` providers: ${plugin.providerIds.join(", ")}`);
|
|
731
739
|
}
|
|
740
|
+
if (plugin.engineKinds.length > 0) {
|
|
741
|
+
console.log(` engines: ${plugin.engineKinds.join(", ")}`);
|
|
742
|
+
}
|
|
732
743
|
if (plugin.error) {
|
|
733
744
|
console.log(` error: ${plugin.error}`);
|
|
734
745
|
}
|
|
@@ -742,7 +753,8 @@ var PluginCommands = class {
|
|
|
742
753
|
config: config2,
|
|
743
754
|
workspaceDir,
|
|
744
755
|
reservedChannelIds: [],
|
|
745
|
-
reservedProviderIds: PROVIDERS.map((provider) => provider.name)
|
|
756
|
+
reservedProviderIds: PROVIDERS.map((provider) => provider.name),
|
|
757
|
+
reservedEngineKinds: ["native"]
|
|
746
758
|
});
|
|
747
759
|
const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
|
|
748
760
|
if (!plugin) {
|
|
@@ -778,6 +790,9 @@ var PluginCommands = class {
|
|
|
778
790
|
if (plugin.providerIds.length > 0) {
|
|
779
791
|
lines.push(`Providers: ${plugin.providerIds.join(", ")}`);
|
|
780
792
|
}
|
|
793
|
+
if (plugin.engineKinds.length > 0) {
|
|
794
|
+
lines.push(`Engines: ${plugin.engineKinds.join(", ")}`);
|
|
795
|
+
}
|
|
781
796
|
if (plugin.error) {
|
|
782
797
|
lines.push(`Error: ${plugin.error}`);
|
|
783
798
|
}
|
|
@@ -823,7 +838,8 @@ var PluginCommands = class {
|
|
|
823
838
|
config: config2,
|
|
824
839
|
workspaceDir,
|
|
825
840
|
reservedChannelIds: [],
|
|
826
|
-
reservedProviderIds: PROVIDERS.map((provider) => provider.name)
|
|
841
|
+
reservedProviderIds: PROVIDERS.map((provider) => provider.name),
|
|
842
|
+
reservedEngineKinds: ["native"]
|
|
827
843
|
});
|
|
828
844
|
const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
|
|
829
845
|
if (opts.keepConfig) {
|
|
@@ -1005,7 +1021,8 @@ var PluginCommands = class {
|
|
|
1005
1021
|
config: config2,
|
|
1006
1022
|
workspaceDir,
|
|
1007
1023
|
reservedChannelIds: [],
|
|
1008
|
-
reservedProviderIds: PROVIDERS.map((provider) => provider.name)
|
|
1024
|
+
reservedProviderIds: PROVIDERS.map((provider) => provider.name),
|
|
1025
|
+
reservedEngineKinds: ["native"]
|
|
1009
1026
|
});
|
|
1010
1027
|
const pluginErrors = report.plugins.filter((plugin) => plugin.status === "error");
|
|
1011
1028
|
const diagnostics = report.diagnostics.filter((diag) => diag.level === "error");
|
|
@@ -2230,6 +2247,8 @@ import { startUiServer } from "@nextclaw/server";
|
|
|
2230
2247
|
import { closeSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync3, openSync, rmSync as rmSync3 } from "fs";
|
|
2231
2248
|
import { dirname, isAbsolute as isAbsolute2, join as join4, relative, resolve as resolve7 } from "path";
|
|
2232
2249
|
import { spawn as spawn2 } from "child_process";
|
|
2250
|
+
import { request as httpRequest } from "http";
|
|
2251
|
+
import { request as httpsRequest } from "https";
|
|
2233
2252
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2234
2253
|
import chokidar from "chokidar";
|
|
2235
2254
|
|
|
@@ -2676,7 +2695,7 @@ var MissingProvider = class extends LLMProvider {
|
|
|
2676
2695
|
setDefaultModel(model) {
|
|
2677
2696
|
this.defaultModel = model;
|
|
2678
2697
|
}
|
|
2679
|
-
async chat() {
|
|
2698
|
+
async chat(_params) {
|
|
2680
2699
|
throw new Error("No API key configured yet. Configure provider credentials in UI and retry.");
|
|
2681
2700
|
}
|
|
2682
2701
|
getDefaultModel() {
|
|
@@ -2686,7 +2705,7 @@ var MissingProvider = class extends LLMProvider {
|
|
|
2686
2705
|
|
|
2687
2706
|
// src/cli/commands/agent-runtime-pool.ts
|
|
2688
2707
|
import {
|
|
2689
|
-
|
|
2708
|
+
NativeAgentEngine,
|
|
2690
2709
|
AgentRouteResolver,
|
|
2691
2710
|
getWorkspacePath as getWorkspacePath4,
|
|
2692
2711
|
parseAgentScopedSessionKey
|
|
@@ -2695,6 +2714,19 @@ function normalizeAgentId(value) {
|
|
|
2695
2714
|
const text = (value ?? "").trim().toLowerCase();
|
|
2696
2715
|
return text || "main";
|
|
2697
2716
|
}
|
|
2717
|
+
function normalizeEngineKind(value) {
|
|
2718
|
+
if (typeof value !== "string") {
|
|
2719
|
+
return "native";
|
|
2720
|
+
}
|
|
2721
|
+
const kind = value.trim().toLowerCase();
|
|
2722
|
+
return kind || "native";
|
|
2723
|
+
}
|
|
2724
|
+
function toRecord(value) {
|
|
2725
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2726
|
+
return void 0;
|
|
2727
|
+
}
|
|
2728
|
+
return value;
|
|
2729
|
+
}
|
|
2698
2730
|
function resolveAgentProfiles(config2) {
|
|
2699
2731
|
const defaults = config2.agents.defaults;
|
|
2700
2732
|
const listed = Array.isArray(config2.agents.list) ? config2.agents.list.map((entry) => ({
|
|
@@ -2702,6 +2734,8 @@ function resolveAgentProfiles(config2) {
|
|
|
2702
2734
|
default: entry.default,
|
|
2703
2735
|
workspace: entry.workspace,
|
|
2704
2736
|
model: entry.model,
|
|
2737
|
+
engine: entry.engine,
|
|
2738
|
+
engineConfig: toRecord(entry.engineConfig),
|
|
2705
2739
|
maxToolIterations: entry.maxToolIterations,
|
|
2706
2740
|
contextTokens: entry.contextTokens
|
|
2707
2741
|
})).filter((entry) => Boolean(entry.id)) : [];
|
|
@@ -2720,6 +2754,8 @@ function resolveAgentProfiles(config2) {
|
|
|
2720
2754
|
id: entry.id,
|
|
2721
2755
|
workspace: getWorkspacePath4(entry.workspace ?? defaults.workspace),
|
|
2722
2756
|
model: entry.model ?? defaults.model,
|
|
2757
|
+
engine: normalizeEngineKind(entry.engine ?? defaults.engine),
|
|
2758
|
+
engineConfig: entry.engineConfig ?? toRecord(defaults.engineConfig),
|
|
2723
2759
|
maxIterations: entry.maxToolIterations ?? defaults.maxToolIterations,
|
|
2724
2760
|
contextTokens: entry.contextTokens ?? defaults.contextTokens
|
|
2725
2761
|
}));
|
|
@@ -2751,32 +2787,48 @@ var GatewayAgentRuntimePool = class {
|
|
|
2751
2787
|
this.rebuild(this.options.config);
|
|
2752
2788
|
}
|
|
2753
2789
|
async processDirect(params) {
|
|
2754
|
-
const message = {
|
|
2755
|
-
channel: params.channel ?? "cli",
|
|
2756
|
-
senderId: "user",
|
|
2757
|
-
chatId: params.chatId ?? "direct",
|
|
2790
|
+
const { message, route } = this.resolveDirectRoute({
|
|
2758
2791
|
content: params.content,
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
const route = this.routeResolver.resolveInbound({
|
|
2765
|
-
message,
|
|
2766
|
-
forcedAgentId,
|
|
2767
|
-
sessionKeyOverride: params.sessionKey
|
|
2792
|
+
sessionKey: params.sessionKey,
|
|
2793
|
+
channel: params.channel,
|
|
2794
|
+
chatId: params.chatId,
|
|
2795
|
+
metadata: params.metadata,
|
|
2796
|
+
agentId: params.agentId
|
|
2768
2797
|
});
|
|
2769
2798
|
const runtime2 = this.resolveRuntime(route.agentId);
|
|
2770
|
-
return runtime2.
|
|
2799
|
+
return runtime2.engine.processDirect({
|
|
2771
2800
|
content: params.content,
|
|
2772
2801
|
sessionKey: route.sessionKey,
|
|
2773
2802
|
channel: message.channel,
|
|
2774
2803
|
chatId: message.chatId,
|
|
2775
2804
|
metadata: message.metadata,
|
|
2805
|
+
abortSignal: params.abortSignal,
|
|
2776
2806
|
onAssistantDelta: params.onAssistantDelta,
|
|
2777
2807
|
onSessionEvent: params.onSessionEvent
|
|
2778
2808
|
});
|
|
2779
2809
|
}
|
|
2810
|
+
supportsTurnAbort(params) {
|
|
2811
|
+
const { route } = this.resolveDirectRoute({
|
|
2812
|
+
content: "",
|
|
2813
|
+
sessionKey: params.sessionKey,
|
|
2814
|
+
channel: params.channel,
|
|
2815
|
+
chatId: params.chatId,
|
|
2816
|
+
metadata: params.metadata,
|
|
2817
|
+
agentId: params.agentId
|
|
2818
|
+
});
|
|
2819
|
+
const runtime2 = this.resolveRuntime(route.agentId);
|
|
2820
|
+
if (runtime2.engine.kind !== "native") {
|
|
2821
|
+
return {
|
|
2822
|
+
supported: false,
|
|
2823
|
+
agentId: route.agentId,
|
|
2824
|
+
reason: `engine "${runtime2.engine.kind}" does not support server-side stop yet`
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
return {
|
|
2828
|
+
supported: true,
|
|
2829
|
+
agentId: route.agentId
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2780
2832
|
async run() {
|
|
2781
2833
|
this.running = true;
|
|
2782
2834
|
while (this.running) {
|
|
@@ -2790,7 +2842,7 @@ var GatewayAgentRuntimePool = class {
|
|
|
2790
2842
|
sessionKeyOverride: explicitSessionKey
|
|
2791
2843
|
});
|
|
2792
2844
|
const runtime2 = this.resolveRuntime(route.agentId);
|
|
2793
|
-
await runtime2.
|
|
2845
|
+
await runtime2.engine.handleInbound({
|
|
2794
2846
|
message,
|
|
2795
2847
|
sessionKey: route.sessionKey,
|
|
2796
2848
|
publishResponse: true
|
|
@@ -2813,6 +2865,27 @@ var GatewayAgentRuntimePool = class {
|
|
|
2813
2865
|
const trimmed = value.trim();
|
|
2814
2866
|
return trimmed || void 0;
|
|
2815
2867
|
}
|
|
2868
|
+
resolveDirectRoute(params) {
|
|
2869
|
+
const message = {
|
|
2870
|
+
channel: params.channel ?? "cli",
|
|
2871
|
+
senderId: "user",
|
|
2872
|
+
chatId: params.chatId ?? "direct",
|
|
2873
|
+
content: params.content,
|
|
2874
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
2875
|
+
attachments: [],
|
|
2876
|
+
metadata: params.metadata ?? {}
|
|
2877
|
+
};
|
|
2878
|
+
const forcedAgentId = this.readString(params.agentId) ?? parseAgentScopedSessionKey(params.sessionKey)?.agentId ?? void 0;
|
|
2879
|
+
const route = this.routeResolver.resolveInbound({
|
|
2880
|
+
message,
|
|
2881
|
+
forcedAgentId,
|
|
2882
|
+
sessionKeyOverride: params.sessionKey
|
|
2883
|
+
});
|
|
2884
|
+
return {
|
|
2885
|
+
message,
|
|
2886
|
+
route
|
|
2887
|
+
};
|
|
2888
|
+
}
|
|
2816
2889
|
resolveRuntime(agentId) {
|
|
2817
2890
|
const normalized = normalizeAgentId(agentId);
|
|
2818
2891
|
const runtime2 = this.runtimes.get(normalized);
|
|
@@ -2825,34 +2898,82 @@ var GatewayAgentRuntimePool = class {
|
|
|
2825
2898
|
}
|
|
2826
2899
|
throw new Error("No agent runtime available");
|
|
2827
2900
|
}
|
|
2901
|
+
createNativeEngineFactory() {
|
|
2902
|
+
return (context) => new NativeAgentEngine({
|
|
2903
|
+
bus: context.bus,
|
|
2904
|
+
providerManager: context.providerManager,
|
|
2905
|
+
workspace: context.workspace,
|
|
2906
|
+
model: context.model,
|
|
2907
|
+
maxIterations: context.maxIterations,
|
|
2908
|
+
contextTokens: context.contextTokens,
|
|
2909
|
+
braveApiKey: context.braveApiKey,
|
|
2910
|
+
execConfig: context.execConfig,
|
|
2911
|
+
cronService: context.cronService,
|
|
2912
|
+
restrictToWorkspace: context.restrictToWorkspace,
|
|
2913
|
+
sessionManager: context.sessionManager,
|
|
2914
|
+
contextConfig: context.contextConfig,
|
|
2915
|
+
gatewayController: context.gatewayController,
|
|
2916
|
+
config: context.config,
|
|
2917
|
+
extensionRegistry: context.extensionRegistry,
|
|
2918
|
+
resolveMessageToolHints: context.resolveMessageToolHints,
|
|
2919
|
+
agentId: context.agentId
|
|
2920
|
+
});
|
|
2921
|
+
}
|
|
2922
|
+
resolveEngineFactory(kind) {
|
|
2923
|
+
if (kind === "native") {
|
|
2924
|
+
return this.createNativeEngineFactory();
|
|
2925
|
+
}
|
|
2926
|
+
const registrations = this.options.extensionRegistry?.engines ?? [];
|
|
2927
|
+
const matched = registrations.find((entry) => normalizeEngineKind(entry.kind) === kind);
|
|
2928
|
+
if (matched) {
|
|
2929
|
+
return matched.factory;
|
|
2930
|
+
}
|
|
2931
|
+
console.warn(`[engine] unknown engine "${kind}", fallback to "native"`);
|
|
2932
|
+
return this.createNativeEngineFactory();
|
|
2933
|
+
}
|
|
2934
|
+
createEngine(profile, config2) {
|
|
2935
|
+
const kind = normalizeEngineKind(profile.engine);
|
|
2936
|
+
const factory = this.resolveEngineFactory(kind);
|
|
2937
|
+
const context = {
|
|
2938
|
+
agentId: profile.id,
|
|
2939
|
+
workspace: profile.workspace,
|
|
2940
|
+
model: profile.model,
|
|
2941
|
+
maxIterations: profile.maxIterations,
|
|
2942
|
+
contextTokens: profile.contextTokens,
|
|
2943
|
+
engineConfig: profile.engineConfig,
|
|
2944
|
+
bus: this.options.bus,
|
|
2945
|
+
providerManager: this.options.providerManager,
|
|
2946
|
+
sessionManager: this.options.sessionManager,
|
|
2947
|
+
cronService: this.options.cronService,
|
|
2948
|
+
restrictToWorkspace: this.options.restrictToWorkspace,
|
|
2949
|
+
braveApiKey: this.options.braveApiKey,
|
|
2950
|
+
execConfig: this.options.execConfig,
|
|
2951
|
+
contextConfig: this.options.contextConfig,
|
|
2952
|
+
gatewayController: this.options.gatewayController,
|
|
2953
|
+
config: config2,
|
|
2954
|
+
extensionRegistry: this.options.extensionRegistry,
|
|
2955
|
+
resolveMessageToolHints: this.options.resolveMessageToolHints
|
|
2956
|
+
};
|
|
2957
|
+
try {
|
|
2958
|
+
return factory(context);
|
|
2959
|
+
} catch (error) {
|
|
2960
|
+
if (kind === "native") {
|
|
2961
|
+
throw error;
|
|
2962
|
+
}
|
|
2963
|
+
console.warn(`[engine] failed to create "${kind}" for agent "${profile.id}": ${String(error)}`);
|
|
2964
|
+
return this.createNativeEngineFactory()(context);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2828
2967
|
rebuild(config2) {
|
|
2829
2968
|
const profiles = resolveAgentProfiles(config2);
|
|
2830
2969
|
const configuredDefault = this.readString(config2.agents.list.find((entry) => entry.default)?.id);
|
|
2831
2970
|
this.defaultAgentId = configuredDefault ?? profiles[0]?.id ?? "main";
|
|
2832
2971
|
const nextRuntimes = /* @__PURE__ */ new Map();
|
|
2833
2972
|
for (const profile of profiles) {
|
|
2834
|
-
const
|
|
2835
|
-
bus: this.options.bus,
|
|
2836
|
-
providerManager: this.options.providerManager,
|
|
2837
|
-
workspace: profile.workspace,
|
|
2838
|
-
model: profile.model,
|
|
2839
|
-
maxIterations: profile.maxIterations,
|
|
2840
|
-
contextTokens: profile.contextTokens,
|
|
2841
|
-
braveApiKey: this.options.braveApiKey,
|
|
2842
|
-
execConfig: this.options.execConfig,
|
|
2843
|
-
cronService: this.options.cronService,
|
|
2844
|
-
restrictToWorkspace: this.options.restrictToWorkspace,
|
|
2845
|
-
sessionManager: this.options.sessionManager,
|
|
2846
|
-
contextConfig: this.options.contextConfig,
|
|
2847
|
-
gatewayController: this.options.gatewayController,
|
|
2848
|
-
config: config2,
|
|
2849
|
-
extensionRegistry: this.options.extensionRegistry,
|
|
2850
|
-
resolveMessageToolHints: this.options.resolveMessageToolHints,
|
|
2851
|
-
agentId: profile.id
|
|
2852
|
-
});
|
|
2973
|
+
const engine = this.createEngine(profile, config2);
|
|
2853
2974
|
nextRuntimes.set(profile.id, {
|
|
2854
2975
|
id: profile.id,
|
|
2855
|
-
|
|
2976
|
+
engine
|
|
2856
2977
|
});
|
|
2857
2978
|
}
|
|
2858
2979
|
this.runtimes = nextRuntimes;
|
|
@@ -2887,6 +3008,21 @@ function createSkillsLoader(workspace) {
|
|
|
2887
3008
|
}
|
|
2888
3009
|
return new ctor(workspace);
|
|
2889
3010
|
}
|
|
3011
|
+
function isAbortError(error) {
|
|
3012
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
3013
|
+
return true;
|
|
3014
|
+
}
|
|
3015
|
+
if (error instanceof Error) {
|
|
3016
|
+
if (error.name === "AbortError") {
|
|
3017
|
+
return true;
|
|
3018
|
+
}
|
|
3019
|
+
const message = error.message.toLowerCase();
|
|
3020
|
+
if (message.includes("aborted") || message.includes("abort")) {
|
|
3021
|
+
return true;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
return false;
|
|
3025
|
+
}
|
|
2890
3026
|
var ServiceCommands = class {
|
|
2891
3027
|
constructor(deps) {
|
|
2892
3028
|
this.deps = deps;
|
|
@@ -3279,7 +3415,7 @@ var ServiceCommands = class {
|
|
|
3279
3415
|
}
|
|
3280
3416
|
await this.printPublicUiUrls(parsedUi.host, parsedUi.port);
|
|
3281
3417
|
console.log(`Logs: ${existing.logPath}`);
|
|
3282
|
-
|
|
3418
|
+
this.printServiceControlHints();
|
|
3283
3419
|
return;
|
|
3284
3420
|
}
|
|
3285
3421
|
if (existing) {
|
|
@@ -3306,12 +3442,20 @@ var ServiceCommands = class {
|
|
|
3306
3442
|
return;
|
|
3307
3443
|
}
|
|
3308
3444
|
const healthUrl = `${apiUrl}/health`;
|
|
3309
|
-
|
|
3445
|
+
let readiness = await this.waitForBackgroundServiceReady({
|
|
3310
3446
|
pid: child.pid,
|
|
3311
3447
|
healthUrl,
|
|
3312
3448
|
timeoutMs: 8e3
|
|
3313
3449
|
});
|
|
3314
|
-
if (!
|
|
3450
|
+
if (!readiness.ready && process.platform === "win32" && isProcessRunning(child.pid)) {
|
|
3451
|
+
console.warn("Warning: Background service is still running but not ready after 8s; waiting up to 20s more on Windows.");
|
|
3452
|
+
readiness = await this.waitForBackgroundServiceReady({
|
|
3453
|
+
pid: child.pid,
|
|
3454
|
+
healthUrl,
|
|
3455
|
+
timeoutMs: 2e4
|
|
3456
|
+
});
|
|
3457
|
+
}
|
|
3458
|
+
if (!readiness.ready) {
|
|
3315
3459
|
if (isProcessRunning(child.pid)) {
|
|
3316
3460
|
try {
|
|
3317
3461
|
process.kill(child.pid, "SIGTERM");
|
|
@@ -3320,7 +3464,8 @@ var ServiceCommands = class {
|
|
|
3320
3464
|
}
|
|
3321
3465
|
}
|
|
3322
3466
|
clearServiceState();
|
|
3323
|
-
|
|
3467
|
+
const hint = readiness.lastProbeError ? ` Last probe error: ${readiness.lastProbeError}` : "";
|
|
3468
|
+
console.error(`Error: Failed to start background service. Check logs: ${logPath}.${hint}`);
|
|
3324
3469
|
return;
|
|
3325
3470
|
}
|
|
3326
3471
|
child.unref();
|
|
@@ -3339,7 +3484,7 @@ var ServiceCommands = class {
|
|
|
3339
3484
|
console.log(`API: ${apiUrl}`);
|
|
3340
3485
|
await this.printPublicUiUrls(uiConfig.host, uiConfig.port);
|
|
3341
3486
|
console.log(`Logs: ${logPath}`);
|
|
3342
|
-
|
|
3487
|
+
this.printServiceControlHints();
|
|
3343
3488
|
if (options.open) {
|
|
3344
3489
|
openBrowser(uiUrl);
|
|
3345
3490
|
}
|
|
@@ -3377,31 +3522,80 @@ var ServiceCommands = class {
|
|
|
3377
3522
|
}
|
|
3378
3523
|
async waitForBackgroundServiceReady(params) {
|
|
3379
3524
|
const startedAt = Date.now();
|
|
3525
|
+
let lastProbeError = null;
|
|
3380
3526
|
while (Date.now() - startedAt < params.timeoutMs) {
|
|
3381
3527
|
if (!isProcessRunning(params.pid)) {
|
|
3382
|
-
return false;
|
|
3528
|
+
return { ready: false, lastProbeError };
|
|
3383
3529
|
}
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
await new Promise((resolve10) => setTimeout(resolve10, 200));
|
|
3394
|
-
continue;
|
|
3395
|
-
}
|
|
3396
|
-
await new Promise((resolve10) => setTimeout(resolve10, 300));
|
|
3397
|
-
if (isProcessRunning(params.pid)) {
|
|
3398
|
-
return true;
|
|
3399
|
-
}
|
|
3400
|
-
} catch {
|
|
3530
|
+
const probe = await this.probeHealthEndpoint(params.healthUrl);
|
|
3531
|
+
if (!probe.healthy) {
|
|
3532
|
+
lastProbeError = probe.error;
|
|
3533
|
+
await new Promise((resolve10) => setTimeout(resolve10, 200));
|
|
3534
|
+
continue;
|
|
3535
|
+
}
|
|
3536
|
+
await new Promise((resolve10) => setTimeout(resolve10, 300));
|
|
3537
|
+
if (isProcessRunning(params.pid)) {
|
|
3538
|
+
return { ready: true, lastProbeError: null };
|
|
3401
3539
|
}
|
|
3402
3540
|
await new Promise((resolve10) => setTimeout(resolve10, 200));
|
|
3403
3541
|
}
|
|
3404
|
-
return false;
|
|
3542
|
+
return { ready: false, lastProbeError };
|
|
3543
|
+
}
|
|
3544
|
+
async probeHealthEndpoint(healthUrl) {
|
|
3545
|
+
let parsed;
|
|
3546
|
+
try {
|
|
3547
|
+
parsed = new URL(healthUrl);
|
|
3548
|
+
} catch {
|
|
3549
|
+
return { healthy: false, error: "invalid health URL" };
|
|
3550
|
+
}
|
|
3551
|
+
const requestImpl = parsed.protocol === "https:" ? httpsRequest : httpRequest;
|
|
3552
|
+
return new Promise((resolve10) => {
|
|
3553
|
+
const req = requestImpl(
|
|
3554
|
+
{
|
|
3555
|
+
protocol: parsed.protocol,
|
|
3556
|
+
hostname: parsed.hostname,
|
|
3557
|
+
port: parsed.port ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80,
|
|
3558
|
+
method: "GET",
|
|
3559
|
+
path: `${parsed.pathname}${parsed.search}`,
|
|
3560
|
+
timeout: 1e3,
|
|
3561
|
+
headers: { Accept: "application/json" }
|
|
3562
|
+
},
|
|
3563
|
+
(res) => {
|
|
3564
|
+
const chunks = [];
|
|
3565
|
+
res.on("data", (chunk) => {
|
|
3566
|
+
if (typeof chunk === "string") {
|
|
3567
|
+
chunks.push(Buffer.from(chunk));
|
|
3568
|
+
return;
|
|
3569
|
+
}
|
|
3570
|
+
chunks.push(chunk);
|
|
3571
|
+
});
|
|
3572
|
+
res.on("end", () => {
|
|
3573
|
+
if ((res.statusCode ?? 0) < 200 || (res.statusCode ?? 0) >= 300) {
|
|
3574
|
+
resolve10({ healthy: false, error: `http ${res.statusCode ?? "unknown"}` });
|
|
3575
|
+
return;
|
|
3576
|
+
}
|
|
3577
|
+
try {
|
|
3578
|
+
const payload = JSON.parse(Buffer.concat(chunks).toString("utf-8"));
|
|
3579
|
+
const healthy = payload?.ok === true && payload?.data?.status === "ok";
|
|
3580
|
+
if (!healthy) {
|
|
3581
|
+
resolve10({ healthy: false, error: "health payload not ok" });
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3584
|
+
resolve10({ healthy: true, error: null });
|
|
3585
|
+
} catch {
|
|
3586
|
+
resolve10({ healthy: false, error: "invalid health JSON response" });
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
}
|
|
3590
|
+
);
|
|
3591
|
+
req.on("timeout", () => {
|
|
3592
|
+
req.destroy(new Error("probe timeout"));
|
|
3593
|
+
});
|
|
3594
|
+
req.on("error", (error) => {
|
|
3595
|
+
resolve10({ healthy: false, error: error.message || String(error) });
|
|
3596
|
+
});
|
|
3597
|
+
req.end();
|
|
3598
|
+
});
|
|
3405
3599
|
}
|
|
3406
3600
|
createMissingProvider(config2) {
|
|
3407
3601
|
return this.makeMissingProvider(config2);
|
|
@@ -3449,10 +3643,23 @@ var ServiceCommands = class {
|
|
|
3449
3643
|
console.log(`Public UI (if firewall/NAT allows): ${publicBase}`);
|
|
3450
3644
|
console.log(`Public API (if firewall/NAT allows): ${publicBase}/api`);
|
|
3451
3645
|
}
|
|
3646
|
+
printServiceControlHints() {
|
|
3647
|
+
console.log("Service controls:");
|
|
3648
|
+
console.log(` - Check status: ${APP_NAME2} status`);
|
|
3649
|
+
console.log(` - If you need to stop the service, run: ${APP_NAME2} stop`);
|
|
3650
|
+
}
|
|
3452
3651
|
startUiIfEnabled(uiConfig, uiStaticDir, cronService, runtimePool) {
|
|
3453
3652
|
if (!uiConfig.enabled) {
|
|
3454
3653
|
return;
|
|
3455
3654
|
}
|
|
3655
|
+
const activeTurnRuns = /* @__PURE__ */ new Map();
|
|
3656
|
+
const resolveStopCapability = (params) => runtimePool.supportsTurnAbort({
|
|
3657
|
+
sessionKey: params.sessionKey,
|
|
3658
|
+
agentId: params.agentId,
|
|
3659
|
+
channel: params.channel,
|
|
3660
|
+
chatId: params.chatId,
|
|
3661
|
+
metadata: params.metadata
|
|
3662
|
+
});
|
|
3456
3663
|
const resolveChatTurnParams = (params) => {
|
|
3457
3664
|
const sessionKey = typeof params.sessionKey === "string" && params.sessionKey.trim().length > 0 ? params.sessionKey.trim() : `ui:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 8)}`;
|
|
3458
3665
|
const inferredAgentId = typeof params.agentId === "string" && params.agentId.trim().length > 0 ? params.agentId.trim() : parseAgentScopedSessionKey2(sessionKey)?.agentId;
|
|
@@ -3461,7 +3668,9 @@ var ServiceCommands = class {
|
|
|
3461
3668
|
if (model) {
|
|
3462
3669
|
metadata.model = model;
|
|
3463
3670
|
}
|
|
3671
|
+
const runId = typeof params.runId === "string" && params.runId.trim().length > 0 ? params.runId.trim() : void 0;
|
|
3464
3672
|
return {
|
|
3673
|
+
runId,
|
|
3465
3674
|
sessionKey,
|
|
3466
3675
|
inferredAgentId,
|
|
3467
3676
|
model,
|
|
@@ -3494,6 +3703,20 @@ var ServiceCommands = class {
|
|
|
3494
3703
|
}
|
|
3495
3704
|
},
|
|
3496
3705
|
chatRuntime: {
|
|
3706
|
+
getCapabilities: async (params) => {
|
|
3707
|
+
const sessionKey = typeof params.sessionKey === "string" && params.sessionKey.trim().length > 0 ? params.sessionKey.trim() : `ui:capability:${Date.now().toString(36)}`;
|
|
3708
|
+
const capability = resolveStopCapability({
|
|
3709
|
+
sessionKey,
|
|
3710
|
+
agentId: typeof params.agentId === "string" ? params.agentId : void 0,
|
|
3711
|
+
channel: "ui",
|
|
3712
|
+
chatId: "web-ui",
|
|
3713
|
+
metadata: {}
|
|
3714
|
+
});
|
|
3715
|
+
return {
|
|
3716
|
+
stopSupported: capability.supported,
|
|
3717
|
+
...capability.reason ? { stopReason: capability.reason } : {}
|
|
3718
|
+
};
|
|
3719
|
+
},
|
|
3497
3720
|
processTurn: async (params) => {
|
|
3498
3721
|
const resolved = resolveChatTurnParams(params);
|
|
3499
3722
|
const reply = await runtimePool.processDirect({
|
|
@@ -3511,9 +3734,60 @@ var ServiceCommands = class {
|
|
|
3511
3734
|
model: resolved.model
|
|
3512
3735
|
});
|
|
3513
3736
|
},
|
|
3737
|
+
stopTurn: async (params) => {
|
|
3738
|
+
const runId = typeof params.runId === "string" ? params.runId.trim() : "";
|
|
3739
|
+
if (!runId) {
|
|
3740
|
+
return {
|
|
3741
|
+
stopped: false,
|
|
3742
|
+
runId: "",
|
|
3743
|
+
reason: "runId is required"
|
|
3744
|
+
};
|
|
3745
|
+
}
|
|
3746
|
+
const active = activeTurnRuns.get(runId);
|
|
3747
|
+
if (!active) {
|
|
3748
|
+
return {
|
|
3749
|
+
stopped: false,
|
|
3750
|
+
runId,
|
|
3751
|
+
...typeof params.sessionKey === "string" && params.sessionKey.trim().length > 0 ? { sessionKey: params.sessionKey.trim() } : {},
|
|
3752
|
+
reason: "run not found or already completed"
|
|
3753
|
+
};
|
|
3754
|
+
}
|
|
3755
|
+
const requestedSessionKey = typeof params.sessionKey === "string" ? params.sessionKey.trim() : "";
|
|
3756
|
+
if (requestedSessionKey && requestedSessionKey !== active.sessionKey) {
|
|
3757
|
+
return {
|
|
3758
|
+
stopped: false,
|
|
3759
|
+
runId,
|
|
3760
|
+
sessionKey: active.sessionKey,
|
|
3761
|
+
reason: "session key mismatch"
|
|
3762
|
+
};
|
|
3763
|
+
}
|
|
3764
|
+
active.controller.abort(new Error("chat turn stopped by user"));
|
|
3765
|
+
return {
|
|
3766
|
+
stopped: true,
|
|
3767
|
+
runId,
|
|
3768
|
+
sessionKey: active.sessionKey
|
|
3769
|
+
};
|
|
3770
|
+
},
|
|
3514
3771
|
processTurnStream: async function* (params) {
|
|
3515
3772
|
const resolved = resolveChatTurnParams(params);
|
|
3773
|
+
const runId = resolved.runId ?? `run-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
3774
|
+
const stopCapability = resolveStopCapability({
|
|
3775
|
+
sessionKey: resolved.sessionKey,
|
|
3776
|
+
agentId: resolved.inferredAgentId,
|
|
3777
|
+
channel: resolved.channel,
|
|
3778
|
+
chatId: resolved.chatId,
|
|
3779
|
+
metadata: resolved.metadata
|
|
3780
|
+
});
|
|
3781
|
+
const controller = stopCapability.supported ? new AbortController() : null;
|
|
3782
|
+
if (controller) {
|
|
3783
|
+
activeTurnRuns.set(runId, {
|
|
3784
|
+
controller,
|
|
3785
|
+
sessionKey: resolved.sessionKey,
|
|
3786
|
+
...resolved.inferredAgentId ? { agentId: resolved.inferredAgentId } : {}
|
|
3787
|
+
});
|
|
3788
|
+
}
|
|
3516
3789
|
const queue = [];
|
|
3790
|
+
const assistantDeltaParts = [];
|
|
3517
3791
|
let waiter = null;
|
|
3518
3792
|
const push = (event) => {
|
|
3519
3793
|
queue.push(event);
|
|
@@ -3528,10 +3802,12 @@ var ServiceCommands = class {
|
|
|
3528
3802
|
chatId: resolved.chatId,
|
|
3529
3803
|
agentId: resolved.inferredAgentId,
|
|
3530
3804
|
metadata: resolved.metadata,
|
|
3805
|
+
...controller ? { abortSignal: controller.signal } : {},
|
|
3531
3806
|
onAssistantDelta: (delta) => {
|
|
3532
3807
|
if (typeof delta !== "string" || delta.length === 0) {
|
|
3533
3808
|
return;
|
|
3534
3809
|
}
|
|
3810
|
+
assistantDeltaParts.push(delta);
|
|
3535
3811
|
push({ type: "delta", delta });
|
|
3536
3812
|
},
|
|
3537
3813
|
onSessionEvent: (event) => {
|
|
@@ -3567,7 +3843,22 @@ var ServiceCommands = class {
|
|
|
3567
3843
|
})
|
|
3568
3844
|
});
|
|
3569
3845
|
}).catch((error) => {
|
|
3846
|
+
if ((controller?.signal.aborted ?? false) || isAbortError(error)) {
|
|
3847
|
+
const partialReply = assistantDeltaParts.join("");
|
|
3848
|
+
push({
|
|
3849
|
+
type: "final",
|
|
3850
|
+
result: buildTurnResult({
|
|
3851
|
+
reply: partialReply,
|
|
3852
|
+
sessionKey: resolved.sessionKey,
|
|
3853
|
+
inferredAgentId: resolved.inferredAgentId,
|
|
3854
|
+
model: resolved.model
|
|
3855
|
+
})
|
|
3856
|
+
});
|
|
3857
|
+
return;
|
|
3858
|
+
}
|
|
3570
3859
|
push({ type: "error", error: String(error) });
|
|
3860
|
+
}).finally(() => {
|
|
3861
|
+
activeTurnRuns.delete(runId);
|
|
3571
3862
|
});
|
|
3572
3863
|
while (true) {
|
|
3573
3864
|
if (queue.length === 0) {
|
|
@@ -4455,7 +4746,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
4455
4746
|
defaultProvider: provider,
|
|
4456
4747
|
config: config2
|
|
4457
4748
|
});
|
|
4458
|
-
const agentLoop = new
|
|
4749
|
+
const agentLoop = new AgentLoop({
|
|
4459
4750
|
bus,
|
|
4460
4751
|
providerManager,
|
|
4461
4752
|
workspace,
|