@nextclaw/kernel 0.4.2 → 0.5.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 +117 -129
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +951 -829
- 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, 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) {
|
|
@@ -145,43 +166,39 @@ function toLegacyMessages(messages, options = {}) {
|
|
|
145
166
|
return legacyMessages;
|
|
146
167
|
}
|
|
147
168
|
//#endregion
|
|
148
|
-
//#region src/features/context-compaction/utils/context-compaction
|
|
169
|
+
//#region src/features/context-compaction/utils/context-compaction.utils.ts
|
|
149
170
|
const NEXTCLAW_TIMELINE_KIND_METADATA_KEY = "nextclaw_timeline_kind";
|
|
150
171
|
const CONTEXT_COMPACTION_TIMELINE_KIND = "context_compaction";
|
|
151
172
|
function readCheckpointTimelineText(checkpoint) {
|
|
152
173
|
return checkpoint.status === "compressing" ? "正在压缩较早上下文" : "较早上下文已自动压缩";
|
|
153
174
|
}
|
|
154
|
-
function
|
|
155
|
-
|
|
175
|
+
function readContextCompactionCheckpoint(message) {
|
|
176
|
+
const metadata = message.metadata;
|
|
177
|
+
return metadata?.["nextclaw_timeline_kind"] === "context_compaction" ? readCompressedContextCompactionCheckpoint(metadata.checkpoint) : null;
|
|
156
178
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const checkpoint = metadata.checkpoint && typeof metadata.checkpoint === "object" && !Array.isArray(metadata.checkpoint) ? metadata.checkpoint : null;
|
|
163
|
-
if (!checkpoint) return null;
|
|
164
|
-
return {
|
|
165
|
-
[NEXTCLAW_TIMELINE_KIND_METADATA_KEY]: CONTEXT_COMPACTION_TIMELINE_KIND,
|
|
166
|
-
checkpoint
|
|
167
|
-
};
|
|
179
|
+
function readLatestContextCompactionMarker(sessionMessages) {
|
|
180
|
+
return sessionMessages.reduce((marker, message) => {
|
|
181
|
+
const candidateCheckpoint = readContextCompactionCheckpoint(message);
|
|
182
|
+
return candidateCheckpoint && (!marker || Date.parse(candidateCheckpoint.updatedAt) >= Date.parse(marker.checkpoint.updatedAt)) ? { checkpoint: candidateCheckpoint } : marker;
|
|
183
|
+
}, null);
|
|
168
184
|
}
|
|
169
|
-
function
|
|
170
|
-
const
|
|
185
|
+
function buildContextCompactionSummaryMessage(params) {
|
|
186
|
+
const { checkpoint, sessionId } = params;
|
|
171
187
|
return {
|
|
172
|
-
|
|
173
|
-
|
|
188
|
+
id: `${sessionId}:context-compaction-summary:${checkpoint.id}:${checkpoint.updatedAt}`,
|
|
189
|
+
sessionId,
|
|
190
|
+
role: "user",
|
|
191
|
+
status: "final",
|
|
174
192
|
timestamp: checkpoint.updatedAt,
|
|
175
|
-
|
|
193
|
+
parts: [{
|
|
176
194
|
type: "text",
|
|
177
|
-
text
|
|
178
|
-
}]
|
|
179
|
-
ncp_metadata: {
|
|
180
|
-
[NEXTCLAW_TIMELINE_KIND_METADATA_KEY]: CONTEXT_COMPACTION_TIMELINE_KIND,
|
|
181
|
-
checkpoint
|
|
182
|
-
}
|
|
195
|
+
text: checkpoint.summary
|
|
196
|
+
}]
|
|
183
197
|
};
|
|
184
198
|
}
|
|
199
|
+
function createContextCompactionMessageId() {
|
|
200
|
+
return `context-compaction-message-${randomUUID()}`;
|
|
201
|
+
}
|
|
185
202
|
function buildContextCompactionTimelineNcpMessage(params) {
|
|
186
203
|
const { checkpoint, messageId, sessionId } = params;
|
|
187
204
|
const text = readCheckpointTimelineText(checkpoint);
|
|
@@ -201,92 +218,65 @@ function buildContextCompactionTimelineNcpMessage(params) {
|
|
|
201
218
|
}
|
|
202
219
|
};
|
|
203
220
|
}
|
|
204
|
-
function upsertContextCompactionTimelineMessage(params) {
|
|
205
|
-
const { checkpoint, insertBeforeMessageIds = [], session } = params;
|
|
206
|
-
const nextMessage = buildTimelineMessage(checkpoint);
|
|
207
|
-
for (let index = session.events.length - 1; index >= 0; index -= 1) {
|
|
208
|
-
const event = session.events[index];
|
|
209
|
-
const metadata = readTimelineMetadata(event?.data?.message && typeof event.data.message === "object" && !Array.isArray(event.data.message) ? event.data.message : null);
|
|
210
|
-
if (!metadata) continue;
|
|
211
|
-
event.timestamp = checkpoint.updatedAt;
|
|
212
|
-
event.data.message = nextMessage;
|
|
213
|
-
session.messages = session.messages.map((item) => {
|
|
214
|
-
return readTimelineMetadata(item)?.checkpoint.id === metadata.checkpoint.id ? nextMessage : item;
|
|
215
|
-
});
|
|
216
|
-
session.updatedAt = new Date(checkpoint.updatedAt);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const event = {
|
|
220
|
-
seq: session.nextSeq,
|
|
221
|
-
type: "message.service",
|
|
222
|
-
timestamp: checkpoint.updatedAt,
|
|
223
|
-
data: { message: nextMessage }
|
|
224
|
-
};
|
|
225
|
-
session.nextSeq += 1;
|
|
226
|
-
const insertionIds = new Set(insertBeforeMessageIds);
|
|
227
|
-
const messageIndex = session.messages.findIndex((message) => typeof message.ncp_message_id === "string" && insertionIds.has(message.ncp_message_id));
|
|
228
|
-
if (messageIndex >= 0) session.messages.splice(messageIndex, 0, nextMessage);
|
|
229
|
-
else session.messages.push(nextMessage);
|
|
230
|
-
const eventIndex = session.events.findIndex((candidateEvent) => {
|
|
231
|
-
const message = candidateEvent?.data?.message && typeof candidateEvent.data.message === "object" && !Array.isArray(candidateEvent.data.message) ? candidateEvent.data.message : null;
|
|
232
|
-
return typeof message?.ncp_message_id === "string" && insertionIds.has(message.ncp_message_id);
|
|
233
|
-
});
|
|
234
|
-
if (eventIndex >= 0) session.events.splice(eventIndex, 0, event);
|
|
235
|
-
else session.events.push(event);
|
|
236
|
-
session.updatedAt = new Date(checkpoint.updatedAt);
|
|
237
|
-
}
|
|
238
221
|
function isContextCompactionTimelineMessage(message) {
|
|
239
222
|
return message?.metadata?.[NEXTCLAW_TIMELINE_KIND_METADATA_KEY] === CONTEXT_COMPACTION_TIMELINE_KIND;
|
|
240
223
|
}
|
|
241
|
-
//#endregion
|
|
242
|
-
//#region src/features/context-compaction/utils/context-compaction-projection.utils.ts
|
|
243
|
-
function readCompactionCheckpoint(message) {
|
|
244
|
-
const metadata = message.metadata;
|
|
245
|
-
return metadata?.["nextclaw_timeline_kind"] === "context_compaction" ? readCompressedContextCompactionCheckpoint(metadata.checkpoint) : null;
|
|
246
|
-
}
|
|
247
224
|
function readLatestContextCompactionCheckpoint(sessionMessages) {
|
|
248
|
-
return sessionMessages
|
|
249
|
-
const candidateCheckpoint = readCompactionCheckpoint(message);
|
|
250
|
-
return candidateCheckpoint && (!checkpoint || Date.parse(candidateCheckpoint.updatedAt) >= Date.parse(checkpoint.updatedAt)) ? candidateCheckpoint : checkpoint;
|
|
251
|
-
}, null);
|
|
225
|
+
return readLatestContextCompactionMarker(sessionMessages)?.checkpoint ?? null;
|
|
252
226
|
}
|
|
253
|
-
function
|
|
227
|
+
function buildContextCompactionModelInput(params) {
|
|
254
228
|
const { sessionId, sessionMessages } = params;
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
229
|
+
const marker = readLatestContextCompactionMarker(sessionMessages);
|
|
230
|
+
const regularMessages = sessionMessages.filter((message) => !readContextCompactionCheckpoint(message));
|
|
231
|
+
if (!marker) return regularMessages.map((message) => structuredClone(message));
|
|
232
|
+
const { checkpoint } = marker;
|
|
233
|
+
return [buildContextCompactionSummaryMessage({
|
|
234
|
+
checkpoint,
|
|
235
|
+
sessionId
|
|
236
|
+
}), ...regularMessages.filter((message) => Date.parse(message.timestamp) > Date.parse(checkpoint.updatedAt)).sort((left, right) => Date.parse(left.timestamp) - Date.parse(right.timestamp))].map((message) => structuredClone(message));
|
|
237
|
+
}
|
|
238
|
+
function readContextWindowEventSessionId(event) {
|
|
239
|
+
const payload = "payload" in event ? event.payload : null;
|
|
240
|
+
if (!payload || typeof payload !== "object") return null;
|
|
241
|
+
return "sessionId" in payload && typeof payload.sessionId === "string" ? payload.sessionId.trim() || null : null;
|
|
242
|
+
}
|
|
243
|
+
function isContextWindowSnapshot(value) {
|
|
244
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
245
|
+
}
|
|
246
|
+
function createContextWindowSignature(value) {
|
|
247
|
+
return JSON.stringify(value);
|
|
248
|
+
}
|
|
249
|
+
function shouldRefreshContextWindowDuringStream(event) {
|
|
250
|
+
switch (event.type) {
|
|
251
|
+
case NcpEventType.MessageTextStart:
|
|
252
|
+
case NcpEventType.MessageTextDelta:
|
|
253
|
+
case NcpEventType.MessageTextEnd:
|
|
254
|
+
case NcpEventType.MessageReasoningStart:
|
|
255
|
+
case NcpEventType.MessageReasoningDelta:
|
|
256
|
+
case NcpEventType.MessageReasoningEnd:
|
|
257
|
+
case NcpEventType.MessageToolCallStart:
|
|
258
|
+
case NcpEventType.MessageToolCallArgs:
|
|
259
|
+
case NcpEventType.MessageToolCallArgsDelta:
|
|
260
|
+
case NcpEventType.MessageToolCallEnd:
|
|
261
|
+
case NcpEventType.MessageToolCallResult: return true;
|
|
262
|
+
default: return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function shouldRefreshContextWindowImmediately(event) {
|
|
266
|
+
switch (event.type) {
|
|
267
|
+
case NcpEventType.MessageSent:
|
|
268
|
+
case NcpEventType.MessageCompleted:
|
|
269
|
+
case NcpEventType.MessageFailed:
|
|
270
|
+
case NcpEventType.MessageAbort:
|
|
271
|
+
case NcpEventType.RunFinished:
|
|
272
|
+
case NcpEventType.RunError: return true;
|
|
273
|
+
default: return false;
|
|
274
|
+
}
|
|
268
275
|
}
|
|
269
276
|
//#endregion
|
|
270
277
|
//#region src/features/context-compaction/services/context-compaction-preflight.service.ts
|
|
271
278
|
const SUMMARY_MAX_TOKENS = 4e3;
|
|
272
279
|
const SUMMARY_SOURCE_MAX_CHARS = 12e4;
|
|
273
|
-
function readRequestedAgentId$1(metadata) {
|
|
274
|
-
return normalizeString$1(metadata.agent_id)?.toLowerCase() ?? normalizeString$1(metadata.agentId)?.toLowerCase() ?? null;
|
|
275
|
-
}
|
|
276
|
-
function resolveCompactionProfile(params) {
|
|
277
|
-
const { config, requestMetadata, storedAgentId } = params;
|
|
278
|
-
const { defaults } = config.agents;
|
|
279
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
280
|
-
const profile = findEffectiveAgentProfile(config, normalizeString$1(storedAgentId)?.toLowerCase() ?? readRequestedAgentId$1(requestMetadata) ?? defaultAgentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
281
|
-
return {
|
|
282
|
-
contextTokens: profile?.contextTokens ?? defaults.contextTokens,
|
|
283
|
-
model: profile?.model ?? defaults.model,
|
|
284
|
-
reservedContextTokens: ContextWindowBudgetService.resolveReservedContextTokens({
|
|
285
|
-
contextTokens: profile?.contextTokens ?? defaults.contextTokens,
|
|
286
|
-
configuredReservedContextTokens: profile?.reservedContextTokens ?? defaults.reservedContextTokens
|
|
287
|
-
})
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
280
|
function mergeInputMessages(params) {
|
|
291
281
|
const messages = params.sessionMessages.map((message) => structuredClone(message));
|
|
292
282
|
const seen = new Set(messages.map((message) => message.id));
|
|
@@ -318,18 +308,18 @@ function buildContextWindowSnapshotFromBudget(params) {
|
|
|
318
308
|
var ContextCompactionPreflightService = class {
|
|
319
309
|
compactionService = new ContextCompactionService();
|
|
320
310
|
contextWindowBudgetService = new ContextWindowBudgetService();
|
|
321
|
-
constructor(
|
|
322
|
-
this.
|
|
311
|
+
constructor(agentManager, providerManager) {
|
|
312
|
+
this.agentManager = agentManager;
|
|
313
|
+
this.providerManager = providerManager;
|
|
323
314
|
}
|
|
324
315
|
preview = (params) => {
|
|
325
316
|
const { requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
326
|
-
const profile = resolveCompactionProfile({
|
|
327
|
-
config: this.options.configManager.loadConfig(),
|
|
317
|
+
const profile = this.resolveCompactionProfile({
|
|
328
318
|
requestMetadata,
|
|
329
319
|
storedAgentId
|
|
330
320
|
});
|
|
331
321
|
const existingCheckpoint = readCompressedContextCompactionCheckpoint(storedMetadata[CONTEXT_COMPACTION_METADATA_KEY]) ?? readLatestContextCompactionCheckpoint(sessionMessages);
|
|
332
|
-
const projectedMessages = existingCheckpoint ?
|
|
322
|
+
const projectedMessages = existingCheckpoint ? buildContextCompactionModelInput({
|
|
333
323
|
sessionId,
|
|
334
324
|
sessionMessages
|
|
335
325
|
}) : sessionMessages.filter((message) => !isContextCompactionTimelineMessage(message));
|
|
@@ -345,8 +335,7 @@ var ContextCompactionPreflightService = class {
|
|
|
345
335
|
};
|
|
346
336
|
begin = (params) => {
|
|
347
337
|
const { inputMessages, requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
348
|
-
const profile = resolveCompactionProfile({
|
|
349
|
-
config: this.options.configManager.loadConfig(),
|
|
338
|
+
const profile = this.resolveCompactionProfile({
|
|
350
339
|
requestMetadata,
|
|
351
340
|
storedAgentId
|
|
352
341
|
});
|
|
@@ -356,7 +345,7 @@ var ContextCompactionPreflightService = class {
|
|
|
356
345
|
sessionMessages
|
|
357
346
|
});
|
|
358
347
|
const existingCheckpoint = readCompressedContextCompactionCheckpoint(storedMetadata[CONTEXT_COMPACTION_METADATA_KEY]) ?? readLatestContextCompactionCheckpoint(ncpMessages);
|
|
359
|
-
const messages = toLegacyMessages(existingCheckpoint ?
|
|
348
|
+
const messages = toLegacyMessages(existingCheckpoint ? buildContextCompactionModelInput({
|
|
360
349
|
sessionId,
|
|
361
350
|
sessionMessages: ncpMessages
|
|
362
351
|
}) : ncpMessages.filter((message) => !isContextCompactionTimelineMessage(message)));
|
|
@@ -366,7 +355,7 @@ var ContextCompactionPreflightService = class {
|
|
|
366
355
|
reservedContextTokens
|
|
367
356
|
});
|
|
368
357
|
const plan = !budget.shouldCompact ? null : this.compactionService.prepareForModelInput({
|
|
369
|
-
messages
|
|
358
|
+
messages,
|
|
370
359
|
contextTokens,
|
|
371
360
|
compactionThresholdTokens: budget.triggerTokens
|
|
372
361
|
});
|
|
@@ -443,24 +432,26 @@ var ContextCompactionPreflightService = class {
|
|
|
443
432
|
};
|
|
444
433
|
};
|
|
445
434
|
generateSummary = async (params) => {
|
|
446
|
-
if (!this.
|
|
435
|
+
if (!this.providerManager) throw new Error("context compaction summary generation requires a provider manager");
|
|
447
436
|
const { messages, model } = params;
|
|
448
|
-
const summary = (await this.
|
|
437
|
+
const summary = (await this.providerManager.chat({
|
|
449
438
|
model,
|
|
450
439
|
maxTokens: SUMMARY_MAX_TOKENS,
|
|
451
440
|
messages: [{
|
|
452
441
|
role: "system",
|
|
453
442
|
content: [
|
|
454
443
|
"You are NextClaw's context compactor for a coding agent session.",
|
|
455
|
-
"Create a
|
|
456
|
-
"
|
|
444
|
+
"Create a complete compressed working context that will replace all prior conversation messages in a future model request.",
|
|
445
|
+
"The model will not receive a raw recent-message tail, so preserve the latest user intent and recent turns with high fidelity inside the summary.",
|
|
446
|
+
"Preserve user goals, explicit instructions, decisions, files touched or inspected, code changes, commands run, test results, failures, blockers, current task state, and exact next steps.",
|
|
457
447
|
"Do not invent facts. If something is uncertain, mark it as uncertain.",
|
|
458
|
-
"Return Markdown only. Start with '# Compressed
|
|
448
|
+
"Return Markdown only. Start with '# Compressed Working Context'."
|
|
459
449
|
].join("\n")
|
|
460
450
|
}, {
|
|
461
451
|
role: "user",
|
|
462
452
|
content: [
|
|
463
|
-
"Compress these
|
|
453
|
+
"Compress these runtime messages into a reusable working context.",
|
|
454
|
+
"Include a 'Recent High-Fidelity Context' section for the latest important user/assistant turns.",
|
|
464
455
|
"",
|
|
465
456
|
"Messages JSON:",
|
|
466
457
|
stringifyCompactionSource(messages)
|
|
@@ -470,14 +461,24 @@ var ContextCompactionPreflightService = class {
|
|
|
470
461
|
if (!summary) throw new Error("context compaction summary is empty");
|
|
471
462
|
return summary;
|
|
472
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
|
+
};
|
|
473
475
|
};
|
|
474
476
|
//#endregion
|
|
475
477
|
//#region src/features/context-compaction/managers/context-compaction.manager.ts
|
|
476
478
|
var ContextWindowPreviewManager = class {
|
|
477
479
|
preflightService;
|
|
478
|
-
constructor(
|
|
479
|
-
this.
|
|
480
|
-
this.preflightService = new ContextCompactionPreflightService({ configManager: options.configManager });
|
|
480
|
+
constructor(agentManager) {
|
|
481
|
+
this.preflightService = new ContextCompactionPreflightService(agentManager);
|
|
481
482
|
}
|
|
482
483
|
preview = (params) => {
|
|
483
484
|
const { requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
@@ -491,55 +492,12 @@ var ContextWindowPreviewManager = class {
|
|
|
491
492
|
};
|
|
492
493
|
};
|
|
493
494
|
//#endregion
|
|
494
|
-
//#region src/features/context-compaction/utils/context-window-event.utils.ts
|
|
495
|
-
function readContextWindowEventSessionId(event) {
|
|
496
|
-
const payload = "payload" in event ? event.payload : null;
|
|
497
|
-
if (!payload || typeof payload !== "object") return null;
|
|
498
|
-
return "sessionId" in payload && typeof payload.sessionId === "string" ? payload.sessionId.trim() || null : null;
|
|
499
|
-
}
|
|
500
|
-
function isContextWindowSnapshot(value) {
|
|
501
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
502
|
-
}
|
|
503
|
-
function createContextWindowSignature(value) {
|
|
504
|
-
return JSON.stringify(value);
|
|
505
|
-
}
|
|
506
|
-
function shouldRefreshContextWindowDuringStream(event) {
|
|
507
|
-
switch (event.type) {
|
|
508
|
-
case NcpEventType.MessageTextStart:
|
|
509
|
-
case NcpEventType.MessageTextDelta:
|
|
510
|
-
case NcpEventType.MessageTextEnd:
|
|
511
|
-
case NcpEventType.MessageReasoningStart:
|
|
512
|
-
case NcpEventType.MessageReasoningDelta:
|
|
513
|
-
case NcpEventType.MessageReasoningEnd:
|
|
514
|
-
case NcpEventType.MessageToolCallStart:
|
|
515
|
-
case NcpEventType.MessageToolCallArgs:
|
|
516
|
-
case NcpEventType.MessageToolCallArgsDelta:
|
|
517
|
-
case NcpEventType.MessageToolCallEnd:
|
|
518
|
-
case NcpEventType.MessageToolCallResult: return true;
|
|
519
|
-
default: return false;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
function shouldRefreshContextWindowImmediately(event) {
|
|
523
|
-
switch (event.type) {
|
|
524
|
-
case NcpEventType.MessageSent:
|
|
525
|
-
case NcpEventType.MessageCompleted:
|
|
526
|
-
case NcpEventType.MessageFailed:
|
|
527
|
-
case NcpEventType.MessageAbort:
|
|
528
|
-
case NcpEventType.RunFinished:
|
|
529
|
-
case NcpEventType.RunError: return true;
|
|
530
|
-
default: return false;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
//#endregion
|
|
534
495
|
//#region src/managers/agent-run-context-compaction.manager.ts
|
|
535
496
|
var AgentRunContextCompactionManager = class {
|
|
536
497
|
preflightService;
|
|
537
|
-
constructor(
|
|
498
|
+
constructor(agentManager, providerManager, sessionManager) {
|
|
538
499
|
this.sessionManager = sessionManager;
|
|
539
|
-
this.preflightService = new ContextCompactionPreflightService(
|
|
540
|
-
configManager,
|
|
541
|
-
providerManager
|
|
542
|
-
});
|
|
500
|
+
this.preflightService = new ContextCompactionPreflightService(agentManager, providerManager);
|
|
543
501
|
}
|
|
544
502
|
runPreflight = async (input) => {
|
|
545
503
|
const beginResult = this.preflightService.begin({
|
|
@@ -571,7 +529,7 @@ var AgentRunContextCompactionManager = class {
|
|
|
571
529
|
//#region src/managers/agent-run-request.manager.ts
|
|
572
530
|
function toAgentRunRequest(envelope) {
|
|
573
531
|
const metadata = envelope.metadata ?? {};
|
|
574
|
-
const peerId = readOptionalString$
|
|
532
|
+
const peerId = readOptionalString$10(envelope.peerId);
|
|
575
533
|
const requestMetadata = {
|
|
576
534
|
agentRuntimeId: metadata.agentRuntimeId,
|
|
577
535
|
agentId: metadata.agentId,
|
|
@@ -584,7 +542,7 @@ function toAgentRunRequest(envelope) {
|
|
|
584
542
|
thinkingEffort: metadata.thinkingEffort
|
|
585
543
|
};
|
|
586
544
|
if (Array.isArray(envelope.content)) {
|
|
587
|
-
const sessionId = readOptionalString$
|
|
545
|
+
const sessionId = readOptionalString$10(envelope.sessionId);
|
|
588
546
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
589
547
|
return {
|
|
590
548
|
...requestMetadata,
|
|
@@ -602,8 +560,8 @@ function toAgentRunRequest(envelope) {
|
|
|
602
560
|
}
|
|
603
561
|
const sourceMessage = envelope.message;
|
|
604
562
|
if (!sourceMessage) throw new Error("Invalid agent run send request.");
|
|
605
|
-
const envelopeSessionId = readOptionalString$
|
|
606
|
-
const messageSessionId = readOptionalString$
|
|
563
|
+
const envelopeSessionId = readOptionalString$10(envelope.sessionId);
|
|
564
|
+
const messageSessionId = readOptionalString$10(sourceMessage.sessionId);
|
|
607
565
|
const sessionId = envelopeSessionId ?? messageSessionId;
|
|
608
566
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
609
567
|
const message = {
|
|
@@ -622,7 +580,7 @@ function toAgentRunRequest(envelope) {
|
|
|
622
580
|
message
|
|
623
581
|
};
|
|
624
582
|
}
|
|
625
|
-
function readOptionalString$
|
|
583
|
+
function readOptionalString$10(value) {
|
|
626
584
|
if (typeof value !== "string") return;
|
|
627
585
|
return value.trim() || void 0;
|
|
628
586
|
}
|
|
@@ -644,8 +602,9 @@ function readMessageTask(message) {
|
|
|
644
602
|
var AgentRunRequestManager = class {
|
|
645
603
|
cleanups = [];
|
|
646
604
|
started = false;
|
|
647
|
-
constructor(agentRuntimeManager, configManager, contextProviderManager, eventBus, ingress, sessionManager, sessionRunManager, toolProviderManager) {
|
|
605
|
+
constructor(agentRuntimeManager, agentManager, configManager, contextProviderManager, eventBus, ingress, sessionManager, sessionRunManager, toolProviderManager) {
|
|
648
606
|
this.agentRuntimeManager = agentRuntimeManager;
|
|
607
|
+
this.agentManager = agentManager;
|
|
649
608
|
this.configManager = configManager;
|
|
650
609
|
this.contextProviderManager = contextProviderManager;
|
|
651
610
|
this.eventBus = eventBus;
|
|
@@ -727,7 +686,7 @@ var AgentRunRequestManager = class {
|
|
|
727
686
|
}
|
|
728
687
|
})();
|
|
729
688
|
const model = request.model ?? session.model ?? this.configManager.getDefaultModel();
|
|
730
|
-
const agentId = request.agentId ?? session.agentId ??
|
|
689
|
+
const agentId = request.agentId ?? session.agentId ?? this.agentManager.getDefaultAgentId();
|
|
731
690
|
const spec = {
|
|
732
691
|
runId: activeRun.runId,
|
|
733
692
|
agentId,
|
|
@@ -801,6 +760,126 @@ var AgentRunRequestManager = class {
|
|
|
801
760
|
//#region src/configs/agent-runtime.config.ts
|
|
802
761
|
const DEFAULT_AGENT_RUNTIME_ENTRY_ID = "native";
|
|
803
762
|
//#endregion
|
|
763
|
+
//#region src/features/runtime-registry/utils/agent-runtime-registry.utils.ts
|
|
764
|
+
function normalizeIdentifier(value) {
|
|
765
|
+
if (typeof value !== "string") return null;
|
|
766
|
+
const normalized = value.trim().toLowerCase();
|
|
767
|
+
return normalized.length > 0 ? normalized : null;
|
|
768
|
+
}
|
|
769
|
+
function normalizeAgentRuntimeSessionTypeIcon(value) {
|
|
770
|
+
if (typeof value === "string") {
|
|
771
|
+
const src = value.trim();
|
|
772
|
+
return src ? {
|
|
773
|
+
kind: "image",
|
|
774
|
+
src
|
|
775
|
+
} : null;
|
|
776
|
+
}
|
|
777
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
778
|
+
const iconRecord = value;
|
|
779
|
+
const src = typeof iconRecord.src === "string" ? iconRecord.src.trim() : "";
|
|
780
|
+
if (!src) return null;
|
|
781
|
+
const alt = typeof iconRecord.alt === "string" && iconRecord.alt.trim().length > 0 ? iconRecord.alt.trim() : null;
|
|
782
|
+
return {
|
|
783
|
+
kind: "image",
|
|
784
|
+
src,
|
|
785
|
+
...alt ? { alt } : {}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
const BUILTIN_RUNTIME_PRESENTATION = { hermes: {
|
|
789
|
+
label: "Hermes",
|
|
790
|
+
icon: {
|
|
791
|
+
kind: "image",
|
|
792
|
+
src: "app://runtime-icons/hermes-agent.png",
|
|
793
|
+
alt: "Hermes"
|
|
794
|
+
}
|
|
795
|
+
} };
|
|
796
|
+
function readString$6(value) {
|
|
797
|
+
if (typeof value !== "string") return;
|
|
798
|
+
return value.trim() || void 0;
|
|
799
|
+
}
|
|
800
|
+
function readRecord$3(value) {
|
|
801
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
802
|
+
return value;
|
|
803
|
+
}
|
|
804
|
+
function resolveBuiltinRuntimePresentation(value) {
|
|
805
|
+
const normalized = readString$6(value)?.toLowerCase();
|
|
806
|
+
if (!normalized) return null;
|
|
807
|
+
if (!(normalized in BUILTIN_RUNTIME_PRESENTATION)) return null;
|
|
808
|
+
return BUILTIN_RUNTIME_PRESENTATION[normalized] ?? null;
|
|
809
|
+
}
|
|
810
|
+
function buildNativeRuntimeEntry(config) {
|
|
811
|
+
const nativeRuntimeConfig = readRecord$3(config.ui?.ncp?.runtimes?.native) ?? {};
|
|
812
|
+
return {
|
|
813
|
+
id: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
814
|
+
label: "Native",
|
|
815
|
+
type: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
816
|
+
enabled: nativeRuntimeConfig.enabled !== false,
|
|
817
|
+
config: nativeRuntimeConfig
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function resolveAgentRuntimeEntries(params) {
|
|
821
|
+
const entries = /* @__PURE__ */ new Map();
|
|
822
|
+
entries.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, buildNativeRuntimeEntry(params.config));
|
|
823
|
+
for (const [rawId, rawEntry] of Object.entries(params.config.agents.runtimes.entries ?? {})) {
|
|
824
|
+
const id = rawId.trim().toLowerCase();
|
|
825
|
+
const type = readString$6(rawEntry.type)?.toLowerCase();
|
|
826
|
+
if (!id || !type) continue;
|
|
827
|
+
const explicitIcon = normalizeAgentRuntimeSessionTypeIcon(rawEntry.icon);
|
|
828
|
+
const builtinPresentation = resolveBuiltinRuntimePresentation(id) ?? resolveBuiltinRuntimePresentation(type);
|
|
829
|
+
entries.set(id, {
|
|
830
|
+
id,
|
|
831
|
+
label: readString$6(rawEntry.label) ?? builtinPresentation?.label ?? id,
|
|
832
|
+
...explicitIcon ?? builtinPresentation?.icon ? { icon: explicitIcon ?? builtinPresentation?.icon } : {},
|
|
833
|
+
type,
|
|
834
|
+
enabled: rawEntry.enabled !== false,
|
|
835
|
+
config: rawEntry.config ? { ...rawEntry.config } : {}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
defaultEntryId: entries.has("native") ? DEFAULT_AGENT_RUNTIME_ENTRY_ID : [...entries.keys()][0] ?? "native",
|
|
840
|
+
entries: [...entries.values()]
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
async function describeAgentRuntimeSessionTypes(params) {
|
|
844
|
+
const entries = params.entries.filter((entry) => entry.enabled !== false);
|
|
845
|
+
return {
|
|
846
|
+
defaultType: normalizeIdentifier(params.defaultEntryId) ?? (entries.some((entry) => entry.id === "native") ? "native" : entries[0]?.id ?? "native"),
|
|
847
|
+
options: await Promise.all(entries.map(async (entry) => {
|
|
848
|
+
const provider = params.providers.get(entry.type);
|
|
849
|
+
if (!provider) return {
|
|
850
|
+
value: entry.id,
|
|
851
|
+
label: entry.label,
|
|
852
|
+
icon: entry.icon ?? null,
|
|
853
|
+
ready: false,
|
|
854
|
+
reason: "runtime_provider_unavailable",
|
|
855
|
+
reasonMessage: `Runtime provider unavailable for type "${entry.type}".`,
|
|
856
|
+
recommendedModel: null,
|
|
857
|
+
modelSelectionMode: "nextclaw",
|
|
858
|
+
cta: {
|
|
859
|
+
kind: "settings",
|
|
860
|
+
label: "Configure Runtime"
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
const descriptor = provider.describeSessionTypeForEntry ? await provider.describeSessionTypeForEntry({
|
|
864
|
+
entry,
|
|
865
|
+
describeParams: params.describeParams
|
|
866
|
+
}) : await provider.describeSessionType?.(params.describeParams);
|
|
867
|
+
return {
|
|
868
|
+
value: entry.id,
|
|
869
|
+
label: entry.label,
|
|
870
|
+
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
871
|
+
ready: descriptor?.ready ?? true,
|
|
872
|
+
reason: descriptor?.reason ?? null,
|
|
873
|
+
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
874
|
+
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
875
|
+
modelSelectionMode: descriptor?.modelSelectionMode ?? "nextclaw",
|
|
876
|
+
cta: descriptor?.cta ?? null,
|
|
877
|
+
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
878
|
+
};
|
|
879
|
+
}))
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
//#endregion
|
|
804
883
|
//#region src/managers/agent-runtime.manager.ts
|
|
805
884
|
var AgentRuntimeManager = class {
|
|
806
885
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -846,31 +925,11 @@ var AgentRuntimeManager = class {
|
|
|
846
925
|
cache.set(cacheKey, agentRuntime);
|
|
847
926
|
return agentRuntime;
|
|
848
927
|
};
|
|
849
|
-
listSessionTypes = async (
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
entry,
|
|
855
|
-
describeParams: _params
|
|
856
|
-
}) : null;
|
|
857
|
-
return {
|
|
858
|
-
value: entry.id,
|
|
859
|
-
label: entry.label,
|
|
860
|
-
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
861
|
-
ready: provider ? descriptor?.ready ?? true : false,
|
|
862
|
-
reason: provider ? descriptor?.reason ?? null : "runtime_provider_unavailable",
|
|
863
|
-
reasonMessage: provider ? descriptor?.reasonMessage ?? null : `Runtime provider unavailable for type "${entry.type}".`,
|
|
864
|
-
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
865
|
-
cta: descriptor?.cta ?? null,
|
|
866
|
-
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
867
|
-
};
|
|
868
|
-
}));
|
|
869
|
-
return {
|
|
870
|
-
defaultType: this.entries.has("native") ? DEFAULT_AGENT_RUNTIME_ENTRY_ID : entries[0]?.id ?? "native",
|
|
871
|
-
options
|
|
872
|
-
};
|
|
873
|
-
};
|
|
928
|
+
listSessionTypes = async (params) => describeAgentRuntimeSessionTypes({
|
|
929
|
+
entries: [...this.entries.values()],
|
|
930
|
+
providers: this.providers,
|
|
931
|
+
describeParams: params
|
|
932
|
+
});
|
|
874
933
|
dispose = async () => {
|
|
875
934
|
await this.disposeAllRuntimes();
|
|
876
935
|
this.providers.clear();
|
|
@@ -1211,6 +1270,117 @@ var AutomationManager = class extends CronService {
|
|
|
1211
1270
|
}
|
|
1212
1271
|
};
|
|
1213
1272
|
//#endregion
|
|
1273
|
+
//#region src/managers/channel.manager.ts
|
|
1274
|
+
var ChannelManager = class {
|
|
1275
|
+
channels = {};
|
|
1276
|
+
channelConfig = null;
|
|
1277
|
+
dispatching = false;
|
|
1278
|
+
dispatchTask = null;
|
|
1279
|
+
extensionChannels = [];
|
|
1280
|
+
constructor(deps) {
|
|
1281
|
+
this.deps = deps;
|
|
1282
|
+
}
|
|
1283
|
+
load = (params) => {
|
|
1284
|
+
this.channelConfig = params.channelConfig;
|
|
1285
|
+
this.extensionChannels = params.extensionChannels ?? [];
|
|
1286
|
+
this.channels = {};
|
|
1287
|
+
this.initChannels();
|
|
1288
|
+
};
|
|
1289
|
+
reload = async (params) => {
|
|
1290
|
+
await this.stop();
|
|
1291
|
+
this.load(params);
|
|
1292
|
+
if (params.start === true) await this.start();
|
|
1293
|
+
};
|
|
1294
|
+
start = async () => {
|
|
1295
|
+
if (!Object.keys(this.channels).length || this.dispatching) return;
|
|
1296
|
+
this.dispatching = true;
|
|
1297
|
+
this.dispatchTask = this.dispatchOutbound();
|
|
1298
|
+
await Promise.allSettled(Object.entries(this.channels).map(([name, channel]) => this.startChannel(name, channel)));
|
|
1299
|
+
};
|
|
1300
|
+
stop = async () => {
|
|
1301
|
+
this.dispatching = false;
|
|
1302
|
+
if (this.dispatchTask) {
|
|
1303
|
+
await this.deps.bus.publishOutbound({
|
|
1304
|
+
channel: "__control__",
|
|
1305
|
+
chatId: "",
|
|
1306
|
+
content: "",
|
|
1307
|
+
media: [],
|
|
1308
|
+
metadata: { reason: "shutdown" }
|
|
1309
|
+
});
|
|
1310
|
+
await this.dispatchTask;
|
|
1311
|
+
}
|
|
1312
|
+
await Promise.allSettled(Object.entries(this.channels).map(async ([name, channel]) => {
|
|
1313
|
+
try {
|
|
1314
|
+
await channel.stop();
|
|
1315
|
+
} catch (error) {
|
|
1316
|
+
console.error(`Error stopping ${name}: ${String(error)}`);
|
|
1317
|
+
}
|
|
1318
|
+
}));
|
|
1319
|
+
this.dispatchTask = null;
|
|
1320
|
+
};
|
|
1321
|
+
status = () => Object.fromEntries(Object.entries(this.channels).map(([name, channel]) => [name, {
|
|
1322
|
+
enabled: true,
|
|
1323
|
+
running: channel.isRunning
|
|
1324
|
+
}]));
|
|
1325
|
+
get enabledChannels() {
|
|
1326
|
+
return Object.keys(this.channels);
|
|
1327
|
+
}
|
|
1328
|
+
getChannel = (name) => this.channels[name] ?? null;
|
|
1329
|
+
deliver = async (message) => {
|
|
1330
|
+
const channel = this.channels[message.channel];
|
|
1331
|
+
if (!channel) return false;
|
|
1332
|
+
if (isNextclawControlMessage(message)) {
|
|
1333
|
+
await channel.handleControlMessage(message);
|
|
1334
|
+
return true;
|
|
1335
|
+
}
|
|
1336
|
+
const outbound = this.normalizeOutbound(message);
|
|
1337
|
+
if (!outbound) return true;
|
|
1338
|
+
await channel.send(outbound);
|
|
1339
|
+
return true;
|
|
1340
|
+
};
|
|
1341
|
+
initChannels = () => {
|
|
1342
|
+
if (!this.channelConfig) return;
|
|
1343
|
+
for (const registration of this.extensionChannels) {
|
|
1344
|
+
const id = registration.channel.id;
|
|
1345
|
+
if (!id) continue;
|
|
1346
|
+
if (this.channels[id]) {
|
|
1347
|
+
console.warn(`Extension channel ignored because id already exists: ${id}`);
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
this.channels[id] = new ExtensionChannelAdapter(this.channelConfig, this.deps.bus, registration);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
startChannel = async (name, channel) => {
|
|
1354
|
+
try {
|
|
1355
|
+
await channel.start();
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
console.error(`Failed to start channel ${name}: ${String(error)}`);
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
normalizeOutbound = (message) => {
|
|
1361
|
+
const silentReplyDecision = evaluateSilentReply({
|
|
1362
|
+
content: sanitizeOutboundAssistantContent(message.content ?? ""),
|
|
1363
|
+
media: message.media
|
|
1364
|
+
});
|
|
1365
|
+
if (silentReplyDecision.shouldDrop) return null;
|
|
1366
|
+
if (silentReplyDecision.content === message.content) return message;
|
|
1367
|
+
return {
|
|
1368
|
+
...message,
|
|
1369
|
+
content: silentReplyDecision.content
|
|
1370
|
+
};
|
|
1371
|
+
};
|
|
1372
|
+
dispatchOutbound = async () => {
|
|
1373
|
+
while (this.dispatching) {
|
|
1374
|
+
const message = await this.deps.bus.consumeOutbound();
|
|
1375
|
+
try {
|
|
1376
|
+
await this.deliver(message);
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
console.error(`Error sending to ${message.channel}: ${String(error)}`);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
};
|
|
1383
|
+
//#endregion
|
|
1214
1384
|
//#region src/managers/config.manager.ts
|
|
1215
1385
|
const hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
1216
1386
|
const mergeDeep = (base, patch) => {
|
|
@@ -1821,21 +1991,6 @@ var CommandRegistry = class {
|
|
|
1821
1991
|
};
|
|
1822
1992
|
//#endregion
|
|
1823
1993
|
//#region src/features/extension-runtime/services/extension-lifecycle.service.ts
|
|
1824
|
-
function sanitizeExtensionNodeOptions(value) {
|
|
1825
|
-
if (!value?.trim()) return;
|
|
1826
|
-
const tokens = value.split(/\s+/).filter(Boolean);
|
|
1827
|
-
const sanitized = [];
|
|
1828
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
1829
|
-
const token = tokens[index];
|
|
1830
|
-
if (token === "--conditions=development" || token === "-C=development") continue;
|
|
1831
|
-
if ((token === "--conditions" || token === "-C") && tokens[index + 1] === "development") {
|
|
1832
|
-
index += 1;
|
|
1833
|
-
continue;
|
|
1834
|
-
}
|
|
1835
|
-
sanitized.push(token);
|
|
1836
|
-
}
|
|
1837
|
-
return sanitized.length > 0 ? sanitized.join(" ") : void 0;
|
|
1838
|
-
}
|
|
1839
1994
|
var ExtensionLifecycleService = class {
|
|
1840
1995
|
processes = /* @__PURE__ */ new Map();
|
|
1841
1996
|
startAll = (manifests, params) => {
|
|
@@ -1865,14 +2020,12 @@ var ExtensionLifecycleService = class {
|
|
|
1865
2020
|
if (existing) return existing;
|
|
1866
2021
|
const child = spawn(manifest.server.command === "node" || manifest.server.command === "node.exe" ? process.execPath : manifest.server.command, manifest.server.args ?? [], {
|
|
1867
2022
|
cwd: manifest.rootDir,
|
|
1868
|
-
env: {
|
|
1869
|
-
...process.env,
|
|
1870
|
-
NODE_OPTIONS: sanitizeExtensionNodeOptions(process.env.NODE_OPTIONS),
|
|
2023
|
+
env: createRuntimeChildEnv(process.env, {
|
|
1871
2024
|
...manifest.server.env,
|
|
1872
2025
|
NEXTCLAW_EXTENSION_ID: manifest.id,
|
|
1873
2026
|
NEXTCLAW_EXTENSION_ENDPOINT: params.endpoint,
|
|
1874
2027
|
NEXTCLAW_EXTENSION_TOKEN: params.tokenForExtension(manifest.id)
|
|
1875
|
-
},
|
|
2028
|
+
}, { inheritBaseEnv: true }),
|
|
1876
2029
|
stdio: [
|
|
1877
2030
|
"ignore",
|
|
1878
2031
|
"ignore",
|
|
@@ -1912,7 +2065,7 @@ const BUILTIN_EXTENSION_PACKAGES = [
|
|
|
1912
2065
|
"@nextclaw/channel-extension-weixin"
|
|
1913
2066
|
];
|
|
1914
2067
|
const runtimeRequire = createRequire(import.meta.url);
|
|
1915
|
-
function readString$
|
|
2068
|
+
function readString$5(value) {
|
|
1916
2069
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1917
2070
|
}
|
|
1918
2071
|
function readStringArray$2(value) {
|
|
@@ -1923,7 +2076,7 @@ function readStringRecord(value) {
|
|
|
1923
2076
|
const entries = Object.entries(value);
|
|
1924
2077
|
return entries.every(([, item]) => typeof item === "string") ? Object.fromEntries(entries) : void 0;
|
|
1925
2078
|
}
|
|
1926
|
-
function readRecord$
|
|
2079
|
+
function readRecord$2(value) {
|
|
1927
2080
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1928
2081
|
}
|
|
1929
2082
|
function uniquePaths(paths) {
|
|
@@ -1960,17 +2113,17 @@ function resolveDevFirstPartyExtensionDir(explicitDir = process.env.NEXTCLAW_DEV
|
|
|
1960
2113
|
function toManifest(value, rootDir) {
|
|
1961
2114
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("extension manifest must be an object");
|
|
1962
2115
|
const record = value;
|
|
1963
|
-
const server = readRecord$
|
|
1964
|
-
const id = readString$
|
|
1965
|
-
const command = readString$
|
|
2116
|
+
const server = readRecord$2(record.server);
|
|
2117
|
+
const id = readString$5(record.id);
|
|
2118
|
+
const command = readString$5(server.command);
|
|
1966
2119
|
if (!id) throw new Error("extension manifest id is required");
|
|
1967
2120
|
if (server.type !== "stdio") throw new Error("extension server.type must be stdio");
|
|
1968
2121
|
if (!command) throw new Error("extension server.command is required");
|
|
1969
2122
|
return {
|
|
1970
2123
|
id,
|
|
1971
2124
|
rootDir,
|
|
1972
|
-
...readString$
|
|
1973
|
-
...readString$
|
|
2125
|
+
...readString$5(record.name) ? { name: readString$5(record.name) } : {},
|
|
2126
|
+
...readString$5(record.version) ? { version: readString$5(record.version) } : {},
|
|
1974
2127
|
server: {
|
|
1975
2128
|
type: "stdio",
|
|
1976
2129
|
command,
|
|
@@ -2074,19 +2227,19 @@ function listExtensionChannelIds(params) {
|
|
|
2074
2227
|
//#region src/services/extension-runtime.service.ts
|
|
2075
2228
|
const EXTENSION_REQUEST_EVENT_TYPE = "extension.request";
|
|
2076
2229
|
const EXTENSION_REQUEST_TIMEOUT_MS = 6e4;
|
|
2077
|
-
function readString$
|
|
2230
|
+
function readString$4(value) {
|
|
2078
2231
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2079
2232
|
}
|
|
2080
|
-
function readRecord$
|
|
2233
|
+
function readRecord$1(value) {
|
|
2081
2234
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2082
2235
|
}
|
|
2083
|
-
function readRequiredString$
|
|
2084
|
-
const trimmed = readString$
|
|
2236
|
+
function readRequiredString$5(value, name) {
|
|
2237
|
+
const trimmed = readString$4(value);
|
|
2085
2238
|
if (!trimmed) throw new Error(`${name} is required`);
|
|
2086
2239
|
return trimmed;
|
|
2087
2240
|
}
|
|
2088
2241
|
function readTextContent(value) {
|
|
2089
|
-
const content = readRecord$
|
|
2242
|
+
const content = readRecord$1(value);
|
|
2090
2243
|
if (content.type !== "text" || typeof content.text !== "string") throw new Error("only text channel messages are supported by the first ingress bridge");
|
|
2091
2244
|
return content.text;
|
|
2092
2245
|
}
|
|
@@ -2096,35 +2249,35 @@ function readOptionalNumber(value) {
|
|
|
2096
2249
|
function readInboundAttachments(value) {
|
|
2097
2250
|
if (!Array.isArray(value)) return [];
|
|
2098
2251
|
return value.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))).map((entry) => ({
|
|
2099
|
-
...readString$
|
|
2100
|
-
...readString$
|
|
2101
|
-
...readString$
|
|
2102
|
-
...readString$
|
|
2103
|
-
...readString$
|
|
2104
|
-
...readString$
|
|
2252
|
+
...readString$4(entry.id) ? { id: readString$4(entry.id) } : {},
|
|
2253
|
+
...readString$4(entry.name) ? { name: readString$4(entry.name) } : {},
|
|
2254
|
+
...readString$4(entry.path) ? { path: readString$4(entry.path) } : {},
|
|
2255
|
+
...readString$4(entry.url) ? { url: readString$4(entry.url) } : {},
|
|
2256
|
+
...readString$4(entry.assetUri) ? { assetUri: readString$4(entry.assetUri) } : {},
|
|
2257
|
+
...readString$4(entry.mimeType) ? { mimeType: readString$4(entry.mimeType) } : {},
|
|
2105
2258
|
...readOptionalNumber(entry.size) !== void 0 ? { size: readOptionalNumber(entry.size) } : {},
|
|
2106
|
-
...readString$
|
|
2259
|
+
...readString$4(entry.source) ? { source: readString$4(entry.source) } : {},
|
|
2107
2260
|
...entry.status === "ready" || entry.status === "remote-only" ? { status: entry.status } : {},
|
|
2108
|
-
...readString$
|
|
2261
|
+
...readString$4(entry.errorCode) ? { errorCode: readString$4(entry.errorCode) } : {}
|
|
2109
2262
|
}));
|
|
2110
2263
|
}
|
|
2111
2264
|
function toInboundMessage(value) {
|
|
2112
|
-
const payload = readRecord$
|
|
2265
|
+
const payload = readRecord$1(value);
|
|
2113
2266
|
return {
|
|
2114
|
-
channel: readRequiredString$
|
|
2115
|
-
chatId: readRequiredString$
|
|
2116
|
-
senderId: readRequiredString$
|
|
2267
|
+
channel: readRequiredString$5(payload.channelId, "channelId"),
|
|
2268
|
+
chatId: readRequiredString$5(payload.conversationId, "conversationId"),
|
|
2269
|
+
senderId: readRequiredString$5(payload.senderId, "senderId"),
|
|
2117
2270
|
content: readTextContent(payload.content),
|
|
2118
2271
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2119
2272
|
attachments: readInboundAttachments(payload.attachments),
|
|
2120
|
-
metadata: readRecord$
|
|
2273
|
+
metadata: readRecord$1(payload.metadata)
|
|
2121
2274
|
};
|
|
2122
2275
|
}
|
|
2123
2276
|
function normalizeChannelConfigResult(value) {
|
|
2124
|
-
return readRecord$
|
|
2277
|
+
return readRecord$1(readRecord$1(value).channelConfig);
|
|
2125
2278
|
}
|
|
2126
2279
|
function normalizeAuthLoginResult(value) {
|
|
2127
|
-
const record = readRecord$
|
|
2280
|
+
const record = readRecord$1(value);
|
|
2128
2281
|
return {
|
|
2129
2282
|
channelConfig: normalizeChannelConfigResult(record),
|
|
2130
2283
|
accountId: typeof record.accountId === "string" ? record.accountId : null,
|
|
@@ -2133,11 +2286,11 @@ function normalizeAuthLoginResult(value) {
|
|
|
2133
2286
|
}
|
|
2134
2287
|
function normalizeAuthPollResult(value) {
|
|
2135
2288
|
if (!value) return null;
|
|
2136
|
-
const record = readRecord$
|
|
2289
|
+
const record = readRecord$1(value);
|
|
2137
2290
|
return {
|
|
2138
|
-
channel: readRequiredString$
|
|
2291
|
+
channel: readRequiredString$5(record.channel, "channel"),
|
|
2139
2292
|
status: record.status,
|
|
2140
|
-
message: readString$
|
|
2293
|
+
message: readString$4(record.message),
|
|
2141
2294
|
nextPollMs: readOptionalNumber(record.nextPollMs),
|
|
2142
2295
|
accountId: typeof record.accountId === "string" ? record.accountId : null,
|
|
2143
2296
|
notes: Array.isArray(record.notes) ? record.notes.filter((note) => typeof note === "string") : [],
|
|
@@ -2233,7 +2386,7 @@ var ExtensionRuntimeService = class {
|
|
|
2233
2386
|
if (running.length > 0) console.log(`✓ Extensions started: ${running.map((entry) => entry.manifest.id).join(", ")}`);
|
|
2234
2387
|
};
|
|
2235
2388
|
getExtensionProcessToken = (extensionId) => {
|
|
2236
|
-
const id = readRequiredString$
|
|
2389
|
+
const id = readRequiredString$5(extensionId, "extensionId");
|
|
2237
2390
|
const current = this.extensionTokens.get(id);
|
|
2238
2391
|
if (current) return current;
|
|
2239
2392
|
const token = randomUUID();
|
|
@@ -2241,8 +2394,8 @@ var ExtensionRuntimeService = class {
|
|
|
2241
2394
|
return token;
|
|
2242
2395
|
};
|
|
2243
2396
|
authenticateEventStreamCredential = (input) => {
|
|
2244
|
-
const extensionId = readString$
|
|
2245
|
-
const token = readString$
|
|
2397
|
+
const extensionId = readString$4(input.extensionId);
|
|
2398
|
+
const token = readString$4(input.token);
|
|
2246
2399
|
if (!extensionId || !token || token !== this.extensionTokens.get(extensionId)) return null;
|
|
2247
2400
|
return { extensionId };
|
|
2248
2401
|
};
|
|
@@ -2261,7 +2414,7 @@ var ExtensionRuntimeService = class {
|
|
|
2261
2414
|
const channelBindings = [];
|
|
2262
2415
|
const uiMetadata = [];
|
|
2263
2416
|
for (const manifest of manifests) for (const channel of manifest.contributes?.channels ?? []) {
|
|
2264
|
-
const channelId = readString$
|
|
2417
|
+
const channelId = readString$4(channel.id);
|
|
2265
2418
|
if (!channelId) continue;
|
|
2266
2419
|
const configUiHints = this.readConfigUiHints(channel.configUiHints);
|
|
2267
2420
|
channelBindings.push({
|
|
@@ -2296,7 +2449,7 @@ var ExtensionRuntimeService = class {
|
|
|
2296
2449
|
};
|
|
2297
2450
|
handleChannelConfigGet = (envelope, context) => {
|
|
2298
2451
|
this.assertAuthorized(envelope, context);
|
|
2299
|
-
const channelId = readRequiredString$
|
|
2452
|
+
const channelId = readRequiredString$5(readRecord$1(envelope.payload).channelId, "channelId");
|
|
2300
2453
|
return { config: this.options.getConfig().channels[channelId] ?? {} };
|
|
2301
2454
|
};
|
|
2302
2455
|
handleChannelMessageSubmit = async (envelope, context) => {
|
|
@@ -2310,11 +2463,11 @@ var ExtensionRuntimeService = class {
|
|
|
2310
2463
|
};
|
|
2311
2464
|
handleChannelCommandExecute = async (envelope, context) => {
|
|
2312
2465
|
this.assertAuthorized(envelope, context);
|
|
2313
|
-
const payload = readRecord$
|
|
2314
|
-
const channel = readRequiredString$
|
|
2315
|
-
const chatId = readRequiredString$
|
|
2316
|
-
const senderId = readRequiredString$
|
|
2317
|
-
const metadata = readRecord$
|
|
2466
|
+
const payload = readRecord$1(envelope.payload);
|
|
2467
|
+
const channel = readRequiredString$5(payload.channelId, "channelId");
|
|
2468
|
+
const chatId = readRequiredString$5(payload.conversationId, "conversationId");
|
|
2469
|
+
const senderId = readRequiredString$5(payload.senderId, "senderId");
|
|
2470
|
+
const metadata = readRecord$1(payload.metadata);
|
|
2318
2471
|
const config = this.options.getConfig();
|
|
2319
2472
|
const registry = new CommandRegistry(config, this.options.sessionManager);
|
|
2320
2473
|
const route = new AgentRouteResolver(config).resolveInbound({
|
|
@@ -2322,15 +2475,15 @@ var ExtensionRuntimeService = class {
|
|
|
2322
2475
|
channel,
|
|
2323
2476
|
chatId,
|
|
2324
2477
|
senderId,
|
|
2325
|
-
content: readString$
|
|
2478
|
+
content: readString$4(payload.rawText) ?? readString$4(payload.commandName) ?? "",
|
|
2326
2479
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2327
2480
|
attachments: [],
|
|
2328
2481
|
metadata
|
|
2329
2482
|
},
|
|
2330
|
-
forcedAgentId: readString$
|
|
2331
|
-
sessionKeyOverride: readString$
|
|
2483
|
+
forcedAgentId: readString$4(metadata.target_agent_id),
|
|
2484
|
+
sessionKeyOverride: readString$4(metadata.session_key_override)
|
|
2332
2485
|
});
|
|
2333
|
-
const rawText = readString$
|
|
2486
|
+
const rawText = readString$4(payload.rawText);
|
|
2334
2487
|
if (rawText) return await registry.executeText(rawText, {
|
|
2335
2488
|
channel,
|
|
2336
2489
|
chatId,
|
|
@@ -2340,7 +2493,7 @@ var ExtensionRuntimeService = class {
|
|
|
2340
2493
|
content: "",
|
|
2341
2494
|
ephemeral: true
|
|
2342
2495
|
};
|
|
2343
|
-
return await registry.execute(readRequiredString$
|
|
2496
|
+
return await registry.execute(readRequiredString$5(payload.commandName, "commandName"), readRecord$1(payload.args), {
|
|
2344
2497
|
channel,
|
|
2345
2498
|
chatId,
|
|
2346
2499
|
senderId,
|
|
@@ -2349,14 +2502,14 @@ var ExtensionRuntimeService = class {
|
|
|
2349
2502
|
};
|
|
2350
2503
|
handleExtensionResponse = (envelope, context) => {
|
|
2351
2504
|
this.assertAuthorized(envelope, context);
|
|
2352
|
-
const payload = readRecord$
|
|
2353
|
-
const requestId = readRequiredString$
|
|
2505
|
+
const payload = readRecord$1(envelope.payload);
|
|
2506
|
+
const requestId = readRequiredString$5(payload.requestId, "requestId");
|
|
2354
2507
|
const pending = this.pendingRequests.get(requestId);
|
|
2355
2508
|
if (!pending) return { accepted: false };
|
|
2356
2509
|
this.pendingRequests.delete(requestId);
|
|
2357
2510
|
clearTimeout(pending.timeout);
|
|
2358
2511
|
if (payload.ok === false) {
|
|
2359
|
-
const message = readString$
|
|
2512
|
+
const message = readString$4(readRecord$1(payload.error).message) ?? "Extension request failed";
|
|
2360
2513
|
pending.reject(new Error(message));
|
|
2361
2514
|
return { accepted: true };
|
|
2362
2515
|
}
|
|
@@ -2403,7 +2556,7 @@ var ExtensionRuntimeService = class {
|
|
|
2403
2556
|
return await result;
|
|
2404
2557
|
};
|
|
2405
2558
|
assertAuthorized = (envelope, context) => {
|
|
2406
|
-
const extensionId = readString$
|
|
2559
|
+
const extensionId = readString$4(envelope.extensionId);
|
|
2407
2560
|
if (!extensionId || context.token !== this.extensionTokens.get(extensionId)) throw new Error("Unauthorized ingress token");
|
|
2408
2561
|
};
|
|
2409
2562
|
};
|
|
@@ -2526,11 +2679,11 @@ var ExtensionManager = class {
|
|
|
2526
2679
|
//#endregion
|
|
2527
2680
|
//#region src/utils/model-message-vision.utils.ts
|
|
2528
2681
|
const IMAGE_OMITTED_TEXT = "[Image omitted: the selected model is not configured for vision input.]";
|
|
2529
|
-
function isRecord$
|
|
2682
|
+
function isRecord$12(value) {
|
|
2530
2683
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2531
2684
|
}
|
|
2532
2685
|
function isImageContentPart(value) {
|
|
2533
|
-
if (!isRecord$
|
|
2686
|
+
if (!isRecord$12(value)) return false;
|
|
2534
2687
|
const type = value.type;
|
|
2535
2688
|
return type === "image_url" || type === "input_image";
|
|
2536
2689
|
}
|
|
@@ -2546,7 +2699,7 @@ function normalizeContentWithoutVision(content) {
|
|
|
2546
2699
|
};
|
|
2547
2700
|
});
|
|
2548
2701
|
if (!sawImage) return content;
|
|
2549
|
-
const textParts = parts.filter((part) => isRecord$
|
|
2702
|
+
const textParts = parts.filter((part) => isRecord$12(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text.trim()).filter(Boolean);
|
|
2550
2703
|
if (textParts.length === parts.length) return textParts.join("\n\n");
|
|
2551
2704
|
return parts;
|
|
2552
2705
|
}
|
|
@@ -3086,11 +3239,11 @@ function createAgentPeerSessionIdentity(params) {
|
|
|
3086
3239
|
}
|
|
3087
3240
|
function resolveAgentPeerScope(params) {
|
|
3088
3241
|
const metadata = params.metadata ?? {};
|
|
3089
|
-
const explicitScope = readOptionalString$
|
|
3242
|
+
const explicitScope = readOptionalString$9(metadata["agent_peer_scope"]) ?? readOptionalString$9(metadata.agentPeerScope);
|
|
3090
3243
|
if (explicitScope) return explicitScope;
|
|
3091
|
-
return `agent:${readOptionalString$
|
|
3244
|
+
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"}`;
|
|
3092
3245
|
}
|
|
3093
|
-
function readOptionalString$
|
|
3246
|
+
function readOptionalString$9(value) {
|
|
3094
3247
|
if (typeof value !== "string") return;
|
|
3095
3248
|
return value.trim() || void 0;
|
|
3096
3249
|
}
|
|
@@ -3109,7 +3262,7 @@ function safeNcpSessionFilename(value) {
|
|
|
3109
3262
|
function normalizeNcpAgentId(agentId) {
|
|
3110
3263
|
return agentId?.trim().toLowerCase() || void 0;
|
|
3111
3264
|
}
|
|
3112
|
-
function isRecord$
|
|
3265
|
+
function isRecord$11(value) {
|
|
3113
3266
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3114
3267
|
}
|
|
3115
3268
|
function toIsoString(value, fallback) {
|
|
@@ -3189,7 +3342,7 @@ function createReplayEvent(event) {
|
|
|
3189
3342
|
return replayEvent;
|
|
3190
3343
|
}
|
|
3191
3344
|
function readLegacyContextCompactionMessageId(message) {
|
|
3192
|
-
const checkpoint = isRecord$
|
|
3345
|
+
const checkpoint = isRecord$11(message?.metadata?.checkpoint) ? message.metadata.checkpoint : null;
|
|
3193
3346
|
const checkpointId = typeof checkpoint?.id === "string" ? checkpoint.id : "";
|
|
3194
3347
|
const coveredCount = checkpoint?.coveredSessionMessageCount;
|
|
3195
3348
|
const legacyId = `${message?.sessionId}:service:context-compaction:${checkpointId}`;
|
|
@@ -3219,11 +3372,11 @@ function rememberReplayMessageId(event, knownMessageIds) {
|
|
|
3219
3372
|
if (message?.id) knownMessageIds.add(message.id);
|
|
3220
3373
|
}
|
|
3221
3374
|
function readEventSessionId$2(event) {
|
|
3222
|
-
const sessionId = ("payload" in event && isRecord$
|
|
3375
|
+
const sessionId = ("payload" in event && isRecord$11(event.payload) ? event.payload : null)?.sessionId;
|
|
3223
3376
|
return typeof sessionId === "string" ? sessionId : "";
|
|
3224
3377
|
}
|
|
3225
3378
|
function readReplayPayloadTimestamp(event) {
|
|
3226
|
-
const payload = "payload" in event && isRecord$
|
|
3379
|
+
const payload = "payload" in event && isRecord$11(event.payload) ? event.payload : null;
|
|
3227
3380
|
const timestamp = typeof payload?.timestamp === "string" ? payload.timestamp : "";
|
|
3228
3381
|
return Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
|
|
3229
3382
|
}
|
|
@@ -3278,7 +3431,7 @@ function applyLimit(items, limit) {
|
|
|
3278
3431
|
if (!Number.isFinite(limit) || typeof limit !== "number" || limit <= 0) return items;
|
|
3279
3432
|
return items.slice(0, Math.trunc(limit));
|
|
3280
3433
|
}
|
|
3281
|
-
function readOptionalString$
|
|
3434
|
+
function readOptionalString$8(value) {
|
|
3282
3435
|
if (typeof value !== "string") return null;
|
|
3283
3436
|
const trimmed = value.trim();
|
|
3284
3437
|
return trimmed.length > 0 ? trimmed : null;
|
|
@@ -3292,8 +3445,8 @@ function readEventSessionId$1(event) {
|
|
|
3292
3445
|
//#endregion
|
|
3293
3446
|
//#region src/services/session-working-dir-resolver.service.ts
|
|
3294
3447
|
var SessionWorkingDirResolver = class {
|
|
3295
|
-
constructor(
|
|
3296
|
-
this.
|
|
3448
|
+
constructor(agentManager) {
|
|
3449
|
+
this.agentManager = agentManager;
|
|
3297
3450
|
}
|
|
3298
3451
|
withWorkingDir = (summary) => ({
|
|
3299
3452
|
...summary,
|
|
@@ -3303,12 +3456,10 @@ var SessionWorkingDirResolver = class {
|
|
|
3303
3456
|
})
|
|
3304
3457
|
});
|
|
3305
3458
|
resolve = (params) => {
|
|
3306
|
-
const
|
|
3307
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
3308
|
-
const profile = findEffectiveAgentProfile(config, readOptionalString$7(params.agentId) ?? defaultAgentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
3459
|
+
const profile = this.agentManager.resolveAgentProfile(readOptionalString$8(params.agentId));
|
|
3309
3460
|
return resolveSessionWorkspacePath({
|
|
3310
3461
|
sessionMetadata: params.metadata,
|
|
3311
|
-
workspace: profile
|
|
3462
|
+
workspace: profile.workspace
|
|
3312
3463
|
});
|
|
3313
3464
|
};
|
|
3314
3465
|
};
|
|
@@ -3320,6 +3471,7 @@ const SESSION_METADATA_LABEL_KEY = "label";
|
|
|
3320
3471
|
const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
|
|
3321
3472
|
const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
|
|
3322
3473
|
const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
|
|
3474
|
+
const SESSION_METADATA_PATCH_RUN_METADATA_KIND = "session_metadata_patch";
|
|
3323
3475
|
function isDurableSessionEvent(event) {
|
|
3324
3476
|
return event.type !== NcpEventType.ContextWindowUpdated;
|
|
3325
3477
|
}
|
|
@@ -3360,7 +3512,7 @@ function mergeMetadataOverrides(metadata, overrides) {
|
|
|
3360
3512
|
}
|
|
3361
3513
|
function resolveSessionType(params) {
|
|
3362
3514
|
const { metadata, runtime, sessionType } = params;
|
|
3363
|
-
return readOptionalString$
|
|
3515
|
+
return readOptionalString$8(runtime) ?? readOptionalString$8(metadata.runtime) ?? readOptionalString$8(sessionType) ?? readOptionalString$8(metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
3364
3516
|
}
|
|
3365
3517
|
function applySessionOverrides(params) {
|
|
3366
3518
|
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
@@ -3370,15 +3522,15 @@ function applySessionOverrides(params) {
|
|
|
3370
3522
|
metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
|
|
3371
3523
|
if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
|
|
3372
3524
|
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
3373
|
-
if (readOptionalString$
|
|
3525
|
+
if (readOptionalString$8(model)) {
|
|
3374
3526
|
metadata.model = model?.trim();
|
|
3375
3527
|
metadata.preferred_model = model?.trim();
|
|
3376
3528
|
}
|
|
3377
|
-
if (readOptionalString$
|
|
3529
|
+
if (readOptionalString$8(thinkingLevel)) {
|
|
3378
3530
|
metadata.thinking = thinkingLevel?.trim();
|
|
3379
3531
|
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
3380
3532
|
}
|
|
3381
|
-
if (readOptionalString$
|
|
3533
|
+
if (readOptionalString$8(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
3382
3534
|
}
|
|
3383
3535
|
function isSessionSummaryRefreshEvent(event) {
|
|
3384
3536
|
switch (event.type) {
|
|
@@ -3390,6 +3542,13 @@ function isSessionSummaryRefreshEvent(event) {
|
|
|
3390
3542
|
default: return false;
|
|
3391
3543
|
}
|
|
3392
3544
|
}
|
|
3545
|
+
function readRuntimeSessionMetadataPatch(event) {
|
|
3546
|
+
if (event.type !== NcpEventType.RunMetadata) return null;
|
|
3547
|
+
const metadata = event.payload.metadata;
|
|
3548
|
+
if (metadata.kind !== SESSION_METADATA_PATCH_RUN_METADATA_KIND || !metadata.sessionMetadataPatch || typeof metadata.sessionMetadataPatch !== "object" || Array.isArray(metadata.sessionMetadataPatch)) return null;
|
|
3549
|
+
const patch = metadata.sessionMetadataPatch;
|
|
3550
|
+
return Object.keys(patch).length > 0 ? structuredClone(patch) : null;
|
|
3551
|
+
}
|
|
3393
3552
|
var SessionManager = class {
|
|
3394
3553
|
cleanups = [];
|
|
3395
3554
|
contextWindowPreview;
|
|
@@ -3397,8 +3556,8 @@ var SessionManager = class {
|
|
|
3397
3556
|
started = false;
|
|
3398
3557
|
constructor(options) {
|
|
3399
3558
|
this.options = options;
|
|
3400
|
-
this.contextWindowPreview = new ContextWindowPreviewManager(
|
|
3401
|
-
this.workingDirResolver = new SessionWorkingDirResolver(options.
|
|
3559
|
+
this.contextWindowPreview = new ContextWindowPreviewManager(options.agentManager);
|
|
3560
|
+
this.workingDirResolver = new SessionWorkingDirResolver(options.agentManager);
|
|
3402
3561
|
}
|
|
3403
3562
|
start = () => {
|
|
3404
3563
|
if (this.started) return;
|
|
@@ -3406,6 +3565,11 @@ var SessionManager = class {
|
|
|
3406
3565
|
this.cleanups.push(this.options.eventBus.on(eventKeys.ncpEvent, async (event) => {
|
|
3407
3566
|
const sessionId = readEventSessionId$1(event);
|
|
3408
3567
|
if (!sessionId || !isDurableSessionEvent(event)) return;
|
|
3568
|
+
const metadataPatch = readRuntimeSessionMetadataPatch(event);
|
|
3569
|
+
if (metadataPatch) {
|
|
3570
|
+
await this.updateSessionMetadata(sessionId, metadataPatch);
|
|
3571
|
+
return;
|
|
3572
|
+
}
|
|
3409
3573
|
await this.appendSessionEvent({
|
|
3410
3574
|
event,
|
|
3411
3575
|
sessionId
|
|
@@ -3420,9 +3584,9 @@ var SessionManager = class {
|
|
|
3420
3584
|
const { agentId: requestedAgentId, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
|
|
3421
3585
|
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
3422
3586
|
const metadata = cloneInheritedMetadata(sourceSessionMetadata);
|
|
3423
|
-
const title = readOptionalString$
|
|
3424
|
-
const parentSessionId = readOptionalString$
|
|
3425
|
-
const requestId = readOptionalString$
|
|
3587
|
+
const title = readOptionalString$8(requestedTitle) ?? summarizeTask(task);
|
|
3588
|
+
const parentSessionId = readOptionalString$8(rawParentSessionId);
|
|
3589
|
+
const requestId = readOptionalString$8(rawRequestId);
|
|
3426
3590
|
const sessionType = resolveSessionType({
|
|
3427
3591
|
runtime,
|
|
3428
3592
|
sessionType: requestedSessionType,
|
|
@@ -3441,8 +3605,8 @@ var SessionManager = class {
|
|
|
3441
3605
|
});
|
|
3442
3606
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3443
3607
|
const nextMetadata = mergeMetadataOverrides(metadata, metadataOverrides);
|
|
3444
|
-
const agentId = readOptionalString$
|
|
3445
|
-
const sessionId = readOptionalString$
|
|
3608
|
+
const agentId = readOptionalString$8(requestedAgentId) ?? readOptionalString$8(sourceRecord?.agentId) ?? BUILTIN_MAIN_AGENT_ID;
|
|
3609
|
+
const sessionId = readOptionalString$8(requestedSessionId) ?? buildSessionId();
|
|
3446
3610
|
const record = {
|
|
3447
3611
|
sessionId,
|
|
3448
3612
|
...agentId ? { agentId } : {},
|
|
@@ -3515,7 +3679,7 @@ var SessionManager = class {
|
|
|
3515
3679
|
return await this.options.journalStore.getSession(normalizedSessionId);
|
|
3516
3680
|
};
|
|
3517
3681
|
listSessions = async (options) => {
|
|
3518
|
-
const peerId = readOptionalString$
|
|
3682
|
+
const peerId = readOptionalString$8(options?.peerId);
|
|
3519
3683
|
return applyLimit((await this.options.journalStore.listSessionSummaries()).filter((summary) => !peerId || summary.peerId === peerId).map(this.workingDirResolver.withWorkingDir), options?.limit);
|
|
3520
3684
|
};
|
|
3521
3685
|
listSessionMessages = async (sessionId, options) => {
|
|
@@ -3548,14 +3712,14 @@ var SessionManager = class {
|
|
|
3548
3712
|
createAgentRunSession = async (params) => {
|
|
3549
3713
|
const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, metadata, model, peerId: rawPeerId, projectRoot, sessionId, task, thinkingEffort } = params;
|
|
3550
3714
|
const agentRuntimeId = requestedAgentRuntimeId ?? "native";
|
|
3551
|
-
const peerId = readOptionalString$
|
|
3715
|
+
const peerId = readOptionalString$8(rawPeerId);
|
|
3552
3716
|
const peerIdentity = peerId ? createAgentPeerSessionIdentity({
|
|
3553
3717
|
agentId,
|
|
3554
3718
|
channel,
|
|
3555
3719
|
metadata,
|
|
3556
3720
|
peerId
|
|
3557
3721
|
}) : void 0;
|
|
3558
|
-
const requestedSessionId = readOptionalString$
|
|
3722
|
+
const requestedSessionId = readOptionalString$8(sessionId);
|
|
3559
3723
|
const created = await this.createSession({
|
|
3560
3724
|
sourceSessionMetadata: {},
|
|
3561
3725
|
sessionId: requestedSessionId ?? peerIdentity?.sessionId,
|
|
@@ -3845,12 +4009,12 @@ var PanelAppCapabilityGrantStore = class {
|
|
|
3845
4009
|
};
|
|
3846
4010
|
};
|
|
3847
4011
|
function normalizeStoreData$2(value) {
|
|
3848
|
-
if (!isRecord$
|
|
4012
|
+
if (!isRecord$10(value) || value.version !== 1 || !isRecord$10(value.grants)) return structuredClone(EMPTY_GRANTS$2);
|
|
3849
4013
|
const grants = {};
|
|
3850
4014
|
for (const [callerKey, callerValue] of Object.entries(value.grants)) {
|
|
3851
|
-
if (!isRecord$
|
|
4015
|
+
if (!isRecord$10(callerValue) || !isRecord$10(callerValue.capabilities)) continue;
|
|
3852
4016
|
const capabilities = {};
|
|
3853
|
-
for (const [capability, grantValue] of Object.entries(callerValue.capabilities)) if (isRecord$
|
|
4017
|
+
for (const [capability, grantValue] of Object.entries(callerValue.capabilities)) if (isRecord$10(grantValue) && typeof grantValue.grantedAt === "string") capabilities[capability] = { grantedAt: grantValue.grantedAt };
|
|
3854
4018
|
grants[callerKey] = { capabilities };
|
|
3855
4019
|
}
|
|
3856
4020
|
return {
|
|
@@ -3861,7 +4025,7 @@ function normalizeStoreData$2(value) {
|
|
|
3861
4025
|
function getCallerKey(caller) {
|
|
3862
4026
|
return `${caller.surface}:${caller.appId}`;
|
|
3863
4027
|
}
|
|
3864
|
-
function isRecord$
|
|
4028
|
+
function isRecord$10(value) {
|
|
3865
4029
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3866
4030
|
}
|
|
3867
4031
|
function isMissingFileError$3(error) {
|
|
@@ -3907,19 +4071,19 @@ var PanelAppClientGrantStore = class {
|
|
|
3907
4071
|
};
|
|
3908
4072
|
};
|
|
3909
4073
|
function normalizeStoreData$1(value) {
|
|
3910
|
-
if (!isRecord$
|
|
4074
|
+
if (!isRecord$9(value) || value.version !== 1 || !isRecord$9(value.grants)) return structuredClone(EMPTY_GRANTS$1);
|
|
3911
4075
|
const grants = {};
|
|
3912
|
-
for (const [appId, grant] of Object.entries(value.grants)) if (isRecord$
|
|
4076
|
+
for (const [appId, grant] of Object.entries(value.grants)) if (isRecord$9(grant) && typeof grant.grantedAt === "string") grants[appId] = { grantedAt: grant.grantedAt };
|
|
3913
4077
|
return {
|
|
3914
4078
|
grants,
|
|
3915
4079
|
version: 1
|
|
3916
4080
|
};
|
|
3917
4081
|
}
|
|
3918
|
-
function isRecord$
|
|
4082
|
+
function isRecord$9(value) {
|
|
3919
4083
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3920
4084
|
}
|
|
3921
4085
|
function isMissingFileError$2(error) {
|
|
3922
|
-
return isRecord$
|
|
4086
|
+
return isRecord$9(error) && error.code === "ENOENT";
|
|
3923
4087
|
}
|
|
3924
4088
|
//#endregion
|
|
3925
4089
|
//#region src/services/agent-run-client.service.ts
|
|
@@ -4138,7 +4302,7 @@ const PANEL_APP_AGENT_MAX_CONTEXT_CHARS = 8e4;
|
|
|
4138
4302
|
function normalizePanelAppGenerateObjectInput(input) {
|
|
4139
4303
|
const peerId = input.peerId.trim();
|
|
4140
4304
|
const prompt = input.prompt.trim();
|
|
4141
|
-
if (!peerId || !prompt || !isRecord$
|
|
4305
|
+
if (!peerId || !prompt || !isRecord$8(input.schema)) throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "invalid generateObject request");
|
|
4142
4306
|
if (prompt.length > PANEL_APP_AGENT_MAX_PROMPT_CHARS) throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "generateObject prompt is too large");
|
|
4143
4307
|
if (stringifyJsonValue(input.context ?? null).length > PANEL_APP_AGENT_MAX_CONTEXT_CHARS) throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "generateObject context is too large");
|
|
4144
4308
|
return {
|
|
@@ -4279,7 +4443,7 @@ function readStructuredResultEvent(event, resultToolCallId) {
|
|
|
4279
4443
|
};
|
|
4280
4444
|
}
|
|
4281
4445
|
function assertToolResultContent(content) {
|
|
4282
|
-
if (!isRecord$
|
|
4446
|
+
if (!isRecord$8(content) || content.ok !== false || !isRecord$8(content.error)) return;
|
|
4283
4447
|
if (content.error.code === "invalid_tool_arguments") throw new PanelAppError("AGENT_OBJECT_RESULT_SCHEMA_INVALID", "agent object result did not match the schema");
|
|
4284
4448
|
throw new PanelAppError("AGENT_OBJECT_REQUEST_FAILED", typeof content.error.message === "string" ? content.error.message : "agent object request failed");
|
|
4285
4449
|
}
|
|
@@ -4295,7 +4459,7 @@ function stringifyJsonValue(value) {
|
|
|
4295
4459
|
throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "value is not JSON serializable");
|
|
4296
4460
|
}
|
|
4297
4461
|
}
|
|
4298
|
-
function isRecord$
|
|
4462
|
+
function isRecord$8(value) {
|
|
4299
4463
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4300
4464
|
}
|
|
4301
4465
|
//#endregion
|
|
@@ -4569,15 +4733,15 @@ function parsePanelAppFolderManifest(raw) {
|
|
|
4569
4733
|
} catch (error) {
|
|
4570
4734
|
throw new Error(`panel-app.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
4571
4735
|
}
|
|
4572
|
-
if (!isRecord$
|
|
4573
|
-
const id = readOptionalString$
|
|
4736
|
+
if (!isRecord$7(parsed)) throw new Error("panel-app.json must contain an object.");
|
|
4737
|
+
const id = readOptionalString$7(parsed, "id");
|
|
4574
4738
|
if (id && !PANEL_APP_ID_PATTERN.test(id)) throw new Error("panel app id must be kebab-case.");
|
|
4575
4739
|
return {
|
|
4576
4740
|
id,
|
|
4577
|
-
title: readRequiredString$
|
|
4578
|
-
description: readOptionalString$
|
|
4579
|
-
icon: readOptionalString$
|
|
4580
|
-
entry: readRequiredString$
|
|
4741
|
+
title: readRequiredString$4(parsed, "title"),
|
|
4742
|
+
description: readOptionalString$7(parsed, "description"),
|
|
4743
|
+
icon: readOptionalString$7(parsed, "icon"),
|
|
4744
|
+
entry: readRequiredString$4(parsed, "entry"),
|
|
4581
4745
|
capabilities: readStringArray$1(parsed.capabilities, "capabilities"),
|
|
4582
4746
|
client: readOptionalBoolean$2(parsed, "client"),
|
|
4583
4747
|
serviceActions: readStringArray$1(parsed.actions, "actions")
|
|
@@ -4637,12 +4801,12 @@ function parseTokenList(content) {
|
|
|
4637
4801
|
if (!content) return [];
|
|
4638
4802
|
return [...new Set(content.split(/[,\s]+/).map((entry) => entry.trim()).filter(Boolean))];
|
|
4639
4803
|
}
|
|
4640
|
-
function readRequiredString$
|
|
4641
|
-
const value = readOptionalString$
|
|
4804
|
+
function readRequiredString$4(record, key) {
|
|
4805
|
+
const value = readOptionalString$7(record, key);
|
|
4642
4806
|
if (!value) throw new Error(`panel app ${key} is required.`);
|
|
4643
4807
|
return value;
|
|
4644
4808
|
}
|
|
4645
|
-
function readOptionalString$
|
|
4809
|
+
function readOptionalString$7(record, key) {
|
|
4646
4810
|
return typeof record[key] === "string" && record[key].trim() ? record[key].trim() : void 0;
|
|
4647
4811
|
}
|
|
4648
4812
|
function readOptionalBoolean$2(record, key) {
|
|
@@ -4656,7 +4820,7 @@ function readStringArray$1(value, key) {
|
|
|
4656
4820
|
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new Error(`panel app ${key} must be a string array.`);
|
|
4657
4821
|
return [...new Set(value.map((entry) => entry.trim()).filter(Boolean))];
|
|
4658
4822
|
}
|
|
4659
|
-
function isRecord$
|
|
4823
|
+
function isRecord$7(value) {
|
|
4660
4824
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4661
4825
|
}
|
|
4662
4826
|
function normalizeTextValue(value) {
|
|
@@ -5374,12 +5538,12 @@ var ServiceActionGrantStore = class {
|
|
|
5374
5538
|
};
|
|
5375
5539
|
};
|
|
5376
5540
|
function normalizeStoreData(value) {
|
|
5377
|
-
if (!isRecord$
|
|
5541
|
+
if (!isRecord$6(value) || value.version !== 1 || !isRecord$6(value.grants)) return structuredClone(EMPTY_GRANTS);
|
|
5378
5542
|
const grants = {};
|
|
5379
5543
|
for (const [callerKey, callerValue] of Object.entries(value.grants)) {
|
|
5380
|
-
if (!isRecord$
|
|
5544
|
+
if (!isRecord$6(callerValue) || !isRecord$6(callerValue.actions)) continue;
|
|
5381
5545
|
const actions = {};
|
|
5382
|
-
for (const [actionId, actionValue] of Object.entries(callerValue.actions)) if (isRecord$
|
|
5546
|
+
for (const [actionId, actionValue] of Object.entries(callerValue.actions)) if (isRecord$6(actionValue) && typeof actionValue.grantedAt === "string" && isServiceActionRisk(actionValue.risk)) actions[actionId] = {
|
|
5383
5547
|
grantedAt: actionValue.grantedAt,
|
|
5384
5548
|
risk: actionValue.risk
|
|
5385
5549
|
};
|
|
@@ -5393,11 +5557,11 @@ function normalizeStoreData(value) {
|
|
|
5393
5557
|
function isServiceActionRisk(value) {
|
|
5394
5558
|
return value === "read" || value === "write" || value === "external" || value === "dangerous";
|
|
5395
5559
|
}
|
|
5396
|
-
function isRecord$
|
|
5560
|
+
function isRecord$6(value) {
|
|
5397
5561
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5398
5562
|
}
|
|
5399
5563
|
function isMissingFileError(error) {
|
|
5400
|
-
return isRecord$
|
|
5564
|
+
return isRecord$6(error) && error.code === "ENOENT";
|
|
5401
5565
|
}
|
|
5402
5566
|
//#endregion
|
|
5403
5567
|
//#region src/utils/service-app-manifest.utils.ts
|
|
@@ -5422,49 +5586,49 @@ function parseServiceAppManifest(raw) {
|
|
|
5422
5586
|
} catch (error) {
|
|
5423
5587
|
throw new Error(`service-app.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
5424
5588
|
}
|
|
5425
|
-
if (!isRecord$
|
|
5426
|
-
const id = readRequiredString$
|
|
5589
|
+
if (!isRecord$5(parsed)) throw new Error("service-app.json must contain an object.");
|
|
5590
|
+
const id = readRequiredString$3(parsed, "id");
|
|
5427
5591
|
if (!SERVICE_APP_ID_PATTERN.test(id)) throw new Error("service app id must be kebab-case.");
|
|
5428
|
-
const protocol = readOptionalString$
|
|
5592
|
+
const protocol = readOptionalString$6(parsed, "protocol") ?? "mcp";
|
|
5429
5593
|
if (protocol !== "mcp") throw new Error("service app protocol must be mcp.");
|
|
5430
5594
|
return {
|
|
5431
5595
|
id,
|
|
5432
|
-
title: readRequiredString$
|
|
5433
|
-
description: readOptionalString$
|
|
5596
|
+
title: readRequiredString$3(parsed, "title"),
|
|
5597
|
+
description: readOptionalString$6(parsed, "description"),
|
|
5434
5598
|
enabled: readOptionalBoolean$1(parsed, "enabled") ?? true,
|
|
5435
5599
|
protocol,
|
|
5436
|
-
command: readRequiredString$
|
|
5600
|
+
command: readRequiredString$3(parsed, "command"),
|
|
5437
5601
|
args: readStringArray(parsed.args, "args"),
|
|
5438
5602
|
actions: readManifestActions(parsed.actions)
|
|
5439
5603
|
};
|
|
5440
5604
|
}
|
|
5441
5605
|
function readManifestActions(value) {
|
|
5442
5606
|
if (value === void 0) throw new Error("service app actions are required.");
|
|
5443
|
-
if (!isRecord$
|
|
5607
|
+
if (!isRecord$5(value)) throw new Error("service app actions must be an object.");
|
|
5444
5608
|
if (Object.keys(value).length === 0) throw new Error("service app actions cannot be empty.");
|
|
5445
5609
|
const actions = {};
|
|
5446
5610
|
for (const [name, action] of Object.entries(value)) {
|
|
5447
5611
|
if (!name.trim()) throw new Error("service app action name cannot be empty.");
|
|
5448
|
-
if (!isRecord$
|
|
5449
|
-
const risk = readOptionalString$
|
|
5612
|
+
if (!isRecord$5(action)) throw new Error(`service app action ${name} must be an object.`);
|
|
5613
|
+
const risk = readOptionalString$6(action, "risk");
|
|
5450
5614
|
if (risk !== void 0 && !SERVICE_ACTION_RISKS.has(risk)) throw new Error(`service app action ${name} has invalid risk.`);
|
|
5451
5615
|
const inputSchema = action.inputSchema;
|
|
5452
|
-
if (inputSchema !== void 0 && !isRecord$
|
|
5616
|
+
if (inputSchema !== void 0 && !isRecord$5(inputSchema)) throw new Error(`service app action ${name} inputSchema must be an object.`);
|
|
5453
5617
|
actions[name] = {
|
|
5454
5618
|
risk,
|
|
5455
|
-
title: readOptionalString$
|
|
5456
|
-
description: readOptionalString$
|
|
5619
|
+
title: readOptionalString$6(action, "title"),
|
|
5620
|
+
description: readOptionalString$6(action, "description"),
|
|
5457
5621
|
inputSchema
|
|
5458
5622
|
};
|
|
5459
5623
|
}
|
|
5460
5624
|
return actions;
|
|
5461
5625
|
}
|
|
5462
|
-
function readRequiredString$
|
|
5463
|
-
const value = readOptionalString$
|
|
5626
|
+
function readRequiredString$3(record, key) {
|
|
5627
|
+
const value = readOptionalString$6(record, key);
|
|
5464
5628
|
if (!value) throw new Error(`service app ${key} is required.`);
|
|
5465
5629
|
return value;
|
|
5466
5630
|
}
|
|
5467
|
-
function readOptionalString$
|
|
5631
|
+
function readOptionalString$6(record, key) {
|
|
5468
5632
|
return typeof record[key] === "string" && record[key].trim() ? record[key].trim() : void 0;
|
|
5469
5633
|
}
|
|
5470
5634
|
function readOptionalBoolean$1(record, key) {
|
|
@@ -5477,7 +5641,7 @@ function readStringArray(value, key) {
|
|
|
5477
5641
|
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new Error(`service app ${key} must be a string array.`);
|
|
5478
5642
|
return value;
|
|
5479
5643
|
}
|
|
5480
|
-
function isRecord$
|
|
5644
|
+
function isRecord$5(value) {
|
|
5481
5645
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5482
5646
|
}
|
|
5483
5647
|
//#endregion
|
|
@@ -5874,12 +6038,12 @@ function parseSkillFrontmatter(raw) {
|
|
|
5874
6038
|
const summaryI18n = readLocalizedTextMap(parsed, "summaryi18n", "summary_i18n");
|
|
5875
6039
|
const descriptionI18n = readLocalizedTextMap(parsed, "descriptioni18n", "description_i18n");
|
|
5876
6040
|
return {
|
|
5877
|
-
name: readString$
|
|
5878
|
-
summary: readString$
|
|
5879
|
-
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$
|
|
5880
|
-
description: readString$
|
|
5881
|
-
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$
|
|
5882
|
-
author: readString$
|
|
6041
|
+
name: readString$3(parsed, "name"),
|
|
6042
|
+
summary: readString$3(parsed, "summary"),
|
|
6043
|
+
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$3(parsed, "summaryzh", "summary_zh") }),
|
|
6044
|
+
description: readString$3(parsed, "description"),
|
|
6045
|
+
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$3(parsed, "descriptionzh", "description_zh") }),
|
|
6046
|
+
author: readString$3(parsed, "author"),
|
|
5883
6047
|
tags: readTags(parsed)
|
|
5884
6048
|
};
|
|
5885
6049
|
}
|
|
@@ -5900,19 +6064,19 @@ function parseFrontmatterBlock(raw) {
|
|
|
5900
6064
|
function parseYamlFrontmatter(raw) {
|
|
5901
6065
|
try {
|
|
5902
6066
|
const parsed = parse(raw);
|
|
5903
|
-
return isRecord$
|
|
6067
|
+
return isRecord$4(parsed) ? parsed : {};
|
|
5904
6068
|
} catch (error) {
|
|
5905
6069
|
const message = error instanceof Error ? error.message : String(error);
|
|
5906
6070
|
throw new Error(`Invalid SKILL.md frontmatter: ${message}`);
|
|
5907
6071
|
}
|
|
5908
6072
|
}
|
|
5909
|
-
function readString$
|
|
6073
|
+
function readString$3(record, ...names) {
|
|
5910
6074
|
const value = readValue(record, names);
|
|
5911
6075
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
5912
6076
|
}
|
|
5913
6077
|
function readLocalizedTextMap(record, ...names) {
|
|
5914
6078
|
const value = readValue(record, names);
|
|
5915
|
-
if (!isRecord$
|
|
6079
|
+
if (!isRecord$4(value)) return;
|
|
5916
6080
|
const localized = Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0).map(([locale, text]) => [normalizeLocaleTag(locale), text.trim()]));
|
|
5917
6081
|
return Object.keys(localized).length > 0 ? localized : void 0;
|
|
5918
6082
|
}
|
|
@@ -5936,7 +6100,7 @@ function normalizeFrontmatterKey(raw) {
|
|
|
5936
6100
|
function normalizeLocaleTag(raw) {
|
|
5937
6101
|
return raw.trim().toLowerCase();
|
|
5938
6102
|
}
|
|
5939
|
-
function isRecord$
|
|
6103
|
+
function isRecord$4(value) {
|
|
5940
6104
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5941
6105
|
}
|
|
5942
6106
|
//#endregion
|
|
@@ -6102,7 +6266,7 @@ var NcpAgentSessionMetadataStore = class {
|
|
|
6102
6266
|
read = async (sessionId, activitySnapshot) => {
|
|
6103
6267
|
try {
|
|
6104
6268
|
const parsed = JSON.parse(await readFile(this.metadataPath(sessionId), "utf-8"));
|
|
6105
|
-
if (!isRecord$
|
|
6269
|
+
if (!isRecord$11(parsed) || parsed._type !== "metadata" || !isRecord$11(parsed.metadata)) throw new Error(`invalid ncp agent session metadata sidecar: ${sessionId}`);
|
|
6106
6270
|
const createdAt = toIsoString(parsed.created_at, activitySnapshot.createdAt);
|
|
6107
6271
|
const agentId = normalizeNcpAgentId(typeof parsed.agent_id === "string" ? parsed.agent_id : void 0);
|
|
6108
6272
|
return {
|
|
@@ -6203,11 +6367,11 @@ var NcpAgentSessionSummaryIndexStore = class {
|
|
|
6203
6367
|
function serializeJournalEntry(entry) {
|
|
6204
6368
|
const serialized = JSON.stringify(entry);
|
|
6205
6369
|
if (!serialized) throw new Error("ncp agent session journal entry serialization produced empty output");
|
|
6206
|
-
if (!isRecord$
|
|
6370
|
+
if (!isRecord$11(JSON.parse(serialized))) throw new Error("ncp agent session journal entry serialization produced a non-object entry");
|
|
6207
6371
|
return serialized;
|
|
6208
6372
|
}
|
|
6209
6373
|
function attachJournalTimestamp(event, timestamp) {
|
|
6210
|
-
if (!("payload" in event) || !isRecord$
|
|
6374
|
+
if (!("payload" in event) || !isRecord$11(event.payload)) return event;
|
|
6211
6375
|
return {
|
|
6212
6376
|
...event,
|
|
6213
6377
|
payload: {
|
|
@@ -6431,15 +6595,15 @@ var NcpAgentSessionJournalStore = class {
|
|
|
6431
6595
|
console.warn(`[ncp-agent-session-journal] skipped corrupted journal line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);
|
|
6432
6596
|
continue;
|
|
6433
6597
|
}
|
|
6434
|
-
if (!isRecord$
|
|
6598
|
+
if (!isRecord$11(parsed)) continue;
|
|
6435
6599
|
if (parsed._type === "metadata") {
|
|
6436
|
-
metadata = isRecord$
|
|
6600
|
+
metadata = isRecord$11(parsed.metadata) ? structuredClone(parsed.metadata) : {};
|
|
6437
6601
|
agentId = normalizeNcpAgentId(typeof parsed.agent_id === "string" ? parsed.agent_id : void 0);
|
|
6438
6602
|
createdAt = toIsoString(parsed.created_at, createdAt);
|
|
6439
6603
|
updatedAt = toIsoString(parsed.updated_at, updatedAt);
|
|
6440
6604
|
continue;
|
|
6441
6605
|
}
|
|
6442
|
-
if (parsed._type === "event" && isRecord$
|
|
6606
|
+
if (parsed._type === "event" && isRecord$11(parsed.event)) {
|
|
6443
6607
|
const seq = Number(parsed.seq);
|
|
6444
6608
|
nextSeq = Math.max(nextSeq, Number.isFinite(seq) ? Math.trunc(seq) + 1 : nextSeq);
|
|
6445
6609
|
const eventTimestamp = toIsoString(parsed.timestamp, updatedAt);
|
|
@@ -6753,11 +6917,11 @@ const NARP_API_MODE_HEADER = "x-nextclaw-narp-api-mode";
|
|
|
6753
6917
|
const NARP_HTTP_RUNTIME_KIND = "narp-http";
|
|
6754
6918
|
const NARP_STDIO_RUNTIME_KIND = "narp-stdio";
|
|
6755
6919
|
const BUILTIN_PROVIDER_REGISTRY = new ProviderRegistry(BUILTIN_PROVIDER_PLUGINS);
|
|
6756
|
-
function readRecord
|
|
6920
|
+
function readRecord(value) {
|
|
6757
6921
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
6758
6922
|
return value;
|
|
6759
6923
|
}
|
|
6760
|
-
function readString$
|
|
6924
|
+
function readString$2(value) {
|
|
6761
6925
|
if (typeof value !== "string") return;
|
|
6762
6926
|
return value.trim() || void 0;
|
|
6763
6927
|
}
|
|
@@ -6765,9 +6929,11 @@ function resolveEntryIcon(entry) {
|
|
|
6765
6929
|
return entry.icon ?? null;
|
|
6766
6930
|
}
|
|
6767
6931
|
function resolveRequestedModel(params) {
|
|
6768
|
-
const { configuredModel, defaultModel, input, sessionMetadata } = params;
|
|
6769
|
-
|
|
6770
|
-
|
|
6932
|
+
const { configuredModel, defaultModel, input, modelSelectionMode, sessionMetadata } = params;
|
|
6933
|
+
if (modelSelectionMode === "runtime-default") return;
|
|
6934
|
+
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);
|
|
6935
|
+
if (isRuntimeDefaultModelValue(requestedModel)) return;
|
|
6936
|
+
return requestedModel ?? configuredModel ?? (modelSelectionMode === "optional" ? void 0 : defaultModel);
|
|
6771
6937
|
}
|
|
6772
6938
|
function resolveProviderApiMode(resolution) {
|
|
6773
6939
|
const wireApi = resolution.provider?.wireApi?.trim().toLowerCase();
|
|
@@ -6814,12 +6980,14 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6814
6980
|
};
|
|
6815
6981
|
describeInternal = async () => {
|
|
6816
6982
|
const config = new HttpRuntimeConfigResolver(this.entry.config ?? {}).resolve({ defaultModel: this.defaultModel });
|
|
6983
|
+
const modelSelectionMode = normalizeRuntimeModelSelectionMode(this.entry.config?.modelSelectionMode);
|
|
6817
6984
|
if (!config.baseUrl) return {
|
|
6818
6985
|
icon: resolveEntryIcon(this.entry),
|
|
6819
6986
|
ready: false,
|
|
6820
6987
|
reason: "base_url_missing",
|
|
6821
6988
|
reasonMessage: "Configure the runtime entry baseUrl before starting an HTTP runtime session.",
|
|
6822
6989
|
recommendedModel: config.recommendedModel ?? null,
|
|
6990
|
+
modelSelectionMode,
|
|
6823
6991
|
cta: {
|
|
6824
6992
|
kind: "settings",
|
|
6825
6993
|
label: "Configure HTTP Runtime"
|
|
@@ -6831,6 +6999,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6831
6999
|
reason: null,
|
|
6832
7000
|
reasonMessage: null,
|
|
6833
7001
|
recommendedModel: config.recommendedModel ?? null,
|
|
7002
|
+
modelSelectionMode,
|
|
6834
7003
|
...config.supportedModels ? { supportedModels: config.supportedModels } : {},
|
|
6835
7004
|
cta: null
|
|
6836
7005
|
};
|
|
@@ -6849,6 +7018,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6849
7018
|
reason: "healthcheck_failed",
|
|
6850
7019
|
reasonMessage: `HTTP runtime healthcheck returned HTTP ${response.status}.`,
|
|
6851
7020
|
recommendedModel: config.recommendedModel ?? null,
|
|
7021
|
+
modelSelectionMode,
|
|
6852
7022
|
...config.supportedModels ? { supportedModels: config.supportedModels } : {},
|
|
6853
7023
|
cta: null
|
|
6854
7024
|
};
|
|
@@ -6858,6 +7028,7 @@ var BuiltinHttpRuntimeSessionTypeService = class {
|
|
|
6858
7028
|
reason: null,
|
|
6859
7029
|
reasonMessage: null,
|
|
6860
7030
|
recommendedModel: config.recommendedModel ?? null,
|
|
7031
|
+
modelSelectionMode,
|
|
6861
7032
|
...config.supportedModels ? { supportedModels: config.supportedModels } : {},
|
|
6862
7033
|
cta: null
|
|
6863
7034
|
};
|
|
@@ -6895,6 +7066,7 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6895
7066
|
};
|
|
6896
7067
|
describeInternal = async (describeMode) => {
|
|
6897
7068
|
const resolver = new StdioRuntimeConfigResolver(this.entry.config ?? {});
|
|
7069
|
+
const modelSelectionMode = normalizeRuntimeModelSelectionMode(this.entry.config?.modelSelectionMode);
|
|
6898
7070
|
try {
|
|
6899
7071
|
const config = resolver.resolve();
|
|
6900
7072
|
if (!await resolveExecutablePath(config.command)) return {
|
|
@@ -6905,7 +7077,8 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6905
7077
|
cta: {
|
|
6906
7078
|
kind: "settings",
|
|
6907
7079
|
label: "Configure Stdio Runtime"
|
|
6908
|
-
}
|
|
7080
|
+
},
|
|
7081
|
+
modelSelectionMode
|
|
6909
7082
|
};
|
|
6910
7083
|
if (describeMode === "probe") try {
|
|
6911
7084
|
await probeStdioRuntime(config);
|
|
@@ -6918,7 +7091,8 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6918
7091
|
cta: {
|
|
6919
7092
|
kind: "settings",
|
|
6920
7093
|
label: "Repair Stdio Runtime"
|
|
6921
|
-
}
|
|
7094
|
+
},
|
|
7095
|
+
modelSelectionMode
|
|
6922
7096
|
};
|
|
6923
7097
|
}
|
|
6924
7098
|
return {
|
|
@@ -6926,6 +7100,7 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6926
7100
|
ready: true,
|
|
6927
7101
|
reason: null,
|
|
6928
7102
|
reasonMessage: null,
|
|
7103
|
+
modelSelectionMode,
|
|
6929
7104
|
cta: null
|
|
6930
7105
|
};
|
|
6931
7106
|
} catch (error) {
|
|
@@ -6937,7 +7112,8 @@ var BuiltinStdioRuntimeSessionTypeService = class {
|
|
|
6937
7112
|
cta: {
|
|
6938
7113
|
kind: "settings",
|
|
6939
7114
|
label: "Configure Stdio Runtime"
|
|
6940
|
-
}
|
|
7115
|
+
},
|
|
7116
|
+
modelSelectionMode
|
|
6941
7117
|
};
|
|
6942
7118
|
}
|
|
6943
7119
|
};
|
|
@@ -6984,7 +7160,7 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
6984
7160
|
throw new Error("[narp] runtime entry is required before creating this runtime");
|
|
6985
7161
|
};
|
|
6986
7162
|
createHttpRuntime = (entry, runtimeParams) => {
|
|
6987
|
-
const config = readRecord
|
|
7163
|
+
const config = readRecord(entry.config) ?? {};
|
|
6988
7164
|
const resolver = new HttpRuntimeConfigResolver(config);
|
|
6989
7165
|
const resolvedConfig = resolver.resolve({ defaultModel: this.configManager.loadConfig().agents.defaults.model });
|
|
6990
7166
|
return new HttpRuntimeNcpAgentRuntime({
|
|
@@ -6999,12 +7175,13 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
6999
7175
|
input,
|
|
7000
7176
|
sessionMetadata: runtimeParams.sessionMetadata,
|
|
7001
7177
|
defaultModel: this.configManager.loadConfig().agents.defaults.model,
|
|
7002
|
-
configuredModel: readString$
|
|
7178
|
+
configuredModel: readString$2(config.model),
|
|
7179
|
+
modelSelectionMode: normalizeRuntimeModelSelectionMode(config.modelSelectionMode)
|
|
7003
7180
|
})
|
|
7004
7181
|
});
|
|
7005
7182
|
};
|
|
7006
7183
|
createStdioRuntime = (entry, runtimeParams) => {
|
|
7007
|
-
const config = readRecord
|
|
7184
|
+
const config = readRecord(entry.config) ?? {};
|
|
7008
7185
|
return new StdioRuntimeNcpAgentRuntime({
|
|
7009
7186
|
...new StdioRuntimeConfigResolver(config).resolve(),
|
|
7010
7187
|
sessionId: runtimeParams.sessionId,
|
|
@@ -7015,7 +7192,8 @@ var BuiltinNarpRuntimeProviderService = class {
|
|
|
7015
7192
|
input,
|
|
7016
7193
|
sessionMetadata: runtimeParams.sessionMetadata,
|
|
7017
7194
|
defaultModel: this.configManager.loadConfig().agents.defaults.model,
|
|
7018
|
-
configuredModel: readString$
|
|
7195
|
+
configuredModel: readString$2(config.model),
|
|
7196
|
+
modelSelectionMode: normalizeRuntimeModelSelectionMode(config.modelSelectionMode)
|
|
7019
7197
|
})
|
|
7020
7198
|
});
|
|
7021
7199
|
};
|
|
@@ -7102,13 +7280,13 @@ var ProviderManagerNcpLLMApi = class {
|
|
|
7102
7280
|
};
|
|
7103
7281
|
//#endregion
|
|
7104
7282
|
//#region src/features/native-runtime/tools/ncp-asset.tools.ts
|
|
7105
|
-
function readOptionalString$
|
|
7283
|
+
function readOptionalString$5(value) {
|
|
7106
7284
|
if (typeof value !== "string") return null;
|
|
7107
7285
|
const trimmed = value.trim();
|
|
7108
7286
|
return trimmed.length > 0 ? trimmed : null;
|
|
7109
7287
|
}
|
|
7110
7288
|
function readOptionalBase64Bytes(value) {
|
|
7111
|
-
const base64 = readOptionalString$
|
|
7289
|
+
const base64 = readOptionalString$5(value);
|
|
7112
7290
|
if (!base64) return null;
|
|
7113
7291
|
try {
|
|
7114
7292
|
return Buffer.from(base64, "base64");
|
|
@@ -7159,18 +7337,18 @@ var AssetPutTool = class {
|
|
|
7159
7337
|
this.contentBasePath = contentBasePath;
|
|
7160
7338
|
}
|
|
7161
7339
|
validateArgs = (args) => {
|
|
7162
|
-
const path = readOptionalString$
|
|
7163
|
-
const bytesBase64 = readOptionalString$
|
|
7164
|
-
const fileName = readOptionalString$
|
|
7340
|
+
const path = readOptionalString$5(args.path);
|
|
7341
|
+
const bytesBase64 = readOptionalString$5(args.bytesBase64);
|
|
7342
|
+
const fileName = readOptionalString$5(args.fileName);
|
|
7165
7343
|
if (path && bytesBase64) return ["Provide either path, or bytesBase64 + fileName, not both."];
|
|
7166
7344
|
if (path) return [];
|
|
7167
7345
|
if (bytesBase64) return fileName ? [] : ["fileName is required when using bytesBase64."];
|
|
7168
7346
|
return ["Provide either path, or bytesBase64 + fileName."];
|
|
7169
7347
|
};
|
|
7170
7348
|
execute = async (args) => {
|
|
7171
|
-
const path = readOptionalString$
|
|
7172
|
-
const fileName = readOptionalString$
|
|
7173
|
-
const mimeType = readOptionalString$
|
|
7349
|
+
const path = readOptionalString$5(args?.path);
|
|
7350
|
+
const fileName = readOptionalString$5(args?.fileName);
|
|
7351
|
+
const mimeType = readOptionalString$5(args?.mimeType);
|
|
7174
7352
|
const bytes = readOptionalBase64Bytes(args?.bytesBase64);
|
|
7175
7353
|
if (path) return {
|
|
7176
7354
|
ok: true,
|
|
@@ -7213,8 +7391,8 @@ var AssetExportTool = class {
|
|
|
7213
7391
|
this.assetStore = assetStore;
|
|
7214
7392
|
}
|
|
7215
7393
|
execute = async (args) => {
|
|
7216
|
-
const assetUri = readOptionalString$
|
|
7217
|
-
const targetPath = readOptionalString$
|
|
7394
|
+
const assetUri = readOptionalString$5(args?.assetUri);
|
|
7395
|
+
const targetPath = readOptionalString$5(args?.targetPath);
|
|
7218
7396
|
if (!assetUri || !targetPath) throw new Error("asset_export requires assetUri and targetPath.");
|
|
7219
7397
|
return {
|
|
7220
7398
|
ok: true,
|
|
@@ -7240,7 +7418,7 @@ var AssetStatTool = class {
|
|
|
7240
7418
|
this.contentBasePath = contentBasePath;
|
|
7241
7419
|
}
|
|
7242
7420
|
execute = async (args) => {
|
|
7243
|
-
const assetUri = readOptionalString$
|
|
7421
|
+
const assetUri = readOptionalString$5(args?.assetUri);
|
|
7244
7422
|
if (!assetUri) throw new Error("asset_stat requires assetUri.");
|
|
7245
7423
|
const record = await this.assetStore.statRecord(assetUri);
|
|
7246
7424
|
if (!record) return {
|
|
@@ -7308,10 +7486,16 @@ function resolveEffectiveModel(params) {
|
|
|
7308
7486
|
const metadata = structuredClone(params.sessionMetadata);
|
|
7309
7487
|
if (requestMetadata.clear_model === true || requestMetadata.reset_model === true) delete metadata.preferred_model;
|
|
7310
7488
|
const inboundModel = readMetadataModel(requestMetadata);
|
|
7311
|
-
if (inboundModel
|
|
7489
|
+
if (inboundModel && isRuntimeDefaultModelValue(inboundModel)) {
|
|
7490
|
+
delete metadata.preferred_model;
|
|
7491
|
+
delete metadata.model;
|
|
7492
|
+
} else if (inboundModel) {
|
|
7493
|
+
metadata.preferred_model = inboundModel;
|
|
7494
|
+
metadata.model = inboundModel;
|
|
7495
|
+
}
|
|
7312
7496
|
return {
|
|
7313
7497
|
metadata,
|
|
7314
|
-
model: normalizeOptionalString(metadata.preferred_model) ?? fallbackModel
|
|
7498
|
+
model: (isRuntimeDefaultModelValue(metadata.preferred_model) ? void 0 : normalizeOptionalString(metadata.preferred_model)) ?? fallbackModel
|
|
7315
7499
|
};
|
|
7316
7500
|
}
|
|
7317
7501
|
function syncSessionThinkingPreference(params) {
|
|
@@ -7342,314 +7526,95 @@ function resolveSessionChannelContext(params) {
|
|
|
7342
7526
|
//#endregion
|
|
7343
7527
|
//#region src/features/native-runtime/utils/nextclaw-ncp-run-context.utils.ts
|
|
7344
7528
|
const REQUESTED_SKILLS_METADATA_READER = new RequestedSkillsMetadataReader();
|
|
7345
|
-
function readRequestedAgentId(metadata) {
|
|
7346
|
-
return normalizeOptionalString(metadata.agent_id)?.toLowerCase() ?? normalizeOptionalString(metadata.agentId)?.toLowerCase() ?? null;
|
|
7347
|
-
}
|
|
7348
|
-
function resolveAgentProfile(params) {
|
|
7349
|
-
const { config, requestMetadata, storedAgentId } = params;
|
|
7350
|
-
const { agents: { defaults }, search: searchConfig, tools: { restrictToWorkspace, exec: { timeout: execTimeoutSeconds } } } = config;
|
|
7351
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
7352
|
-
const profile = findEffectiveAgentProfile(config, normalizeOptionalString(storedAgentId)?.toLowerCase() ?? readRequestedAgentId(requestMetadata) ?? defaultAgentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
7353
|
-
if (!profile) throw new Error(`default agent profile not found: ${defaultAgentId}`);
|
|
7354
|
-
const contextTokens = profile.contextTokens ?? defaults.contextTokens;
|
|
7355
|
-
return {
|
|
7356
|
-
agentId: profile.id,
|
|
7357
|
-
workspace: getWorkspacePath(profile.workspace ?? defaults.workspace),
|
|
7358
|
-
model: profile.model ?? defaults.model,
|
|
7359
|
-
contextTokens,
|
|
7360
|
-
reservedContextTokens: ContextWindowBudgetService.resolveReservedContextTokens({
|
|
7361
|
-
contextTokens,
|
|
7362
|
-
configuredReservedContextTokens: profile.reservedContextTokens ?? defaults.reservedContextTokens
|
|
7363
|
-
}),
|
|
7364
|
-
restrictToWorkspace,
|
|
7365
|
-
searchConfig,
|
|
7366
|
-
execTimeoutSeconds
|
|
7367
|
-
};
|
|
7368
|
-
}
|
|
7369
7529
|
function resolveRequestedToolNames(metadata) {
|
|
7370
7530
|
const rawValue = metadata.requested_tools ?? metadata.requestedTools;
|
|
7371
7531
|
if (!Array.isArray(rawValue)) return [];
|
|
7372
7532
|
return Array.from(new Set(rawValue.map((item) => normalizeOptionalString(item)).filter((item) => Boolean(item))));
|
|
7373
|
-
}
|
|
7374
|
-
function mergeRunMetadata(params) {
|
|
7375
|
-
const { requestMetadata, sessionMetadata } = params;
|
|
7376
|
-
return {
|
|
7377
|
-
...sessionMetadata ? structuredClone(sessionMetadata) : {},
|
|
7378
|
-
...requestMetadata ? structuredClone(requestMetadata) : {}
|
|
7379
|
-
};
|
|
7380
|
-
}
|
|
7381
|
-
function resolveNextclawNcpRunContext(params) {
|
|
7382
|
-
const { configManager, requestMetadata: inputRequestMetadata, sessionId, sessionMetadata: inputSessionMetadata, storedAgentId } = params;
|
|
7383
|
-
const config = configManager.loadConfig();
|
|
7384
|
-
const requestMetadata = mergeRunMetadata({
|
|
7385
|
-
sessionMetadata: inputSessionMetadata,
|
|
7386
|
-
requestMetadata: inputRequestMetadata
|
|
7387
|
-
});
|
|
7388
|
-
const profile = resolveAgentProfile({
|
|
7389
|
-
config,
|
|
7390
|
-
storedAgentId,
|
|
7391
|
-
requestMetadata
|
|
7392
|
-
});
|
|
7393
|
-
const { metadata: modelMetadata, model: effectiveModel } = resolveEffectiveModel({
|
|
7394
|
-
sessionMetadata: requestMetadata,
|
|
7395
|
-
requestMetadata,
|
|
7396
|
-
fallbackModel: profile.model
|
|
7397
|
-
});
|
|
7398
|
-
const effectiveWorkspace = resolveSessionWorkspacePath({
|
|
7399
|
-
sessionMetadata: modelMetadata,
|
|
7400
|
-
workspace: profile.workspace
|
|
7401
|
-
});
|
|
7402
|
-
const channelContext = resolveSessionChannelContext({
|
|
7403
|
-
sessionMetadata: modelMetadata,
|
|
7404
|
-
requestMetadata
|
|
7405
|
-
});
|
|
7406
|
-
const sessionMetadata = channelContext.metadata;
|
|
7407
|
-
const requestedSkills = REQUESTED_SKILLS_METADATA_READER.readSelection(requestMetadata);
|
|
7408
|
-
const runtimeThinking = resolveThinkingLevel({
|
|
7409
|
-
config,
|
|
7410
|
-
agentId: profile.agentId,
|
|
7411
|
-
model: effectiveModel,
|
|
7412
|
-
sessionThinkingLevel: parseThinkingLevel(sessionMetadata.preferred_thinking) ?? null
|
|
7413
|
-
});
|
|
7414
|
-
return {
|
|
7415
|
-
channel: channelContext.channel,
|
|
7416
|
-
chatId: channelContext.chatId,
|
|
7417
|
-
config,
|
|
7418
|
-
effectiveModel,
|
|
7419
|
-
effectiveWorkspace,
|
|
7420
|
-
profile,
|
|
7421
|
-
requestMetadata,
|
|
7422
|
-
requestedSkills,
|
|
7423
|
-
requestedToolNames: resolveRequestedToolNames(requestMetadata),
|
|
7424
|
-
runtimeThinking,
|
|
7425
|
-
sessionKey: sessionId,
|
|
7426
|
-
sessionMetadata,
|
|
7427
|
-
toolRunContext: {
|
|
7428
|
-
sessionId,
|
|
7429
|
-
channel: channelContext.channel,
|
|
7430
|
-
chatId: channelContext.chatId,
|
|
7431
|
-
agentId: profile.agentId,
|
|
7432
|
-
config,
|
|
7433
|
-
execTimeoutSeconds: profile.execTimeoutSeconds,
|
|
7434
|
-
handoffDepth: resolveAgentHandoffDepth(requestMetadata),
|
|
7435
|
-
metadata: requestMetadata,
|
|
7436
|
-
restrictToWorkspace: profile.restrictToWorkspace,
|
|
7437
|
-
searchConfig: profile.searchConfig,
|
|
7438
|
-
workspace: effectiveWorkspace
|
|
7439
|
-
}
|
|
7440
|
-
};
|
|
7441
|
-
}
|
|
7442
|
-
//#endregion
|
|
7443
|
-
//#region src/features/runtime-registry/services/agent-runtime-registry.service.ts
|
|
7444
|
-
function normalizeIdentifier(value) {
|
|
7445
|
-
if (typeof value !== "string") return null;
|
|
7446
|
-
const normalized = value.trim().toLowerCase();
|
|
7447
|
-
return normalized.length > 0 ? normalized : null;
|
|
7448
|
-
}
|
|
7449
|
-
function cloneRuntimeEntry(entry) {
|
|
7450
|
-
return {
|
|
7451
|
-
id: entry.id,
|
|
7452
|
-
label: entry.label,
|
|
7453
|
-
...entry.icon ? { icon: { ...entry.icon } } : {},
|
|
7454
|
-
type: entry.type,
|
|
7455
|
-
enabled: entry.enabled !== false,
|
|
7456
|
-
config: entry.config ? { ...entry.config } : {}
|
|
7457
|
-
};
|
|
7458
|
-
}
|
|
7459
|
-
function normalizeAgentRuntimeSessionTypeIcon(value) {
|
|
7460
|
-
if (typeof value === "string") {
|
|
7461
|
-
const src = value.trim();
|
|
7462
|
-
return src ? {
|
|
7463
|
-
kind: "image",
|
|
7464
|
-
src
|
|
7465
|
-
} : null;
|
|
7466
|
-
}
|
|
7467
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
7468
|
-
const iconRecord = value;
|
|
7469
|
-
const src = typeof iconRecord.src === "string" ? iconRecord.src.trim() : "";
|
|
7470
|
-
if (!src) return null;
|
|
7471
|
-
const alt = typeof iconRecord.alt === "string" && iconRecord.alt.trim().length > 0 ? iconRecord.alt.trim() : null;
|
|
7472
|
-
return {
|
|
7473
|
-
kind: "image",
|
|
7474
|
-
src,
|
|
7475
|
-
...alt ? { alt } : {}
|
|
7476
|
-
};
|
|
7477
|
-
}
|
|
7478
|
-
const BUILTIN_RUNTIME_PRESENTATION = { hermes: {
|
|
7479
|
-
label: "Hermes",
|
|
7480
|
-
icon: {
|
|
7481
|
-
kind: "image",
|
|
7482
|
-
src: "app://runtime-icons/hermes-agent.png",
|
|
7483
|
-
alt: "Hermes"
|
|
7484
|
-
}
|
|
7485
|
-
} };
|
|
7486
|
-
function readString$2(value) {
|
|
7487
|
-
if (typeof value !== "string") return;
|
|
7488
|
-
return value.trim() || void 0;
|
|
7489
|
-
}
|
|
7490
|
-
function readRecord(value) {
|
|
7491
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
7492
|
-
return value;
|
|
7493
|
-
}
|
|
7494
|
-
function resolveBuiltinRuntimePresentation(value) {
|
|
7495
|
-
const normalized = readString$2(value)?.toLowerCase();
|
|
7496
|
-
if (!normalized) return null;
|
|
7497
|
-
if (!(normalized in BUILTIN_RUNTIME_PRESENTATION)) return null;
|
|
7498
|
-
return BUILTIN_RUNTIME_PRESENTATION[normalized] ?? null;
|
|
7499
|
-
}
|
|
7500
|
-
function buildNativeRuntimeEntry(config) {
|
|
7501
|
-
const nativeRuntimeConfig = readRecord(config.ui?.ncp?.runtimes?.native) ?? {};
|
|
7502
|
-
return {
|
|
7503
|
-
id: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
7504
|
-
label: "Native",
|
|
7505
|
-
type: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
7506
|
-
enabled: nativeRuntimeConfig.enabled !== false,
|
|
7507
|
-
config: nativeRuntimeConfig
|
|
7508
|
-
};
|
|
7509
|
-
}
|
|
7510
|
-
function resolveAgentRuntimeEntries(params) {
|
|
7511
|
-
const entries = /* @__PURE__ */ new Map();
|
|
7512
|
-
entries.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, buildNativeRuntimeEntry(params.config));
|
|
7513
|
-
for (const [rawId, rawEntry] of Object.entries(params.config.agents.runtimes.entries ?? {})) {
|
|
7514
|
-
const id = rawId.trim().toLowerCase();
|
|
7515
|
-
const type = readString$2(rawEntry.type)?.toLowerCase();
|
|
7516
|
-
if (!id || !type) continue;
|
|
7517
|
-
const explicitIcon = normalizeAgentRuntimeSessionTypeIcon(rawEntry.icon);
|
|
7518
|
-
const builtinPresentation = resolveBuiltinRuntimePresentation(id) ?? resolveBuiltinRuntimePresentation(type);
|
|
7519
|
-
entries.set(id, {
|
|
7520
|
-
id,
|
|
7521
|
-
label: readString$2(rawEntry.label) ?? builtinPresentation?.label ?? id,
|
|
7522
|
-
...explicitIcon ?? builtinPresentation?.icon ? { icon: explicitIcon ?? builtinPresentation?.icon } : {},
|
|
7523
|
-
type,
|
|
7524
|
-
enabled: rawEntry.enabled !== false,
|
|
7525
|
-
config: rawEntry.config ? { ...rawEntry.config } : {}
|
|
7526
|
-
});
|
|
7527
|
-
}
|
|
7533
|
+
}
|
|
7534
|
+
function mergeRunMetadata(params) {
|
|
7535
|
+
const { requestMetadata, sessionMetadata } = params;
|
|
7528
7536
|
return {
|
|
7529
|
-
|
|
7530
|
-
|
|
7537
|
+
...sessionMetadata ? structuredClone(sessionMetadata) : {},
|
|
7538
|
+
...requestMetadata ? structuredClone(requestMetadata) : {}
|
|
7531
7539
|
};
|
|
7532
7540
|
}
|
|
7533
|
-
function
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7541
|
+
function buildNextclawNcpRunContext(params) {
|
|
7542
|
+
const { agentProfile, config, requestMetadata: inputRequestMetadata, sessionId, sessionMetadata: inputSessionMetadata } = params;
|
|
7543
|
+
const requestMetadata = mergeRunMetadata({
|
|
7544
|
+
sessionMetadata: inputSessionMetadata,
|
|
7545
|
+
requestMetadata: inputRequestMetadata
|
|
7546
|
+
});
|
|
7547
|
+
const profile = buildResolvedAgentProfile({
|
|
7548
|
+
config,
|
|
7549
|
+
profile: agentProfile
|
|
7550
|
+
});
|
|
7551
|
+
const { metadata: modelMetadata, model: effectiveModel } = resolveEffectiveModel({
|
|
7552
|
+
sessionMetadata: requestMetadata,
|
|
7553
|
+
requestMetadata,
|
|
7554
|
+
fallbackModel: profile.model
|
|
7555
|
+
});
|
|
7556
|
+
const effectiveWorkspace = resolveSessionWorkspacePath({
|
|
7557
|
+
sessionMetadata: modelMetadata,
|
|
7558
|
+
workspace: profile.workspace
|
|
7559
|
+
});
|
|
7560
|
+
const channelContext = resolveSessionChannelContext({
|
|
7561
|
+
sessionMetadata: modelMetadata,
|
|
7562
|
+
requestMetadata
|
|
7563
|
+
});
|
|
7564
|
+
const sessionMetadata = channelContext.metadata;
|
|
7565
|
+
const requestedSkills = REQUESTED_SKILLS_METADATA_READER.readSelection(requestMetadata);
|
|
7566
|
+
const runtimeThinking = resolveThinkingLevel({
|
|
7567
|
+
config,
|
|
7568
|
+
agentId: profile.agentId,
|
|
7569
|
+
model: effectiveModel,
|
|
7570
|
+
sessionThinkingLevel: parseThinkingLevel(sessionMetadata.preferred_thinking) ?? null
|
|
7571
|
+
});
|
|
7572
|
+
return {
|
|
7573
|
+
channel: channelContext.channel,
|
|
7574
|
+
chatId: channelContext.chatId,
|
|
7575
|
+
config,
|
|
7576
|
+
effectiveModel,
|
|
7577
|
+
effectiveWorkspace,
|
|
7578
|
+
profile,
|
|
7579
|
+
requestMetadata,
|
|
7580
|
+
requestedSkills,
|
|
7581
|
+
requestedToolNames: resolveRequestedToolNames(requestMetadata),
|
|
7582
|
+
runtimeThinking,
|
|
7583
|
+
sessionKey: sessionId,
|
|
7584
|
+
sessionMetadata,
|
|
7585
|
+
toolRunContext: {
|
|
7586
|
+
sessionId,
|
|
7587
|
+
channel: channelContext.channel,
|
|
7588
|
+
chatId: channelContext.chatId,
|
|
7589
|
+
agentId: profile.agentId,
|
|
7590
|
+
config,
|
|
7591
|
+
execTimeoutSeconds: profile.execTimeoutSeconds,
|
|
7592
|
+
handoffDepth: resolveAgentHandoffDepth(requestMetadata),
|
|
7593
|
+
metadata: requestMetadata,
|
|
7594
|
+
restrictToWorkspace: profile.restrictToWorkspace,
|
|
7595
|
+
searchConfig: profile.searchConfig,
|
|
7596
|
+
workspace: effectiveWorkspace
|
|
7568
7597
|
}
|
|
7569
|
-
this.entries = nextEntries;
|
|
7570
|
-
this.defaultEntryId = normalizeIdentifier(params.defaultEntryId) ?? (nextEntries.has("native") ? "native" : [...nextEntries.keys()][0] ?? "native");
|
|
7571
|
-
};
|
|
7572
|
-
resolveSessionMetadata = (sessionMetadata) => {
|
|
7573
|
-
const { entry } = this.resolveRuntimeEntry(sessionMetadata);
|
|
7574
|
-
return {
|
|
7575
|
-
...sessionMetadata,
|
|
7576
|
-
runtime: entry.id,
|
|
7577
|
-
session_type: entry.id,
|
|
7578
|
-
runtime_type: entry.type
|
|
7579
|
-
};
|
|
7580
|
-
};
|
|
7581
|
-
createRuntime = (params) => {
|
|
7582
|
-
const nextSessionMetadata = this.resolveSessionMetadata(params.sessionMetadata);
|
|
7583
|
-
const { entry, provider } = this.resolveRuntimeEntry(nextSessionMetadata);
|
|
7584
|
-
if (provider.createRuntimeForEntry) return provider.createRuntimeForEntry({
|
|
7585
|
-
entry: cloneRuntimeEntry(entry),
|
|
7586
|
-
runtimeParams: {
|
|
7587
|
-
...params,
|
|
7588
|
-
sessionMetadata: nextSessionMetadata
|
|
7589
|
-
}
|
|
7590
|
-
});
|
|
7591
|
-
return provider.createRuntime({
|
|
7592
|
-
...params,
|
|
7593
|
-
sessionMetadata: nextSessionMetadata
|
|
7594
|
-
});
|
|
7595
|
-
};
|
|
7596
|
-
resolveRuntimeEntry = (sessionMetadata) => {
|
|
7597
|
-
const requestedEntryId = readRequestedRuntimeEntryId(sessionMetadata) ?? this.defaultEntryId;
|
|
7598
|
-
const entry = this.entries.get(requestedEntryId);
|
|
7599
|
-
if (!entry || entry.enabled === false) throw new Error(`ncp runtime unavailable: ${requestedEntryId}`);
|
|
7600
|
-
const provider = this.providers.get(entry.type);
|
|
7601
|
-
if (!provider) throw new Error(`ncp runtime provider unavailable: ${entry.type}`);
|
|
7602
|
-
return {
|
|
7603
|
-
entry,
|
|
7604
|
-
provider
|
|
7605
|
-
};
|
|
7606
7598
|
};
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
label: "Configure Runtime"
|
|
7621
|
-
}
|
|
7622
|
-
};
|
|
7623
|
-
const descriptor = provider.describeSessionTypeForEntry ? await provider.describeSessionTypeForEntry({
|
|
7624
|
-
entry: cloneRuntimeEntry(entry),
|
|
7625
|
-
describeParams: params
|
|
7626
|
-
}) : await provider.describeSessionType?.(params);
|
|
7627
|
-
return {
|
|
7628
|
-
value: entry.id,
|
|
7629
|
-
label: entry.label,
|
|
7630
|
-
icon: descriptor?.icon ?? entry.icon ?? null,
|
|
7631
|
-
ready: descriptor?.ready ?? true,
|
|
7632
|
-
reason: descriptor?.reason ?? null,
|
|
7633
|
-
reasonMessage: descriptor?.reasonMessage ?? null,
|
|
7634
|
-
recommendedModel: descriptor?.recommendedModel ?? null,
|
|
7635
|
-
cta: descriptor?.cta ?? null,
|
|
7636
|
-
...descriptor?.supportedModels ? { supportedModels: descriptor.supportedModels } : {}
|
|
7637
|
-
};
|
|
7638
|
-
}));
|
|
7639
|
-
return {
|
|
7640
|
-
defaultType: this.defaultEntryId,
|
|
7641
|
-
options: options.sort((left, right) => {
|
|
7642
|
-
if (left.value === this.defaultEntryId) return -1;
|
|
7643
|
-
if (right.value === this.defaultEntryId) return 1;
|
|
7644
|
-
return left.value.localeCompare(right.value);
|
|
7645
|
-
})
|
|
7646
|
-
};
|
|
7599
|
+
}
|
|
7600
|
+
function buildResolvedAgentProfile(params) {
|
|
7601
|
+
const { config, profile } = params;
|
|
7602
|
+
const { search: searchConfig, tools: { restrictToWorkspace, exec: { timeout: execTimeoutSeconds } } } = config;
|
|
7603
|
+
return {
|
|
7604
|
+
agentId: profile.id,
|
|
7605
|
+
workspace: getWorkspacePath(profile.workspace),
|
|
7606
|
+
model: profile.model,
|
|
7607
|
+
contextTokens: profile.contextTokens,
|
|
7608
|
+
reservedContextTokens: profile.reservedContextTokens,
|
|
7609
|
+
restrictToWorkspace,
|
|
7610
|
+
searchConfig,
|
|
7611
|
+
execTimeoutSeconds
|
|
7647
7612
|
};
|
|
7648
|
-
}
|
|
7613
|
+
}
|
|
7649
7614
|
//#endregion
|
|
7650
7615
|
//#region src/services/agent-run-message-projector.service.ts
|
|
7651
7616
|
var AgentRunMessageProjector = class {
|
|
7652
|
-
project = (params) =>
|
|
7617
|
+
project = (params) => buildContextCompactionModelInput({
|
|
7653
7618
|
sessionId: params.sessionId,
|
|
7654
7619
|
sessionMessages: params.messages
|
|
7655
7620
|
});
|
|
@@ -7658,22 +7623,15 @@ var AgentRunMessageProjector = class {
|
|
|
7658
7623
|
//#region src/services/agent-run-model-input-budgeter.service.ts
|
|
7659
7624
|
var AgentRunModelInputBudgeter = class {
|
|
7660
7625
|
inputBudgetPruner = new InputBudgetPruner();
|
|
7661
|
-
constructor(
|
|
7662
|
-
this.
|
|
7626
|
+
constructor(agentManager) {
|
|
7627
|
+
this.agentManager = agentManager;
|
|
7663
7628
|
}
|
|
7664
7629
|
prune = async (params) => {
|
|
7665
|
-
const
|
|
7666
|
-
const defaultAgentId = resolveDefaultAgentProfileId(config);
|
|
7667
|
-
const profile = findEffectiveAgentProfile(config, params.spec.agentId) ?? findEffectiveAgentProfile(config, defaultAgentId);
|
|
7668
|
-
const contextTokens = profile?.contextTokens ?? config.agents.defaults.contextTokens;
|
|
7669
|
-
const reservedContextTokens = ContextWindowBudgetService.resolveReservedContextTokens({
|
|
7670
|
-
contextTokens,
|
|
7671
|
-
configuredReservedContextTokens: profile?.reservedContextTokens ?? config.agents.defaults.reservedContextTokens
|
|
7672
|
-
});
|
|
7630
|
+
const profile = this.agentManager.resolveAgentProfile(params.spec.agentId);
|
|
7673
7631
|
const pruned = this.inputBudgetPruner.prune({
|
|
7674
7632
|
messages: params.messages.map((message) => ({ ...message })),
|
|
7675
|
-
contextTokens,
|
|
7676
|
-
reserveTokensFloor: reservedContextTokens,
|
|
7633
|
+
contextTokens: profile.contextTokens,
|
|
7634
|
+
reserveTokensFloor: profile.reservedContextTokens,
|
|
7677
7635
|
softThresholdTokens: 0
|
|
7678
7636
|
});
|
|
7679
7637
|
return {
|
|
@@ -7788,18 +7746,22 @@ var AgentRunRuntimeContribution = class {
|
|
|
7788
7746
|
modelInputBuilder;
|
|
7789
7747
|
constructor(kernel) {
|
|
7790
7748
|
this.kernel = kernel;
|
|
7791
|
-
this.modelInputBuilder = new AgentRunModelInputBuilder(new AgentRunMessageProjector(), new AgentRunModelInputBudgeter(kernel.
|
|
7749
|
+
this.modelInputBuilder = new AgentRunModelInputBuilder(new AgentRunMessageProjector(), new AgentRunModelInputBudgeter(kernel.agents), kernel.assetStore);
|
|
7792
7750
|
}
|
|
7793
7751
|
start = () => {
|
|
7794
7752
|
if (this.cleanups.length > 0) return;
|
|
7795
|
-
|
|
7796
|
-
this.kernel.
|
|
7753
|
+
this.applyRuntimeConfig(this.kernel.configManager.loadConfig());
|
|
7754
|
+
this.kernel.configManager.installRuntimeHooks({ applyAgentRuntimeConfig: this.applyRuntimeConfig });
|
|
7797
7755
|
this.cleanups.push(this.registerNativeRuntime());
|
|
7798
7756
|
for (const provider of new BuiltinNarpRuntimeProviderService(this.kernel.configManager).createProviders()) this.cleanups.push(this.registerNarpRuntime(provider));
|
|
7799
7757
|
};
|
|
7800
7758
|
dispose = async () => {
|
|
7801
7759
|
while (this.cleanups.length > 0) await this.cleanups.pop()?.();
|
|
7802
7760
|
};
|
|
7761
|
+
applyRuntimeConfig = (config) => {
|
|
7762
|
+
const { entries } = resolveAgentRuntimeEntries({ config });
|
|
7763
|
+
this.kernel.agentRuntimeManager.applyEntries(entries);
|
|
7764
|
+
};
|
|
7803
7765
|
registerNativeRuntime = () => this.kernel.agentRuntimeManager.register({
|
|
7804
7766
|
kind: DEFAULT_AGENT_RUNTIME_ENTRY_ID,
|
|
7805
7767
|
label: "Native",
|
|
@@ -8157,11 +8119,7 @@ var ProjectContextProvider = class {
|
|
|
8157
8119
|
//#endregion
|
|
8158
8120
|
//#region src/contributions/context-provider/providers/reply-format-context.provider.ts
|
|
8159
8121
|
var ReplyFormatContextProvider = class {
|
|
8160
|
-
provide = (_request) => [[
|
|
8161
|
-
"## Reply Formatting",
|
|
8162
|
-
"- When mentioning a local project file in a user-visible reply, prefer a Markdown link such as `[AGENTS.md](AGENTS.md)` or `[file](packages/example/file.ts)` so the user can open it.",
|
|
8163
|
-
"- Use project-relative links for files under the active/session-bound project root; use absolute links only for files outside it."
|
|
8164
|
-
].join("\n")];
|
|
8122
|
+
provide = (_request) => ["## Reply Formatting Contract\nGoal: local openable files mentioned in user-visible replies must be clickable.\nAllowed form: use Markdown links only, with a plain text label and an openable href: [MEMORY.md](MEMORY.md), [file](packages/example/file.ts), [notes.md](/Users/example/Documents/notes.md).\nPath choice: use project-relative hrefs for files under the active/session project root, and absolute hrefs for local files outside it.\nForbidden forms: bare file names or paths, inline-code file names, bold-only file names, code-styled link labels, code blocks for file references, and unlinked comma-separated file lists.\nExamples: bad `MEMORY.md` -> good [MEMORY.md](MEMORY.md); bad `memory/` -> good [memory/](memory/); bad `2026-03-07.md` / `feishu-notes.md` -> good [2026-03-07.md](memory/2026-03-07.md) / [feishu-notes.md](memory/feishu-notes.md).\nSelf-check before sending: scan the final visible reply for local file names or paths. If every concrete file cannot be linked, remove the exact names and summarize instead."];
|
|
8165
8123
|
};
|
|
8166
8124
|
//#endregion
|
|
8167
8125
|
//#region src/contributions/context-provider/providers/skills-context.provider.ts
|
|
@@ -8372,12 +8330,15 @@ var ContextProviderRunContextService = class {
|
|
|
8372
8330
|
request,
|
|
8373
8331
|
session
|
|
8374
8332
|
});
|
|
8375
|
-
const runContext =
|
|
8376
|
-
|
|
8333
|
+
const runContext = buildNextclawNcpRunContext({
|
|
8334
|
+
agentProfile: this.kernel.agents.resolveAgentProfileForRun({
|
|
8335
|
+
requestMetadata,
|
|
8336
|
+
storedAgentId: request.agentId ?? session?.agentId
|
|
8337
|
+
}),
|
|
8338
|
+
config: this.kernel.configManager.loadConfig(),
|
|
8377
8339
|
sessionId,
|
|
8378
8340
|
requestMetadata,
|
|
8379
|
-
sessionMetadata: session?.metadata ?? requestMetadata
|
|
8380
|
-
storedAgentId: request.agentId ?? session?.agentId
|
|
8341
|
+
sessionMetadata: session?.metadata ?? requestMetadata
|
|
8381
8342
|
});
|
|
8382
8343
|
const tools = await this.kernel.toolProviderManager.buildTools(request);
|
|
8383
8344
|
const sessionProjectRoot = readSessionProjectRoot(runContext.sessionMetadata);
|
|
@@ -8451,7 +8412,7 @@ var ContextWindowContribution = class {
|
|
|
8451
8412
|
unsubscribeNcpEvent = null;
|
|
8452
8413
|
constructor(kernel) {
|
|
8453
8414
|
this.kernel = kernel;
|
|
8454
|
-
this.contextWindowPreview = new ContextCompactionPreflightService(
|
|
8415
|
+
this.contextWindowPreview = new ContextCompactionPreflightService(kernel.agents);
|
|
8455
8416
|
}
|
|
8456
8417
|
start = () => {
|
|
8457
8418
|
if (this.unsubscribeNcpEvent) return;
|
|
@@ -8788,24 +8749,24 @@ const SESSION_ACTIVITY_PREVIEW_STATES = new Set([
|
|
|
8788
8749
|
"failed",
|
|
8789
8750
|
"idle"
|
|
8790
8751
|
]);
|
|
8791
|
-
function isRecord$
|
|
8752
|
+
function isRecord$3(value) {
|
|
8792
8753
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8793
8754
|
}
|
|
8794
|
-
function readOptionalString$
|
|
8755
|
+
function readOptionalString$4(value) {
|
|
8795
8756
|
if (typeof value !== "string") return;
|
|
8796
8757
|
const trimmed = value.trim();
|
|
8797
8758
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
8798
8759
|
}
|
|
8799
8760
|
function readSessionActivityPreviewMetadata(value) {
|
|
8800
|
-
if (!isRecord$
|
|
8761
|
+
if (!isRecord$3(value)) return null;
|
|
8801
8762
|
const state = value.state;
|
|
8802
|
-
const timestamp = readOptionalString$
|
|
8763
|
+
const timestamp = readOptionalString$4(value.timestamp);
|
|
8803
8764
|
if (!SESSION_ACTIVITY_PREVIEW_STATES.has(state) || !timestamp) return null;
|
|
8804
8765
|
return {
|
|
8805
8766
|
state,
|
|
8806
8767
|
timestamp,
|
|
8807
|
-
...readOptionalString$
|
|
8808
|
-
...readOptionalString$
|
|
8768
|
+
...readOptionalString$4(value.statusText) ? { statusText: readOptionalString$4(value.statusText) } : {},
|
|
8769
|
+
...readOptionalString$4(value.replyText) ? { replyText: readOptionalString$4(value.replyText) } : {}
|
|
8809
8770
|
};
|
|
8810
8771
|
}
|
|
8811
8772
|
function compareIsoTimestamp(left, right) {
|
|
@@ -8901,47 +8862,20 @@ var SessionActivityPreviewContribution = class {
|
|
|
8901
8862
|
//#endregion
|
|
8902
8863
|
//#region src/contributions/tool-provider/providers/asset-tool.provider.ts
|
|
8903
8864
|
var AssetToolProvider = class {
|
|
8904
|
-
constructor(
|
|
8905
|
-
this.
|
|
8865
|
+
constructor(assetStore) {
|
|
8866
|
+
this.assetStore = assetStore;
|
|
8906
8867
|
}
|
|
8907
|
-
provide = async (_request) => createAssetTools({ assetStore: this.
|
|
8868
|
+
provide = async (_request) => createAssetTools({ assetStore: this.assetStore });
|
|
8908
8869
|
};
|
|
8909
8870
|
//#endregion
|
|
8910
|
-
//#region src/contributions/tool-provider/utils/tool-provider-run-context.utils.ts
|
|
8911
|
-
async function resolveToolProviderRunContext(params) {
|
|
8912
|
-
const { kernel, request } = params;
|
|
8913
|
-
const session = request.sessionId ? await kernel.sessionManager.getAgentRunSession(request.sessionId) : null;
|
|
8914
|
-
const sessionId = session?.sessionId ?? request.sessionId ?? request.message.sessionId ?? "";
|
|
8915
|
-
const requestMetadata = buildAgentRunRequestMetadata({
|
|
8916
|
-
request,
|
|
8917
|
-
session
|
|
8918
|
-
});
|
|
8919
|
-
const runContext = resolveNextclawNcpRunContext({
|
|
8920
|
-
configManager: kernel.configManager,
|
|
8921
|
-
sessionId,
|
|
8922
|
-
requestMetadata,
|
|
8923
|
-
sessionMetadata: session?.metadata ?? requestMetadata,
|
|
8924
|
-
storedAgentId: request.agentId ?? session?.agentId
|
|
8925
|
-
});
|
|
8926
|
-
return {
|
|
8927
|
-
requestMetadata,
|
|
8928
|
-
runContext,
|
|
8929
|
-
session,
|
|
8930
|
-
sessionId,
|
|
8931
|
-
toolRunContext: runContext.toolRunContext
|
|
8932
|
-
};
|
|
8933
|
-
}
|
|
8934
|
-
//#endregion
|
|
8935
8871
|
//#region src/contributions/tool-provider/providers/core-tool.provider.ts
|
|
8936
8872
|
var CoreToolProvider = class {
|
|
8937
|
-
constructor(
|
|
8938
|
-
this.
|
|
8873
|
+
constructor(runContextService, getGatewayController) {
|
|
8874
|
+
this.runContextService = runContextService;
|
|
8875
|
+
this.getGatewayController = getGatewayController;
|
|
8939
8876
|
}
|
|
8940
8877
|
provide = async (request) => {
|
|
8941
|
-
const { toolRunContext } = await
|
|
8942
|
-
kernel: this.kernel,
|
|
8943
|
-
request
|
|
8944
|
-
});
|
|
8878
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
8945
8879
|
const { channel, chatId, execTimeoutSeconds, restrictToWorkspace, searchConfig, sessionId, workspace } = toolRunContext;
|
|
8946
8880
|
const allowedDir = restrictToWorkspace ? workspace : void 0;
|
|
8947
8881
|
const execTool = new ExecTool({
|
|
@@ -8954,7 +8888,7 @@ var CoreToolProvider = class {
|
|
|
8954
8888
|
chatId,
|
|
8955
8889
|
sessionKey: sessionId
|
|
8956
8890
|
});
|
|
8957
|
-
const gatewayTool = new GatewayTool(this.
|
|
8891
|
+
const gatewayTool = new GatewayTool(this.getGatewayController());
|
|
8958
8892
|
gatewayTool.setContext({ sessionKey: sessionId });
|
|
8959
8893
|
return [
|
|
8960
8894
|
new ReadFileTool(allowedDir),
|
|
@@ -8973,15 +8907,13 @@ var CoreToolProvider = class {
|
|
|
8973
8907
|
//#endregion
|
|
8974
8908
|
//#region src/contributions/tool-provider/providers/mcp-tool.provider.ts
|
|
8975
8909
|
var McpToolProvider = class {
|
|
8976
|
-
constructor(
|
|
8977
|
-
this.
|
|
8910
|
+
constructor(runContextService, mcpManager) {
|
|
8911
|
+
this.runContextService = runContextService;
|
|
8912
|
+
this.mcpManager = mcpManager;
|
|
8978
8913
|
}
|
|
8979
8914
|
provide = async (request) => {
|
|
8980
|
-
const { toolRunContext } = await
|
|
8981
|
-
|
|
8982
|
-
request
|
|
8983
|
-
});
|
|
8984
|
-
return this.kernel.mcpManager.listToolsForRun({ agentId: toolRunContext.agentId });
|
|
8915
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
8916
|
+
return this.mcpManager.listToolsForRun({ agentId: toolRunContext.agentId });
|
|
8985
8917
|
};
|
|
8986
8918
|
};
|
|
8987
8919
|
//#endregion
|
|
@@ -8994,24 +8926,24 @@ function readMetadataAccountId(metadata) {
|
|
|
8994
8926
|
}
|
|
8995
8927
|
}
|
|
8996
8928
|
var MessagingToolProvider = class {
|
|
8997
|
-
constructor(
|
|
8998
|
-
this.
|
|
8929
|
+
constructor(runContextService, channels, automation, extensions) {
|
|
8930
|
+
this.runContextService = runContextService;
|
|
8931
|
+
this.channels = channels;
|
|
8932
|
+
this.automation = automation;
|
|
8933
|
+
this.extensions = extensions;
|
|
8999
8934
|
}
|
|
9000
8935
|
provide = async (request) => {
|
|
9001
|
-
const { toolRunContext } = await
|
|
9002
|
-
kernel: this.kernel,
|
|
9003
|
-
request
|
|
9004
|
-
});
|
|
8936
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
9005
8937
|
const { channel, chatId, metadata } = toolRunContext;
|
|
9006
8938
|
const accountId = readMetadataAccountId(metadata);
|
|
9007
8939
|
const messageTool = new MessageTool(async (message) => {
|
|
9008
|
-
if (!await this.
|
|
8940
|
+
if (!await this.channels.deliver(message)) throw new Error(`channel "${message.channel}" is not available`);
|
|
9009
8941
|
}, { resolveChannels: this.resolveMessageChannels });
|
|
9010
8942
|
messageTool.setContext(channel, chatId, accountId ?? null);
|
|
9011
|
-
return [messageTool, new CronTool(this.
|
|
8943
|
+
return [messageTool, new CronTool(this.automation)];
|
|
9012
8944
|
};
|
|
9013
8945
|
resolveMessageChannels = () => {
|
|
9014
|
-
const channels = this.
|
|
8946
|
+
const channels = this.extensions.getExtensionRegistry()?.channels ?? [];
|
|
9015
8947
|
return [...new Set(channels.map((registration) => registration.channel.id.trim()).filter(Boolean))].sort();
|
|
9016
8948
|
};
|
|
9017
8949
|
};
|
|
@@ -9150,12 +9082,12 @@ var SessionsHistoryTool = class {
|
|
|
9150
9082
|
};
|
|
9151
9083
|
//#endregion
|
|
9152
9084
|
//#region src/tools/session-request.tools.ts
|
|
9153
|
-
function readRequiredString$
|
|
9085
|
+
function readRequiredString$2(params, key) {
|
|
9154
9086
|
const value = params[key];
|
|
9155
9087
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9156
9088
|
return value.trim();
|
|
9157
9089
|
}
|
|
9158
|
-
function readOptionalString$
|
|
9090
|
+
function readOptionalString$3(params, key) {
|
|
9159
9091
|
const value = params[key];
|
|
9160
9092
|
if (typeof value !== "string") return;
|
|
9161
9093
|
const trimmed = value.trim();
|
|
@@ -9209,16 +9141,16 @@ var SessionRequestTool = class {
|
|
|
9209
9141
|
const params = normalizeToolParams(args);
|
|
9210
9142
|
const target = params.target;
|
|
9211
9143
|
if (!target || typeof target !== "object" || Array.isArray(target)) throw new Error("target must be an object.");
|
|
9212
|
-
const task = readRequiredString$
|
|
9213
|
-
const notifyMode = readOptionalString$
|
|
9144
|
+
const task = readRequiredString$2(params, "task");
|
|
9145
|
+
const notifyMode = readOptionalString$3(params, "notify")?.toLowerCase();
|
|
9214
9146
|
if (notifyMode !== "none" && notifyMode !== "final_reply") throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
9215
9147
|
return this.manager.requestSession({
|
|
9216
9148
|
sourceSessionId: this.sourceSessionId,
|
|
9217
9149
|
sourceToolCallId: context?.toolCallId,
|
|
9218
9150
|
updateToolCallResult: context?.updateToolCallResult,
|
|
9219
|
-
targetSessionId: readRequiredString$
|
|
9151
|
+
targetSessionId: readRequiredString$2(target, "session_id"),
|
|
9220
9152
|
task,
|
|
9221
|
-
title: readOptionalString$
|
|
9153
|
+
title: readOptionalString$3(params, "title"),
|
|
9222
9154
|
notify: notifyMode,
|
|
9223
9155
|
handoffDepth: this.handoffDepth
|
|
9224
9156
|
});
|
|
@@ -9226,7 +9158,7 @@ var SessionRequestTool = class {
|
|
|
9226
9158
|
};
|
|
9227
9159
|
//#endregion
|
|
9228
9160
|
//#region src/tools/session-search.tools.ts
|
|
9229
|
-
function isRecord$
|
|
9161
|
+
function isRecord$2(value) {
|
|
9230
9162
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9231
9163
|
}
|
|
9232
9164
|
function readOptionalInteger(value) {
|
|
@@ -9276,7 +9208,7 @@ var SessionSearchTool = class {
|
|
|
9276
9208
|
return issues;
|
|
9277
9209
|
};
|
|
9278
9210
|
execute = async (args) => {
|
|
9279
|
-
if (!isRecord$
|
|
9211
|
+
if (!isRecord$2(args)) throw new Error("session_search requires an object argument.");
|
|
9280
9212
|
const issues = this.validateArgs(args);
|
|
9281
9213
|
if (issues.length > 0) throw new Error(issues.join(" "));
|
|
9282
9214
|
return this.queryService.search({
|
|
@@ -9289,23 +9221,23 @@ var SessionSearchTool = class {
|
|
|
9289
9221
|
};
|
|
9290
9222
|
//#endregion
|
|
9291
9223
|
//#region src/tools/session-spawn.tools.ts
|
|
9292
|
-
function readRequiredString(value, key) {
|
|
9224
|
+
function readRequiredString$1(value, key) {
|
|
9293
9225
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9294
9226
|
return value.trim();
|
|
9295
9227
|
}
|
|
9296
|
-
function readOptionalString$
|
|
9228
|
+
function readOptionalString$2(value) {
|
|
9297
9229
|
if (typeof value !== "string") return;
|
|
9298
9230
|
const trimmed = value.trim();
|
|
9299
9231
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
9300
9232
|
}
|
|
9301
9233
|
function readSpawnScope(value) {
|
|
9302
|
-
const normalized = readOptionalString$
|
|
9234
|
+
const normalized = readOptionalString$2(value)?.toLowerCase();
|
|
9303
9235
|
if (!normalized || normalized === "standalone") return "standalone";
|
|
9304
9236
|
if (normalized === "child") return "child";
|
|
9305
9237
|
throw new Error("scope must be \"standalone\" or \"child\".");
|
|
9306
9238
|
}
|
|
9307
9239
|
function readSpawnNotify(value) {
|
|
9308
|
-
const notifyMode = readOptionalString$
|
|
9240
|
+
const notifyMode = readOptionalString$2(value)?.toLowerCase();
|
|
9309
9241
|
if (!notifyMode && typeof value === "undefined") return;
|
|
9310
9242
|
if (notifyMode === "none" || notifyMode === "final_reply") return notifyMode;
|
|
9311
9243
|
throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
@@ -9364,7 +9296,7 @@ var SessionSpawnTool = class {
|
|
|
9364
9296
|
};
|
|
9365
9297
|
execute = async (args, context) => {
|
|
9366
9298
|
const { agentId: rawAgentId, model: rawModel, notify: rawNotify, runtime: rawRuntime, scope: rawScope, task: rawTask, title: rawTitle } = normalizeToolParams(args);
|
|
9367
|
-
const task = readRequiredString(rawTask, "task");
|
|
9299
|
+
const task = readRequiredString$1(rawTask, "task");
|
|
9368
9300
|
const scope = readSpawnScope(rawScope);
|
|
9369
9301
|
const notify = readSpawnNotify(rawNotify);
|
|
9370
9302
|
const parentSessionId = scope === "child" ? this.readParentSessionIdOrThrow() : void 0;
|
|
@@ -9374,10 +9306,10 @@ var SessionSpawnTool = class {
|
|
|
9374
9306
|
updateToolCallResult: context?.updateToolCallResult,
|
|
9375
9307
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9376
9308
|
task,
|
|
9377
|
-
title: readOptionalString$
|
|
9378
|
-
agentId: readOptionalString$
|
|
9379
|
-
model: readOptionalString$
|
|
9380
|
-
runtime: readOptionalString$
|
|
9309
|
+
title: readOptionalString$2(rawTitle),
|
|
9310
|
+
agentId: readOptionalString$2(rawAgentId),
|
|
9311
|
+
model: readOptionalString$2(rawModel),
|
|
9312
|
+
runtime: readOptionalString$2(rawRuntime),
|
|
9381
9313
|
handoffDepth: this.handoffDepth,
|
|
9382
9314
|
parentSessionId,
|
|
9383
9315
|
notify
|
|
@@ -9385,11 +9317,11 @@ var SessionSpawnTool = class {
|
|
|
9385
9317
|
const session = await this.sessionManager.createSession({
|
|
9386
9318
|
sourceSessionId: this.sourceSessionId,
|
|
9387
9319
|
task,
|
|
9388
|
-
title: readOptionalString$
|
|
9320
|
+
title: readOptionalString$2(rawTitle),
|
|
9389
9321
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9390
|
-
agentId: readOptionalString$
|
|
9391
|
-
model: readOptionalString$
|
|
9392
|
-
runtime: readOptionalString$
|
|
9322
|
+
agentId: readOptionalString$2(rawAgentId),
|
|
9323
|
+
model: readOptionalString$2(rawModel),
|
|
9324
|
+
runtime: readOptionalString$2(rawRuntime),
|
|
9393
9325
|
parentSessionId
|
|
9394
9326
|
});
|
|
9395
9327
|
return {
|
|
@@ -9413,22 +9345,22 @@ var SessionSpawnTool = class {
|
|
|
9413
9345
|
//#endregion
|
|
9414
9346
|
//#region src/contributions/tool-provider/providers/session-tool.provider.ts
|
|
9415
9347
|
var SessionToolProvider = class {
|
|
9416
|
-
constructor(
|
|
9417
|
-
this.
|
|
9348
|
+
constructor(runContextService, sessionManager, sessionRequests, sessionSearch) {
|
|
9349
|
+
this.runContextService = runContextService;
|
|
9350
|
+
this.sessionManager = sessionManager;
|
|
9351
|
+
this.sessionRequests = sessionRequests;
|
|
9352
|
+
this.sessionSearch = sessionSearch;
|
|
9418
9353
|
}
|
|
9419
9354
|
provide = async (request) => {
|
|
9420
|
-
const { toolRunContext } = await
|
|
9421
|
-
kernel: this.kernel,
|
|
9422
|
-
request
|
|
9423
|
-
});
|
|
9355
|
+
const { toolRunContext } = await this.runContextService.resolve(request);
|
|
9424
9356
|
const { handoffDepth, metadata, sessionId } = toolRunContext;
|
|
9425
|
-
const sessionsSpawnTool = new SessionSpawnTool(this.
|
|
9357
|
+
const sessionsSpawnTool = new SessionSpawnTool(this.sessionManager, this.sessionRequests);
|
|
9426
9358
|
sessionsSpawnTool.setContext({
|
|
9427
9359
|
sourceSessionId: sessionId,
|
|
9428
9360
|
sourceSessionMetadata: metadata,
|
|
9429
9361
|
handoffDepth
|
|
9430
9362
|
});
|
|
9431
|
-
const sessionsRequestTool = new SessionRequestTool(this.
|
|
9363
|
+
const sessionsRequestTool = new SessionRequestTool(this.sessionRequests);
|
|
9432
9364
|
sessionsRequestTool.setContext({
|
|
9433
9365
|
sourceSessionId: sessionId,
|
|
9434
9366
|
handoffDepth
|
|
@@ -9436,15 +9368,166 @@ var SessionToolProvider = class {
|
|
|
9436
9368
|
const tools = [
|
|
9437
9369
|
sessionsSpawnTool,
|
|
9438
9370
|
sessionsRequestTool,
|
|
9439
|
-
new SessionsListTool(this.
|
|
9440
|
-
new SessionsHistoryTool(this.
|
|
9371
|
+
new SessionsListTool(this.sessionManager),
|
|
9372
|
+
new SessionsHistoryTool(this.sessionManager)
|
|
9441
9373
|
];
|
|
9442
|
-
if (!this.
|
|
9443
|
-
tools.push(new SessionSearchTool({ search: this.
|
|
9374
|
+
if (!this.sessionSearch.isReady()) return tools;
|
|
9375
|
+
tools.push(new SessionSearchTool({ search: this.sessionSearch.search }, { currentSessionId: sessionId }));
|
|
9444
9376
|
return tools;
|
|
9445
9377
|
};
|
|
9446
9378
|
};
|
|
9447
9379
|
//#endregion
|
|
9380
|
+
//#region src/tools/show-content.tools.ts
|
|
9381
|
+
const SHOW_CONTENT_TOOL_NAME = "show_content";
|
|
9382
|
+
function isRecord$1(value) {
|
|
9383
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9384
|
+
}
|
|
9385
|
+
function readRequiredString(value, key) {
|
|
9386
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9387
|
+
return value.trim();
|
|
9388
|
+
}
|
|
9389
|
+
function readOptionalString$1(value) {
|
|
9390
|
+
if (typeof value !== "string") return;
|
|
9391
|
+
const trimmed = value.trim();
|
|
9392
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
9393
|
+
}
|
|
9394
|
+
function readOptionalPositiveInteger(value, key) {
|
|
9395
|
+
if (typeof value === "undefined") return;
|
|
9396
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) throw new Error(`${key} must be a positive integer.`);
|
|
9397
|
+
return value;
|
|
9398
|
+
}
|
|
9399
|
+
function readPurpose(value) {
|
|
9400
|
+
const normalized = readOptionalString$1(value);
|
|
9401
|
+
if (!normalized) return;
|
|
9402
|
+
if (normalized === "read" || normalized === "preview" || normalized === "edit" || normalized === "interact") return normalized;
|
|
9403
|
+
throw new Error("purpose must be \"read\", \"preview\", \"edit\", or \"interact\".");
|
|
9404
|
+
}
|
|
9405
|
+
function readPayload(params) {
|
|
9406
|
+
if (!isRecord$1(params.payload)) throw new Error("payload must be an object.");
|
|
9407
|
+
return params.payload;
|
|
9408
|
+
}
|
|
9409
|
+
function readUrl(value) {
|
|
9410
|
+
const url = readRequiredString(value, "payload.url");
|
|
9411
|
+
let parsed;
|
|
9412
|
+
try {
|
|
9413
|
+
parsed = new URL(url);
|
|
9414
|
+
} catch {
|
|
9415
|
+
throw new Error("payload.url must be a valid URL.");
|
|
9416
|
+
}
|
|
9417
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error("payload.url must use http or https.");
|
|
9418
|
+
return parsed.toString();
|
|
9419
|
+
}
|
|
9420
|
+
function normalizeShowContentArgs(args) {
|
|
9421
|
+
const params = normalizeToolParams(args);
|
|
9422
|
+
const type = readRequiredString(params.type, "type");
|
|
9423
|
+
const payload = readPayload(params);
|
|
9424
|
+
const title = readOptionalString$1(params.title);
|
|
9425
|
+
const purpose = readPurpose(params.purpose);
|
|
9426
|
+
if (type === "file") return {
|
|
9427
|
+
target: {
|
|
9428
|
+
type,
|
|
9429
|
+
payload: {
|
|
9430
|
+
path: readRequiredString(payload.path, "payload.path"),
|
|
9431
|
+
line: readOptionalPositiveInteger(payload.line, "payload.line"),
|
|
9432
|
+
column: readOptionalPositiveInteger(payload.column, "payload.column")
|
|
9433
|
+
}
|
|
9434
|
+
},
|
|
9435
|
+
title,
|
|
9436
|
+
purpose
|
|
9437
|
+
};
|
|
9438
|
+
if (type === "url") return {
|
|
9439
|
+
target: {
|
|
9440
|
+
type,
|
|
9441
|
+
payload: { url: readUrl(payload.url) }
|
|
9442
|
+
},
|
|
9443
|
+
title,
|
|
9444
|
+
purpose
|
|
9445
|
+
};
|
|
9446
|
+
if (type === "panel_app") return {
|
|
9447
|
+
target: {
|
|
9448
|
+
type,
|
|
9449
|
+
payload: { appId: readRequiredString(payload.appId, "payload.appId") }
|
|
9450
|
+
},
|
|
9451
|
+
title,
|
|
9452
|
+
purpose
|
|
9453
|
+
};
|
|
9454
|
+
throw new Error("type must be \"file\", \"url\", or \"panel_app\".");
|
|
9455
|
+
}
|
|
9456
|
+
function summarizeTarget(target) {
|
|
9457
|
+
if (target.type === "file") return target.payload.path;
|
|
9458
|
+
if (target.type === "url") return target.payload.url;
|
|
9459
|
+
return target.payload.appId;
|
|
9460
|
+
}
|
|
9461
|
+
function createShowContentEventPayload(request, context) {
|
|
9462
|
+
const toolCallId = readOptionalString$1(context?.toolCallId);
|
|
9463
|
+
return {
|
|
9464
|
+
id: toolCallId ? `tool:${toolCallId}:show-content` : `show-content:${request.target.type}:${summarizeTarget(request.target)}`,
|
|
9465
|
+
toolCallId,
|
|
9466
|
+
target: request.target,
|
|
9467
|
+
title: request.title,
|
|
9468
|
+
purpose: request.purpose
|
|
9469
|
+
};
|
|
9470
|
+
}
|
|
9471
|
+
var ShowContentTool = class {
|
|
9472
|
+
name = SHOW_CONTENT_TOOL_NAME;
|
|
9473
|
+
description = "Show file, URL, or panel app content in the current chat UI.";
|
|
9474
|
+
parameters = {
|
|
9475
|
+
type: "object",
|
|
9476
|
+
properties: {
|
|
9477
|
+
type: {
|
|
9478
|
+
type: "string",
|
|
9479
|
+
enum: [
|
|
9480
|
+
"file",
|
|
9481
|
+
"url",
|
|
9482
|
+
"panel_app"
|
|
9483
|
+
],
|
|
9484
|
+
description: "Content target type."
|
|
9485
|
+
},
|
|
9486
|
+
title: {
|
|
9487
|
+
type: "string",
|
|
9488
|
+
description: "Optional title for the shown content."
|
|
9489
|
+
},
|
|
9490
|
+
purpose: {
|
|
9491
|
+
type: "string",
|
|
9492
|
+
enum: [
|
|
9493
|
+
"read",
|
|
9494
|
+
"preview",
|
|
9495
|
+
"edit",
|
|
9496
|
+
"interact"
|
|
9497
|
+
],
|
|
9498
|
+
description: "Optional user intent for the content."
|
|
9499
|
+
},
|
|
9500
|
+
payload: {
|
|
9501
|
+
type: "object",
|
|
9502
|
+
description: "Type-specific fields: file={path,line,column}; url={url}; panel_app={appId}.",
|
|
9503
|
+
additionalProperties: true
|
|
9504
|
+
}
|
|
9505
|
+
},
|
|
9506
|
+
required: ["type", "payload"],
|
|
9507
|
+
additionalProperties: false
|
|
9508
|
+
};
|
|
9509
|
+
constructor(eventBus) {
|
|
9510
|
+
this.eventBus = eventBus;
|
|
9511
|
+
}
|
|
9512
|
+
execute = async (args, context) => {
|
|
9513
|
+
const request = normalizeShowContentArgs(args);
|
|
9514
|
+
this.eventBus.emit(eventKeys.uiShowContent, createShowContentEventPayload(request, context), { source: "kernel" });
|
|
9515
|
+
return {
|
|
9516
|
+
ok: true,
|
|
9517
|
+
action: "showContent",
|
|
9518
|
+
request
|
|
9519
|
+
};
|
|
9520
|
+
};
|
|
9521
|
+
};
|
|
9522
|
+
//#endregion
|
|
9523
|
+
//#region src/contributions/tool-provider/providers/show-content-tool.provider.ts
|
|
9524
|
+
var ShowContentToolProvider = class {
|
|
9525
|
+
constructor(eventBus) {
|
|
9526
|
+
this.eventBus = eventBus;
|
|
9527
|
+
}
|
|
9528
|
+
provide = () => [new ShowContentTool(this.eventBus)];
|
|
9529
|
+
};
|
|
9530
|
+
//#endregion
|
|
9448
9531
|
//#region src/contributions/tool-provider/providers/structured-result-tool.provider.ts
|
|
9449
9532
|
var StructuredResultToolProvider = class {
|
|
9450
9533
|
provide = (request) => {
|
|
@@ -9467,6 +9550,40 @@ function isRecord(value) {
|
|
|
9467
9550
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9468
9551
|
}
|
|
9469
9552
|
//#endregion
|
|
9553
|
+
//#region src/contributions/tool-provider/services/tool-provider-run-context.service.ts
|
|
9554
|
+
var ToolProviderRunContextService = class {
|
|
9555
|
+
constructor(sessionManager, agentManager, configManager) {
|
|
9556
|
+
this.sessionManager = sessionManager;
|
|
9557
|
+
this.agentManager = agentManager;
|
|
9558
|
+
this.configManager = configManager;
|
|
9559
|
+
}
|
|
9560
|
+
resolve = async (request) => {
|
|
9561
|
+
const session = request.sessionId ? await this.sessionManager.getAgentRunSession(request.sessionId) : null;
|
|
9562
|
+
const sessionId = session?.sessionId ?? request.sessionId ?? request.message.sessionId ?? "";
|
|
9563
|
+
const requestMetadata = buildAgentRunRequestMetadata({
|
|
9564
|
+
request,
|
|
9565
|
+
session
|
|
9566
|
+
});
|
|
9567
|
+
const runContext = buildNextclawNcpRunContext({
|
|
9568
|
+
agentProfile: this.agentManager.resolveAgentProfileForRun({
|
|
9569
|
+
requestMetadata,
|
|
9570
|
+
storedAgentId: request.agentId ?? session?.agentId
|
|
9571
|
+
}),
|
|
9572
|
+
config: this.configManager.loadConfig(),
|
|
9573
|
+
sessionId,
|
|
9574
|
+
requestMetadata,
|
|
9575
|
+
sessionMetadata: session?.metadata ?? requestMetadata
|
|
9576
|
+
});
|
|
9577
|
+
return {
|
|
9578
|
+
requestMetadata,
|
|
9579
|
+
runContext,
|
|
9580
|
+
session,
|
|
9581
|
+
sessionId,
|
|
9582
|
+
toolRunContext: runContext.toolRunContext
|
|
9583
|
+
};
|
|
9584
|
+
};
|
|
9585
|
+
};
|
|
9586
|
+
//#endregion
|
|
9470
9587
|
//#region src/contributions/tool-provider/index.ts
|
|
9471
9588
|
var ToolProviderContribution = class {
|
|
9472
9589
|
cleanups = [];
|
|
@@ -9480,14 +9597,18 @@ var ToolProviderContribution = class {
|
|
|
9480
9597
|
dispose = () => {
|
|
9481
9598
|
while (this.cleanups.length > 0) this.cleanups.pop()?.();
|
|
9482
9599
|
};
|
|
9483
|
-
createToolProviders = () =>
|
|
9484
|
-
new
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9600
|
+
createToolProviders = () => {
|
|
9601
|
+
const runContextService = new ToolProviderRunContextService(this.kernel.sessionManager, this.kernel.agents, this.kernel.configManager);
|
|
9602
|
+
return [
|
|
9603
|
+
new StructuredResultToolProvider(),
|
|
9604
|
+
new ShowContentToolProvider(this.kernel.eventBus),
|
|
9605
|
+
new CoreToolProvider(runContextService, this.kernel.getGatewayController),
|
|
9606
|
+
new MessagingToolProvider(runContextService, this.kernel.channels, this.kernel.automation, this.kernel.extensions),
|
|
9607
|
+
new SessionToolProvider(runContextService, this.kernel.sessionManager, this.kernel.sessionRequests, this.kernel.sessionSearch),
|
|
9608
|
+
new AssetToolProvider(this.kernel.assetStore),
|
|
9609
|
+
new McpToolProvider(runContextService, this.kernel.mcpManager)
|
|
9610
|
+
];
|
|
9611
|
+
};
|
|
9491
9612
|
};
|
|
9492
9613
|
//#endregion
|
|
9493
9614
|
//#region src/app/nextclaw-kernel.ts
|
|
@@ -9543,26 +9664,27 @@ var NextclawKernel = class {
|
|
|
9543
9664
|
gatewayController;
|
|
9544
9665
|
constructor(options = {}) {
|
|
9545
9666
|
const sessionsDir = resolveKernelSessionsDir(options);
|
|
9546
|
-
this.sessionSearch = new
|
|
9667
|
+
this.sessionSearch = new SessionSearchService({
|
|
9547
9668
|
databasePath: resolve(getDataDir(), "session-search.db"),
|
|
9548
9669
|
sessionsDir
|
|
9549
9670
|
});
|
|
9550
9671
|
this.ncpAgentSessionJournalStore = new NcpAgentSessionJournalStore(resolve(sessionsDir, ".ncp-agent-journal"));
|
|
9551
9672
|
this.automation = new AutomationManager({ storePath: resolveKernelAutomationStorePath(options) });
|
|
9552
9673
|
this.assetStore = new LocalAssetStore({ rootDir: resolve(getDataDir(), "assets") });
|
|
9553
|
-
this.agents = new AgentManager();
|
|
9554
9674
|
this.control = new NextclawKernelControlManager();
|
|
9555
|
-
this.channels = new ChannelManager
|
|
9675
|
+
this.channels = new ChannelManager({ bus: this.messageBus });
|
|
9556
9676
|
this.configManager = new ConfigManager({
|
|
9557
9677
|
configPath: options.configPath,
|
|
9558
9678
|
channels: this.channels,
|
|
9559
9679
|
providerManager: this.llmProviders
|
|
9560
9680
|
});
|
|
9681
|
+
this.agents = new AgentManager(this.configManager);
|
|
9561
9682
|
this.accessManager = new AccessManager({
|
|
9562
9683
|
configManager: this.configManager,
|
|
9563
9684
|
homeDir: options.homeDir
|
|
9564
9685
|
});
|
|
9565
9686
|
this.sessionManager = new SessionManager({
|
|
9687
|
+
agentManager: this.agents,
|
|
9566
9688
|
configManager: this.configManager,
|
|
9567
9689
|
eventBus: this.eventBus,
|
|
9568
9690
|
journalStore: this.ncpAgentSessionJournalStore,
|
|
@@ -9595,9 +9717,9 @@ var NextclawKernel = class {
|
|
|
9595
9717
|
ingress: this.ingress
|
|
9596
9718
|
})
|
|
9597
9719
|
});
|
|
9598
|
-
this.contextCompactionManager = new AgentRunContextCompactionManager(this.
|
|
9720
|
+
this.contextCompactionManager = new AgentRunContextCompactionManager(this.agents, this.llmProviders, this.sessionManager);
|
|
9599
9721
|
this.sessionRunManager = new SessionRunManager(this.sessionManager);
|
|
9600
|
-
this.agentRunRequestManager = new AgentRunRequestManager(this.agentRuntimeManager, this.configManager, this.contextProviderManager, this.eventBus, this.ingress, this.sessionManager, this.sessionRunManager, this.toolProviderManager);
|
|
9722
|
+
this.agentRunRequestManager = new AgentRunRequestManager(this.agentRuntimeManager, this.agents, this.configManager, this.contextProviderManager, this.eventBus, this.ingress, this.sessionManager, this.sessionRunManager, this.toolProviderManager);
|
|
9601
9723
|
this.contributions = [
|
|
9602
9724
|
new ToolProviderContribution(this),
|
|
9603
9725
|
new SessionActivityPreviewContribution(this),
|
|
@@ -10237,6 +10359,6 @@ function resolveLegacyEventType(message) {
|
|
|
10237
10359
|
return `message.${role || "other"}`;
|
|
10238
10360
|
}
|
|
10239
10361
|
//#endregion
|
|
10240
|
-
export { AccessManager, AgentManager, AgentRunClient,
|
|
10362
|
+
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 };
|
|
10241
10363
|
|
|
10242
10364
|
//# sourceMappingURL=index.js.map
|