@nextclaw/kernel 0.4.3 → 0.5.1-beta.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/index.d.ts +111 -97
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1136 -873
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as getUnsignedUpdateManifest, r as serializeUnsignedUpdateManifest, t as UpdateManifestReader } from "./update-manifest.types-C0qPrjGQ.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
+
import { APP_NAME, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, CLEAR_THINKING_TOKENS, CONTEXT_COMPACTION_METADATA_KEY, ConfigSchema, ContextCompactionService, ContextWindowBudgetService, CronService, CronTool, DEFAULT_PANELS_DIR, DEFAULT_SERVICE_APPS_DIR, DEFAULT_SESSION_SEARCH_LIMIT, DEFAULT_WORKSPACE_REPOSITORY_IDENTITY_RESOLVER, EditFileTool, ExecTool, ExtensionChannelAdapter, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderRegistry, ReadFileTool, RequestedSkillsMetadataReader, SILENT_REPLY_TOKEN, SessionProjectContextResolver, SessionSearchService, SkillsLoader, THINKING_LEVELS, WebFetchTool, WebSearchTool, WriteFileTool, buildCompressingCompactionCheckpoint, buildConfigSchema, buildContextWindowSnapshot, buildReloadPlan, buildSessionRequestToolResult, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createCompletedSessionRequest, createFailedSessionRequest, createRunningSessionRequest, createRuntimeChildEnv, createTypingStopControlMessage, diffConfigPaths, ensureDir, evaluateSilentReply, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getSessionsPath, getWorkspacePath, getWorkspacePathFromConfig, isNextclawControlMessage, loadConfig, mergeExtensionConfigView, modelSupportsVision, normalizeAgentProfileId, normalizeInlineSecretRefs, normalizeModelThinkingCapability, normalizeProviderModelConfig, normalizeToolParams, parseAgentScopedSessionKey, parseThinkingLevel, readCompressedContextCompactionCheckpoint, readOptionalString, readParentSessionId, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveNextclawSelfManageGuidePaths, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, sanitizeOutboundAssistantContent, saveConfig, summarizeSessionRequestTask, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
3
4
|
import { NcpEventType, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
|
|
4
|
-
import { APP_NAME, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, CLEAR_THINKING_TOKENS, CONTEXT_COMPACTION_METADATA_KEY, ChannelManager, ChannelManager as ChannelManager$1, ConfigSchema, ContextCompactionService, ContextWindowBudgetService, CronService, CronTool, DEFAULT_PANELS_DIR, DEFAULT_SERVICE_APPS_DIR, DEFAULT_SESSION_SEARCH_LIMIT, DEFAULT_WORKSPACE_REPOSITORY_IDENTITY_RESOLVER, EditFileTool, ExecTool, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderRegistry, ReadFileTool, RequestedSkillsMetadataReader, SILENT_REPLY_TOKEN, SessionProjectContextResolver, SessionSearchManager, SkillsLoader, THINKING_LEVELS, WebFetchTool, WebSearchTool, WriteFileTool, buildCompressingCompactionCheckpoint, buildConfigSchema, buildContextWindowSnapshot, buildReloadPlan, buildSessionRequestToolResult, buildToolCatalogEntries, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createCompletedSessionRequest, createFailedSessionRequest, createRunningSessionRequest, createRuntimeChildEnv, createTypingStopControlMessage, diffConfigPaths, ensureDir, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getSessionsPath, getWorkspacePath, getWorkspacePathFromConfig, loadConfig, mergeExtensionConfigView, modelSupportsVision, normalizeInlineSecretRefs, normalizeProviderModelConfig, normalizeToolParams, parseAgentScopedSessionKey, parseThinkingLevel, readCompressedContextCompactionCheckpoint, readOptionalString, readParentSessionId, readSessionProjectRoot, redactConfigObject, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveNextclawSelfManageGuidePaths, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, summarizeSessionRequestTask, toDisposable, toExtensionConfigView } from "@nextclaw/core";
|
|
5
5
|
import { LocalAssetStore, buildAssetContentPath, buildNcpUserContent, buildOpenAiFunctionTool, ncpMessageToOpenAiMessages, validateToolArgs } from "@nextclaw/ncp-agent-runtime";
|
|
6
6
|
import { createHash, createHmac, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
7
|
-
import { EventBus, Ingress, eventKeys, ingressKeys } from "@nextclaw/shared";
|
|
7
|
+
import { EventBus, Ingress, eventKeys, ingressKeys, isRuntimeDefaultModelValue, normalizeRuntimeModelSelectionMode } from "@nextclaw/shared";
|
|
8
8
|
import { catchError, from, lastValueFrom, tap } from "rxjs";
|
|
9
9
|
import { appendFileSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve } from "node:path";
|
|
@@ -21,34 +21,55 @@ import { StdioRuntimeConfigResolver, StdioRuntimeNcpAgentRuntime, probeStdioRunt
|
|
|
21
21
|
import { DefaultNcpAgentRuntime } from "@nextclaw/ncp-agent-runtime-next";
|
|
22
22
|
//#region src/managers/agent.manager.ts
|
|
23
23
|
var AgentManager = class {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
constructor(configManager, options = {}) {
|
|
25
|
+
this.configManager = configManager;
|
|
26
|
+
this.options = options;
|
|
27
|
+
}
|
|
28
|
+
listAgents = () => resolveEffectiveAgentProfiles(this.loadConfig());
|
|
29
|
+
getAgent = (agentId) => findEffectiveAgentProfile(this.loadConfig(), agentId);
|
|
30
|
+
getDefaultAgentId = () => resolveDefaultAgentProfileId(this.loadConfig());
|
|
31
|
+
resolveAgentProfile = (agentId) => this.resolveAgentProfileFromConfig(this.loadConfig(), agentId);
|
|
32
|
+
resolveAgentProfileForRun = (params = {}) => this.resolveAgentProfile(params.agentId ?? params.storedAgentId ?? readRequestedAgentId(params.requestMetadata ?? {}) ?? null);
|
|
33
|
+
createAgent = async (input) => {
|
|
34
|
+
const agent = createAgentProfile(input, {
|
|
35
|
+
configPath: this.options.configPath,
|
|
36
|
+
initializeHomeDirectory: this.options.initializeAgentHomeDirectory
|
|
37
|
+
});
|
|
38
|
+
await this.reloadLiveConfig();
|
|
39
|
+
return agent;
|
|
40
|
+
};
|
|
41
|
+
updateAgent = async (input) => {
|
|
42
|
+
const agent = updateAgentProfile(input, { configPath: this.options.configPath });
|
|
43
|
+
await this.reloadLiveConfig();
|
|
44
|
+
return agent;
|
|
45
|
+
};
|
|
46
|
+
removeAgent = async (agentId) => {
|
|
47
|
+
const removed = removeAgentProfile(agentId, { configPath: this.options.configPath });
|
|
48
|
+
if (removed) await this.reloadLiveConfig();
|
|
49
|
+
return removed;
|
|
50
|
+
};
|
|
51
|
+
loadConfig = () => this.configManager?.loadConfig() ?? loadConfig(this.options.configPath);
|
|
52
|
+
reloadLiveConfig = async () => {
|
|
53
|
+
await this.configManager?.applyLiveConfigReload();
|
|
54
|
+
};
|
|
55
|
+
resolveAgentProfileFromConfig = (config, agentId) => {
|
|
56
|
+
const profile = findEffectiveAgentProfile(config, normalizeAgentProfileId(agentId) || resolveDefaultAgentProfileId(config)) ?? findEffectiveAgentProfile(config, resolveDefaultAgentProfileId(config));
|
|
57
|
+
if (!profile) throw new Error(`default agent profile not found: ${BUILTIN_MAIN_AGENT_ID}`);
|
|
58
|
+
const contextTokens = profile.contextTokens ?? config.agents.defaults.contextTokens;
|
|
59
|
+
return {
|
|
60
|
+
...profile,
|
|
61
|
+
contextTokens,
|
|
62
|
+
model: profile.model ?? config.agents.defaults.model,
|
|
63
|
+
reservedContextTokens: ContextWindowBudgetService.resolveReservedContextTokens({
|
|
64
|
+
contextTokens,
|
|
65
|
+
configuredReservedContextTokens: profile.reservedContextTokens ?? config.agents.defaults.reservedContextTokens
|
|
66
|
+
})
|
|
67
|
+
};
|
|
50
68
|
};
|
|
51
69
|
};
|
|
70
|
+
function readRequestedAgentId(metadata) {
|
|
71
|
+
return normalizeAgentProfileId(metadata.agent_id) || normalizeAgentProfileId(metadata.agentId) || null;
|
|
72
|
+
}
|
|
52
73
|
//#endregion
|
|
53
74
|
//#region src/utils/ncp-message-bridge.utils.ts
|
|
54
75
|
function normalizeString$1(value) {
|
|
@@ -256,23 +277,6 @@ function shouldRefreshContextWindowImmediately(event) {
|
|
|
256
277
|
//#region src/features/context-compaction/services/context-compaction-preflight.service.ts
|
|
257
278
|
const SUMMARY_MAX_TOKENS = 4e3;
|
|
258
279
|
const SUMMARY_SOURCE_MAX_CHARS = 12e4;
|
|
259
|
-
function readRequestedAgentId$1(metadata) {
|
|
260
|
-
return normalizeString$1(metadata.agent_id)?.toLowerCase() ?? normalizeString$1(metadata.agentId)?.toLowerCase() ?? null;
|
|
261
|
-
}
|
|
262
|
-
function resolveCompactionProfile(params) {
|
|
263
|
-
const { config, requestMetadata, storedAgentId } = params;
|
|
264
|
-
const { defaults } = config.agents;
|
|
265
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
266
|
-
const profile = findEffectiveAgentProfile(config, normalizeString$1(storedAgentId)?.toLowerCase() ?? readRequestedAgentId$1(requestMetadata) ?? defaultAgentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
267
|
-
return {
|
|
268
|
-
contextTokens: profile?.contextTokens ?? defaults.contextTokens,
|
|
269
|
-
model: profile?.model ?? defaults.model,
|
|
270
|
-
reservedContextTokens: ContextWindowBudgetService.resolveReservedContextTokens({
|
|
271
|
-
contextTokens: profile?.contextTokens ?? defaults.contextTokens,
|
|
272
|
-
configuredReservedContextTokens: profile?.reservedContextTokens ?? defaults.reservedContextTokens
|
|
273
|
-
})
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
280
|
function mergeInputMessages(params) {
|
|
277
281
|
const messages = params.sessionMessages.map((message) => structuredClone(message));
|
|
278
282
|
const seen = new Set(messages.map((message) => message.id));
|
|
@@ -304,13 +308,13 @@ function buildContextWindowSnapshotFromBudget(params) {
|
|
|
304
308
|
var ContextCompactionPreflightService = class {
|
|
305
309
|
compactionService = new ContextCompactionService();
|
|
306
310
|
contextWindowBudgetService = new ContextWindowBudgetService();
|
|
307
|
-
constructor(
|
|
308
|
-
this.
|
|
311
|
+
constructor(agentManager, providerManager) {
|
|
312
|
+
this.agentManager = agentManager;
|
|
313
|
+
this.providerManager = providerManager;
|
|
309
314
|
}
|
|
310
315
|
preview = (params) => {
|
|
311
316
|
const { requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
312
|
-
const profile = resolveCompactionProfile({
|
|
313
|
-
config: this.options.configManager.loadConfig(),
|
|
317
|
+
const profile = this.resolveCompactionProfile({
|
|
314
318
|
requestMetadata,
|
|
315
319
|
storedAgentId
|
|
316
320
|
});
|
|
@@ -331,8 +335,7 @@ var ContextCompactionPreflightService = class {
|
|
|
331
335
|
};
|
|
332
336
|
begin = (params) => {
|
|
333
337
|
const { inputMessages, requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
334
|
-
const profile = resolveCompactionProfile({
|
|
335
|
-
config: this.options.configManager.loadConfig(),
|
|
338
|
+
const profile = this.resolveCompactionProfile({
|
|
336
339
|
requestMetadata,
|
|
337
340
|
storedAgentId
|
|
338
341
|
});
|
|
@@ -429,9 +432,9 @@ var ContextCompactionPreflightService = class {
|
|
|
429
432
|
};
|
|
430
433
|
};
|
|
431
434
|
generateSummary = async (params) => {
|
|
432
|
-
if (!this.
|
|
435
|
+
if (!this.providerManager) throw new Error("context compaction summary generation requires a provider manager");
|
|
433
436
|
const { messages, model } = params;
|
|
434
|
-
const summary = (await this.
|
|
437
|
+
const summary = (await this.providerManager.chat({
|
|
435
438
|
model,
|
|
436
439
|
maxTokens: SUMMARY_MAX_TOKENS,
|
|
437
440
|
messages: [{
|
|
@@ -458,14 +461,24 @@ var ContextCompactionPreflightService = class {
|
|
|
458
461
|
if (!summary) throw new Error("context compaction summary is empty");
|
|
459
462
|
return summary;
|
|
460
463
|
};
|
|
464
|
+
resolveCompactionProfile = (params) => {
|
|
465
|
+
const profile = this.agentManager.resolveAgentProfileForRun({
|
|
466
|
+
requestMetadata: params.requestMetadata,
|
|
467
|
+
storedAgentId: params.storedAgentId
|
|
468
|
+
});
|
|
469
|
+
return {
|
|
470
|
+
contextTokens: profile.contextTokens,
|
|
471
|
+
model: profile.model,
|
|
472
|
+
reservedContextTokens: profile.reservedContextTokens
|
|
473
|
+
};
|
|
474
|
+
};
|
|
461
475
|
};
|
|
462
476
|
//#endregion
|
|
463
477
|
//#region src/features/context-compaction/managers/context-compaction.manager.ts
|
|
464
478
|
var ContextWindowPreviewManager = class {
|
|
465
479
|
preflightService;
|
|
466
|
-
constructor(
|
|
467
|
-
this.
|
|
468
|
-
this.preflightService = new ContextCompactionPreflightService({ configManager: options.configManager });
|
|
480
|
+
constructor(agentManager) {
|
|
481
|
+
this.preflightService = new ContextCompactionPreflightService(agentManager);
|
|
469
482
|
}
|
|
470
483
|
preview = (params) => {
|
|
471
484
|
const { requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
@@ -482,12 +495,9 @@ var ContextWindowPreviewManager = class {
|
|
|
482
495
|
//#region src/managers/agent-run-context-compaction.manager.ts
|
|
483
496
|
var AgentRunContextCompactionManager = class {
|
|
484
497
|
preflightService;
|
|
485
|
-
constructor(
|
|
498
|
+
constructor(agentManager, providerManager, sessionManager) {
|
|
486
499
|
this.sessionManager = sessionManager;
|
|
487
|
-
this.preflightService = new ContextCompactionPreflightService(
|
|
488
|
-
configManager,
|
|
489
|
-
providerManager
|
|
490
|
-
});
|
|
500
|
+
this.preflightService = new ContextCompactionPreflightService(agentManager, providerManager);
|
|
491
501
|
}
|
|
492
502
|
runPreflight = async (input) => {
|
|
493
503
|
const beginResult = this.preflightService.begin({
|
|
@@ -519,7 +529,7 @@ var AgentRunContextCompactionManager = class {
|
|
|
519
529
|
//#region src/managers/agent-run-request.manager.ts
|
|
520
530
|
function toAgentRunRequest(envelope) {
|
|
521
531
|
const metadata = envelope.metadata ?? {};
|
|
522
|
-
const peerId = readOptionalString$
|
|
532
|
+
const peerId = readOptionalString$10(envelope.peerId);
|
|
523
533
|
const requestMetadata = {
|
|
524
534
|
agentRuntimeId: metadata.agentRuntimeId,
|
|
525
535
|
agentId: metadata.agentId,
|
|
@@ -532,7 +542,7 @@ function toAgentRunRequest(envelope) {
|
|
|
532
542
|
thinkingEffort: metadata.thinkingEffort
|
|
533
543
|
};
|
|
534
544
|
if (Array.isArray(envelope.content)) {
|
|
535
|
-
const sessionId = readOptionalString$
|
|
545
|
+
const sessionId = readOptionalString$10(envelope.sessionId);
|
|
536
546
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
537
547
|
return {
|
|
538
548
|
...requestMetadata,
|
|
@@ -550,8 +560,8 @@ function toAgentRunRequest(envelope) {
|
|
|
550
560
|
}
|
|
551
561
|
const sourceMessage = envelope.message;
|
|
552
562
|
if (!sourceMessage) throw new Error("Invalid agent run send request.");
|
|
553
|
-
const envelopeSessionId = readOptionalString$
|
|
554
|
-
const messageSessionId = readOptionalString$
|
|
563
|
+
const envelopeSessionId = readOptionalString$10(envelope.sessionId);
|
|
564
|
+
const messageSessionId = readOptionalString$10(sourceMessage.sessionId);
|
|
555
565
|
const sessionId = envelopeSessionId ?? messageSessionId;
|
|
556
566
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
557
567
|
const message = {
|
|
@@ -570,7 +580,7 @@ function toAgentRunRequest(envelope) {
|
|
|
570
580
|
message
|
|
571
581
|
};
|
|
572
582
|
}
|
|
573
|
-
function readOptionalString$
|
|
583
|
+
function readOptionalString$10(value) {
|
|
574
584
|
if (typeof value !== "string") return;
|
|
575
585
|
return value.trim() || void 0;
|
|
576
586
|
}
|
|
@@ -592,8 +602,9 @@ function readMessageTask(message) {
|
|
|
592
602
|
var AgentRunRequestManager = class {
|
|
593
603
|
cleanups = [];
|
|
594
604
|
started = false;
|
|
595
|
-
constructor(agentRuntimeManager, configManager, contextProviderManager, eventBus, ingress, sessionManager, sessionRunManager, toolProviderManager) {
|
|
605
|
+
constructor(agentRuntimeManager, agentManager, configManager, contextProviderManager, eventBus, ingress, sessionManager, sessionRunManager, toolProviderManager) {
|
|
596
606
|
this.agentRuntimeManager = agentRuntimeManager;
|
|
607
|
+
this.agentManager = agentManager;
|
|
597
608
|
this.configManager = configManager;
|
|
598
609
|
this.contextProviderManager = contextProviderManager;
|
|
599
610
|
this.eventBus = eventBus;
|
|
@@ -675,7 +686,7 @@ var AgentRunRequestManager = class {
|
|
|
675
686
|
}
|
|
676
687
|
})();
|
|
677
688
|
const model = request.model ?? session.model ?? this.configManager.getDefaultModel();
|
|
678
|
-
const agentId = request.agentId ?? session.agentId ??
|
|
689
|
+
const agentId = request.agentId ?? session.agentId ?? this.agentManager.getDefaultAgentId();
|
|
679
690
|
const spec = {
|
|
680
691
|
runId: activeRun.runId,
|
|
681
692
|
agentId,
|
|
@@ -692,13 +703,16 @@ var AgentRunRequestManager = class {
|
|
|
692
703
|
const contextBlocks = await this.contextProviderManager.buildContext(providerRequest);
|
|
693
704
|
const tools = await this.toolProviderManager.buildTools(providerRequest);
|
|
694
705
|
let messageCompletedSeen = false;
|
|
706
|
+
let runtimeFailed = false;
|
|
695
707
|
lastValueFrom(from(runtime.run(spec, {
|
|
696
708
|
contextBlocks,
|
|
709
|
+
session,
|
|
697
710
|
sessionRun,
|
|
698
711
|
signal: activeRun.signal,
|
|
699
712
|
tools
|
|
700
713
|
})).pipe(tap((event) => {
|
|
701
714
|
const eventsToPublish = [];
|
|
715
|
+
if (event.type === NcpEventType.RunError) runtimeFailed = true;
|
|
702
716
|
if (event.type === NcpEventType.MessageCompleted) messageCompletedSeen = true;
|
|
703
717
|
if (event.type === NcpEventType.RunFinished && !messageCompletedSeen) {
|
|
704
718
|
const message = findCompletedAssistantMessage(sessionRun.getSnapshot().messages, event.payload.messageId);
|
|
@@ -719,6 +733,7 @@ var AgentRunRequestManager = class {
|
|
|
719
733
|
source: "agent-run-request"
|
|
720
734
|
});
|
|
721
735
|
}), catchError(async (error) => {
|
|
736
|
+
runtimeFailed = true;
|
|
722
737
|
const event = {
|
|
723
738
|
type: NcpEventType.RunError,
|
|
724
739
|
payload: {
|
|
@@ -733,7 +748,14 @@ var AgentRunRequestManager = class {
|
|
|
733
748
|
emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
734
749
|
source: "agent-run-request"
|
|
735
750
|
});
|
|
736
|
-
})), { defaultValue: void 0 })
|
|
751
|
+
})), { defaultValue: void 0 }).finally(() => {
|
|
752
|
+
if (!runtimeFailed) return;
|
|
753
|
+
this.agentRuntimeManager.disposeRuntime({
|
|
754
|
+
agentRuntimeId: session.agentRuntimeId,
|
|
755
|
+
session,
|
|
756
|
+
sessionRun
|
|
757
|
+
}).catch(() => void 0);
|
|
758
|
+
});
|
|
737
759
|
return {
|
|
738
760
|
sessionId: session.sessionId,
|
|
739
761
|
userMessageId: message.id,
|
|
@@ -749,6 +771,128 @@ var AgentRunRequestManager = class {
|
|
|
749
771
|
//#region src/configs/agent-runtime.config.ts
|
|
750
772
|
const DEFAULT_AGENT_RUNTIME_ENTRY_ID = "native";
|
|
751
773
|
//#endregion
|
|
774
|
+
//#region src/features/runtime-registry/utils/agent-runtime-registry.utils.ts
|
|
775
|
+
function normalizeIdentifier(value) {
|
|
776
|
+
if (typeof value !== "string") return null;
|
|
777
|
+
const normalized = value.trim().toLowerCase();
|
|
778
|
+
return normalized.length > 0 ? normalized : null;
|
|
779
|
+
}
|
|
780
|
+
function normalizeAgentRuntimeSessionTypeIcon(value) {
|
|
781
|
+
if (typeof value === "string") {
|
|
782
|
+
const src = value.trim();
|
|
783
|
+
return src ? {
|
|
784
|
+
kind: "image",
|
|
785
|
+
src
|
|
786
|
+
} : null;
|
|
787
|
+
}
|
|
788
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
789
|
+
const iconRecord = value;
|
|
790
|
+
const src = typeof iconRecord.src === "string" ? iconRecord.src.trim() : "";
|
|
791
|
+
if (!src) return null;
|
|
792
|
+
const alt = typeof iconRecord.alt === "string" && iconRecord.alt.trim().length > 0 ? iconRecord.alt.trim() : null;
|
|
793
|
+
return {
|
|
794
|
+
kind: "image",
|
|
795
|
+
src,
|
|
796
|
+
...alt ? { alt } : {}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
const BUILTIN_RUNTIME_PRESENTATION = { hermes: {
|
|
800
|
+
label: "Hermes",
|
|
801
|
+
icon: {
|
|
802
|
+
kind: "image",
|
|
803
|
+
src: "app://runtime-icons/hermes-agent.png",
|
|
804
|
+
alt: "Hermes"
|
|
805
|
+
}
|
|
806
|
+
} };
|
|
807
|
+
function readString$6(value) {
|
|
808
|
+
if (typeof value !== "string") return;
|
|
809
|
+
return value.trim() || void 0;
|
|
810
|
+
}
|
|
811
|
+
function readRecord$3(value) {
|
|
812
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
813
|
+
return value;
|
|
814
|
+
}
|
|
815
|
+
function resolveBuiltinRuntimePresentation(value) {
|
|
816
|
+
const normalized = readString$6(value)?.toLowerCase();
|
|
817
|
+
if (!normalized) return null;
|
|
818
|
+
if (!(normalized in BUILTIN_RUNTIME_PRESENTATION)) return null;
|
|
819
|
+
return BUILTIN_RUNTIME_PRESENTATION[normalized] ?? null;
|
|
820
|
+
}
|
|
821
|
+
function buildNativeRuntimeEntry(config) {
|
|
822
|
+
const nativeRuntimeConfig = readRecord$3(config.ui?.ncp?.runtimes?.native) ?? {};
|
|
823
|
+
return {
|
|
824
|
+
id: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
825
|
+
label: "Native",
|
|
826
|
+
type: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
827
|
+
enabled: nativeRuntimeConfig.enabled !== false,
|
|
828
|
+
config: nativeRuntimeConfig
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
function resolveAgentRuntimeEntries(params) {
|
|
832
|
+
const entries = /* @__PURE__ */ new Map();
|
|
833
|
+
entries.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, buildNativeRuntimeEntry(params.config));
|
|
834
|
+
for (const [rawId, rawEntry] of Object.entries(params.config.agents.runtimes.entries ?? {})) {
|
|
835
|
+
const id = rawId.trim().toLowerCase();
|
|
836
|
+
const type = readString$6(rawEntry.type)?.toLowerCase();
|
|
837
|
+
if (!id || !type) continue;
|
|
838
|
+
const explicitIcon = normalizeAgentRuntimeSessionTypeIcon(rawEntry.icon);
|
|
839
|
+
const builtinPresentation = resolveBuiltinRuntimePresentation(id) ?? resolveBuiltinRuntimePresentation(type);
|
|
840
|
+
entries.set(id, {
|
|
841
|
+
id,
|
|
842
|
+
label: readString$6(rawEntry.label) ?? builtinPresentation?.label ?? id,
|
|
843
|
+
...explicitIcon ?? builtinPresentation?.icon ? { icon: explicitIcon ?? builtinPresentation?.icon } : {},
|
|
844
|
+
type,
|
|
845
|
+
enabled: rawEntry.enabled !== false,
|
|
846
|
+
config: rawEntry.config ? { ...rawEntry.config } : {}
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
return {
|
|
850
|
+
defaultEntryId: entries.has("native") ? DEFAULT_AGENT_RUNTIME_ENTRY_ID : [...entries.keys()][0] ?? "native",
|
|
851
|
+
entries: [...entries.values()]
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
async function describeAgentRuntimeSessionTypes(params) {
|
|
855
|
+
const entries = params.entries.filter((entry) => entry.enabled !== false);
|
|
856
|
+
return {
|
|
857
|
+
defaultType: normalizeIdentifier(params.defaultEntryId) ?? (entries.some((entry) => entry.id === "native") ? "native" : entries[0]?.id ?? "native"),
|
|
858
|
+
options: await Promise.all(entries.map(async (entry) => {
|
|
859
|
+
const provider = params.providers.get(entry.type);
|
|
860
|
+
if (!provider) return {
|
|
861
|
+
value: entry.id,
|
|
862
|
+
label: entry.label,
|
|
863
|
+
icon: entry.icon ?? null,
|
|
864
|
+
ready: false,
|
|
865
|
+
reason: "runtime_provider_unavailable",
|
|
866
|
+
reasonMessage: `Runtime provider unavailable for type "${entry.type}".`,
|
|
867
|
+
recommendedModel: null,
|
|
868
|
+
modelSelectionMode: "nextclaw",
|
|
869
|
+
runtimeDefaultThinking: null,
|
|
870
|
+
cta: {
|
|
871
|
+
kind: "settings",
|
|
872
|
+
label: "Configure Runtime"
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
const descriptor = provider.describeSessionTypeForEntry ? await provider.describeSessionTypeForEntry({
|
|
876
|
+
entry,
|
|
877
|
+
describeParams: params.describeParams
|
|
878
|
+
}) : await provider.describeSessionType?.(params.describeParams);
|
|
879
|
+
return {
|
|
880
|
+
value: entry.id,
|
|
881
|
+
label: entry.label,
|
|
882
|
+
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
883
|
+
ready: descriptor?.ready ?? true,
|
|
884
|
+
reason: descriptor?.reason ?? null,
|
|
885
|
+
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
886
|
+
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
887
|
+
modelSelectionMode: descriptor?.modelSelectionMode ?? "nextclaw",
|
|
888
|
+
runtimeDefaultThinking: descriptor?.runtimeDefaultThinking ?? null,
|
|
889
|
+
cta: descriptor?.cta ?? null,
|
|
890
|
+
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
891
|
+
};
|
|
892
|
+
}))
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
//#endregion
|
|
752
896
|
//#region src/managers/agent-runtime.manager.ts
|
|
753
897
|
var AgentRuntimeManager = class {
|
|
754
898
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -778,12 +922,8 @@ var AgentRuntimeManager = class {
|
|
|
778
922
|
});
|
|
779
923
|
};
|
|
780
924
|
getOrCreate = (params) => {
|
|
781
|
-
const {
|
|
782
|
-
const entry = this.
|
|
783
|
-
const provider = this.getProvider(entry.type);
|
|
784
|
-
const reuseScope = this.resolveReuseScope(entry, provider);
|
|
785
|
-
const cacheKey = reuseScope === "global" ? entry.id : `${entry.id}:${session.sessionId}`;
|
|
786
|
-
const cache = reuseScope === "global" ? this.globalRuntimes : this.sessionRuntimes;
|
|
925
|
+
const { session, sessionRun } = params;
|
|
926
|
+
const { cache, cacheKey, entry, provider } = this.resolveRuntimeCache(params);
|
|
787
927
|
const existing = cache.get(cacheKey);
|
|
788
928
|
if (existing) return existing;
|
|
789
929
|
const agentRuntime = provider.createRuntime({
|
|
@@ -794,31 +934,19 @@ var AgentRuntimeManager = class {
|
|
|
794
934
|
cache.set(cacheKey, agentRuntime);
|
|
795
935
|
return agentRuntime;
|
|
796
936
|
};
|
|
797
|
-
|
|
798
|
-
const
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
}) : null;
|
|
805
|
-
return {
|
|
806
|
-
value: entry.id,
|
|
807
|
-
label: entry.label,
|
|
808
|
-
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
809
|
-
ready: provider ? descriptor?.ready ?? true : false,
|
|
810
|
-
reason: provider ? descriptor?.reason ?? null : "runtime_provider_unavailable",
|
|
811
|
-
reasonMessage: provider ? descriptor?.reasonMessage ?? null : `Runtime provider unavailable for type "${entry.type}".`,
|
|
812
|
-
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
813
|
-
cta: descriptor?.cta ?? null,
|
|
814
|
-
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
815
|
-
};
|
|
816
|
-
}));
|
|
817
|
-
return {
|
|
818
|
-
defaultType: this.entries.has("native") ? DEFAULT_AGENT_RUNTIME_ENTRY_ID : entries[0]?.id ?? "native",
|
|
819
|
-
options
|
|
820
|
-
};
|
|
937
|
+
disposeRuntime = async (params) => {
|
|
938
|
+
const { cache, cacheKey } = this.resolveRuntimeCache(params);
|
|
939
|
+
const runtime = cache.get(cacheKey);
|
|
940
|
+
if (!runtime) return false;
|
|
941
|
+
cache.delete(cacheKey);
|
|
942
|
+
await runtime.dispose?.();
|
|
943
|
+
return true;
|
|
821
944
|
};
|
|
945
|
+
listSessionTypes = async (params) => describeAgentRuntimeSessionTypes({
|
|
946
|
+
entries: [...this.entries.values()],
|
|
947
|
+
providers: this.providers,
|
|
948
|
+
describeParams: params
|
|
949
|
+
});
|
|
822
950
|
dispose = async () => {
|
|
823
951
|
await this.disposeAllRuntimes();
|
|
824
952
|
this.providers.clear();
|
|
@@ -843,6 +971,19 @@ var AgentRuntimeManager = class {
|
|
|
843
971
|
resolveReuseScope = (entry, provider) => {
|
|
844
972
|
return entry.config?.reuseScope === "session" || entry.config?.reuseScope === "global" ? entry.config.reuseScope : provider.defaultReuseScope;
|
|
845
973
|
};
|
|
974
|
+
resolveRuntimeCache = (params) => {
|
|
975
|
+
const { agentRuntimeId, session } = params;
|
|
976
|
+
const entry = this.getEntry(agentRuntimeId);
|
|
977
|
+
const provider = this.getProvider(entry.type);
|
|
978
|
+
const reuseScope = this.resolveReuseScope(entry, provider);
|
|
979
|
+
const cacheKey = reuseScope === "global" ? entry.id : `${entry.id}:${session.sessionId}`;
|
|
980
|
+
return {
|
|
981
|
+
cache: reuseScope === "global" ? this.globalRuntimes : this.sessionRuntimes,
|
|
982
|
+
cacheKey,
|
|
983
|
+
entry,
|
|
984
|
+
provider
|
|
985
|
+
};
|
|
986
|
+
};
|
|
846
987
|
disposeAllRuntimes = async () => {
|
|
847
988
|
for (const runtime of [...this.globalRuntimes.values(), ...this.sessionRuntimes.values()]) await runtime.dispose?.();
|
|
848
989
|
this.globalRuntimes.clear();
|
|
@@ -1159,6 +1300,117 @@ var AutomationManager = class extends CronService {
|
|
|
1159
1300
|
}
|
|
1160
1301
|
};
|
|
1161
1302
|
//#endregion
|
|
1303
|
+
//#region src/managers/channel.manager.ts
|
|
1304
|
+
var ChannelManager = class {
|
|
1305
|
+
channels = {};
|
|
1306
|
+
channelConfig = null;
|
|
1307
|
+
dispatching = false;
|
|
1308
|
+
dispatchTask = null;
|
|
1309
|
+
extensionChannels = [];
|
|
1310
|
+
constructor(deps) {
|
|
1311
|
+
this.deps = deps;
|
|
1312
|
+
}
|
|
1313
|
+
load = (params) => {
|
|
1314
|
+
this.channelConfig = params.channelConfig;
|
|
1315
|
+
this.extensionChannels = params.extensionChannels ?? [];
|
|
1316
|
+
this.channels = {};
|
|
1317
|
+
this.initChannels();
|
|
1318
|
+
};
|
|
1319
|
+
reload = async (params) => {
|
|
1320
|
+
await this.stop();
|
|
1321
|
+
this.load(params);
|
|
1322
|
+
if (params.start === true) await this.start();
|
|
1323
|
+
};
|
|
1324
|
+
start = async () => {
|
|
1325
|
+
if (!Object.keys(this.channels).length || this.dispatching) return;
|
|
1326
|
+
this.dispatching = true;
|
|
1327
|
+
this.dispatchTask = this.dispatchOutbound();
|
|
1328
|
+
await Promise.allSettled(Object.entries(this.channels).map(([name, channel]) => this.startChannel(name, channel)));
|
|
1329
|
+
};
|
|
1330
|
+
stop = async () => {
|
|
1331
|
+
this.dispatching = false;
|
|
1332
|
+
if (this.dispatchTask) {
|
|
1333
|
+
await this.deps.bus.publishOutbound({
|
|
1334
|
+
channel: "__control__",
|
|
1335
|
+
chatId: "",
|
|
1336
|
+
content: "",
|
|
1337
|
+
media: [],
|
|
1338
|
+
metadata: { reason: "shutdown" }
|
|
1339
|
+
});
|
|
1340
|
+
await this.dispatchTask;
|
|
1341
|
+
}
|
|
1342
|
+
await Promise.allSettled(Object.entries(this.channels).map(async ([name, channel]) => {
|
|
1343
|
+
try {
|
|
1344
|
+
await channel.stop();
|
|
1345
|
+
} catch (error) {
|
|
1346
|
+
console.error(`Error stopping ${name}: ${String(error)}`);
|
|
1347
|
+
}
|
|
1348
|
+
}));
|
|
1349
|
+
this.dispatchTask = null;
|
|
1350
|
+
};
|
|
1351
|
+
status = () => Object.fromEntries(Object.entries(this.channels).map(([name, channel]) => [name, {
|
|
1352
|
+
enabled: true,
|
|
1353
|
+
running: channel.isRunning
|
|
1354
|
+
}]));
|
|
1355
|
+
get enabledChannels() {
|
|
1356
|
+
return Object.keys(this.channels);
|
|
1357
|
+
}
|
|
1358
|
+
getChannel = (name) => this.channels[name] ?? null;
|
|
1359
|
+
deliver = async (message) => {
|
|
1360
|
+
const channel = this.channels[message.channel];
|
|
1361
|
+
if (!channel) return false;
|
|
1362
|
+
if (isNextclawControlMessage(message)) {
|
|
1363
|
+
await channel.handleControlMessage(message);
|
|
1364
|
+
return true;
|
|
1365
|
+
}
|
|
1366
|
+
const outbound = this.normalizeOutbound(message);
|
|
1367
|
+
if (!outbound) return true;
|
|
1368
|
+
await channel.send(outbound);
|
|
1369
|
+
return true;
|
|
1370
|
+
};
|
|
1371
|
+
initChannels = () => {
|
|
1372
|
+
if (!this.channelConfig) return;
|
|
1373
|
+
for (const registration of this.extensionChannels) {
|
|
1374
|
+
const id = registration.channel.id;
|
|
1375
|
+
if (!id) continue;
|
|
1376
|
+
if (this.channels[id]) {
|
|
1377
|
+
console.warn(`Extension channel ignored because id already exists: ${id}`);
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
this.channels[id] = new ExtensionChannelAdapter(this.channelConfig, this.deps.bus, registration);
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
startChannel = async (name, channel) => {
|
|
1384
|
+
try {
|
|
1385
|
+
await channel.start();
|
|
1386
|
+
} catch (error) {
|
|
1387
|
+
console.error(`Failed to start channel ${name}: ${String(error)}`);
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
normalizeOutbound = (message) => {
|
|
1391
|
+
const silentReplyDecision = evaluateSilentReply({
|
|
1392
|
+
content: sanitizeOutboundAssistantContent(message.content ?? ""),
|
|
1393
|
+
media: message.media
|
|
1394
|
+
});
|
|
1395
|
+
if (silentReplyDecision.shouldDrop) return null;
|
|
1396
|
+
if (silentReplyDecision.content === message.content) return message;
|
|
1397
|
+
return {
|
|
1398
|
+
...message,
|
|
1399
|
+
content: silentReplyDecision.content
|
|
1400
|
+
};
|
|
1401
|
+
};
|
|
1402
|
+
dispatchOutbound = async () => {
|
|
1403
|
+
while (this.dispatching) {
|
|
1404
|
+
const message = await this.deps.bus.consumeOutbound();
|
|
1405
|
+
try {
|
|
1406
|
+
await this.deliver(message);
|
|
1407
|
+
} catch (error) {
|
|
1408
|
+
console.error(`Error sending to ${message.channel}: ${String(error)}`);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
};
|
|
1413
|
+
//#endregion
|
|
1162
1414
|
//#region src/managers/config.manager.ts
|
|
1163
1415
|
const hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
1164
1416
|
const mergeDeep = (base, patch) => {
|
|
@@ -1769,21 +2021,6 @@ var CommandRegistry = class {
|
|
|
1769
2021
|
};
|
|
1770
2022
|
//#endregion
|
|
1771
2023
|
//#region src/features/extension-runtime/services/extension-lifecycle.service.ts
|
|
1772
|
-
function sanitizeExtensionNodeOptions(value) {
|
|
1773
|
-
if (!value?.trim()) return;
|
|
1774
|
-
const tokens = value.split(/\s+/).filter(Boolean);
|
|
1775
|
-
const sanitized = [];
|
|
1776
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
1777
|
-
const token = tokens[index];
|
|
1778
|
-
if (token === "--conditions=development" || token === "-C=development") continue;
|
|
1779
|
-
if ((token === "--conditions" || token === "-C") && tokens[index + 1] === "development") {
|
|
1780
|
-
index += 1;
|
|
1781
|
-
continue;
|
|
1782
|
-
}
|
|
1783
|
-
sanitized.push(token);
|
|
1784
|
-
}
|
|
1785
|
-
return sanitized.length > 0 ? sanitized.join(" ") : void 0;
|
|
1786
|
-
}
|
|
1787
2024
|
var ExtensionLifecycleService = class {
|
|
1788
2025
|
processes = /* @__PURE__ */ new Map();
|
|
1789
2026
|
startAll = (manifests, params) => {
|
|
@@ -1813,14 +2050,12 @@ var ExtensionLifecycleService = class {
|
|
|
1813
2050
|
if (existing) return existing;
|
|
1814
2051
|
const child = spawn(manifest.server.command === "node" || manifest.server.command === "node.exe" ? process.execPath : manifest.server.command, manifest.server.args ?? [], {
|
|
1815
2052
|
cwd: manifest.rootDir,
|
|
1816
|
-
env: {
|
|
1817
|
-
...process.env,
|
|
1818
|
-
NODE_OPTIONS: sanitizeExtensionNodeOptions(process.env.NODE_OPTIONS),
|
|
2053
|
+
env: createRuntimeChildEnv(process.env, {
|
|
1819
2054
|
...manifest.server.env,
|
|
1820
2055
|
NEXTCLAW_EXTENSION_ID: manifest.id,
|
|
1821
2056
|
NEXTCLAW_EXTENSION_ENDPOINT: params.endpoint,
|
|
1822
2057
|
NEXTCLAW_EXTENSION_TOKEN: params.tokenForExtension(manifest.id)
|
|
1823
|
-
},
|
|
2058
|
+
}, { inheritBaseEnv: true }),
|
|
1824
2059
|
stdio: [
|
|
1825
2060
|
"ignore",
|
|
1826
2061
|
"ignore",
|
|
@@ -1860,7 +2095,7 @@ const BUILTIN_EXTENSION_PACKAGES = [
|
|
|
1860
2095
|
"@nextclaw/channel-extension-weixin"
|
|
1861
2096
|
];
|
|
1862
2097
|
const runtimeRequire = createRequire(import.meta.url);
|
|
1863
|
-
function readString$
|
|
2098
|
+
function readString$5(value) {
|
|
1864
2099
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1865
2100
|
}
|
|
1866
2101
|
function readStringArray$2(value) {
|
|
@@ -1871,7 +2106,7 @@ function readStringRecord(value) {
|
|
|
1871
2106
|
const entries = Object.entries(value);
|
|
1872
2107
|
return entries.every(([, item]) => typeof item === "string") ? Object.fromEntries(entries) : void 0;
|
|
1873
2108
|
}
|
|
1874
|
-
function readRecord$
|
|
2109
|
+
function readRecord$2(value) {
|
|
1875
2110
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1876
2111
|
}
|
|
1877
2112
|
function uniquePaths(paths) {
|
|
@@ -1908,17 +2143,17 @@ function resolveDevFirstPartyExtensionDir(explicitDir = process.env.NEXTCLAW_DEV
|
|
|
1908
2143
|
function toManifest(value, rootDir) {
|
|
1909
2144
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("extension manifest must be an object");
|
|
1910
2145
|
const record = value;
|
|
1911
|
-
const server = readRecord$
|
|
1912
|
-
const id = readString$
|
|
1913
|
-
const command = readString$
|
|
2146
|
+
const server = readRecord$2(record.server);
|
|
2147
|
+
const id = readString$5(record.id);
|
|
2148
|
+
const command = readString$5(server.command);
|
|
1914
2149
|
if (!id) throw new Error("extension manifest id is required");
|
|
1915
2150
|
if (server.type !== "stdio") throw new Error("extension server.type must be stdio");
|
|
1916
2151
|
if (!command) throw new Error("extension server.command is required");
|
|
1917
2152
|
return {
|
|
1918
2153
|
id,
|
|
1919
2154
|
rootDir,
|
|
1920
|
-
...readString$
|
|
1921
|
-
...readString$
|
|
2155
|
+
...readString$5(record.name) ? { name: readString$5(record.name) } : {},
|
|
2156
|
+
...readString$5(record.version) ? { version: readString$5(record.version) } : {},
|
|
1922
2157
|
server: {
|
|
1923
2158
|
type: "stdio",
|
|
1924
2159
|
command,
|
|
@@ -2022,19 +2257,19 @@ function listExtensionChannelIds(params) {
|
|
|
2022
2257
|
//#region src/services/extension-runtime.service.ts
|
|
2023
2258
|
const EXTENSION_REQUEST_EVENT_TYPE = "extension.request";
|
|
2024
2259
|
const EXTENSION_REQUEST_TIMEOUT_MS = 6e4;
|
|
2025
|
-
function readString$
|
|
2260
|
+
function readString$4(value) {
|
|
2026
2261
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2027
2262
|
}
|
|
2028
|
-
function readRecord$
|
|
2263
|
+
function readRecord$1(value) {
|
|
2029
2264
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2030
2265
|
}
|
|
2031
|
-
function readRequiredString$
|
|
2032
|
-
const trimmed = readString$
|
|
2266
|
+
function readRequiredString$5(value, name) {
|
|
2267
|
+
const trimmed = readString$4(value);
|
|
2033
2268
|
if (!trimmed) throw new Error(`${name} is required`);
|
|
2034
2269
|
return trimmed;
|
|
2035
2270
|
}
|
|
2036
2271
|
function readTextContent(value) {
|
|
2037
|
-
const content = readRecord$
|
|
2272
|
+
const content = readRecord$1(value);
|
|
2038
2273
|
if (content.type !== "text" || typeof content.text !== "string") throw new Error("only text channel messages are supported by the first ingress bridge");
|
|
2039
2274
|
return content.text;
|
|
2040
2275
|
}
|
|
@@ -2044,35 +2279,35 @@ function readOptionalNumber(value) {
|
|
|
2044
2279
|
function readInboundAttachments(value) {
|
|
2045
2280
|
if (!Array.isArray(value)) return [];
|
|
2046
2281
|
return value.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))).map((entry) => ({
|
|
2047
|
-
...readString$
|
|
2048
|
-
...readString$
|
|
2049
|
-
...readString$
|
|
2050
|
-
...readString$
|
|
2051
|
-
...readString$
|
|
2052
|
-
...readString$
|
|
2282
|
+
...readString$4(entry.id) ? { id: readString$4(entry.id) } : {},
|
|
2283
|
+
...readString$4(entry.name) ? { name: readString$4(entry.name) } : {},
|
|
2284
|
+
...readString$4(entry.path) ? { path: readString$4(entry.path) } : {},
|
|
2285
|
+
...readString$4(entry.url) ? { url: readString$4(entry.url) } : {},
|
|
2286
|
+
...readString$4(entry.assetUri) ? { assetUri: readString$4(entry.assetUri) } : {},
|
|
2287
|
+
...readString$4(entry.mimeType) ? { mimeType: readString$4(entry.mimeType) } : {},
|
|
2053
2288
|
...readOptionalNumber(entry.size) !== void 0 ? { size: readOptionalNumber(entry.size) } : {},
|
|
2054
|
-
...readString$
|
|
2289
|
+
...readString$4(entry.source) ? { source: readString$4(entry.source) } : {},
|
|
2055
2290
|
...entry.status === "ready" || entry.status === "remote-only" ? { status: entry.status } : {},
|
|
2056
|
-
...readString$
|
|
2291
|
+
...readString$4(entry.errorCode) ? { errorCode: readString$4(entry.errorCode) } : {}
|
|
2057
2292
|
}));
|
|
2058
2293
|
}
|
|
2059
2294
|
function toInboundMessage(value) {
|
|
2060
|
-
const payload = readRecord$
|
|
2295
|
+
const payload = readRecord$1(value);
|
|
2061
2296
|
return {
|
|
2062
|
-
channel: readRequiredString$
|
|
2063
|
-
chatId: readRequiredString$
|
|
2064
|
-
senderId: readRequiredString$
|
|
2297
|
+
channel: readRequiredString$5(payload.channelId, "channelId"),
|
|
2298
|
+
chatId: readRequiredString$5(payload.conversationId, "conversationId"),
|
|
2299
|
+
senderId: readRequiredString$5(payload.senderId, "senderId"),
|
|
2065
2300
|
content: readTextContent(payload.content),
|
|
2066
2301
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2067
2302
|
attachments: readInboundAttachments(payload.attachments),
|
|
2068
|
-
metadata: readRecord$
|
|
2303
|
+
metadata: readRecord$1(payload.metadata)
|
|
2069
2304
|
};
|
|
2070
2305
|
}
|
|
2071
2306
|
function normalizeChannelConfigResult(value) {
|
|
2072
|
-
return readRecord$
|
|
2307
|
+
return readRecord$1(readRecord$1(value).channelConfig);
|
|
2073
2308
|
}
|
|
2074
2309
|
function normalizeAuthLoginResult(value) {
|
|
2075
|
-
const record = readRecord$
|
|
2310
|
+
const record = readRecord$1(value);
|
|
2076
2311
|
return {
|
|
2077
2312
|
channelConfig: normalizeChannelConfigResult(record),
|
|
2078
2313
|
accountId: typeof record.accountId === "string" ? record.accountId : null,
|
|
@@ -2081,11 +2316,11 @@ function normalizeAuthLoginResult(value) {
|
|
|
2081
2316
|
}
|
|
2082
2317
|
function normalizeAuthPollResult(value) {
|
|
2083
2318
|
if (!value) return null;
|
|
2084
|
-
const record = readRecord$
|
|
2319
|
+
const record = readRecord$1(value);
|
|
2085
2320
|
return {
|
|
2086
|
-
channel: readRequiredString$
|
|
2321
|
+
channel: readRequiredString$5(record.channel, "channel"),
|
|
2087
2322
|
status: record.status,
|
|
2088
|
-
message: readString$
|
|
2323
|
+
message: readString$4(record.message),
|
|
2089
2324
|
nextPollMs: readOptionalNumber(record.nextPollMs),
|
|
2090
2325
|
accountId: typeof record.accountId === "string" ? record.accountId : null,
|
|
2091
2326
|
notes: Array.isArray(record.notes) ? record.notes.filter((note) => typeof note === "string") : [],
|
|
@@ -2181,7 +2416,7 @@ var ExtensionRuntimeService = class {
|
|
|
2181
2416
|
if (running.length > 0) console.log(`✓ Extensions started: ${running.map((entry) => entry.manifest.id).join(", ")}`);
|
|
2182
2417
|
};
|
|
2183
2418
|
getExtensionProcessToken = (extensionId) => {
|
|
2184
|
-
const id = readRequiredString$
|
|
2419
|
+
const id = readRequiredString$5(extensionId, "extensionId");
|
|
2185
2420
|
const current = this.extensionTokens.get(id);
|
|
2186
2421
|
if (current) return current;
|
|
2187
2422
|
const token = randomUUID();
|
|
@@ -2189,8 +2424,8 @@ var ExtensionRuntimeService = class {
|
|
|
2189
2424
|
return token;
|
|
2190
2425
|
};
|
|
2191
2426
|
authenticateEventStreamCredential = (input) => {
|
|
2192
|
-
const extensionId = readString$
|
|
2193
|
-
const token = readString$
|
|
2427
|
+
const extensionId = readString$4(input.extensionId);
|
|
2428
|
+
const token = readString$4(input.token);
|
|
2194
2429
|
if (!extensionId || !token || token !== this.extensionTokens.get(extensionId)) return null;
|
|
2195
2430
|
return { extensionId };
|
|
2196
2431
|
};
|
|
@@ -2209,7 +2444,7 @@ var ExtensionRuntimeService = class {
|
|
|
2209
2444
|
const channelBindings = [];
|
|
2210
2445
|
const uiMetadata = [];
|
|
2211
2446
|
for (const manifest of manifests) for (const channel of manifest.contributes?.channels ?? []) {
|
|
2212
|
-
const channelId = readString$
|
|
2447
|
+
const channelId = readString$4(channel.id);
|
|
2213
2448
|
if (!channelId) continue;
|
|
2214
2449
|
const configUiHints = this.readConfigUiHints(channel.configUiHints);
|
|
2215
2450
|
channelBindings.push({
|
|
@@ -2244,7 +2479,7 @@ var ExtensionRuntimeService = class {
|
|
|
2244
2479
|
};
|
|
2245
2480
|
handleChannelConfigGet = (envelope, context) => {
|
|
2246
2481
|
this.assertAuthorized(envelope, context);
|
|
2247
|
-
const channelId = readRequiredString$
|
|
2482
|
+
const channelId = readRequiredString$5(readRecord$1(envelope.payload).channelId, "channelId");
|
|
2248
2483
|
return { config: this.options.getConfig().channels[channelId] ?? {} };
|
|
2249
2484
|
};
|
|
2250
2485
|
handleChannelMessageSubmit = async (envelope, context) => {
|
|
@@ -2258,11 +2493,11 @@ var ExtensionRuntimeService = class {
|
|
|
2258
2493
|
};
|
|
2259
2494
|
handleChannelCommandExecute = async (envelope, context) => {
|
|
2260
2495
|
this.assertAuthorized(envelope, context);
|
|
2261
|
-
const payload = readRecord$
|
|
2262
|
-
const channel = readRequiredString$
|
|
2263
|
-
const chatId = readRequiredString$
|
|
2264
|
-
const senderId = readRequiredString$
|
|
2265
|
-
const metadata = readRecord$
|
|
2496
|
+
const payload = readRecord$1(envelope.payload);
|
|
2497
|
+
const channel = readRequiredString$5(payload.channelId, "channelId");
|
|
2498
|
+
const chatId = readRequiredString$5(payload.conversationId, "conversationId");
|
|
2499
|
+
const senderId = readRequiredString$5(payload.senderId, "senderId");
|
|
2500
|
+
const metadata = readRecord$1(payload.metadata);
|
|
2266
2501
|
const config = this.options.getConfig();
|
|
2267
2502
|
const registry = new CommandRegistry(config, this.options.sessionManager);
|
|
2268
2503
|
const route = new AgentRouteResolver(config).resolveInbound({
|
|
@@ -2270,15 +2505,15 @@ var ExtensionRuntimeService = class {
|
|
|
2270
2505
|
channel,
|
|
2271
2506
|
chatId,
|
|
2272
2507
|
senderId,
|
|
2273
|
-
content: readString$
|
|
2508
|
+
content: readString$4(payload.rawText) ?? readString$4(payload.commandName) ?? "",
|
|
2274
2509
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2275
2510
|
attachments: [],
|
|
2276
2511
|
metadata
|
|
2277
2512
|
},
|
|
2278
|
-
forcedAgentId: readString$
|
|
2279
|
-
sessionKeyOverride: readString$
|
|
2513
|
+
forcedAgentId: readString$4(metadata.target_agent_id),
|
|
2514
|
+
sessionKeyOverride: readString$4(metadata.session_key_override)
|
|
2280
2515
|
});
|
|
2281
|
-
const rawText = readString$
|
|
2516
|
+
const rawText = readString$4(payload.rawText);
|
|
2282
2517
|
if (rawText) return await registry.executeText(rawText, {
|
|
2283
2518
|
channel,
|
|
2284
2519
|
chatId,
|
|
@@ -2288,7 +2523,7 @@ var ExtensionRuntimeService = class {
|
|
|
2288
2523
|
content: "",
|
|
2289
2524
|
ephemeral: true
|
|
2290
2525
|
};
|
|
2291
|
-
return await registry.execute(readRequiredString$
|
|
2526
|
+
return await registry.execute(readRequiredString$5(payload.commandName, "commandName"), readRecord$1(payload.args), {
|
|
2292
2527
|
channel,
|
|
2293
2528
|
chatId,
|
|
2294
2529
|
senderId,
|
|
@@ -2297,14 +2532,14 @@ var ExtensionRuntimeService = class {
|
|
|
2297
2532
|
};
|
|
2298
2533
|
handleExtensionResponse = (envelope, context) => {
|
|
2299
2534
|
this.assertAuthorized(envelope, context);
|
|
2300
|
-
const payload = readRecord$
|
|
2301
|
-
const requestId = readRequiredString$
|
|
2535
|
+
const payload = readRecord$1(envelope.payload);
|
|
2536
|
+
const requestId = readRequiredString$5(payload.requestId, "requestId");
|
|
2302
2537
|
const pending = this.pendingRequests.get(requestId);
|
|
2303
2538
|
if (!pending) return { accepted: false };
|
|
2304
2539
|
this.pendingRequests.delete(requestId);
|
|
2305
2540
|
clearTimeout(pending.timeout);
|
|
2306
2541
|
if (payload.ok === false) {
|
|
2307
|
-
const message = readString$
|
|
2542
|
+
const message = readString$4(readRecord$1(payload.error).message) ?? "Extension request failed";
|
|
2308
2543
|
pending.reject(new Error(message));
|
|
2309
2544
|
return { accepted: true };
|
|
2310
2545
|
}
|
|
@@ -2351,7 +2586,7 @@ var ExtensionRuntimeService = class {
|
|
|
2351
2586
|
return await result;
|
|
2352
2587
|
};
|
|
2353
2588
|
assertAuthorized = (envelope, context) => {
|
|
2354
|
-
const extensionId = readString$
|
|
2589
|
+
const extensionId = readString$4(envelope.extensionId);
|
|
2355
2590
|
if (!extensionId || context.token !== this.extensionTokens.get(extensionId)) throw new Error("Unauthorized ingress token");
|
|
2356
2591
|
};
|
|
2357
2592
|
};
|
|
@@ -2474,11 +2709,11 @@ var ExtensionManager = class {
|
|
|
2474
2709
|
//#endregion
|
|
2475
2710
|
//#region src/utils/model-message-vision.utils.ts
|
|
2476
2711
|
const IMAGE_OMITTED_TEXT = "[Image omitted: the selected model is not configured for vision input.]";
|
|
2477
|
-
function isRecord$
|
|
2712
|
+
function isRecord$12(value) {
|
|
2478
2713
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2479
2714
|
}
|
|
2480
2715
|
function isImageContentPart(value) {
|
|
2481
|
-
if (!isRecord$
|
|
2716
|
+
if (!isRecord$12(value)) return false;
|
|
2482
2717
|
const type = value.type;
|
|
2483
2718
|
return type === "image_url" || type === "input_image";
|
|
2484
2719
|
}
|
|
@@ -2494,7 +2729,7 @@ function normalizeContentWithoutVision(content) {
|
|
|
2494
2729
|
};
|
|
2495
2730
|
});
|
|
2496
2731
|
if (!sawImage) return content;
|
|
2497
|
-
const textParts = parts.filter((part) => isRecord$
|
|
2732
|
+
const textParts = parts.filter((part) => isRecord$12(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text.trim()).filter(Boolean);
|
|
2498
2733
|
if (textParts.length === parts.length) return textParts.join("\n\n");
|
|
2499
2734
|
return parts;
|
|
2500
2735
|
}
|
|
@@ -3034,11 +3269,11 @@ function createAgentPeerSessionIdentity(params) {
|
|
|
3034
3269
|
}
|
|
3035
3270
|
function resolveAgentPeerScope(params) {
|
|
3036
3271
|
const metadata = params.metadata ?? {};
|
|
3037
|
-
const explicitScope = readOptionalString$
|
|
3272
|
+
const explicitScope = readOptionalString$9(metadata["agent_peer_scope"]) ?? readOptionalString$9(metadata.agentPeerScope);
|
|
3038
3273
|
if (explicitScope) return explicitScope;
|
|
3039
|
-
return `agent:${readOptionalString$
|
|
3274
|
+
return `agent:${readOptionalString$9(params.agentId) ?? BUILTIN_MAIN_AGENT_ID}:${readOptionalString$9(params.channel) ?? readOptionalString$9(metadata.channel) ?? "agent-run"}:${readOptionalString$9(metadata.accountId) ?? readOptionalString$9(metadata.account_id) ?? "default"}`;
|
|
3040
3275
|
}
|
|
3041
|
-
function readOptionalString$
|
|
3276
|
+
function readOptionalString$9(value) {
|
|
3042
3277
|
if (typeof value !== "string") return;
|
|
3043
3278
|
return value.trim() || void 0;
|
|
3044
3279
|
}
|
|
@@ -3057,7 +3292,7 @@ function safeNcpSessionFilename(value) {
|
|
|
3057
3292
|
function normalizeNcpAgentId(agentId) {
|
|
3058
3293
|
return agentId?.trim().toLowerCase() || void 0;
|
|
3059
3294
|
}
|
|
3060
|
-
function isRecord$
|
|
3295
|
+
function isRecord$11(value) {
|
|
3061
3296
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3062
3297
|
}
|
|
3063
3298
|
function toIsoString(value, fallback) {
|
|
@@ -3137,7 +3372,7 @@ function createReplayEvent(event) {
|
|
|
3137
3372
|
return replayEvent;
|
|
3138
3373
|
}
|
|
3139
3374
|
function readLegacyContextCompactionMessageId(message) {
|
|
3140
|
-
const checkpoint = isRecord$
|
|
3375
|
+
const checkpoint = isRecord$11(message?.metadata?.checkpoint) ? message.metadata.checkpoint : null;
|
|
3141
3376
|
const checkpointId = typeof checkpoint?.id === "string" ? checkpoint.id : "";
|
|
3142
3377
|
const coveredCount = checkpoint?.coveredSessionMessageCount;
|
|
3143
3378
|
const legacyId = `${message?.sessionId}:service:context-compaction:${checkpointId}`;
|
|
@@ -3167,11 +3402,11 @@ function rememberReplayMessageId(event, knownMessageIds) {
|
|
|
3167
3402
|
if (message?.id) knownMessageIds.add(message.id);
|
|
3168
3403
|
}
|
|
3169
3404
|
function readEventSessionId$2(event) {
|
|
3170
|
-
const sessionId = ("payload" in event && isRecord$
|
|
3405
|
+
const sessionId = ("payload" in event && isRecord$11(event.payload) ? event.payload : null)?.sessionId;
|
|
3171
3406
|
return typeof sessionId === "string" ? sessionId : "";
|
|
3172
3407
|
}
|
|
3173
3408
|
function readReplayPayloadTimestamp(event) {
|
|
3174
|
-
const payload = "payload" in event && isRecord$
|
|
3409
|
+
const payload = "payload" in event && isRecord$11(event.payload) ? event.payload : null;
|
|
3175
3410
|
const timestamp = typeof payload?.timestamp === "string" ? payload.timestamp : "";
|
|
3176
3411
|
return Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
|
|
3177
3412
|
}
|
|
@@ -3226,7 +3461,7 @@ function applyLimit(items, limit) {
|
|
|
3226
3461
|
if (!Number.isFinite(limit) || typeof limit !== "number" || limit <= 0) return items;
|
|
3227
3462
|
return items.slice(0, Math.trunc(limit));
|
|
3228
3463
|
}
|
|
3229
|
-
function readOptionalString$
|
|
3464
|
+
function readOptionalString$8(value) {
|
|
3230
3465
|
if (typeof value !== "string") return null;
|
|
3231
3466
|
const trimmed = value.trim();
|
|
3232
3467
|
return trimmed.length > 0 ? trimmed : null;
|
|
@@ -3238,43 +3473,294 @@ function readEventSessionId$1(event) {
|
|
|
3238
3473
|
return "payload" in event && "sessionId" in event.payload ? readOptionalMetadataString(event.payload.sessionId) : void 0;
|
|
3239
3474
|
}
|
|
3240
3475
|
//#endregion
|
|
3241
|
-
//#region src/
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
}
|
|
3274
|
-
|
|
3275
|
-
return
|
|
3276
|
-
}
|
|
3277
|
-
function
|
|
3476
|
+
//#region src/contributions/session-activity-preview/utils/session-activity-preview-ncp-event.utils.ts
|
|
3477
|
+
const PREVIEW_TEXT_MAX_LENGTH = 160;
|
|
3478
|
+
function readSessionId(value) {
|
|
3479
|
+
if (typeof value !== "string") return null;
|
|
3480
|
+
const trimmed = value.trim();
|
|
3481
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
3482
|
+
}
|
|
3483
|
+
function compactPreviewText(value) {
|
|
3484
|
+
return value.replace(/\s+/g, " ").trim();
|
|
3485
|
+
}
|
|
3486
|
+
function truncatePreviewText(value) {
|
|
3487
|
+
const compacted = compactPreviewText(value);
|
|
3488
|
+
if (compacted.length <= PREVIEW_TEXT_MAX_LENGTH) return compacted;
|
|
3489
|
+
return compacted.slice(0, PREVIEW_TEXT_MAX_LENGTH - 1).trimEnd();
|
|
3490
|
+
}
|
|
3491
|
+
function readSessionActivityPreviewText(message) {
|
|
3492
|
+
const chunks = [];
|
|
3493
|
+
for (const part of message.parts) if ((part.type === "text" || part.type === "rich-text") && part.text.trim()) chunks.push(part.text);
|
|
3494
|
+
const previewText = truncatePreviewText(chunks.join(" "));
|
|
3495
|
+
return previewText.length > 0 ? previewText : null;
|
|
3496
|
+
}
|
|
3497
|
+
function createProjection(sessionId, preview) {
|
|
3498
|
+
if (!sessionId) return null;
|
|
3499
|
+
return {
|
|
3500
|
+
sessionId,
|
|
3501
|
+
preview
|
|
3502
|
+
};
|
|
3503
|
+
}
|
|
3504
|
+
function formatErrorStatus(error) {
|
|
3505
|
+
if (typeof error === "string" && error.trim()) return `运行出错:${truncatePreviewText(error)}`;
|
|
3506
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
3507
|
+
const message = error.message;
|
|
3508
|
+
if (typeof message === "string" && message.trim()) return `运行出错:${truncatePreviewText(message)}`;
|
|
3509
|
+
}
|
|
3510
|
+
return "运行出错";
|
|
3511
|
+
}
|
|
3512
|
+
function readToolCallId(value) {
|
|
3513
|
+
if (typeof value !== "string") return null;
|
|
3514
|
+
const trimmed = value.trim();
|
|
3515
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
3516
|
+
}
|
|
3517
|
+
function formatToolDoneStatus(toolName) {
|
|
3518
|
+
return toolName ? `工具调用完成:${toolName}` : "工具调用完成";
|
|
3519
|
+
}
|
|
3520
|
+
function createSessionActivityPreviewFromNcpEvent(event, timestamp, options = {}) {
|
|
3521
|
+
switch (event.type) {
|
|
3522
|
+
case NcpEventType.RunStarted: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3523
|
+
state: "running",
|
|
3524
|
+
statusText: "正在思考",
|
|
3525
|
+
timestamp
|
|
3526
|
+
});
|
|
3527
|
+
case NcpEventType.RunFinished: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3528
|
+
state: "completed",
|
|
3529
|
+
timestamp
|
|
3530
|
+
});
|
|
3531
|
+
case NcpEventType.RunError: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3532
|
+
state: "failed",
|
|
3533
|
+
statusText: formatErrorStatus(event.payload.error),
|
|
3534
|
+
timestamp
|
|
3535
|
+
});
|
|
3536
|
+
case NcpEventType.MessageSent: {
|
|
3537
|
+
const text = readSessionActivityPreviewText(event.payload.message);
|
|
3538
|
+
if (!text || event.payload.message.role !== "user") return null;
|
|
3539
|
+
return createProjection(readSessionId(event.payload.sessionId), {
|
|
3540
|
+
state: "running",
|
|
3541
|
+
statusText: text,
|
|
3542
|
+
timestamp: event.payload.message.timestamp || timestamp
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
case NcpEventType.MessageCompleted: {
|
|
3546
|
+
const text = readSessionActivityPreviewText(event.payload.message);
|
|
3547
|
+
if (!text || event.payload.message.role !== "assistant") return null;
|
|
3548
|
+
return createProjection(readSessionId(event.payload.sessionId), {
|
|
3549
|
+
state: "completed",
|
|
3550
|
+
replyText: text,
|
|
3551
|
+
timestamp: event.payload.message.timestamp || timestamp
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
case NcpEventType.MessageFailed: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3555
|
+
state: "failed",
|
|
3556
|
+
statusText: formatErrorStatus(event.payload.error),
|
|
3557
|
+
timestamp
|
|
3558
|
+
});
|
|
3559
|
+
case NcpEventType.MessageToolCallStart: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3560
|
+
state: "running",
|
|
3561
|
+
statusText: `正在调用工具:${event.payload.toolName}`,
|
|
3562
|
+
timestamp
|
|
3563
|
+
});
|
|
3564
|
+
case NcpEventType.MessageToolCallEnd:
|
|
3565
|
+
case NcpEventType.MessageToolCallResult: {
|
|
3566
|
+
const sessionId = readSessionId(event.payload.sessionId);
|
|
3567
|
+
const toolCallId = readToolCallId(event.payload.toolCallId);
|
|
3568
|
+
return createProjection(sessionId, {
|
|
3569
|
+
state: "running",
|
|
3570
|
+
statusText: formatToolDoneStatus(sessionId && toolCallId ? options.readToolName?.(sessionId, toolCallId) ?? null : null),
|
|
3571
|
+
timestamp
|
|
3572
|
+
});
|
|
3573
|
+
}
|
|
3574
|
+
default: return null;
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
//#endregion
|
|
3578
|
+
//#region src/contributions/session-activity-preview/utils/session-activity-preview-metadata.utils.ts
|
|
3579
|
+
const SESSION_ACTIVITY_PREVIEW_METADATA_KEY = "last_activity_preview";
|
|
3580
|
+
const SESSION_ACTIVITY_PREVIEW_STATES = new Set([
|
|
3581
|
+
"running",
|
|
3582
|
+
"completed",
|
|
3583
|
+
"failed",
|
|
3584
|
+
"idle"
|
|
3585
|
+
]);
|
|
3586
|
+
function isRecord$10(value) {
|
|
3587
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3588
|
+
}
|
|
3589
|
+
function readOptionalString$7(value) {
|
|
3590
|
+
if (typeof value !== "string") return;
|
|
3591
|
+
const trimmed = value.trim();
|
|
3592
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3593
|
+
}
|
|
3594
|
+
function readSessionActivityPreviewMetadata(value) {
|
|
3595
|
+
if (!isRecord$10(value)) return null;
|
|
3596
|
+
const state = value.state;
|
|
3597
|
+
const timestamp = readOptionalString$7(value.timestamp);
|
|
3598
|
+
if (!SESSION_ACTIVITY_PREVIEW_STATES.has(state) || !timestamp) return null;
|
|
3599
|
+
return {
|
|
3600
|
+
state,
|
|
3601
|
+
timestamp,
|
|
3602
|
+
...readOptionalString$7(value.statusText) ? { statusText: readOptionalString$7(value.statusText) } : {},
|
|
3603
|
+
...readOptionalString$7(value.replyText) ? { replyText: readOptionalString$7(value.replyText) } : {}
|
|
3604
|
+
};
|
|
3605
|
+
}
|
|
3606
|
+
function compareIsoTimestamp(left, right) {
|
|
3607
|
+
const leftTime = Date.parse(left);
|
|
3608
|
+
const rightTime = Date.parse(right);
|
|
3609
|
+
if (!Number.isFinite(leftTime) || !Number.isFinite(rightTime)) return left.localeCompare(right);
|
|
3610
|
+
return leftTime - rightTime;
|
|
3611
|
+
}
|
|
3612
|
+
function mergeSessionActivityPreview(current, incoming) {
|
|
3613
|
+
if (current && compareIsoTimestamp(incoming.timestamp, current.timestamp) < 0) return incoming.replyText && !current.replyText ? {
|
|
3614
|
+
...current,
|
|
3615
|
+
replyText: incoming.replyText
|
|
3616
|
+
} : current;
|
|
3617
|
+
return {
|
|
3618
|
+
state: incoming.state,
|
|
3619
|
+
timestamp: incoming.timestamp,
|
|
3620
|
+
...incoming.statusText ?? (incoming.state === "completed" ? current?.statusText : void 0) ? { statusText: incoming.statusText ?? current?.statusText } : {},
|
|
3621
|
+
...incoming.replyText ?? (incoming.state === "completed" ? current?.replyText : void 0) ? { replyText: incoming.replyText ?? current?.replyText } : {}
|
|
3622
|
+
};
|
|
3623
|
+
}
|
|
3624
|
+
function areSessionActivityPreviewsEqual(left, right) {
|
|
3625
|
+
return Boolean(left) && left?.state === right.state && left.timestamp === right.timestamp && left.statusText === right.statusText && left.replyText === right.replyText;
|
|
3626
|
+
}
|
|
3627
|
+
function writeSessionActivityPreviewMetadata(metadata, projection) {
|
|
3628
|
+
const current = readSessionActivityPreviewMetadata(metadata?.[SESSION_ACTIVITY_PREVIEW_METADATA_KEY]);
|
|
3629
|
+
const next = mergeSessionActivityPreview(current, projection.preview);
|
|
3630
|
+
if (areSessionActivityPreviewsEqual(current, next)) return null;
|
|
3631
|
+
return {
|
|
3632
|
+
...metadata ?? {},
|
|
3633
|
+
[SESSION_ACTIVITY_PREVIEW_METADATA_KEY]: next
|
|
3634
|
+
};
|
|
3635
|
+
}
|
|
3636
|
+
//#endregion
|
|
3637
|
+
//#region src/contributions/session-activity-preview/services/session-activity-preview-event.service.ts
|
|
3638
|
+
var SessionActivityPreviewEventService = class {
|
|
3639
|
+
toolNames = /* @__PURE__ */ new Map();
|
|
3640
|
+
constructor(options) {
|
|
3641
|
+
this.options = options;
|
|
3642
|
+
}
|
|
3643
|
+
projectEvent = (event, timestamp) => {
|
|
3644
|
+
this.rememberToolName(event);
|
|
3645
|
+
const projection = createSessionActivityPreviewFromNcpEvent(event, timestamp, { readToolName: this.readToolName });
|
|
3646
|
+
this.clearFinishedRunToolNames(event);
|
|
3647
|
+
return projection;
|
|
3648
|
+
};
|
|
3649
|
+
updatePreview = async (projection) => {
|
|
3650
|
+
const session = await this.options.getSessionRecord(projection.sessionId);
|
|
3651
|
+
const replyText = projection.preview.replyText ?? (projection.preview.state === "completed" ? this.readLatestAssistantPreviewText(session?.messages) : void 0);
|
|
3652
|
+
const nextMetadata = writeSessionActivityPreviewMetadata(session?.metadata, {
|
|
3653
|
+
...projection,
|
|
3654
|
+
preview: {
|
|
3655
|
+
...projection.preview,
|
|
3656
|
+
replyText
|
|
3657
|
+
}
|
|
3658
|
+
});
|
|
3659
|
+
if (nextMetadata) await this.options.updateSessionMetadata(projection.sessionId, nextMetadata);
|
|
3660
|
+
};
|
|
3661
|
+
clear = () => {
|
|
3662
|
+
this.toolNames.clear();
|
|
3663
|
+
};
|
|
3664
|
+
rememberToolName = (event) => {
|
|
3665
|
+
if (event.type !== NcpEventType.MessageToolCallStart) return;
|
|
3666
|
+
const { sessionId, toolCallId, toolName } = event.payload;
|
|
3667
|
+
if (sessionId && toolCallId && toolName) this.toolNames.set(this.createToolNameKey(sessionId, toolCallId), toolName);
|
|
3668
|
+
};
|
|
3669
|
+
readToolName = (sessionId, toolCallId) => this.toolNames.get(this.createToolNameKey(sessionId, toolCallId)) ?? null;
|
|
3670
|
+
clearFinishedRunToolNames = (event) => {
|
|
3671
|
+
if (event.type !== NcpEventType.RunFinished && event.type !== NcpEventType.RunError) return;
|
|
3672
|
+
const sessionId = event.payload.sessionId;
|
|
3673
|
+
for (const key of this.toolNames.keys()) if (key.startsWith(`${sessionId}:`)) this.toolNames.delete(key);
|
|
3674
|
+
};
|
|
3675
|
+
createToolNameKey = (sessionId, toolCallId) => `${sessionId}:${toolCallId}`;
|
|
3676
|
+
readLatestAssistantPreviewText = (messages) => {
|
|
3677
|
+
for (let index = (messages?.length ?? 0) - 1; index >= 0; index -= 1) {
|
|
3678
|
+
const message = messages?.[index];
|
|
3679
|
+
if (message?.role === "assistant") return readSessionActivityPreviewText(message) ?? void 0;
|
|
3680
|
+
}
|
|
3681
|
+
};
|
|
3682
|
+
};
|
|
3683
|
+
//#endregion
|
|
3684
|
+
//#region src/services/session-event-ingestion.service.ts
|
|
3685
|
+
const SESSION_METADATA_PATCH_RUN_METADATA_KIND = "session_metadata_patch";
|
|
3686
|
+
function isDurableSessionEvent(event) {
|
|
3687
|
+
return event.type !== NcpEventType.ContextWindowUpdated;
|
|
3688
|
+
}
|
|
3689
|
+
function readRuntimeSessionMetadataPatch(event) {
|
|
3690
|
+
if (event.type !== NcpEventType.RunMetadata) return null;
|
|
3691
|
+
const metadata = event.payload.metadata;
|
|
3692
|
+
if (metadata.kind !== SESSION_METADATA_PATCH_RUN_METADATA_KIND || !metadata.sessionMetadataPatch || typeof metadata.sessionMetadataPatch !== "object" || Array.isArray(metadata.sessionMetadataPatch)) return null;
|
|
3693
|
+
const patch = metadata.sessionMetadataPatch;
|
|
3694
|
+
return Object.keys(patch).length > 0 ? structuredClone(patch) : null;
|
|
3695
|
+
}
|
|
3696
|
+
var SessionEventIngestionService = class {
|
|
3697
|
+
activityPreview;
|
|
3698
|
+
chains = /* @__PURE__ */ new Map();
|
|
3699
|
+
constructor(options) {
|
|
3700
|
+
this.options = options;
|
|
3701
|
+
this.activityPreview = new SessionActivityPreviewEventService({
|
|
3702
|
+
getSessionRecord: options.getSessionRecord,
|
|
3703
|
+
updateSessionMetadata: options.updateSessionMetadata
|
|
3704
|
+
});
|
|
3705
|
+
}
|
|
3706
|
+
handleEvent = (event) => {
|
|
3707
|
+
const sessionId = readEventSessionId$1(event);
|
|
3708
|
+
if (!sessionId || !isDurableSessionEvent(event)) return;
|
|
3709
|
+
const next = (this.chains.get(sessionId) ?? Promise.resolve()).then(() => this.handleDurableEvent(sessionId, event));
|
|
3710
|
+
this.chains.set(sessionId, next.catch(() => void 0));
|
|
3711
|
+
next.catch((error) => this.options.onError(sessionId, error));
|
|
3712
|
+
};
|
|
3713
|
+
clear = () => {
|
|
3714
|
+
this.chains.clear();
|
|
3715
|
+
this.activityPreview.clear();
|
|
3716
|
+
};
|
|
3717
|
+
handleDurableEvent = async (sessionId, event) => {
|
|
3718
|
+
const preview = this.activityPreview.projectEvent(event, (/* @__PURE__ */ new Date()).toISOString());
|
|
3719
|
+
const metadataPatch = readRuntimeSessionMetadataPatch(event);
|
|
3720
|
+
if (metadataPatch) {
|
|
3721
|
+
await this.options.updateSessionMetadata(sessionId, metadataPatch);
|
|
3722
|
+
return;
|
|
3723
|
+
}
|
|
3724
|
+
await this.options.appendSessionEvent({
|
|
3725
|
+
event,
|
|
3726
|
+
sessionId
|
|
3727
|
+
});
|
|
3728
|
+
if (preview) await this.activityPreview.updatePreview(preview);
|
|
3729
|
+
};
|
|
3730
|
+
};
|
|
3731
|
+
//#endregion
|
|
3732
|
+
//#region src/services/session-working-dir-resolver.service.ts
|
|
3733
|
+
var SessionWorkingDirResolver = class {
|
|
3734
|
+
constructor(agentManager) {
|
|
3735
|
+
this.agentManager = agentManager;
|
|
3736
|
+
}
|
|
3737
|
+
withWorkingDir = (summary) => ({
|
|
3738
|
+
...summary,
|
|
3739
|
+
workingDir: this.resolve({
|
|
3740
|
+
agentId: summary.agentId,
|
|
3741
|
+
metadata: summary.metadata
|
|
3742
|
+
})
|
|
3743
|
+
});
|
|
3744
|
+
resolve = (params) => {
|
|
3745
|
+
const profile = this.agentManager.resolveAgentProfile(readOptionalString$8(params.agentId));
|
|
3746
|
+
return resolveSessionWorkspacePath({
|
|
3747
|
+
sessionMetadata: params.metadata,
|
|
3748
|
+
workspace: profile.workspace
|
|
3749
|
+
});
|
|
3750
|
+
};
|
|
3751
|
+
};
|
|
3752
|
+
//#endregion
|
|
3753
|
+
//#region src/managers/session.manager.ts
|
|
3754
|
+
const DEFAULT_SESSION_TYPE = "native";
|
|
3755
|
+
const DEFAULT_LIFECYCLE = "persistent";
|
|
3756
|
+
const SESSION_METADATA_LABEL_KEY = "label";
|
|
3757
|
+
const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
|
|
3758
|
+
const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
|
|
3759
|
+
const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
|
|
3760
|
+
function readThinkingEffort(metadata) {
|
|
3761
|
+
return readOptionalMetadataString(metadata?.thinkingEffort) ?? null;
|
|
3762
|
+
}
|
|
3763
|
+
function readProjectRoot(metadata) {
|
|
3278
3764
|
return readOptionalMetadataString(metadata?.project_root) ?? readOptionalMetadataString(metadata?.projectRoot);
|
|
3279
3765
|
}
|
|
3280
3766
|
function summarizeTask(task) {
|
|
@@ -3308,7 +3794,7 @@ function mergeMetadataOverrides(metadata, overrides) {
|
|
|
3308
3794
|
}
|
|
3309
3795
|
function resolveSessionType(params) {
|
|
3310
3796
|
const { metadata, runtime, sessionType } = params;
|
|
3311
|
-
return readOptionalString$
|
|
3797
|
+
return readOptionalString$8(runtime) ?? readOptionalString$8(metadata.runtime) ?? readOptionalString$8(sessionType) ?? readOptionalString$8(metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
3312
3798
|
}
|
|
3313
3799
|
function applySessionOverrides(params) {
|
|
3314
3800
|
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
@@ -3318,15 +3804,15 @@ function applySessionOverrides(params) {
|
|
|
3318
3804
|
metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
|
|
3319
3805
|
if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
|
|
3320
3806
|
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
3321
|
-
if (readOptionalString$
|
|
3807
|
+
if (readOptionalString$8(model)) {
|
|
3322
3808
|
metadata.model = model?.trim();
|
|
3323
3809
|
metadata.preferred_model = model?.trim();
|
|
3324
3810
|
}
|
|
3325
|
-
if (readOptionalString$
|
|
3811
|
+
if (readOptionalString$8(thinkingLevel)) {
|
|
3326
3812
|
metadata.thinking = thinkingLevel?.trim();
|
|
3327
3813
|
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
3328
3814
|
}
|
|
3329
|
-
if (readOptionalString$
|
|
3815
|
+
if (readOptionalString$8(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
3330
3816
|
}
|
|
3331
3817
|
function isSessionSummaryRefreshEvent(event) {
|
|
3332
3818
|
switch (event.type) {
|
|
@@ -3341,36 +3827,40 @@ function isSessionSummaryRefreshEvent(event) {
|
|
|
3341
3827
|
var SessionManager = class {
|
|
3342
3828
|
cleanups = [];
|
|
3343
3829
|
contextWindowPreview;
|
|
3830
|
+
eventIngestion;
|
|
3344
3831
|
workingDirResolver;
|
|
3345
3832
|
started = false;
|
|
3346
3833
|
constructor(options) {
|
|
3347
3834
|
this.options = options;
|
|
3348
|
-
this.
|
|
3349
|
-
|
|
3835
|
+
this.eventIngestion = new SessionEventIngestionService({
|
|
3836
|
+
appendSessionEvent: (params) => this.appendSessionEvent(params),
|
|
3837
|
+
getSessionRecord: (sessionId) => this.getSessionRecord(sessionId),
|
|
3838
|
+
onError: (sessionId, error) => {
|
|
3839
|
+
const message = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
3840
|
+
console.error(`[session-manager] failed to handle ncp event for ${sessionId}: ${message}`);
|
|
3841
|
+
},
|
|
3842
|
+
updateSessionMetadata: (sessionId, metadata) => this.updateSessionMetadata(sessionId, metadata)
|
|
3843
|
+
});
|
|
3844
|
+
this.contextWindowPreview = new ContextWindowPreviewManager(options.agentManager);
|
|
3845
|
+
this.workingDirResolver = new SessionWorkingDirResolver(options.agentManager);
|
|
3350
3846
|
}
|
|
3351
3847
|
start = () => {
|
|
3352
3848
|
if (this.started) return;
|
|
3353
3849
|
this.started = true;
|
|
3354
|
-
this.cleanups.push(this.options.eventBus.on(eventKeys.ncpEvent,
|
|
3355
|
-
const sessionId = readEventSessionId$1(event);
|
|
3356
|
-
if (!sessionId || !isDurableSessionEvent(event)) return;
|
|
3357
|
-
await this.appendSessionEvent({
|
|
3358
|
-
event,
|
|
3359
|
-
sessionId
|
|
3360
|
-
});
|
|
3361
|
-
}));
|
|
3850
|
+
this.cleanups.push(this.options.eventBus.on(eventKeys.ncpEvent, this.eventIngestion.handleEvent));
|
|
3362
3851
|
};
|
|
3363
3852
|
dispose = () => {
|
|
3364
3853
|
while (this.cleanups.length > 0) this.cleanups.pop()?.();
|
|
3854
|
+
this.eventIngestion.clear();
|
|
3365
3855
|
this.started = false;
|
|
3366
3856
|
};
|
|
3367
3857
|
createSession = async (params) => {
|
|
3368
3858
|
const { agentId: requestedAgentId, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
|
|
3369
3859
|
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
3370
3860
|
const metadata = cloneInheritedMetadata(sourceSessionMetadata);
|
|
3371
|
-
const title = readOptionalString$
|
|
3372
|
-
const parentSessionId = readOptionalString$
|
|
3373
|
-
const requestId = readOptionalString$
|
|
3861
|
+
const title = readOptionalString$8(requestedTitle) ?? summarizeTask(task);
|
|
3862
|
+
const parentSessionId = readOptionalString$8(rawParentSessionId);
|
|
3863
|
+
const requestId = readOptionalString$8(rawRequestId);
|
|
3374
3864
|
const sessionType = resolveSessionType({
|
|
3375
3865
|
runtime,
|
|
3376
3866
|
sessionType: requestedSessionType,
|
|
@@ -3389,8 +3879,8 @@ var SessionManager = class {
|
|
|
3389
3879
|
});
|
|
3390
3880
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3391
3881
|
const nextMetadata = mergeMetadataOverrides(metadata, metadataOverrides);
|
|
3392
|
-
const agentId = readOptionalString$
|
|
3393
|
-
const sessionId = readOptionalString$
|
|
3882
|
+
const agentId = readOptionalString$8(requestedAgentId) ?? readOptionalString$8(sourceRecord?.agentId) ?? BUILTIN_MAIN_AGENT_ID;
|
|
3883
|
+
const sessionId = readOptionalString$8(requestedSessionId) ?? buildSessionId();
|
|
3394
3884
|
const record = {
|
|
3395
3885
|
sessionId,
|
|
3396
3886
|
...agentId ? { agentId } : {},
|
|
@@ -3463,7 +3953,7 @@ var SessionManager = class {
|
|
|
3463
3953
|
return await this.options.journalStore.getSession(normalizedSessionId);
|
|
3464
3954
|
};
|
|
3465
3955
|
listSessions = async (options) => {
|
|
3466
|
-
const peerId = readOptionalString$
|
|
3956
|
+
const peerId = readOptionalString$8(options?.peerId);
|
|
3467
3957
|
return applyLimit((await this.options.journalStore.listSessionSummaries()).filter((summary) => !peerId || summary.peerId === peerId).map(this.workingDirResolver.withWorkingDir), options?.limit);
|
|
3468
3958
|
};
|
|
3469
3959
|
listSessionMessages = async (sessionId, options) => {
|
|
@@ -3490,20 +3980,24 @@ var SessionManager = class {
|
|
|
3490
3980
|
metadata: structuredClone(record.metadata ?? {}),
|
|
3491
3981
|
model,
|
|
3492
3982
|
projectRoot: readProjectRoot(record.metadata),
|
|
3983
|
+
workingDir: this.workingDirResolver.resolve({
|
|
3984
|
+
agentId: record.agentId,
|
|
3985
|
+
metadata: record.metadata
|
|
3986
|
+
}),
|
|
3493
3987
|
thinkingEffort: readThinkingEffort(record.metadata)
|
|
3494
3988
|
};
|
|
3495
3989
|
};
|
|
3496
3990
|
createAgentRunSession = async (params) => {
|
|
3497
3991
|
const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, metadata, model, peerId: rawPeerId, projectRoot, sessionId, task, thinkingEffort } = params;
|
|
3498
3992
|
const agentRuntimeId = requestedAgentRuntimeId ?? "native";
|
|
3499
|
-
const peerId = readOptionalString$
|
|
3993
|
+
const peerId = readOptionalString$8(rawPeerId);
|
|
3500
3994
|
const peerIdentity = peerId ? createAgentPeerSessionIdentity({
|
|
3501
3995
|
agentId,
|
|
3502
3996
|
channel,
|
|
3503
3997
|
metadata,
|
|
3504
3998
|
peerId
|
|
3505
3999
|
}) : void 0;
|
|
3506
|
-
const requestedSessionId = readOptionalString$
|
|
4000
|
+
const requestedSessionId = readOptionalString$8(sessionId);
|
|
3507
4001
|
const created = await this.createSession({
|
|
3508
4002
|
sourceSessionMetadata: {},
|
|
3509
4003
|
sessionId: requestedSessionId ?? peerIdentity?.sessionId,
|
|
@@ -3526,6 +4020,10 @@ var SessionManager = class {
|
|
|
3526
4020
|
metadata: structuredClone(created.metadata ?? {}),
|
|
3527
4021
|
model,
|
|
3528
4022
|
projectRoot,
|
|
4023
|
+
workingDir: this.workingDirResolver.resolve({
|
|
4024
|
+
agentId,
|
|
4025
|
+
metadata: created.metadata
|
|
4026
|
+
}),
|
|
3529
4027
|
thinkingEffort: thinkingEffort ?? null
|
|
3530
4028
|
};
|
|
3531
4029
|
};
|
|
@@ -4522,10 +5020,10 @@ function parsePanelAppFolderManifest(raw) {
|
|
|
4522
5020
|
if (id && !PANEL_APP_ID_PATTERN.test(id)) throw new Error("panel app id must be kebab-case.");
|
|
4523
5021
|
return {
|
|
4524
5022
|
id,
|
|
4525
|
-
title: readRequiredString$
|
|
5023
|
+
title: readRequiredString$4(parsed, "title"),
|
|
4526
5024
|
description: readOptionalString$6(parsed, "description"),
|
|
4527
5025
|
icon: readOptionalString$6(parsed, "icon"),
|
|
4528
|
-
entry: readRequiredString$
|
|
5026
|
+
entry: readRequiredString$4(parsed, "entry"),
|
|
4529
5027
|
capabilities: readStringArray$1(parsed.capabilities, "capabilities"),
|
|
4530
5028
|
client: readOptionalBoolean$2(parsed, "client"),
|
|
4531
5029
|
serviceActions: readStringArray$1(parsed.actions, "actions")
|
|
@@ -4585,7 +5083,7 @@ function parseTokenList(content) {
|
|
|
4585
5083
|
if (!content) return [];
|
|
4586
5084
|
return [...new Set(content.split(/[,\s]+/).map((entry) => entry.trim()).filter(Boolean))];
|
|
4587
5085
|
}
|
|
4588
|
-
function readRequiredString$
|
|
5086
|
+
function readRequiredString$4(record, key) {
|
|
4589
5087
|
const value = readOptionalString$6(record, key);
|
|
4590
5088
|
if (!value) throw new Error(`panel app ${key} is required.`);
|
|
4591
5089
|
return value;
|
|
@@ -5371,17 +5869,17 @@ function parseServiceAppManifest(raw) {
|
|
|
5371
5869
|
throw new Error(`service-app.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
5372
5870
|
}
|
|
5373
5871
|
if (!isRecord$4(parsed)) throw new Error("service-app.json must contain an object.");
|
|
5374
|
-
const id = readRequiredString$
|
|
5872
|
+
const id = readRequiredString$3(parsed, "id");
|
|
5375
5873
|
if (!SERVICE_APP_ID_PATTERN.test(id)) throw new Error("service app id must be kebab-case.");
|
|
5376
5874
|
const protocol = readOptionalString$5(parsed, "protocol") ?? "mcp";
|
|
5377
5875
|
if (protocol !== "mcp") throw new Error("service app protocol must be mcp.");
|
|
5378
5876
|
return {
|
|
5379
5877
|
id,
|
|
5380
|
-
title: readRequiredString$
|
|
5878
|
+
title: readRequiredString$3(parsed, "title"),
|
|
5381
5879
|
description: readOptionalString$5(parsed, "description"),
|
|
5382
5880
|
enabled: readOptionalBoolean$1(parsed, "enabled") ?? true,
|
|
5383
5881
|
protocol,
|
|
5384
|
-
command: readRequiredString$
|
|
5882
|
+
command: readRequiredString$3(parsed, "command"),
|
|
5385
5883
|
args: readStringArray(parsed.args, "args"),
|
|
5386
5884
|
actions: readManifestActions(parsed.actions)
|
|
5387
5885
|
};
|
|
@@ -5407,7 +5905,7 @@ function readManifestActions(value) {
|
|
|
5407
5905
|
}
|
|
5408
5906
|
return actions;
|
|
5409
5907
|
}
|
|
5410
|
-
function readRequiredString$
|
|
5908
|
+
function readRequiredString$3(record, key) {
|
|
5411
5909
|
const value = readOptionalString$5(record, key);
|
|
5412
5910
|
if (!value) throw new Error(`service app ${key} is required.`);
|
|
5413
5911
|
return value;
|
|
@@ -5822,12 +6320,12 @@ function parseSkillFrontmatter(raw) {
|
|
|
5822
6320
|
const summaryI18n = readLocalizedTextMap(parsed, "summaryi18n", "summary_i18n");
|
|
5823
6321
|
const descriptionI18n = readLocalizedTextMap(parsed, "descriptioni18n", "description_i18n");
|
|
5824
6322
|
return {
|
|
5825
|
-
name: readString$
|
|
5826
|
-
summary: readString$
|
|
5827
|
-
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$
|
|
5828
|
-
description: readString$
|
|
5829
|
-
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$
|
|
5830
|
-
author: readString$
|
|
6323
|
+
name: readString$3(parsed, "name"),
|
|
6324
|
+
summary: readString$3(parsed, "summary"),
|
|
6325
|
+
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$3(parsed, "summaryzh", "summary_zh") }),
|
|
6326
|
+
description: readString$3(parsed, "description"),
|
|
6327
|
+
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$3(parsed, "descriptionzh", "description_zh") }),
|
|
6328
|
+
author: readString$3(parsed, "author"),
|
|
5831
6329
|
tags: readTags(parsed)
|
|
5832
6330
|
};
|
|
5833
6331
|
}
|
|
@@ -5854,7 +6352,7 @@ function parseYamlFrontmatter(raw) {
|
|
|
5854
6352
|
throw new Error(`Invalid SKILL.md frontmatter: ${message}`);
|
|
5855
6353
|
}
|
|
5856
6354
|
}
|
|
5857
|
-
function readString$
|
|
6355
|
+
function readString$3(record, ...names) {
|
|
5858
6356
|
const value = readValue(record, names);
|
|
5859
6357
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
5860
6358
|
}
|
|
@@ -6050,7 +6548,7 @@ var NcpAgentSessionMetadataStore = class {
|
|
|
6050
6548
|
read = async (sessionId, activitySnapshot) => {
|
|
6051
6549
|
try {
|
|
6052
6550
|
const parsed = JSON.parse(await readFile(this.metadataPath(sessionId), "utf-8"));
|
|
6053
|
-
if (!isRecord$
|
|
6551
|
+
if (!isRecord$11(parsed) || parsed._type !== "metadata" || !isRecord$11(parsed.metadata)) throw new Error(`invalid ncp agent session metadata sidecar: ${sessionId}`);
|
|
6054
6552
|
const createdAt = toIsoString(parsed.created_at, activitySnapshot.createdAt);
|
|
6055
6553
|
const agentId = normalizeNcpAgentId(typeof parsed.agent_id === "string" ? parsed.agent_id : void 0);
|
|
6056
6554
|
return {
|
|
@@ -6151,11 +6649,11 @@ var NcpAgentSessionSummaryIndexStore = class {
|
|
|
6151
6649
|
function serializeJournalEntry(entry) {
|
|
6152
6650
|
const serialized = JSON.stringify(entry);
|
|
6153
6651
|
if (!serialized) throw new Error("ncp agent session journal entry serialization produced empty output");
|
|
6154
|
-
if (!isRecord$
|
|
6652
|
+
if (!isRecord$11(JSON.parse(serialized))) throw new Error("ncp agent session journal entry serialization produced a non-object entry");
|
|
6155
6653
|
return serialized;
|
|
6156
6654
|
}
|
|
6157
6655
|
function attachJournalTimestamp(event, timestamp) {
|
|
6158
|
-
if (!("payload" in event) || !isRecord$
|
|
6656
|
+
if (!("payload" in event) || !isRecord$11(event.payload)) return event;
|
|
6159
6657
|
return {
|
|
6160
6658
|
...event,
|
|
6161
6659
|
payload: {
|
|
@@ -6379,15 +6877,15 @@ var NcpAgentSessionJournalStore = class {
|
|
|
6379
6877
|
console.warn(`[ncp-agent-session-journal] skipped corrupted journal line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);
|
|
6380
6878
|
continue;
|
|
6381
6879
|
}
|
|
6382
|
-
if (!isRecord$
|
|
6880
|
+
if (!isRecord$11(parsed)) continue;
|
|
6383
6881
|
if (parsed._type === "metadata") {
|
|
6384
|
-
metadata = isRecord$
|
|
6882
|
+
metadata = isRecord$11(parsed.metadata) ? structuredClone(parsed.metadata) : {};
|
|
6385
6883
|
agentId = normalizeNcpAgentId(typeof parsed.agent_id === "string" ? parsed.agent_id : void 0);
|
|
6386
6884
|
createdAt = toIsoString(parsed.created_at, createdAt);
|
|
6387
6885
|
updatedAt = toIsoString(parsed.updated_at, updatedAt);
|
|
6388
6886
|
continue;
|
|
6389
6887
|
}
|
|
6390
|
-
if (parsed._type === "event" && isRecord$
|
|
6888
|
+
if (parsed._type === "event" && isRecord$11(parsed.event)) {
|
|
6391
6889
|
const seq = Number(parsed.seq);
|
|
6392
6890
|
nextSeq = Math.max(nextSeq, Number.isFinite(seq) ? Math.trunc(seq) + 1 : nextSeq);
|
|
6393
6891
|
const eventTimestamp = toIsoString(parsed.timestamp, updatedAt);
|
|
@@ -6701,21 +7199,20 @@ const NARP_API_MODE_HEADER = "x-nextclaw-narp-api-mode";
|
|
|
6701
7199
|
const NARP_HTTP_RUNTIME_KIND = "narp-http";
|
|
6702
7200
|
const NARP_STDIO_RUNTIME_KIND = "narp-stdio";
|
|
6703
7201
|
const BUILTIN_PROVIDER_REGISTRY = new ProviderRegistry(BUILTIN_PROVIDER_PLUGINS);
|
|
6704
|
-
function readRecord
|
|
7202
|
+
function readRecord(value) {
|
|
6705
7203
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
6706
7204
|
return value;
|
|
6707
7205
|
}
|
|
6708
|
-
function readString$
|
|
7206
|
+
function readString$2(value) {
|
|
6709
7207
|
if (typeof value !== "string") return;
|
|
6710
7208
|
return value.trim() || void 0;
|
|
6711
7209
|
}
|
|
6712
|
-
function resolveEntryIcon(entry) {
|
|
6713
|
-
return entry.icon ?? null;
|
|
6714
|
-
}
|
|
6715
7210
|
function resolveRequestedModel(params) {
|
|
6716
|
-
const { configuredModel, defaultModel, input, sessionMetadata } = params;
|
|
6717
|
-
|
|
6718
|
-
|
|
7211
|
+
const { configuredModel, defaultModel, input, modelSelectionMode, sessionMetadata } = params;
|
|
7212
|
+
if (modelSelectionMode === "runtime-default") return;
|
|
7213
|
+
const requestedModel = readString$2(readRecord(input.metadata)?.preferred_model) ?? readString$2(readRecord(input.metadata)?.preferredModel) ?? readString$2(readRecord(input.metadata)?.model) ?? readString$2(sessionMetadata.preferred_model) ?? readString$2(sessionMetadata.preferredModel) ?? readString$2(sessionMetadata.model);
|
|
7214
|
+
if (isRuntimeDefaultModelValue(requestedModel)) return;
|
|
7215
|
+
return requestedModel ?? configuredModel ?? (modelSelectionMode === "optional" ? void 0 : defaultModel);
|
|
6719
7216
|
}
|
|
6720
7217
|
function resolveProviderApiMode(resolution) {
|
|
6721
7218
|
const wireApi = resolution.provider?.wireApi?.trim().toLowerCase();
|
|
@@ -6762,8 +7259,14 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6762
7259
|
};
|
|
6763
7260
|
describeInternal = async () => {
|
|
6764
7261
|
const config = new HttpRuntimeConfigResolver(this.entry.config ?? {}).resolve({ defaultModel: this.defaultModel });
|
|
7262
|
+
const modelSelectionMode = normalizeRuntimeModelSelectionMode(this.entry.config?.modelSelectionMode);
|
|
7263
|
+
const baseDescriptor = {
|
|
7264
|
+
icon: this.entry.icon ?? null,
|
|
7265
|
+
modelSelectionMode,
|
|
7266
|
+
runtimeDefaultThinking: normalizeModelThinkingCapability(this.entry.config?.runtimeDefaultThinking)
|
|
7267
|
+
};
|
|
6765
7268
|
if (!config.baseUrl) return {
|
|
6766
|
-
|
|
7269
|
+
...baseDescriptor,
|
|
6767
7270
|
ready: false,
|
|
6768
7271
|
reason: "base_url_missing",
|
|
6769
7272
|
reasonMessage: "Configure the runtime entry baseUrl before starting an HTTP runtime session.",
|
|
@@ -6774,7 +7277,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6774
7277
|
}
|
|
6775
7278
|
};
|
|
6776
7279
|
if (!((config.capabilityProbe ?? true) && Boolean(config.healthcheckUrl))) return {
|
|
6777
|
-
|
|
7280
|
+
...baseDescriptor,
|
|
6778
7281
|
ready: true,
|
|
6779
7282
|
reason: null,
|
|
6780
7283
|
reasonMessage: null,
|
|
@@ -6792,7 +7295,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6792
7295
|
signal: controller.signal
|
|
6793
7296
|
});
|
|
6794
7297
|
if (!response.ok) return {
|
|
6795
|
-
|
|
7298
|
+
...baseDescriptor,
|
|
6796
7299
|
ready: false,
|
|
6797
7300
|
reason: "healthcheck_failed",
|
|
6798
7301
|
reasonMessage: `HTTP runtime healthcheck returned HTTP ${response.status}.`,
|
|
@@ -6801,7 +7304,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6801
7304
|
cta: null
|
|
6802
7305
|
};
|
|
6803
7306
|
return {
|
|
6804
|
-
|
|
7307
|
+
...baseDescriptor,
|
|
6805
7308
|
ready: true,
|
|
6806
7309
|
reason: null,
|
|
6807
7310
|
reasonMessage: null,
|
|
@@ -6811,7 +7314,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6811
7314
|
};
|
|
6812
7315
|
} catch (error) {
|
|
6813
7316
|
return {
|
|
6814
|
-
|
|
7317
|
+
...baseDescriptor,
|
|
6815
7318
|
ready: false,
|
|
6816
7319
|
reason: "healthcheck_unreachable",
|
|
6817
7320
|
reasonMessage: error instanceof Error ? error.message : "Failed to reach the configured HTTP runtime healthcheck.",
|
|
@@ -6843,10 +7346,16 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6843
7346
|
};
|
|
6844
7347
|
describeInternal = async (describeMode) => {
|
|
6845
7348
|
const resolver = new StdioRuntimeConfigResolver(this.entry.config ?? {});
|
|
7349
|
+
const modelSelectionMode = normalizeRuntimeModelSelectionMode(this.entry.config?.modelSelectionMode);
|
|
7350
|
+
const baseDescriptor = {
|
|
7351
|
+
icon: this.entry.icon ?? null,
|
|
7352
|
+
modelSelectionMode,
|
|
7353
|
+
runtimeDefaultThinking: normalizeModelThinkingCapability(this.entry.config?.runtimeDefaultThinking)
|
|
7354
|
+
};
|
|
6846
7355
|
try {
|
|
6847
7356
|
const config = resolver.resolve();
|
|
6848
7357
|
if (!await resolveExecutablePath(config.command)) return {
|
|
6849
|
-
|
|
7358
|
+
...baseDescriptor,
|
|
6850
7359
|
ready: false,
|
|
6851
7360
|
reason: "command_missing",
|
|
6852
7361
|
reasonMessage: `Configured stdio command "${config.command}" is not available. Update the runtime entry command or install the required launcher first.`,
|
|
@@ -6859,7 +7368,7 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6859
7368
|
await probeStdioRuntime(config);
|
|
6860
7369
|
} catch (error) {
|
|
6861
7370
|
return {
|
|
6862
|
-
|
|
7371
|
+
...baseDescriptor,
|
|
6863
7372
|
ready: false,
|
|
6864
7373
|
reason: "probe_failed",
|
|
6865
7374
|
reasonMessage: error instanceof Error ? error.message : "Configured stdio runtime could not complete the ACP probe.",
|
|
@@ -6870,7 +7379,7 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6870
7379
|
};
|
|
6871
7380
|
}
|
|
6872
7381
|
return {
|
|
6873
|
-
|
|
7382
|
+
...baseDescriptor,
|
|
6874
7383
|
ready: true,
|
|
6875
7384
|
reason: null,
|
|
6876
7385
|
reasonMessage: null,
|
|
@@ -6878,7 +7387,7 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6878
7387
|
};
|
|
6879
7388
|
} catch (error) {
|
|
6880
7389
|
return {
|
|
6881
|
-
|
|
7390
|
+
...baseDescriptor,
|
|
6882
7391
|
ready: false,
|
|
6883
7392
|
reason: "command_missing",
|
|
6884
7393
|
reasonMessage: error instanceof Error ? error.message : "Configure a stdio command before starting this runtime.",
|
|
@@ -6932,7 +7441,7 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
6932
7441
|
throw new Error("[narp] runtime entry is required before creating this runtime");
|
|
6933
7442
|
};
|
|
6934
7443
|
createHttpRuntime = (entry, runtimeParams) => {
|
|
6935
|
-
const config = readRecord
|
|
7444
|
+
const config = readRecord(entry.config) ?? {};
|
|
6936
7445
|
const resolver = new HttpRuntimeConfigResolver(config);
|
|
6937
7446
|
const resolvedConfig = resolver.resolve({ defaultModel: this.configManager.loadConfig().agents.defaults.model });
|
|
6938
7447
|
return new HttpRuntimeNcpAgentRuntime({
|
|
@@ -6947,15 +7456,15 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
6947
7456
|
input,
|
|
6948
7457
|
sessionMetadata: runtimeParams.sessionMetadata,
|
|
6949
7458
|
defaultModel: this.configManager.loadConfig().agents.defaults.model,
|
|
6950
|
-
configuredModel: readString$
|
|
7459
|
+
configuredModel: readString$2(config.model),
|
|
7460
|
+
modelSelectionMode: normalizeRuntimeModelSelectionMode(config.modelSelectionMode)
|
|
6951
7461
|
})
|
|
6952
7462
|
});
|
|
6953
7463
|
};
|
|
6954
7464
|
createStdioRuntime = (entry, runtimeParams) => {
|
|
6955
|
-
const config = readRecord
|
|
7465
|
+
const config = readRecord(entry.config) ?? {};
|
|
6956
7466
|
return new StdioRuntimeNcpAgentRuntime({
|
|
6957
7467
|
...new StdioRuntimeConfigResolver(config).resolve(),
|
|
6958
|
-
sessionId: runtimeParams.sessionId,
|
|
6959
7468
|
resolveTools: runtimeParams.resolveTools,
|
|
6960
7469
|
stateManager: runtimeParams.stateManager,
|
|
6961
7470
|
resolveProviderRoute: (input) => buildProviderRoute({
|
|
@@ -6963,7 +7472,8 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
6963
7472
|
input,
|
|
6964
7473
|
sessionMetadata: runtimeParams.sessionMetadata,
|
|
6965
7474
|
defaultModel: this.configManager.loadConfig().agents.defaults.model,
|
|
6966
|
-
configuredModel: readString$
|
|
7475
|
+
configuredModel: readString$2(config.model),
|
|
7476
|
+
modelSelectionMode: normalizeRuntimeModelSelectionMode(config.modelSelectionMode)
|
|
6967
7477
|
})
|
|
6968
7478
|
});
|
|
6969
7479
|
};
|
|
@@ -7256,10 +7766,16 @@ function resolveEffectiveModel(params) {
|
|
|
7256
7766
|
const metadata = structuredClone(params.sessionMetadata);
|
|
7257
7767
|
if (requestMetadata.clear_model === true || requestMetadata.reset_model === true) delete metadata.preferred_model;
|
|
7258
7768
|
const inboundModel = readMetadataModel(requestMetadata);
|
|
7259
|
-
if (inboundModel
|
|
7769
|
+
if (inboundModel && isRuntimeDefaultModelValue(inboundModel)) {
|
|
7770
|
+
delete metadata.preferred_model;
|
|
7771
|
+
delete metadata.model;
|
|
7772
|
+
} else if (inboundModel) {
|
|
7773
|
+
metadata.preferred_model = inboundModel;
|
|
7774
|
+
metadata.model = inboundModel;
|
|
7775
|
+
}
|
|
7260
7776
|
return {
|
|
7261
7777
|
metadata,
|
|
7262
|
-
model: normalizeOptionalString(metadata.preferred_model) ?? fallbackModel
|
|
7778
|
+
model: (isRuntimeDefaultModelValue(metadata.preferred_model) ? void 0 : normalizeOptionalString(metadata.preferred_model)) ?? fallbackModel
|
|
7263
7779
|
};
|
|
7264
7780
|
}
|
|
7265
7781
|
function syncSessionThinkingPreference(params) {
|
|
@@ -7290,30 +7806,6 @@ function resolveSessionChannelContext(params) {
|
|
|
7290
7806
|
//#endregion
|
|
7291
7807
|
//#region src/features/native-runtime/utils/nextclaw-ncp-run-context.utils.ts
|
|
7292
7808
|
const REQUESTED_SKILLS_METADATA_READER = new RequestedSkillsMetadataReader();
|
|
7293
|
-
function readRequestedAgentId(metadata) {
|
|
7294
|
-
return normalizeOptionalString(metadata.agent_id)?.toLowerCase() ?? normalizeOptionalString(metadata.agentId)?.toLowerCase() ?? null;
|
|
7295
|
-
}
|
|
7296
|
-
function resolveAgentProfile(params) {
|
|
7297
|
-
const { config, requestMetadata, storedAgentId } = params;
|
|
7298
|
-
const { agents: { defaults }, search: searchConfig, tools: { restrictToWorkspace, exec: { timeout: execTimeoutSeconds } } } = config;
|
|
7299
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
7300
|
-
const profile = findEffectiveAgentProfile(config, normalizeOptionalString(storedAgentId)?.toLowerCase() ?? readRequestedAgentId(requestMetadata) ?? defaultAgentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
7301
|
-
if (!profile) throw new Error(`default agent profile not found: ${defaultAgentId}`);
|
|
7302
|
-
const contextTokens = profile.contextTokens ?? defaults.contextTokens;
|
|
7303
|
-
return {
|
|
7304
|
-
agentId: profile.id,
|
|
7305
|
-
workspace: getWorkspacePath(profile.workspace ?? defaults.workspace),
|
|
7306
|
-
model: profile.model ?? defaults.model,
|
|
7307
|
-
contextTokens,
|
|
7308
|
-
reservedContextTokens: ContextWindowBudgetService.resolveReservedContextTokens({
|
|
7309
|
-
contextTokens,
|
|
7310
|
-
configuredReservedContextTokens: profile.reservedContextTokens ?? defaults.reservedContextTokens
|
|
7311
|
-
}),
|
|
7312
|
-
restrictToWorkspace,
|
|
7313
|
-
searchConfig,
|
|
7314
|
-
execTimeoutSeconds
|
|
7315
|
-
};
|
|
7316
|
-
}
|
|
7317
7809
|
function resolveRequestedToolNames(metadata) {
|
|
7318
7810
|
const rawValue = metadata.requested_tools ?? metadata.requestedTools;
|
|
7319
7811
|
if (!Array.isArray(rawValue)) return [];
|
|
@@ -7326,17 +7818,15 @@ function mergeRunMetadata(params) {
|
|
|
7326
7818
|
...requestMetadata ? structuredClone(requestMetadata) : {}
|
|
7327
7819
|
};
|
|
7328
7820
|
}
|
|
7329
|
-
function
|
|
7330
|
-
const {
|
|
7331
|
-
const config = configManager.loadConfig();
|
|
7821
|
+
function buildNextclawNcpRunContext(params) {
|
|
7822
|
+
const { agentProfile, config, requestMetadata: inputRequestMetadata, sessionId, sessionMetadata: inputSessionMetadata } = params;
|
|
7332
7823
|
const requestMetadata = mergeRunMetadata({
|
|
7333
7824
|
sessionMetadata: inputSessionMetadata,
|
|
7334
7825
|
requestMetadata: inputRequestMetadata
|
|
7335
7826
|
});
|
|
7336
|
-
const profile =
|
|
7827
|
+
const profile = buildResolvedAgentProfile({
|
|
7337
7828
|
config,
|
|
7338
|
-
|
|
7339
|
-
requestMetadata
|
|
7829
|
+
profile: agentProfile
|
|
7340
7830
|
});
|
|
7341
7831
|
const { metadata: modelMetadata, model: effectiveModel } = resolveEffectiveModel({
|
|
7342
7832
|
sessionMetadata: requestMetadata,
|
|
@@ -7387,213 +7877,20 @@ function resolveNextclawNcpRunContext(params) {
|
|
|
7387
7877
|
}
|
|
7388
7878
|
};
|
|
7389
7879
|
}
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
if (typeof value !== "string") return null;
|
|
7394
|
-
const normalized = value.trim().toLowerCase();
|
|
7395
|
-
return normalized.length > 0 ? normalized : null;
|
|
7396
|
-
}
|
|
7397
|
-
function cloneRuntimeEntry(entry) {
|
|
7398
|
-
return {
|
|
7399
|
-
id: entry.id,
|
|
7400
|
-
label: entry.label,
|
|
7401
|
-
...entry.icon ? { icon: { ...entry.icon } } : {},
|
|
7402
|
-
type: entry.type,
|
|
7403
|
-
enabled: entry.enabled !== false,
|
|
7404
|
-
config: entry.config ? { ...entry.config } : {}
|
|
7405
|
-
};
|
|
7406
|
-
}
|
|
7407
|
-
function normalizeAgentRuntimeSessionTypeIcon(value) {
|
|
7408
|
-
if (typeof value === "string") {
|
|
7409
|
-
const src = value.trim();
|
|
7410
|
-
return src ? {
|
|
7411
|
-
kind: "image",
|
|
7412
|
-
src
|
|
7413
|
-
} : null;
|
|
7414
|
-
}
|
|
7415
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
7416
|
-
const iconRecord = value;
|
|
7417
|
-
const src = typeof iconRecord.src === "string" ? iconRecord.src.trim() : "";
|
|
7418
|
-
if (!src) return null;
|
|
7419
|
-
const alt = typeof iconRecord.alt === "string" && iconRecord.alt.trim().length > 0 ? iconRecord.alt.trim() : null;
|
|
7420
|
-
return {
|
|
7421
|
-
kind: "image",
|
|
7422
|
-
src,
|
|
7423
|
-
...alt ? { alt } : {}
|
|
7424
|
-
};
|
|
7425
|
-
}
|
|
7426
|
-
const BUILTIN_RUNTIME_PRESENTATION = { hermes: {
|
|
7427
|
-
label: "Hermes",
|
|
7428
|
-
icon: {
|
|
7429
|
-
kind: "image",
|
|
7430
|
-
src: "app://runtime-icons/hermes-agent.png",
|
|
7431
|
-
alt: "Hermes"
|
|
7432
|
-
}
|
|
7433
|
-
} };
|
|
7434
|
-
function readString$2(value) {
|
|
7435
|
-
if (typeof value !== "string") return;
|
|
7436
|
-
return value.trim() || void 0;
|
|
7437
|
-
}
|
|
7438
|
-
function readRecord(value) {
|
|
7439
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
7440
|
-
return value;
|
|
7441
|
-
}
|
|
7442
|
-
function resolveBuiltinRuntimePresentation(value) {
|
|
7443
|
-
const normalized = readString$2(value)?.toLowerCase();
|
|
7444
|
-
if (!normalized) return null;
|
|
7445
|
-
if (!(normalized in BUILTIN_RUNTIME_PRESENTATION)) return null;
|
|
7446
|
-
return BUILTIN_RUNTIME_PRESENTATION[normalized] ?? null;
|
|
7447
|
-
}
|
|
7448
|
-
function buildNativeRuntimeEntry(config) {
|
|
7449
|
-
const nativeRuntimeConfig = readRecord(config.ui?.ncp?.runtimes?.native) ?? {};
|
|
7880
|
+
function buildResolvedAgentProfile(params) {
|
|
7881
|
+
const { config, profile } = params;
|
|
7882
|
+
const { search: searchConfig, tools: { restrictToWorkspace, exec: { timeout: execTimeoutSeconds } } } = config;
|
|
7450
7883
|
return {
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
const entries = /* @__PURE__ */ new Map();
|
|
7460
|
-
entries.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, buildNativeRuntimeEntry(params.config));
|
|
7461
|
-
for (const [rawId, rawEntry] of Object.entries(params.config.agents.runtimes.entries ?? {})) {
|
|
7462
|
-
const id = rawId.trim().toLowerCase();
|
|
7463
|
-
const type = readString$2(rawEntry.type)?.toLowerCase();
|
|
7464
|
-
if (!id || !type) continue;
|
|
7465
|
-
const explicitIcon = normalizeAgentRuntimeSessionTypeIcon(rawEntry.icon);
|
|
7466
|
-
const builtinPresentation = resolveBuiltinRuntimePresentation(id) ?? resolveBuiltinRuntimePresentation(type);
|
|
7467
|
-
entries.set(id, {
|
|
7468
|
-
id,
|
|
7469
|
-
label: readString$2(rawEntry.label) ?? builtinPresentation?.label ?? id,
|
|
7470
|
-
...explicitIcon ?? builtinPresentation?.icon ? { icon: explicitIcon ?? builtinPresentation?.icon } : {},
|
|
7471
|
-
type,
|
|
7472
|
-
enabled: rawEntry.enabled !== false,
|
|
7473
|
-
config: rawEntry.config ? { ...rawEntry.config } : {}
|
|
7474
|
-
});
|
|
7475
|
-
}
|
|
7476
|
-
return {
|
|
7477
|
-
defaultEntryId: entries.has("native") ? DEFAULT_AGENT_RUNTIME_ENTRY_ID : [...entries.keys()][0] ?? "native",
|
|
7478
|
-
entries: [...entries.values()]
|
|
7884
|
+
agentId: profile.id,
|
|
7885
|
+
workspace: getWorkspacePath(profile.workspace),
|
|
7886
|
+
model: profile.model,
|
|
7887
|
+
contextTokens: profile.contextTokens,
|
|
7888
|
+
reservedContextTokens: profile.reservedContextTokens,
|
|
7889
|
+
restrictToWorkspace,
|
|
7890
|
+
searchConfig,
|
|
7891
|
+
execTimeoutSeconds
|
|
7479
7892
|
};
|
|
7480
7893
|
}
|
|
7481
|
-
function readRequestedRuntimeEntryId(sessionMetadata) {
|
|
7482
|
-
return normalizeIdentifier(sessionMetadata.runtime) ?? normalizeIdentifier(sessionMetadata.session_type) ?? normalizeIdentifier(sessionMetadata.sessionType) ?? null;
|
|
7483
|
-
}
|
|
7484
|
-
var AgentRuntimeRegistry = class {
|
|
7485
|
-
providers = /* @__PURE__ */ new Map();
|
|
7486
|
-
entries = /* @__PURE__ */ new Map();
|
|
7487
|
-
defaultEntryId = DEFAULT_AGENT_RUNTIME_ENTRY_ID;
|
|
7488
|
-
register = (registration) => {
|
|
7489
|
-
const normalizedKind = normalizeIdentifier(registration.kind);
|
|
7490
|
-
if (!normalizedKind) throw new Error("agent runtime kind must be a non-empty string");
|
|
7491
|
-
const token = Symbol(normalizedKind);
|
|
7492
|
-
this.providers.set(normalizedKind, {
|
|
7493
|
-
...registration,
|
|
7494
|
-
kind: normalizedKind,
|
|
7495
|
-
token
|
|
7496
|
-
});
|
|
7497
|
-
return toDisposable(() => {
|
|
7498
|
-
const current = this.providers.get(normalizedKind);
|
|
7499
|
-
if (!current || current.token !== token) return;
|
|
7500
|
-
this.providers.delete(normalizedKind);
|
|
7501
|
-
});
|
|
7502
|
-
};
|
|
7503
|
-
applyEntries = (params) => {
|
|
7504
|
-
const nextEntries = /* @__PURE__ */ new Map();
|
|
7505
|
-
for (const rawEntry of params.entries) {
|
|
7506
|
-
const id = normalizeIdentifier(rawEntry.id);
|
|
7507
|
-
const type = normalizeIdentifier(rawEntry.type);
|
|
7508
|
-
const label = rawEntry.label?.trim() ?? "";
|
|
7509
|
-
if (!id || !type || !label) continue;
|
|
7510
|
-
nextEntries.set(id, cloneRuntimeEntry({
|
|
7511
|
-
...rawEntry,
|
|
7512
|
-
id,
|
|
7513
|
-
type,
|
|
7514
|
-
label
|
|
7515
|
-
}));
|
|
7516
|
-
}
|
|
7517
|
-
this.entries = nextEntries;
|
|
7518
|
-
this.defaultEntryId = normalizeIdentifier(params.defaultEntryId) ?? (nextEntries.has("native") ? "native" : [...nextEntries.keys()][0] ?? "native");
|
|
7519
|
-
};
|
|
7520
|
-
resolveSessionMetadata = (sessionMetadata) => {
|
|
7521
|
-
const { entry } = this.resolveRuntimeEntry(sessionMetadata);
|
|
7522
|
-
return {
|
|
7523
|
-
...sessionMetadata,
|
|
7524
|
-
runtime: entry.id,
|
|
7525
|
-
session_type: entry.id,
|
|
7526
|
-
runtime_type: entry.type
|
|
7527
|
-
};
|
|
7528
|
-
};
|
|
7529
|
-
createRuntime = (params) => {
|
|
7530
|
-
const nextSessionMetadata = this.resolveSessionMetadata(params.sessionMetadata);
|
|
7531
|
-
const { entry, provider } = this.resolveRuntimeEntry(nextSessionMetadata);
|
|
7532
|
-
if (provider.createRuntimeForEntry) return provider.createRuntimeForEntry({
|
|
7533
|
-
entry: cloneRuntimeEntry(entry),
|
|
7534
|
-
runtimeParams: {
|
|
7535
|
-
...params,
|
|
7536
|
-
sessionMetadata: nextSessionMetadata
|
|
7537
|
-
}
|
|
7538
|
-
});
|
|
7539
|
-
return provider.createRuntime({
|
|
7540
|
-
...params,
|
|
7541
|
-
sessionMetadata: nextSessionMetadata
|
|
7542
|
-
});
|
|
7543
|
-
};
|
|
7544
|
-
resolveRuntimeEntry = (sessionMetadata) => {
|
|
7545
|
-
const requestedEntryId = readRequestedRuntimeEntryId(sessionMetadata) ?? this.defaultEntryId;
|
|
7546
|
-
const entry = this.entries.get(requestedEntryId);
|
|
7547
|
-
if (!entry || entry.enabled === false) throw new Error(`ncp runtime unavailable: ${requestedEntryId}`);
|
|
7548
|
-
const provider = this.providers.get(entry.type);
|
|
7549
|
-
if (!provider) throw new Error(`ncp runtime provider unavailable: ${entry.type}`);
|
|
7550
|
-
return {
|
|
7551
|
-
entry,
|
|
7552
|
-
provider
|
|
7553
|
-
};
|
|
7554
|
-
};
|
|
7555
|
-
listSessionTypes = async (params) => {
|
|
7556
|
-
const options = await Promise.all([...this.entries.values()].filter((entry) => entry.enabled !== false).map(async (entry) => {
|
|
7557
|
-
const provider = this.providers.get(entry.type);
|
|
7558
|
-
if (!provider) return {
|
|
7559
|
-
value: entry.id,
|
|
7560
|
-
label: entry.label,
|
|
7561
|
-
icon: entry.icon ?? null,
|
|
7562
|
-
ready: false,
|
|
7563
|
-
reason: "runtime_provider_unavailable",
|
|
7564
|
-
reasonMessage: `Runtime provider unavailable for type "${entry.type}".`,
|
|
7565
|
-
recommendedModel: null,
|
|
7566
|
-
cta: {
|
|
7567
|
-
kind: "settings",
|
|
7568
|
-
label: "Configure Runtime"
|
|
7569
|
-
}
|
|
7570
|
-
};
|
|
7571
|
-
const descriptor = provider.describeSessionTypeForEntry ? await provider.describeSessionTypeForEntry({
|
|
7572
|
-
entry: cloneRuntimeEntry(entry),
|
|
7573
|
-
describeParams: params
|
|
7574
|
-
}) : await provider.describeSessionType?.(params);
|
|
7575
|
-
return {
|
|
7576
|
-
value: entry.id,
|
|
7577
|
-
label: entry.label,
|
|
7578
|
-
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
7579
|
-
ready: descriptor?.ready ?? true,
|
|
7580
|
-
reason: descriptor?.reason ?? null,
|
|
7581
|
-
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
7582
|
-
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
7583
|
-
cta: descriptor?.cta ?? null,
|
|
7584
|
-
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
7585
|
-
};
|
|
7586
|
-
}));
|
|
7587
|
-
return {
|
|
7588
|
-
defaultType: this.defaultEntryId,
|
|
7589
|
-
options: options.sort((left, right) => {
|
|
7590
|
-
if (left.value === this.defaultEntryId) return -1;
|
|
7591
|
-
if (right.value === this.defaultEntryId) return 1;
|
|
7592
|
-
return left.value.localeCompare(right.value);
|
|
7593
|
-
})
|
|
7594
|
-
};
|
|
7595
|
-
};
|
|
7596
|
-
};
|
|
7597
7894
|
//#endregion
|
|
7598
7895
|
//#region src/services/agent-run-message-projector.service.ts
|
|
7599
7896
|
var AgentRunMessageProjector = class {
|
|
@@ -7606,22 +7903,15 @@ var AgentRunMessageProjector = class {
|
|
|
7606
7903
|
//#region src/services/agent-run-model-input-budgeter.service.ts
|
|
7607
7904
|
var AgentRunModelInputBudgeter = class {
|
|
7608
7905
|
inputBudgetPruner = new InputBudgetPruner();
|
|
7609
|
-
constructor(
|
|
7610
|
-
this.
|
|
7906
|
+
constructor(agentManager) {
|
|
7907
|
+
this.agentManager = agentManager;
|
|
7611
7908
|
}
|
|
7612
7909
|
prune = async (params) => {
|
|
7613
|
-
const
|
|
7614
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
7615
|
-
const profile = findEffectiveAgentProfile(config, params.spec.agentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
7616
|
-
const contextTokens = profile?.contextTokens ?? config.agents.defaults.contextTokens;
|
|
7617
|
-
const reservedContextTokens = ContextWindowBudgetService.resolveReservedContextTokens({
|
|
7618
|
-
contextTokens,
|
|
7619
|
-
configuredReservedContextTokens: profile?.reservedContextTokens ?? config.agents.defaults.reservedContextTokens
|
|
7620
|
-
});
|
|
7910
|
+
const profile = this.agentManager.resolveAgentProfile(params.spec.agentId);
|
|
7621
7911
|
const pruned = this.inputBudgetPruner.prune({
|
|
7622
7912
|
messages: params.messages.map((message) => ({ ...message })),
|
|
7623
|
-
contextTokens,
|
|
7624
|
-
reserveTokensFloor: reservedContextTokens,
|
|
7913
|
+
contextTokens: profile.contextTokens,
|
|
7914
|
+
reserveTokensFloor: profile.reservedContextTokens,
|
|
7625
7915
|
softThresholdTokens: 0
|
|
7626
7916
|
});
|
|
7627
7917
|
return {
|
|
@@ -7685,7 +7975,8 @@ var NcpAgentRuntimeWrapper = class {
|
|
|
7685
7975
|
runId: spec.runId,
|
|
7686
7976
|
messages,
|
|
7687
7977
|
correlationId: spec.correlationId,
|
|
7688
|
-
metadata: this.buildMetadata(spec)
|
|
7978
|
+
metadata: this.buildMetadata(options.session, spec),
|
|
7979
|
+
executionContext: { cwd: options.session.workingDir }
|
|
7689
7980
|
};
|
|
7690
7981
|
for await (const event of this.getRuntime().run(input, { signal: options.signal })) yield await this.applyEvent(sessionRun, event);
|
|
7691
7982
|
this.currentTools = [];
|
|
@@ -7710,10 +8001,10 @@ var NcpAgentRuntimeWrapper = class {
|
|
|
7710
8001
|
correlationId: spec.correlationId
|
|
7711
8002
|
}
|
|
7712
8003
|
}));
|
|
7713
|
-
buildMetadata = (spec) => ({
|
|
7714
|
-
...
|
|
8004
|
+
buildMetadata = (session, spec) => ({
|
|
8005
|
+
...session.metadata,
|
|
7715
8006
|
agentId: spec.agentId,
|
|
7716
|
-
agentRuntimeId:
|
|
8007
|
+
agentRuntimeId: session.agentRuntimeId,
|
|
7717
8008
|
maxTokens: spec.maxTokens,
|
|
7718
8009
|
model: spec.model,
|
|
7719
8010
|
preferred_model: spec.model,
|
|
@@ -7736,18 +8027,22 @@ var AgentRunRuntimeContribution = class {
|
|
|
7736
8027
|
modelInputBuilder;
|
|
7737
8028
|
constructor(kernel) {
|
|
7738
8029
|
this.kernel = kernel;
|
|
7739
|
-
this.modelInputBuilder = new AgentRunModelInputBuilder(new AgentRunMessageProjector(), new AgentRunModelInputBudgeter(kernel.
|
|
8030
|
+
this.modelInputBuilder = new AgentRunModelInputBuilder(new AgentRunMessageProjector(), new AgentRunModelInputBudgeter(kernel.agents), kernel.assetStore);
|
|
7740
8031
|
}
|
|
7741
8032
|
start = () => {
|
|
7742
8033
|
if (this.cleanups.length > 0) return;
|
|
7743
|
-
|
|
7744
|
-
this.kernel.
|
|
8034
|
+
this.applyRuntimeConfig(this.kernel.configManager.loadConfig());
|
|
8035
|
+
this.kernel.configManager.installRuntimeHooks({ applyAgentRuntimeConfig: this.applyRuntimeConfig });
|
|
7745
8036
|
this.cleanups.push(this.registerNativeRuntime());
|
|
7746
8037
|
for (const provider of new BuiltinNarpRuntimeProviderService(this.kernel.configManager).createProviders()) this.cleanups.push(this.registerNarpRuntime(provider));
|
|
7747
8038
|
};
|
|
7748
8039
|
dispose = async () => {
|
|
7749
8040
|
while (this.cleanups.length > 0) await this.cleanups.pop()?.();
|
|
7750
8041
|
};
|
|
8042
|
+
applyRuntimeConfig = (config) => {
|
|
8043
|
+
const { entries } = resolveAgentRuntimeEntries({ config });
|
|
8044
|
+
this.kernel.agentRuntimeManager.applyEntries(entries);
|
|
8045
|
+
};
|
|
7751
8046
|
registerNativeRuntime = () => this.kernel.agentRuntimeManager.register({
|
|
7752
8047
|
kind: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
7753
8048
|
label: "Native",
|
|
@@ -7773,20 +8068,16 @@ var AgentRunRuntimeContribution = class {
|
|
|
7773
8068
|
describeSessionTypeForEntry: provider.describeSessionTypeForEntry,
|
|
7774
8069
|
createRuntime: ({ entry, session }) => {
|
|
7775
8070
|
if (!provider.createRuntimeForEntry) throw new Error(`Agent runtime provider does not support entries: ${provider.kind}`);
|
|
7776
|
-
return new NcpAgentRuntimeWrapper({
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
stateManager
|
|
7787
|
-
}
|
|
7788
|
-
})
|
|
7789
|
-
});
|
|
8071
|
+
return new NcpAgentRuntimeWrapper({ createRuntime: ({ resolveTools, stateManager }) => provider.createRuntimeForEntry({
|
|
8072
|
+
entry,
|
|
8073
|
+
runtimeParams: {
|
|
8074
|
+
...session.agentId ? { agentId: session.agentId } : {},
|
|
8075
|
+
resolveAssetContentPath: (assetUri) => this.kernel.assetStore.resolveContentPath(assetUri),
|
|
8076
|
+
resolveTools,
|
|
8077
|
+
sessionMetadata: session.metadata,
|
|
8078
|
+
stateManager
|
|
8079
|
+
}
|
|
8080
|
+
}) });
|
|
7790
8081
|
}
|
|
7791
8082
|
});
|
|
7792
8083
|
};
|
|
@@ -7952,6 +8243,13 @@ const createToolCallStyleContextProvider = () => staticBlock([
|
|
|
7952
8243
|
"Keep narration brief and value-dense; avoid repeating obvious steps.",
|
|
7953
8244
|
"Use plain human language for narration unless in a technical context."
|
|
7954
8245
|
]);
|
|
8246
|
+
const createInlineInteractiveSurfaceContextProvider = () => staticBlock([
|
|
8247
|
+
"## Inline Interactive Surfaces",
|
|
8248
|
+
"Do not make every UI an inline card. Choose inline only when the intended result is a compact, immediately usable card or short interaction; use the side panel for normal Panel Apps, long reading, rich editing, file browsing, large tables, multi-page workflows, or sustained workspaces.",
|
|
8249
|
+
"When you choose an inline card, call `show_content` with `type=\"panel_app\"` and `placement=\"inline\"` so the user can try it directly in the chat. Do not wait for the user to say \"inline\" or \"placement\" after you have already chosen the card form.",
|
|
8250
|
+
"A Panel Card must be designed card-first: prefer a landscape composition where width carries the main information and the card is wider than it is tall; collapse to one column only in narrow containers. Core value must be visible in the first 220-420px, with no horizontal scrolling, no reliance on document-level internal scrolling, compact controls, at most one primary action, clear loading/empty/error states, and an obvious expand path for details.",
|
|
8251
|
+
"Typical Panel Card fits: weather cards, calculators, timers, checklists, pickers, compact forms, previews, and small dashboards. If the UI needs more space than a card, choose `placement=\"side_panel\"` instead. Inline hosts may pass `nextclawDisplayMode=card` and `nextclawPlacement=inline`; use those hints to render a compact card layout instead of a full page."
|
|
8252
|
+
]);
|
|
7955
8253
|
const createChatComposerTokensContextProvider = () => staticBlock([
|
|
7956
8254
|
"## Chat Composer Tokens",
|
|
7957
8255
|
"When a user message contains tokens like `$weather` or `$web-search`, treat each `$<skill-spec>` token as a user-visible marker that the corresponding skill was explicitly selected in the chat composer.",
|
|
@@ -8316,12 +8614,15 @@ var ContextProviderRunContextService = class {
|
|
|
8316
8614
|
request,
|
|
8317
8615
|
session
|
|
8318
8616
|
});
|
|
8319
|
-
const runContext =
|
|
8320
|
-
|
|
8617
|
+
const runContext = buildNextclawNcpRunContext({
|
|
8618
|
+
agentProfile: this.kernel.agents.resolveAgentProfileForRun({
|
|
8619
|
+
requestMetadata,
|
|
8620
|
+
storedAgentId: request.agentId ?? session?.agentId
|
|
8621
|
+
}),
|
|
8622
|
+
config: this.kernel.configManager.loadConfig(),
|
|
8321
8623
|
sessionId,
|
|
8322
8624
|
requestMetadata,
|
|
8323
|
-
sessionMetadata: session?.metadata ?? requestMetadata
|
|
8324
|
-
storedAgentId: request.agentId ?? session?.agentId
|
|
8625
|
+
sessionMetadata: session?.metadata ?? requestMetadata
|
|
8325
8626
|
});
|
|
8326
8627
|
const tools = await this.kernel.toolProviderManager.buildTools(request);
|
|
8327
8628
|
const sessionProjectRoot = readSessionProjectRoot(runContext.sessionMetadata);
|
|
@@ -8355,6 +8656,7 @@ var ContextProviderContribution = class {
|
|
|
8355
8656
|
createAssistantIdentityContextProvider(),
|
|
8356
8657
|
new ToolingContextProvider(context),
|
|
8357
8658
|
createToolCallStyleContextProvider(),
|
|
8659
|
+
createInlineInteractiveSurfaceContextProvider(),
|
|
8358
8660
|
createChatComposerTokensContextProvider(),
|
|
8359
8661
|
createSafetyContextProvider(),
|
|
8360
8662
|
createCliQuickReferenceContextProvider(),
|
|
@@ -8395,7 +8697,7 @@ var ContextWindowContribution = class {
|
|
|
8395
8697
|
unsubscribeNcpEvent = null;
|
|
8396
8698
|
constructor(kernel) {
|
|
8397
8699
|
this.kernel = kernel;
|
|
8398
|
-
this.contextWindowPreview = new ContextCompactionPreflightService(
|
|
8700
|
+
this.contextWindowPreview = new ContextCompactionPreflightService(kernel.agents);
|
|
8399
8701
|
}
|
|
8400
8702
|
start = () => {
|
|
8401
8703
|
if (this.unsubscribeNcpEvent) return;
|
|
@@ -8622,270 +8924,22 @@ var LearningLoopContribution = class {
|
|
|
8622
8924
|
};
|
|
8623
8925
|
};
|
|
8624
8926
|
//#endregion
|
|
8625
|
-
//#region src/contributions/session-activity-preview/utils/session-activity-preview-ncp-event.utils.ts
|
|
8626
|
-
const PREVIEW_TEXT_MAX_LENGTH = 160;
|
|
8627
|
-
function readSessionId(value) {
|
|
8628
|
-
if (typeof value !== "string") return null;
|
|
8629
|
-
const trimmed = value.trim();
|
|
8630
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
8631
|
-
}
|
|
8632
|
-
function compactPreviewText(value) {
|
|
8633
|
-
return value.replace(/\s+/g, " ").trim();
|
|
8634
|
-
}
|
|
8635
|
-
function truncatePreviewText(value) {
|
|
8636
|
-
const compacted = compactPreviewText(value);
|
|
8637
|
-
if (compacted.length <= PREVIEW_TEXT_MAX_LENGTH) return compacted;
|
|
8638
|
-
return compacted.slice(0, PREVIEW_TEXT_MAX_LENGTH - 1).trimEnd();
|
|
8639
|
-
}
|
|
8640
|
-
function readMessagePreviewText(message) {
|
|
8641
|
-
const chunks = [];
|
|
8642
|
-
for (const part of message.parts) if ((part.type === "text" || part.type === "rich-text") && part.text.trim()) chunks.push(part.text);
|
|
8643
|
-
const previewText = truncatePreviewText(chunks.join(" "));
|
|
8644
|
-
return previewText.length > 0 ? previewText : null;
|
|
8645
|
-
}
|
|
8646
|
-
function createProjection(sessionId, preview) {
|
|
8647
|
-
if (!sessionId) return null;
|
|
8648
|
-
return {
|
|
8649
|
-
sessionId,
|
|
8650
|
-
preview
|
|
8651
|
-
};
|
|
8652
|
-
}
|
|
8653
|
-
function formatErrorStatus(error) {
|
|
8654
|
-
if (typeof error === "string" && error.trim()) return `运行出错:${truncatePreviewText(error)}`;
|
|
8655
|
-
if (error && typeof error === "object" && "message" in error) {
|
|
8656
|
-
const message = error.message;
|
|
8657
|
-
if (typeof message === "string" && message.trim()) return `运行出错:${truncatePreviewText(message)}`;
|
|
8658
|
-
}
|
|
8659
|
-
return "运行出错";
|
|
8660
|
-
}
|
|
8661
|
-
function readToolCallId(value) {
|
|
8662
|
-
if (typeof value !== "string") return null;
|
|
8663
|
-
const trimmed = value.trim();
|
|
8664
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
8665
|
-
}
|
|
8666
|
-
function formatToolDoneStatus(toolName) {
|
|
8667
|
-
return toolName ? `工具调用完成:${toolName}` : "工具调用完成";
|
|
8668
|
-
}
|
|
8669
|
-
function createSessionActivityPreviewFromNcpEvent(event, timestamp, options = {}) {
|
|
8670
|
-
switch (event.type) {
|
|
8671
|
-
case NcpEventType.RunStarted: return createProjection(readSessionId(event.payload.sessionId), {
|
|
8672
|
-
state: "running",
|
|
8673
|
-
statusText: "正在思考",
|
|
8674
|
-
timestamp
|
|
8675
|
-
});
|
|
8676
|
-
case NcpEventType.RunFinished: return createProjection(readSessionId(event.payload.sessionId), {
|
|
8677
|
-
state: "completed",
|
|
8678
|
-
timestamp
|
|
8679
|
-
});
|
|
8680
|
-
case NcpEventType.RunError: return createProjection(readSessionId(event.payload.sessionId), {
|
|
8681
|
-
state: "failed",
|
|
8682
|
-
statusText: formatErrorStatus(event.payload.error),
|
|
8683
|
-
timestamp
|
|
8684
|
-
});
|
|
8685
|
-
case NcpEventType.MessageSent: {
|
|
8686
|
-
const text = readMessagePreviewText(event.payload.message);
|
|
8687
|
-
if (!text || event.payload.message.role !== "user") return null;
|
|
8688
|
-
return createProjection(readSessionId(event.payload.sessionId), {
|
|
8689
|
-
state: "running",
|
|
8690
|
-
statusText: text,
|
|
8691
|
-
timestamp: event.payload.message.timestamp || timestamp
|
|
8692
|
-
});
|
|
8693
|
-
}
|
|
8694
|
-
case NcpEventType.MessageCompleted: {
|
|
8695
|
-
const text = readMessagePreviewText(event.payload.message);
|
|
8696
|
-
if (!text || event.payload.message.role !== "assistant") return null;
|
|
8697
|
-
return createProjection(readSessionId(event.payload.sessionId), {
|
|
8698
|
-
state: "completed",
|
|
8699
|
-
replyText: text,
|
|
8700
|
-
timestamp: event.payload.message.timestamp || timestamp
|
|
8701
|
-
});
|
|
8702
|
-
}
|
|
8703
|
-
case NcpEventType.MessageFailed: return createProjection(readSessionId(event.payload.sessionId), {
|
|
8704
|
-
state: "failed",
|
|
8705
|
-
statusText: formatErrorStatus(event.payload.error),
|
|
8706
|
-
timestamp
|
|
8707
|
-
});
|
|
8708
|
-
case NcpEventType.MessageToolCallStart: return createProjection(readSessionId(event.payload.sessionId), {
|
|
8709
|
-
state: "running",
|
|
8710
|
-
statusText: `正在调用工具:${event.payload.toolName}`,
|
|
8711
|
-
timestamp
|
|
8712
|
-
});
|
|
8713
|
-
case NcpEventType.MessageToolCallEnd:
|
|
8714
|
-
case NcpEventType.MessageToolCallResult: {
|
|
8715
|
-
const sessionId = readSessionId(event.payload.sessionId);
|
|
8716
|
-
const toolCallId = readToolCallId(event.payload.toolCallId);
|
|
8717
|
-
return createProjection(sessionId, {
|
|
8718
|
-
state: "running",
|
|
8719
|
-
statusText: formatToolDoneStatus(sessionId && toolCallId ? options.readToolName?.(sessionId, toolCallId) ?? null : null),
|
|
8720
|
-
timestamp
|
|
8721
|
-
});
|
|
8722
|
-
}
|
|
8723
|
-
default: return null;
|
|
8724
|
-
}
|
|
8725
|
-
}
|
|
8726
|
-
//#endregion
|
|
8727
|
-
//#region src/contributions/session-activity-preview/utils/session-activity-preview-metadata.utils.ts
|
|
8728
|
-
const SESSION_ACTIVITY_PREVIEW_METADATA_KEY = "last_activity_preview";
|
|
8729
|
-
const SESSION_ACTIVITY_PREVIEW_STATES = new Set([
|
|
8730
|
-
"running",
|
|
8731
|
-
"completed",
|
|
8732
|
-
"failed",
|
|
8733
|
-
"idle"
|
|
8734
|
-
]);
|
|
8735
|
-
function isRecord$2(value) {
|
|
8736
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8737
|
-
}
|
|
8738
|
-
function readOptionalString$3(value) {
|
|
8739
|
-
if (typeof value !== "string") return;
|
|
8740
|
-
const trimmed = value.trim();
|
|
8741
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
8742
|
-
}
|
|
8743
|
-
function readSessionActivityPreviewMetadata(value) {
|
|
8744
|
-
if (!isRecord$2(value)) return null;
|
|
8745
|
-
const state = value.state;
|
|
8746
|
-
const timestamp = readOptionalString$3(value.timestamp);
|
|
8747
|
-
if (!SESSION_ACTIVITY_PREVIEW_STATES.has(state) || !timestamp) return null;
|
|
8748
|
-
return {
|
|
8749
|
-
state,
|
|
8750
|
-
timestamp,
|
|
8751
|
-
...readOptionalString$3(value.statusText) ? { statusText: readOptionalString$3(value.statusText) } : {},
|
|
8752
|
-
...readOptionalString$3(value.replyText) ? { replyText: readOptionalString$3(value.replyText) } : {}
|
|
8753
|
-
};
|
|
8754
|
-
}
|
|
8755
|
-
function compareIsoTimestamp(left, right) {
|
|
8756
|
-
const leftTime = Date.parse(left);
|
|
8757
|
-
const rightTime = Date.parse(right);
|
|
8758
|
-
if (!Number.isFinite(leftTime) || !Number.isFinite(rightTime)) return left.localeCompare(right);
|
|
8759
|
-
return leftTime - rightTime;
|
|
8760
|
-
}
|
|
8761
|
-
function mergeSessionActivityPreview(current, incoming) {
|
|
8762
|
-
if (current && compareIsoTimestamp(incoming.timestamp, current.timestamp) < 0) return incoming.replyText && !current.replyText ? {
|
|
8763
|
-
...current,
|
|
8764
|
-
replyText: incoming.replyText
|
|
8765
|
-
} : current;
|
|
8766
|
-
return {
|
|
8767
|
-
state: incoming.state,
|
|
8768
|
-
timestamp: incoming.timestamp,
|
|
8769
|
-
...incoming.statusText ?? (incoming.state === "completed" ? current?.statusText : void 0) ? { statusText: incoming.statusText ?? current?.statusText } : {},
|
|
8770
|
-
...incoming.replyText ?? current?.replyText ? { replyText: incoming.replyText ?? current?.replyText } : {}
|
|
8771
|
-
};
|
|
8772
|
-
}
|
|
8773
|
-
function areSessionActivityPreviewsEqual(left, right) {
|
|
8774
|
-
return Boolean(left) && left?.state === right.state && left.timestamp === right.timestamp && left.statusText === right.statusText && left.replyText === right.replyText;
|
|
8775
|
-
}
|
|
8776
|
-
function writeSessionActivityPreviewMetadata(metadata, projection) {
|
|
8777
|
-
const current = readSessionActivityPreviewMetadata(metadata?.[SESSION_ACTIVITY_PREVIEW_METADATA_KEY]);
|
|
8778
|
-
const next = mergeSessionActivityPreview(current, projection.preview);
|
|
8779
|
-
if (areSessionActivityPreviewsEqual(current, next)) return null;
|
|
8780
|
-
return {
|
|
8781
|
-
...metadata ?? {},
|
|
8782
|
-
[SESSION_ACTIVITY_PREVIEW_METADATA_KEY]: next
|
|
8783
|
-
};
|
|
8784
|
-
}
|
|
8785
|
-
//#endregion
|
|
8786
|
-
//#region src/contributions/session-activity-preview/index.ts
|
|
8787
|
-
var SessionActivityPreviewContribution = class {
|
|
8788
|
-
unsubscribeNcpEvent = null;
|
|
8789
|
-
metadataWriteChains = /* @__PURE__ */ new Map();
|
|
8790
|
-
toolNames = /* @__PURE__ */ new Map();
|
|
8791
|
-
constructor(kernel) {
|
|
8792
|
-
this.kernel = kernel;
|
|
8793
|
-
}
|
|
8794
|
-
start = () => {
|
|
8795
|
-
if (this.unsubscribeNcpEvent) return;
|
|
8796
|
-
this.unsubscribeNcpEvent = this.kernel.eventBus.on(eventKeys.ncpEvent, (event) => {
|
|
8797
|
-
this.rememberToolName(event);
|
|
8798
|
-
const projection = createSessionActivityPreviewFromNcpEvent(event, (/* @__PURE__ */ new Date()).toISOString(), { readToolName: this.readToolName });
|
|
8799
|
-
this.clearFinishedRunToolNames(event);
|
|
8800
|
-
if (!projection) return;
|
|
8801
|
-
this.updatePreview(projection);
|
|
8802
|
-
});
|
|
8803
|
-
};
|
|
8804
|
-
dispose = () => {
|
|
8805
|
-
this.unsubscribeNcpEvent?.();
|
|
8806
|
-
this.unsubscribeNcpEvent = null;
|
|
8807
|
-
this.metadataWriteChains.clear();
|
|
8808
|
-
this.toolNames.clear();
|
|
8809
|
-
};
|
|
8810
|
-
rememberToolName = (event) => {
|
|
8811
|
-
if (event.type !== NcpEventType.MessageToolCallStart) return;
|
|
8812
|
-
const sessionId = event.payload.sessionId.trim();
|
|
8813
|
-
const toolCallId = event.payload.toolCallId.trim();
|
|
8814
|
-
const toolName = event.payload.toolName.trim();
|
|
8815
|
-
if (!sessionId || !toolCallId || !toolName) return;
|
|
8816
|
-
this.toolNames.set(this.createToolNameKey(sessionId, toolCallId), toolName);
|
|
8817
|
-
};
|
|
8818
|
-
readToolName = (sessionId, toolCallId) => this.toolNames.get(this.createToolNameKey(sessionId, toolCallId)) ?? null;
|
|
8819
|
-
clearFinishedRunToolNames = (event) => {
|
|
8820
|
-
if (event.type !== NcpEventType.RunFinished && event.type !== NcpEventType.RunError) return;
|
|
8821
|
-
const sessionId = this.readNonEmptyString(event.payload.sessionId);
|
|
8822
|
-
if (!sessionId) return;
|
|
8823
|
-
for (const key of this.toolNames.keys()) if (key.startsWith(`${sessionId}:`)) this.toolNames.delete(key);
|
|
8824
|
-
};
|
|
8825
|
-
readNonEmptyString = (value) => {
|
|
8826
|
-
if (typeof value !== "string") return null;
|
|
8827
|
-
const trimmed = value.trim();
|
|
8828
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
8829
|
-
};
|
|
8830
|
-
createToolNameKey = (sessionId, toolCallId) => `${sessionId}:${toolCallId}`;
|
|
8831
|
-
updatePreview = (projection) => {
|
|
8832
|
-
const next = (this.metadataWriteChains.get(projection.sessionId) ?? Promise.resolve()).then(() => this.updatePreviewMetadata(projection));
|
|
8833
|
-
this.metadataWriteChains.set(projection.sessionId, next.catch(() => void 0));
|
|
8834
|
-
next.catch((error) => {
|
|
8835
|
-
const message = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
8836
|
-
console.error(`[session-activity-preview] failed to update ${projection.sessionId}: ${message}`);
|
|
8837
|
-
});
|
|
8838
|
-
};
|
|
8839
|
-
updatePreviewMetadata = async (projection) => {
|
|
8840
|
-
const nextMetadata = writeSessionActivityPreviewMetadata((await this.kernel.sessionManager.getSessionRecord(projection.sessionId))?.metadata, projection);
|
|
8841
|
-
if (!nextMetadata) return;
|
|
8842
|
-
await this.kernel.sessionManager.updateSessionMetadata(projection.sessionId, nextMetadata);
|
|
8843
|
-
};
|
|
8844
|
-
};
|
|
8845
|
-
//#endregion
|
|
8846
8927
|
//#region src/contributions/tool-provider/providers/asset-tool.provider.ts
|
|
8847
8928
|
var AssetToolProvider = class {
|
|
8848
|
-
constructor(
|
|
8849
|
-
this.
|
|
8929
|
+
constructor(assetStore) {
|
|
8930
|
+
this.assetStore = assetStore;
|
|
8850
8931
|
}
|
|
8851
|
-
provide = async (_request) => createAssetTools({ assetStore: this.
|
|
8932
|
+
provide = async (_request) => createAssetTools({ assetStore: this.assetStore });
|
|
8852
8933
|
};
|
|
8853
8934
|
//#endregion
|
|
8854
|
-
//#region src/contributions/tool-provider/utils/tool-provider-run-context.utils.ts
|
|
8855
|
-
async function resolveToolProviderRunContext(params) {
|
|
8856
|
-
const { kernel, request } = params;
|
|
8857
|
-
const session = request.sessionId ? await kernel.sessionManager.getAgentRunSession(request.sessionId) : null;
|
|
8858
|
-
const sessionId = session?.sessionId ?? request.sessionId ?? request.message.sessionId ?? "";
|
|
8859
|
-
const requestMetadata = buildAgentRunRequestMetadata({
|
|
8860
|
-
request,
|
|
8861
|
-
session
|
|
8862
|
-
});
|
|
8863
|
-
const runContext = resolveNextclawNcpRunContext({
|
|
8864
|
-
configManager: kernel.configManager,
|
|
8865
|
-
sessionId,
|
|
8866
|
-
requestMetadata,
|
|
8867
|
-
sessionMetadata: session?.metadata ?? requestMetadata,
|
|
8868
|
-
storedAgentId: request.agentId ?? session?.agentId
|
|
8869
|
-
});
|
|
8870
|
-
return {
|
|
8871
|
-
requestMetadata,
|
|
8872
|
-
runContext,
|
|
8873
|
-
session,
|
|
8874
|
-
sessionId,
|
|
8875
|
-
toolRunContext: runContext.toolRunContext
|
|
8876
|
-
};
|
|
8877
|
-
}
|
|
8878
|
-
//#endregion
|
|
8879
8935
|
//#region src/contributions/tool-provider/providers/core-tool.provider.ts
|
|
8880
8936
|
var CoreToolProvider = class {
|
|
8881
|
-
constructor(
|
|
8882
|
-
this.
|
|
8937
|
+
constructor(runContextService, getGatewayController) {
|
|
8938
|
+
this.runContextService = runContextService;
|
|
8939
|
+
this.getGatewayController = getGatewayController;
|
|
8883
8940
|
}
|
|
8884
8941
|
provide = async (request) => {
|
|
8885
|
-
const { toolRunContext } = await
|
|
8886
|
-
kernel: this.kernel,
|
|
8887
|
-
request
|
|
8888
|
-
});
|
|
8942
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
8889
8943
|
const { channel, chatId, execTimeoutSeconds, restrictToWorkspace, searchConfig, sessionId, workspace } = toolRunContext;
|
|
8890
8944
|
const allowedDir = restrictToWorkspace ? workspace : void 0;
|
|
8891
8945
|
const execTool = new ExecTool({
|
|
@@ -8898,7 +8952,7 @@ var CoreToolProvider = class {
|
|
|
8898
8952
|
chatId,
|
|
8899
8953
|
sessionKey: sessionId
|
|
8900
8954
|
});
|
|
8901
|
-
const gatewayTool = new GatewayTool(this.
|
|
8955
|
+
const gatewayTool = new GatewayTool(this.getGatewayController());
|
|
8902
8956
|
gatewayTool.setContext({ sessionKey: sessionId });
|
|
8903
8957
|
return [
|
|
8904
8958
|
new ReadFileTool(allowedDir),
|
|
@@ -8917,15 +8971,13 @@ var CoreToolProvider = class {
|
|
|
8917
8971
|
//#endregion
|
|
8918
8972
|
//#region src/contributions/tool-provider/providers/mcp-tool.provider.ts
|
|
8919
8973
|
var McpToolProvider = class {
|
|
8920
|
-
constructor(
|
|
8921
|
-
this.
|
|
8974
|
+
constructor(runContextService, mcpManager) {
|
|
8975
|
+
this.runContextService = runContextService;
|
|
8976
|
+
this.mcpManager = mcpManager;
|
|
8922
8977
|
}
|
|
8923
8978
|
provide = async (request) => {
|
|
8924
|
-
const { toolRunContext } = await
|
|
8925
|
-
|
|
8926
|
-
request
|
|
8927
|
-
});
|
|
8928
|
-
return this.kernel.mcpManager.listToolsForRun({ agentId: toolRunContext.agentId });
|
|
8979
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
8980
|
+
return this.mcpManager.listToolsForRun({ agentId: toolRunContext.agentId });
|
|
8929
8981
|
};
|
|
8930
8982
|
};
|
|
8931
8983
|
//#endregion
|
|
@@ -8938,24 +8990,24 @@ function readMetadataAccountId(metadata) {
|
|
|
8938
8990
|
}
|
|
8939
8991
|
}
|
|
8940
8992
|
var MessagingToolProvider = class {
|
|
8941
|
-
constructor(
|
|
8942
|
-
this.
|
|
8993
|
+
constructor(runContextService, channels, automation, extensions) {
|
|
8994
|
+
this.runContextService = runContextService;
|
|
8995
|
+
this.channels = channels;
|
|
8996
|
+
this.automation = automation;
|
|
8997
|
+
this.extensions = extensions;
|
|
8943
8998
|
}
|
|
8944
8999
|
provide = async (request) => {
|
|
8945
|
-
const { toolRunContext } = await
|
|
8946
|
-
kernel: this.kernel,
|
|
8947
|
-
request
|
|
8948
|
-
});
|
|
9000
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
8949
9001
|
const { channel, chatId, metadata } = toolRunContext;
|
|
8950
9002
|
const accountId = readMetadataAccountId(metadata);
|
|
8951
9003
|
const messageTool = new MessageTool(async (message) => {
|
|
8952
|
-
if (!await this.
|
|
9004
|
+
if (!await this.channels.deliver(message)) throw new Error(`channel "${message.channel}" is not available`);
|
|
8953
9005
|
}, { resolveChannels: this.resolveMessageChannels });
|
|
8954
9006
|
messageTool.setContext(channel, chatId, accountId ?? null);
|
|
8955
|
-
return [messageTool, new CronTool(this.
|
|
9007
|
+
return [messageTool, new CronTool(this.automation)];
|
|
8956
9008
|
};
|
|
8957
9009
|
resolveMessageChannels = () => {
|
|
8958
|
-
const channels = this.
|
|
9010
|
+
const channels = this.extensions.getExtensionRegistry()?.channels ?? [];
|
|
8959
9011
|
return [...new Set(channels.map((registration) => registration.channel.id.trim()).filter(Boolean))].sort();
|
|
8960
9012
|
};
|
|
8961
9013
|
};
|
|
@@ -9094,12 +9146,12 @@ var SessionsHistoryTool = class {
|
|
|
9094
9146
|
};
|
|
9095
9147
|
//#endregion
|
|
9096
9148
|
//#region src/tools/session-request.tools.ts
|
|
9097
|
-
function readRequiredString$
|
|
9149
|
+
function readRequiredString$2(params, key) {
|
|
9098
9150
|
const value = params[key];
|
|
9099
9151
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9100
9152
|
return value.trim();
|
|
9101
9153
|
}
|
|
9102
|
-
function readOptionalString$
|
|
9154
|
+
function readOptionalString$3(params, key) {
|
|
9103
9155
|
const value = params[key];
|
|
9104
9156
|
if (typeof value !== "string") return;
|
|
9105
9157
|
const trimmed = value.trim();
|
|
@@ -9153,16 +9205,16 @@ var SessionRequestTool = class {
|
|
|
9153
9205
|
const params = normalizeToolParams(args);
|
|
9154
9206
|
const target = params.target;
|
|
9155
9207
|
if (!target || typeof target !== "object" || Array.isArray(target)) throw new Error("target must be an object.");
|
|
9156
|
-
const task = readRequiredString$
|
|
9157
|
-
const notifyMode = readOptionalString$
|
|
9208
|
+
const task = readRequiredString$2(params, "task");
|
|
9209
|
+
const notifyMode = readOptionalString$3(params, "notify")?.toLowerCase();
|
|
9158
9210
|
if (notifyMode !== "none" && notifyMode !== "final_reply") throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
9159
9211
|
return this.manager.requestSession({
|
|
9160
9212
|
sourceSessionId: this.sourceSessionId,
|
|
9161
9213
|
sourceToolCallId: context?.toolCallId,
|
|
9162
9214
|
updateToolCallResult: context?.updateToolCallResult,
|
|
9163
|
-
targetSessionId: readRequiredString$
|
|
9215
|
+
targetSessionId: readRequiredString$2(target, "session_id"),
|
|
9164
9216
|
task,
|
|
9165
|
-
title: readOptionalString$
|
|
9217
|
+
title: readOptionalString$3(params, "title"),
|
|
9166
9218
|
notify: notifyMode,
|
|
9167
9219
|
handoffDepth: this.handoffDepth
|
|
9168
9220
|
});
|
|
@@ -9170,7 +9222,7 @@ var SessionRequestTool = class {
|
|
|
9170
9222
|
};
|
|
9171
9223
|
//#endregion
|
|
9172
9224
|
//#region src/tools/session-search.tools.ts
|
|
9173
|
-
function isRecord$
|
|
9225
|
+
function isRecord$2(value) {
|
|
9174
9226
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9175
9227
|
}
|
|
9176
9228
|
function readOptionalInteger(value) {
|
|
@@ -9220,7 +9272,7 @@ var SessionSearchTool = class {
|
|
|
9220
9272
|
return issues;
|
|
9221
9273
|
};
|
|
9222
9274
|
execute = async (args) => {
|
|
9223
|
-
if (!isRecord$
|
|
9275
|
+
if (!isRecord$2(args)) throw new Error("session_search requires an object argument.");
|
|
9224
9276
|
const issues = this.validateArgs(args);
|
|
9225
9277
|
if (issues.length > 0) throw new Error(issues.join(" "));
|
|
9226
9278
|
return this.queryService.search({
|
|
@@ -9233,23 +9285,23 @@ var SessionSearchTool = class {
|
|
|
9233
9285
|
};
|
|
9234
9286
|
//#endregion
|
|
9235
9287
|
//#region src/tools/session-spawn.tools.ts
|
|
9236
|
-
function readRequiredString(value, key) {
|
|
9288
|
+
function readRequiredString$1(value, key) {
|
|
9237
9289
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9238
9290
|
return value.trim();
|
|
9239
9291
|
}
|
|
9240
|
-
function readOptionalString$
|
|
9292
|
+
function readOptionalString$2(value) {
|
|
9241
9293
|
if (typeof value !== "string") return;
|
|
9242
9294
|
const trimmed = value.trim();
|
|
9243
9295
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
9244
9296
|
}
|
|
9245
9297
|
function readSpawnScope(value) {
|
|
9246
|
-
const normalized = readOptionalString$
|
|
9298
|
+
const normalized = readOptionalString$2(value)?.toLowerCase();
|
|
9247
9299
|
if (!normalized || normalized === "standalone") return "standalone";
|
|
9248
9300
|
if (normalized === "child") return "child";
|
|
9249
9301
|
throw new Error("scope must be \"standalone\" or \"child\".");
|
|
9250
9302
|
}
|
|
9251
9303
|
function readSpawnNotify(value) {
|
|
9252
|
-
const notifyMode = readOptionalString$
|
|
9304
|
+
const notifyMode = readOptionalString$2(value)?.toLowerCase();
|
|
9253
9305
|
if (!notifyMode && typeof value === "undefined") return;
|
|
9254
9306
|
if (notifyMode === "none" || notifyMode === "final_reply") return notifyMode;
|
|
9255
9307
|
throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
@@ -9308,7 +9360,7 @@ var SessionSpawnTool = class {
|
|
|
9308
9360
|
};
|
|
9309
9361
|
execute = async (args, context) => {
|
|
9310
9362
|
const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle } = normalizeToolParams(args);
|
|
9311
|
-
const task = readRequiredString(rawTask, "task");
|
|
9363
|
+
const task = readRequiredString$1(rawTask, "task");
|
|
9312
9364
|
const scope = readSpawnScope(rawScope);
|
|
9313
9365
|
const notify = readSpawnNotify(rawNotify);
|
|
9314
9366
|
const parentSessionId = scope === "child" ? this.readParentSessionIdOrThrow() : void 0;
|
|
@@ -9318,10 +9370,10 @@ var SessionSpawnTool = class {
|
|
|
9318
9370
|
updateToolCallResult: context?.updateToolCallResult,
|
|
9319
9371
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9320
9372
|
task,
|
|
9321
|
-
title: readOptionalString$
|
|
9322
|
-
agentId: readOptionalString$
|
|
9323
|
-
model: readOptionalString$
|
|
9324
|
-
runtime: readOptionalString$
|
|
9373
|
+
title: readOptionalString$2(rawTitle),
|
|
9374
|
+
agentId: readOptionalString$2(rawAgentId),
|
|
9375
|
+
model: readOptionalString$2(rawModel),
|
|
9376
|
+
runtime: readOptionalString$2(rawRuntime),
|
|
9325
9377
|
handoffDepth: this.handoffDepth,
|
|
9326
9378
|
parentSessionId,
|
|
9327
9379
|
notify
|
|
@@ -9329,11 +9381,11 @@ var SessionSpawnTool = class {
|
|
|
9329
9381
|
const session = await this.sessionManager.createSession({
|
|
9330
9382
|
sourceSessionId: this.sourceSessionId,
|
|
9331
9383
|
task,
|
|
9332
|
-
title: readOptionalString$
|
|
9384
|
+
title: readOptionalString$2(rawTitle),
|
|
9333
9385
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9334
|
-
agentId: readOptionalString$
|
|
9335
|
-
model: readOptionalString$
|
|
9336
|
-
runtime: readOptionalString$
|
|
9386
|
+
agentId: readOptionalString$2(rawAgentId),
|
|
9387
|
+
model: readOptionalString$2(rawModel),
|
|
9388
|
+
runtime: readOptionalString$2(rawRuntime),
|
|
9337
9389
|
parentSessionId
|
|
9338
9390
|
});
|
|
9339
9391
|
return {
|
|
@@ -9357,22 +9409,22 @@ var SessionSpawnTool = class {
|
|
|
9357
9409
|
//#endregion
|
|
9358
9410
|
//#region src/contributions/tool-provider/providers/session-tool.provider.ts
|
|
9359
9411
|
var SessionToolProvider = class {
|
|
9360
|
-
constructor(
|
|
9361
|
-
this.
|
|
9412
|
+
constructor(runContextService, sessionManager, sessionRequests, sessionSearch) {
|
|
9413
|
+
this.runContextService = runContextService;
|
|
9414
|
+
this.sessionManager = sessionManager;
|
|
9415
|
+
this.sessionRequests = sessionRequests;
|
|
9416
|
+
this.sessionSearch = sessionSearch;
|
|
9362
9417
|
}
|
|
9363
9418
|
provide = async (request) => {
|
|
9364
|
-
const { toolRunContext } = await
|
|
9365
|
-
kernel: this.kernel,
|
|
9366
|
-
request
|
|
9367
|
-
});
|
|
9419
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
9368
9420
|
const { handoffDepth, metadata, sessionId } = toolRunContext;
|
|
9369
|
-
const sessionsSpawnTool = new SessionSpawnTool(this.
|
|
9421
|
+
const sessionsSpawnTool = new SessionSpawnTool(this.sessionManager, this.sessionRequests);
|
|
9370
9422
|
sessionsSpawnTool.setContext({
|
|
9371
9423
|
sourceSessionId: sessionId,
|
|
9372
9424
|
sourceSessionMetadata: metadata,
|
|
9373
9425
|
handoffDepth
|
|
9374
9426
|
});
|
|
9375
|
-
const sessionsRequestTool = new SessionRequestTool(this.
|
|
9427
|
+
const sessionsRequestTool = new SessionRequestTool(this.sessionRequests);
|
|
9376
9428
|
sessionsRequestTool.setContext({
|
|
9377
9429
|
sourceSessionId: sessionId,
|
|
9378
9430
|
handoffDepth
|
|
@@ -9380,15 +9432,188 @@ var SessionToolProvider = class {
|
|
|
9380
9432
|
const tools = [
|
|
9381
9433
|
sessionsSpawnTool,
|
|
9382
9434
|
sessionsRequestTool,
|
|
9383
|
-
new SessionsListTool(this.
|
|
9384
|
-
new SessionsHistoryTool(this.
|
|
9435
|
+
new SessionsListTool(this.sessionManager),
|
|
9436
|
+
new SessionsHistoryTool(this.sessionManager)
|
|
9385
9437
|
];
|
|
9386
|
-
if (!this.
|
|
9387
|
-
tools.push(new SessionSearchTool({ search: this.
|
|
9438
|
+
if (!this.sessionSearch.isReady()) return tools;
|
|
9439
|
+
tools.push(new SessionSearchTool({ search: this.sessionSearch.search }, { currentSessionId: sessionId }));
|
|
9388
9440
|
return tools;
|
|
9389
9441
|
};
|
|
9390
9442
|
};
|
|
9391
9443
|
//#endregion
|
|
9444
|
+
//#region src/tools/show-content.tools.ts
|
|
9445
|
+
const SHOW_CONTENT_TOOL_NAME = "show_content";
|
|
9446
|
+
function isRecord$1(value) {
|
|
9447
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9448
|
+
}
|
|
9449
|
+
function readRequiredString(value, key) {
|
|
9450
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9451
|
+
return value.trim();
|
|
9452
|
+
}
|
|
9453
|
+
function readOptionalString$1(value) {
|
|
9454
|
+
if (typeof value !== "string") return;
|
|
9455
|
+
const trimmed = value.trim();
|
|
9456
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
9457
|
+
}
|
|
9458
|
+
function readOptionalPositiveInteger(value, key) {
|
|
9459
|
+
if (typeof value === "undefined") return;
|
|
9460
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) throw new Error(`${key} must be a positive integer.`);
|
|
9461
|
+
return value;
|
|
9462
|
+
}
|
|
9463
|
+
function readPurpose(value) {
|
|
9464
|
+
const normalized = readOptionalString$1(value);
|
|
9465
|
+
if (!normalized) return;
|
|
9466
|
+
if (normalized === "read" || normalized === "preview" || normalized === "edit" || normalized === "interact") return normalized;
|
|
9467
|
+
throw new Error("purpose must be \"read\", \"preview\", \"edit\", or \"interact\".");
|
|
9468
|
+
}
|
|
9469
|
+
function readPlacement(value) {
|
|
9470
|
+
const normalized = readOptionalString$1(value);
|
|
9471
|
+
if (!normalized) return;
|
|
9472
|
+
if (normalized === "inline" || normalized === "side_panel") return normalized;
|
|
9473
|
+
throw new Error("placement must be \"inline\" or \"side_panel\".");
|
|
9474
|
+
}
|
|
9475
|
+
function readPayload(params) {
|
|
9476
|
+
if (!isRecord$1(params.payload)) throw new Error("payload must be an object.");
|
|
9477
|
+
return params.payload;
|
|
9478
|
+
}
|
|
9479
|
+
function readUrl(value) {
|
|
9480
|
+
const url = readRequiredString(value, "payload.url");
|
|
9481
|
+
let parsed;
|
|
9482
|
+
try {
|
|
9483
|
+
parsed = new URL(url);
|
|
9484
|
+
} catch {
|
|
9485
|
+
throw new Error("payload.url must be a valid URL.");
|
|
9486
|
+
}
|
|
9487
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error("payload.url must use http or https.");
|
|
9488
|
+
return parsed.toString();
|
|
9489
|
+
}
|
|
9490
|
+
function normalizeShowContentArgs(args) {
|
|
9491
|
+
const params = normalizeToolParams(args);
|
|
9492
|
+
const type = readRequiredString(params.type, "type");
|
|
9493
|
+
const payload = readPayload(params);
|
|
9494
|
+
const title = readOptionalString$1(params.title);
|
|
9495
|
+
const purpose = readPurpose(params.purpose);
|
|
9496
|
+
const placement = readPlacement(params.placement);
|
|
9497
|
+
if (type === "file") return {
|
|
9498
|
+
target: {
|
|
9499
|
+
type,
|
|
9500
|
+
payload: {
|
|
9501
|
+
path: readRequiredString(payload.path, "payload.path"),
|
|
9502
|
+
line: readOptionalPositiveInteger(payload.line, "payload.line"),
|
|
9503
|
+
column: readOptionalPositiveInteger(payload.column, "payload.column")
|
|
9504
|
+
}
|
|
9505
|
+
},
|
|
9506
|
+
title,
|
|
9507
|
+
purpose,
|
|
9508
|
+
placement
|
|
9509
|
+
};
|
|
9510
|
+
if (type === "url") return {
|
|
9511
|
+
target: {
|
|
9512
|
+
type,
|
|
9513
|
+
payload: { url: readUrl(payload.url) }
|
|
9514
|
+
},
|
|
9515
|
+
title,
|
|
9516
|
+
purpose,
|
|
9517
|
+
placement
|
|
9518
|
+
};
|
|
9519
|
+
if (type === "panel_app") return {
|
|
9520
|
+
target: {
|
|
9521
|
+
type,
|
|
9522
|
+
payload: { appId: readRequiredString(payload.appId, "payload.appId") }
|
|
9523
|
+
},
|
|
9524
|
+
title,
|
|
9525
|
+
purpose,
|
|
9526
|
+
placement
|
|
9527
|
+
};
|
|
9528
|
+
throw new Error("type must be \"file\", \"url\", or \"panel_app\".");
|
|
9529
|
+
}
|
|
9530
|
+
function summarizeTarget(target) {
|
|
9531
|
+
if (target.type === "file") return target.payload.path;
|
|
9532
|
+
if (target.type === "url") return target.payload.url;
|
|
9533
|
+
return target.payload.appId;
|
|
9534
|
+
}
|
|
9535
|
+
function createShowContentEventPayload(request, context) {
|
|
9536
|
+
const toolCallId = readOptionalString$1(context?.toolCallId);
|
|
9537
|
+
return {
|
|
9538
|
+
id: toolCallId ? `tool:${toolCallId}:show-content` : `show-content:${request.target.type}:${summarizeTarget(request.target)}`,
|
|
9539
|
+
toolCallId,
|
|
9540
|
+
target: request.target,
|
|
9541
|
+
title: request.title,
|
|
9542
|
+
purpose: request.purpose,
|
|
9543
|
+
placement: request.placement
|
|
9544
|
+
};
|
|
9545
|
+
}
|
|
9546
|
+
var ShowContentTool = class {
|
|
9547
|
+
name = SHOW_CONTENT_TOOL_NAME;
|
|
9548
|
+
description = [
|
|
9549
|
+
"Show file, URL, or panel app content in the current chat UI.",
|
|
9550
|
+
"placement=\"inline\" embeds a lightweight panel_app as an interactive chat card so the user can try it directly in the conversation.",
|
|
9551
|
+
"placement=\"side_panel\" opens content in the right side panel for larger reading, editing, or sustained workflows.",
|
|
9552
|
+
"Choose the placement yourself: after creating a lightweight Panel App such as a weather card, calculator, timer, checklist, picker, form, preview, or small dashboard, call this tool with placement=\"inline\" without waiting for the user to ask to see it.",
|
|
9553
|
+
"Omit placement only when preserving the existing default side panel behavior is intentional."
|
|
9554
|
+
].join(" ");
|
|
9555
|
+
parameters = {
|
|
9556
|
+
type: "object",
|
|
9557
|
+
properties: {
|
|
9558
|
+
type: {
|
|
9559
|
+
type: "string",
|
|
9560
|
+
enum: [
|
|
9561
|
+
"file",
|
|
9562
|
+
"url",
|
|
9563
|
+
"panel_app"
|
|
9564
|
+
],
|
|
9565
|
+
description: "Content target type."
|
|
9566
|
+
},
|
|
9567
|
+
title: {
|
|
9568
|
+
type: "string",
|
|
9569
|
+
description: "Optional title for the shown content."
|
|
9570
|
+
},
|
|
9571
|
+
purpose: {
|
|
9572
|
+
type: "string",
|
|
9573
|
+
enum: [
|
|
9574
|
+
"read",
|
|
9575
|
+
"preview",
|
|
9576
|
+
"edit",
|
|
9577
|
+
"interact"
|
|
9578
|
+
],
|
|
9579
|
+
description: "Optional user intent for the content."
|
|
9580
|
+
},
|
|
9581
|
+
placement: {
|
|
9582
|
+
type: "string",
|
|
9583
|
+
enum: ["inline", "side_panel"],
|
|
9584
|
+
description: "Optional display placement. \"inline\" embeds a lightweight panel app as an interactive chat card; \"side_panel\" opens it in the right panel for larger workflows. Choose the appropriate placement yourself; defaults to the existing side panel behavior when omitted."
|
|
9585
|
+
},
|
|
9586
|
+
payload: {
|
|
9587
|
+
type: "object",
|
|
9588
|
+
description: "Type-specific fields: file={path,line,column}; url={url}; panel_app={appId}.",
|
|
9589
|
+
additionalProperties: true
|
|
9590
|
+
}
|
|
9591
|
+
},
|
|
9592
|
+
required: ["type", "payload"],
|
|
9593
|
+
additionalProperties: false
|
|
9594
|
+
};
|
|
9595
|
+
constructor(eventBus) {
|
|
9596
|
+
this.eventBus = eventBus;
|
|
9597
|
+
}
|
|
9598
|
+
execute = async (args, context) => {
|
|
9599
|
+
const request = normalizeShowContentArgs(args);
|
|
9600
|
+
this.eventBus.emit(eventKeys.uiShowContent, createShowContentEventPayload(request, context), { source: "kernel" });
|
|
9601
|
+
return {
|
|
9602
|
+
ok: true,
|
|
9603
|
+
action: "showContent",
|
|
9604
|
+
request
|
|
9605
|
+
};
|
|
9606
|
+
};
|
|
9607
|
+
};
|
|
9608
|
+
//#endregion
|
|
9609
|
+
//#region src/contributions/tool-provider/providers/show-content-tool.provider.ts
|
|
9610
|
+
var ShowContentToolProvider = class {
|
|
9611
|
+
constructor(eventBus) {
|
|
9612
|
+
this.eventBus = eventBus;
|
|
9613
|
+
}
|
|
9614
|
+
provide = () => [new ShowContentTool(this.eventBus)];
|
|
9615
|
+
};
|
|
9616
|
+
//#endregion
|
|
9392
9617
|
//#region src/contributions/tool-provider/providers/structured-result-tool.provider.ts
|
|
9393
9618
|
var StructuredResultToolProvider = class {
|
|
9394
9619
|
provide = (request) => {
|
|
@@ -9411,6 +9636,40 @@ function isRecord(value) {
|
|
|
9411
9636
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9412
9637
|
}
|
|
9413
9638
|
//#endregion
|
|
9639
|
+
//#region src/contributions/tool-provider/services/tool-provider-run-context.service.ts
|
|
9640
|
+
var ToolProviderRunContextService = class {
|
|
9641
|
+
constructor(sessionManager, agentManager, configManager) {
|
|
9642
|
+
this.sessionManager = sessionManager;
|
|
9643
|
+
this.agentManager = agentManager;
|
|
9644
|
+
this.configManager = configManager;
|
|
9645
|
+
}
|
|
9646
|
+
resolve = async (request) => {
|
|
9647
|
+
const session = request.sessionId ? await this.sessionManager.getAgentRunSession(request.sessionId) : null;
|
|
9648
|
+
const sessionId = session?.sessionId ?? request.sessionId ?? request.message.sessionId ?? "";
|
|
9649
|
+
const requestMetadata = buildAgentRunRequestMetadata({
|
|
9650
|
+
request,
|
|
9651
|
+
session
|
|
9652
|
+
});
|
|
9653
|
+
const runContext = buildNextclawNcpRunContext({
|
|
9654
|
+
agentProfile: this.agentManager.resolveAgentProfileForRun({
|
|
9655
|
+
requestMetadata,
|
|
9656
|
+
storedAgentId: request.agentId ?? session?.agentId
|
|
9657
|
+
}),
|
|
9658
|
+
config: this.configManager.loadConfig(),
|
|
9659
|
+
sessionId,
|
|
9660
|
+
requestMetadata,
|
|
9661
|
+
sessionMetadata: session?.metadata ?? requestMetadata
|
|
9662
|
+
});
|
|
9663
|
+
return {
|
|
9664
|
+
requestMetadata,
|
|
9665
|
+
runContext,
|
|
9666
|
+
session,
|
|
9667
|
+
sessionId,
|
|
9668
|
+
toolRunContext: runContext.toolRunContext
|
|
9669
|
+
};
|
|
9670
|
+
};
|
|
9671
|
+
};
|
|
9672
|
+
//#endregion
|
|
9414
9673
|
//#region src/contributions/tool-provider/index.ts
|
|
9415
9674
|
var ToolProviderContribution = class {
|
|
9416
9675
|
cleanups = [];
|
|
@@ -9424,14 +9683,18 @@ var ToolProviderContribution = class {
|
|
|
9424
9683
|
dispose = () => {
|
|
9425
9684
|
while (this.cleanups.length > 0) this.cleanups.pop()?.();
|
|
9426
9685
|
};
|
|
9427
|
-
createToolProviders = () =>
|
|
9428
|
-
new
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9686
|
+
createToolProviders = () => {
|
|
9687
|
+
const runContextService = new ToolProviderRunContextService(this.kernel.sessionManager, this.kernel.agents, this.kernel.configManager);
|
|
9688
|
+
return [
|
|
9689
|
+
new StructuredResultToolProvider(),
|
|
9690
|
+
new ShowContentToolProvider(this.kernel.eventBus),
|
|
9691
|
+
new CoreToolProvider(runContextService, this.kernel.getGatewayController),
|
|
9692
|
+
new MessagingToolProvider(runContextService, this.kernel.channels, this.kernel.automation, this.kernel.extensions),
|
|
9693
|
+
new SessionToolProvider(runContextService, this.kernel.sessionManager, this.kernel.sessionRequests, this.kernel.sessionSearch),
|
|
9694
|
+
new AssetToolProvider(this.kernel.assetStore),
|
|
9695
|
+
new McpToolProvider(runContextService, this.kernel.mcpManager)
|
|
9696
|
+
];
|
|
9697
|
+
};
|
|
9435
9698
|
};
|
|
9436
9699
|
//#endregion
|
|
9437
9700
|
//#region src/app/nextclaw-kernel.ts
|
|
@@ -9487,26 +9750,27 @@ var NextclawKernel = class {
|
|
|
9487
9750
|
gatewayController;
|
|
9488
9751
|
constructor(options = {}) {
|
|
9489
9752
|
const sessionsDir = resolveKernelSessionsDir(options);
|
|
9490
|
-
this.sessionSearch = new
|
|
9753
|
+
this.sessionSearch = new SessionSearchService({
|
|
9491
9754
|
databasePath: resolve(getDataDir(), "session-search.db"),
|
|
9492
9755
|
sessionsDir
|
|
9493
9756
|
});
|
|
9494
9757
|
this.ncpAgentSessionJournalStore = new NcpAgentSessionJournalStore(resolve(sessionsDir, ".ncp-agent-journal"));
|
|
9495
9758
|
this.automation = new AutomationManager({ storePath: resolveKernelAutomationStorePath(options) });
|
|
9496
9759
|
this.assetStore = new LocalAssetStore({ rootDir: resolve(getDataDir(), "assets") });
|
|
9497
|
-
this.agents = new AgentManager();
|
|
9498
9760
|
this.control = new NextclawKernelControlManager();
|
|
9499
|
-
this.channels = new ChannelManager
|
|
9761
|
+
this.channels = new ChannelManager({ bus: this.messageBus });
|
|
9500
9762
|
this.configManager = new ConfigManager({
|
|
9501
9763
|
configPath: options.configPath,
|
|
9502
9764
|
channels: this.channels,
|
|
9503
9765
|
providerManager: this.llmProviders
|
|
9504
9766
|
});
|
|
9767
|
+
this.agents = new AgentManager(this.configManager);
|
|
9505
9768
|
this.accessManager = new AccessManager({
|
|
9506
9769
|
configManager: this.configManager,
|
|
9507
9770
|
homeDir: options.homeDir
|
|
9508
9771
|
});
|
|
9509
9772
|
this.sessionManager = new SessionManager({
|
|
9773
|
+
agentManager: this.agents,
|
|
9510
9774
|
configManager: this.configManager,
|
|
9511
9775
|
eventBus: this.eventBus,
|
|
9512
9776
|
journalStore: this.ncpAgentSessionJournalStore,
|
|
@@ -9539,12 +9803,11 @@ var NextclawKernel = class {
|
|
|
9539
9803
|
ingress: this.ingress
|
|
9540
9804
|
})
|
|
9541
9805
|
});
|
|
9542
|
-
this.contextCompactionManager = new AgentRunContextCompactionManager(this.
|
|
9806
|
+
this.contextCompactionManager = new AgentRunContextCompactionManager(this.agents, this.llmProviders, this.sessionManager);
|
|
9543
9807
|
this.sessionRunManager = new SessionRunManager(this.sessionManager);
|
|
9544
|
-
this.agentRunRequestManager = new AgentRunRequestManager(this.agentRuntimeManager, this.configManager, this.contextProviderManager, this.eventBus, this.ingress, this.sessionManager, this.sessionRunManager, this.toolProviderManager);
|
|
9808
|
+
this.agentRunRequestManager = new AgentRunRequestManager(this.agentRuntimeManager, this.agents, this.configManager, this.contextProviderManager, this.eventBus, this.ingress, this.sessionManager, this.sessionRunManager, this.toolProviderManager);
|
|
9545
9809
|
this.contributions = [
|
|
9546
9810
|
new ToolProviderContribution(this),
|
|
9547
|
-
new SessionActivityPreviewContribution(this),
|
|
9548
9811
|
new LearningLoopContribution(this),
|
|
9549
9812
|
new ContextProviderContribution(this),
|
|
9550
9813
|
new AgentRunRuntimeContribution(this),
|
|
@@ -10181,6 +10444,6 @@ function resolveLegacyEventType(message) {
|
|
|
10181
10444
|
return `message.${role || "other"}`;
|
|
10182
10445
|
}
|
|
10183
10446
|
//#endregion
|
|
10184
|
-
export { AccessManager, AgentManager, AgentRunClient,
|
|
10447
|
+
export { AccessManager, AgentManager, AgentRunClient, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_TIMELINE_KIND, ChannelManager, CommandRegistry, ConfigManager, ContextCompactionPreflightService, ContextWindowPreviewManager, DEFAULT_AGENT_RUNTIME_ENTRY_ID, DEFAULT_SERVICE_ACTION_RISK, ExtensionManager, GatewayInboundProcessor, LlmProviderManager, LlmUsageManager, LlmUsageStore, McpManager, McpServiceAppRuntimeService, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, NEXTCLAW_TIMELINE_KIND_METADATA_KEY, NcpAgentSessionJournalStore, NextclawKernel, PANEL_APP_AGENT_CAPABILITIES, PanelAppAssetTokenService, PanelAppError, PanelAppManager, ProviderManagerNcpLLMApi, SERVICE_APP_MANIFEST_FILE_NAME, ServiceAppError, ServiceAppManager, SessionManager, SessionRequestManager, SkillManager, UpdateManifestReader, buildAgentRunSendPayload, buildContextCompactionModelInput, buildContextCompactionTimelineNcpMessage, buildLlmUsageSummary, buildLocalizedTextMap, buildNextclawNcpRunContext, buildServiceActionId, createAgentRuntimeSessionRequestDispatcher, createAssetTools, createContextCompactionMessageId, createContextWindowSignature, createLlmUsageRecord, describeAgentRuntimeSessionTypes, dispatchAgentRuntimeSessionRequest, dispatchChannelReplyRoute, dispatchPromptOverNcp, getServiceActionName, getServiceAppManifestPath, getUnsignedUpdateManifest, hasLlmUsageTelemetry, isContextCompactionTimelineMessage, isContextWindowSnapshot, isPanelAppAgentCapability, isPanelAppError, isReplyCapableChannel, isServiceAppError, listExtensionChannelIds, listServiceAppManifestActions, mergeServiceAppRuntimeActions, normalizeAgentRuntimeSessionTypeIcon, normalizeLlmUsageModel, normalizeOptionalString, parseServiceAppManifest, parseSkillFrontmatter, readContextWindowEventSessionId, readLatestContextCompactionCheckpoint, readLearningLoopRuntimeConfig, readMetadataModel, readMetadataThinking, readServiceAppManifest, resolveAgentRuntimeEntries, resolveChannelReplyRoute, resolveEffectiveModel, resolveLegacyEventType, resolveSessionChannelContext, runGatewayInboundLoop, sanitizeLlmUsage, serializeUnsignedUpdateManifest, shouldRefreshContextWindowDuringStream, shouldRefreshContextWindowImmediately, stripSkillFrontmatter, syncSessionThinkingPreference, toNcpMessages, waitForAgentRuntimeSessionReply };
|
|
10185
10448
|
|
|
10186
10449
|
//# sourceMappingURL=index.js.map
|