@nextclaw/kernel 0.6.0 → 0.6.2
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 +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +246 -57
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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
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, ViewImageTool, WebFetchTool, WebSearchTool, WriteFileTool, buildCompressingCompactionCheckpoint, buildConfigSchema, buildContextWindowSnapshot, buildReloadPlan, buildSessionRequestToolResult, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createCompletedSessionRequest, createFailedSessionRequest, createRunningSessionRequest, createRuntimeChildEnv, createTypingStopControlMessage, diffConfigPaths, ensureDir, evaluateSilentReply, expandHome, findEffectiveAgentProfile, getConfigPath, getDataDir, getDataPath, getSessionsPath, getWorkspacePath, getWorkspacePathFromConfig, isNextclawControlMessage, loadConfig, mergeExtensionConfigView, modelSupportsVision, normalizeAgentProfileId, normalizeInlineSecretRefs, normalizeModelThinkingCapability, normalizeProviderModelConfig, normalizeToolParams, parseAgentScopedSessionKey, parseThinkingLevel, readCompressedContextCompactionCheckpoint, readOptionalString, readParentSessionId, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveNextclawSelfManageGuidePaths, resolveProviderRuntime, resolveSessionProjectContext, resolveSessionWorkspacePath, resolveThinkingLevel, sanitizeOutboundAssistantContent, saveConfig, summarizeSessionRequestTask, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
4
|
-
import { NcpEventType, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
|
|
4
|
+
import { NcpEventType, normalizeAssistantText, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
|
|
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
7
|
import { CHAT_SESSION_MATERIALIZATION_METADATA_KEY, EventBus, Ingress, eventKeys, ingressKeys, isRuntimeDefaultModelValue, normalizeRuntimeModelSelectionMode } from "@nextclaw/shared";
|
|
@@ -203,8 +203,18 @@ function toLegacyMessages(messages, options = {}) {
|
|
|
203
203
|
//#region src/features/context-compaction/utils/context-compaction.utils.ts
|
|
204
204
|
const NEXTCLAW_TIMELINE_KIND_METADATA_KEY = "nextclaw_timeline_kind";
|
|
205
205
|
const CONTEXT_COMPACTION_TIMELINE_KIND = "context_compaction";
|
|
206
|
+
const CONTEXT_COMPACTION_PROJECTION_METADATA_KEY = "nextclaw_context_projection";
|
|
207
|
+
const CONTEXT_COMPACTION_PROJECTION_KIND = "compressed_context";
|
|
206
208
|
function readCheckpointTimelineText(checkpoint) {
|
|
207
|
-
return checkpoint.status === "compressing" ? "
|
|
209
|
+
return checkpoint.status === "compressing" ? "Compressing earlier context" : "Earlier context was auto-compacted";
|
|
210
|
+
}
|
|
211
|
+
function buildCompressedContextSystemText(checkpoint) {
|
|
212
|
+
return [
|
|
213
|
+
"Authoritative compressed prior conversation context for this session.",
|
|
214
|
+
"Continue from this context and the latest user message. Do not restart onboarding or treat missing profile fields as a new-session trigger unless the compressed context says onboarding is the active user task.",
|
|
215
|
+
"",
|
|
216
|
+
checkpoint.summary
|
|
217
|
+
].join("\n");
|
|
208
218
|
}
|
|
209
219
|
function readContextCompactionCheckpoint(message) {
|
|
210
220
|
const metadata = message.metadata;
|
|
@@ -221,15 +231,19 @@ function buildContextCompactionSummaryMessage(params) {
|
|
|
221
231
|
return {
|
|
222
232
|
id: `${sessionId}:context-compaction-summary:${checkpoint.id}:${checkpoint.updatedAt}`,
|
|
223
233
|
sessionId,
|
|
224
|
-
role: "
|
|
234
|
+
role: "service",
|
|
225
235
|
status: "final",
|
|
226
236
|
timestamp: checkpoint.updatedAt,
|
|
227
237
|
parts: [{
|
|
228
238
|
type: "text",
|
|
229
|
-
text: checkpoint
|
|
230
|
-
}]
|
|
239
|
+
text: buildCompressedContextSystemText(checkpoint)
|
|
240
|
+
}],
|
|
241
|
+
metadata: { [CONTEXT_COMPACTION_PROJECTION_METADATA_KEY]: CONTEXT_COMPACTION_PROJECTION_KIND }
|
|
231
242
|
};
|
|
232
243
|
}
|
|
244
|
+
function readCheckpointCoveredUntil(checkpoint) {
|
|
245
|
+
return checkpoint.coveredUntil ?? checkpoint.updatedAt;
|
|
246
|
+
}
|
|
233
247
|
function createContextCompactionMessageId() {
|
|
234
248
|
return `context-compaction-message-${randomUUID()}`;
|
|
235
249
|
}
|
|
@@ -255,6 +269,9 @@ function buildContextCompactionTimelineNcpMessage(params) {
|
|
|
255
269
|
function isContextCompactionTimelineMessage(message) {
|
|
256
270
|
return message?.metadata?.[NEXTCLAW_TIMELINE_KIND_METADATA_KEY] === CONTEXT_COMPACTION_TIMELINE_KIND;
|
|
257
271
|
}
|
|
272
|
+
function isContextCompactionProjectionMessage(message) {
|
|
273
|
+
return message?.metadata?.[CONTEXT_COMPACTION_PROJECTION_METADATA_KEY] === CONTEXT_COMPACTION_PROJECTION_KIND;
|
|
274
|
+
}
|
|
258
275
|
function readLatestContextCompactionCheckpoint(sessionMessages) {
|
|
259
276
|
return readLatestContextCompactionMarker(sessionMessages)?.checkpoint ?? null;
|
|
260
277
|
}
|
|
@@ -264,10 +281,11 @@ function buildContextCompactionModelInput(params) {
|
|
|
264
281
|
const regularMessages = sessionMessages.filter((message) => !readContextCompactionCheckpoint(message));
|
|
265
282
|
if (!marker) return regularMessages.map((message) => structuredClone(message));
|
|
266
283
|
const { checkpoint } = marker;
|
|
284
|
+
const coveredUntil = readCheckpointCoveredUntil(checkpoint);
|
|
267
285
|
return [buildContextCompactionSummaryMessage({
|
|
268
286
|
checkpoint,
|
|
269
287
|
sessionId
|
|
270
|
-
}), ...regularMessages.filter((message) => Date.parse(message.timestamp) > Date.parse(
|
|
288
|
+
}), ...regularMessages.filter((message) => Date.parse(message.timestamp) > Date.parse(coveredUntil)).sort((left, right) => Date.parse(left.timestamp) - Date.parse(right.timestamp))].map((message) => structuredClone(message));
|
|
271
289
|
}
|
|
272
290
|
function readContextWindowEventSessionId(event) {
|
|
273
291
|
const payload = "payload" in event ? event.payload : null;
|
|
@@ -311,6 +329,17 @@ function shouldRefreshContextWindowImmediately(event) {
|
|
|
311
329
|
//#region src/features/context-compaction/services/context-compaction-preflight.service.ts
|
|
312
330
|
const SUMMARY_MAX_TOKENS = 4e3;
|
|
313
331
|
const SUMMARY_SOURCE_MAX_CHARS = 12e4;
|
|
332
|
+
const SUMMARY_SOURCE_HEAD_MESSAGES = 2;
|
|
333
|
+
const SUMMARY_SOURCE_TAIL_MESSAGES = 8;
|
|
334
|
+
const SUMMARY_SOURCE_STRING_HEAD_CHARS = 6e3;
|
|
335
|
+
const SUMMARY_SOURCE_STRING_TAIL_CHARS = 6e3;
|
|
336
|
+
function buildContextBlockMessage(contextBlocks = []) {
|
|
337
|
+
const contextContent = contextBlocks.map((block) => block.trim()).filter(Boolean).join("\n\n");
|
|
338
|
+
return contextContent ? [{
|
|
339
|
+
role: "system",
|
|
340
|
+
content: contextContent
|
|
341
|
+
}] : [];
|
|
342
|
+
}
|
|
314
343
|
function mergeInputMessages(params) {
|
|
315
344
|
const messages = params.sessionMessages.map((message) => structuredClone(message));
|
|
316
345
|
const seen = new Set(messages.map((message) => message.id));
|
|
@@ -320,10 +349,47 @@ function mergeInputMessages(params) {
|
|
|
320
349
|
}
|
|
321
350
|
return messages;
|
|
322
351
|
}
|
|
352
|
+
function toCompactionSourceMessage(message) {
|
|
353
|
+
return {
|
|
354
|
+
role: message.role,
|
|
355
|
+
content: message.content,
|
|
356
|
+
timestamp: message.timestamp,
|
|
357
|
+
ncp_message_id: message.ncp_message_id
|
|
358
|
+
};
|
|
359
|
+
}
|
|
323
360
|
function stringifyCompactionSource(messages) {
|
|
324
|
-
const
|
|
361
|
+
const sourceMessages = messages.map(toCompactionSourceMessage);
|
|
362
|
+
const json = JSON.stringify(sourceMessages, null, 2);
|
|
325
363
|
if (json.length <= SUMMARY_SOURCE_MAX_CHARS) return json;
|
|
326
|
-
|
|
364
|
+
const tailStart = Math.max(SUMMARY_SOURCE_HEAD_MESSAGES, sourceMessages.length - SUMMARY_SOURCE_TAIL_MESSAGES);
|
|
365
|
+
const compactedMessages = [
|
|
366
|
+
...sourceMessages.slice(0, SUMMARY_SOURCE_HEAD_MESSAGES),
|
|
367
|
+
...tailStart > SUMMARY_SOURCE_HEAD_MESSAGES ? [{
|
|
368
|
+
role: "system",
|
|
369
|
+
content: `[${tailStart - SUMMARY_SOURCE_HEAD_MESSAGES} middle messages omitted from compaction source]`
|
|
370
|
+
}] : [],
|
|
371
|
+
...sourceMessages.slice(tailStart)
|
|
372
|
+
];
|
|
373
|
+
const compactedJson = JSON.stringify(compactedMessages, (_key, value) => truncateSummarySourceString(value), 2);
|
|
374
|
+
if (compactedJson.length <= SUMMARY_SOURCE_MAX_CHARS) return compactedJson;
|
|
375
|
+
const marker = "\n[truncated_compaction_source_middle]\n";
|
|
376
|
+
const headChars = Math.floor((SUMMARY_SOURCE_MAX_CHARS - 38) / 2);
|
|
377
|
+
const tailChars = SUMMARY_SOURCE_MAX_CHARS - 38 - headChars;
|
|
378
|
+
return `${compactedJson.slice(0, headChars).trimEnd()}${marker}${compactedJson.slice(-tailChars).trimStart()}`;
|
|
379
|
+
}
|
|
380
|
+
function truncateSummarySourceString(value) {
|
|
381
|
+
if (typeof value === "string") {
|
|
382
|
+
if (value.length <= SUMMARY_SOURCE_STRING_HEAD_CHARS + SUMMARY_SOURCE_STRING_TAIL_CHARS) return value;
|
|
383
|
+
return [
|
|
384
|
+
value.slice(0, SUMMARY_SOURCE_STRING_HEAD_CHARS).trimEnd(),
|
|
385
|
+
`[${value.length - SUMMARY_SOURCE_STRING_HEAD_CHARS - SUMMARY_SOURCE_STRING_TAIL_CHARS} chars omitted]`,
|
|
386
|
+
value.slice(-SUMMARY_SOURCE_STRING_TAIL_CHARS).trimStart()
|
|
387
|
+
].join("\n");
|
|
388
|
+
}
|
|
389
|
+
return value;
|
|
390
|
+
}
|
|
391
|
+
function normalizeCompactionSummary(content) {
|
|
392
|
+
return normalizeAssistantText(content, "think-tags").text.trim();
|
|
327
393
|
}
|
|
328
394
|
function buildContextWindowSnapshotFromBudget(params) {
|
|
329
395
|
const { budget, checkpoint, totalContextTokens } = params;
|
|
@@ -347,7 +413,7 @@ var ContextCompactionPreflightService = class {
|
|
|
347
413
|
this.providerManager = providerManager;
|
|
348
414
|
}
|
|
349
415
|
preview = (params) => {
|
|
350
|
-
const { requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
416
|
+
const { contextBlocks = [], requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
351
417
|
const profile = this.resolveCompactionProfile({
|
|
352
418
|
requestMetadata,
|
|
353
419
|
storedAgentId
|
|
@@ -357,9 +423,10 @@ var ContextCompactionPreflightService = class {
|
|
|
357
423
|
sessionId,
|
|
358
424
|
sessionMessages
|
|
359
425
|
}) : sessionMessages.filter((message) => !isContextCompactionTimelineMessage(message));
|
|
426
|
+
const messages = [...buildContextBlockMessage(contextBlocks), ...toLegacyMessages(projectedMessages)];
|
|
360
427
|
return buildContextWindowSnapshotFromBudget({
|
|
361
428
|
budget: this.contextWindowBudgetService.evaluate({
|
|
362
|
-
messages
|
|
429
|
+
messages,
|
|
363
430
|
contextTokens: profile.contextTokens,
|
|
364
431
|
reservedContextTokens: profile.reservedContextTokens
|
|
365
432
|
}),
|
|
@@ -368,7 +435,7 @@ var ContextCompactionPreflightService = class {
|
|
|
368
435
|
});
|
|
369
436
|
};
|
|
370
437
|
begin = (params) => {
|
|
371
|
-
const { inputMessages, requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
438
|
+
const { contextBlocks = [], inputMessages, requestMetadata, sessionId, sessionMessages, storedAgentId, storedMetadata } = params;
|
|
372
439
|
const profile = this.resolveCompactionProfile({
|
|
373
440
|
requestMetadata,
|
|
374
441
|
storedAgentId
|
|
@@ -379,10 +446,11 @@ var ContextCompactionPreflightService = class {
|
|
|
379
446
|
sessionMessages
|
|
380
447
|
});
|
|
381
448
|
const existingCheckpoint = readCompressedContextCompactionCheckpoint(storedMetadata[CONTEXT_COMPACTION_METADATA_KEY]) ?? readLatestContextCompactionCheckpoint(ncpMessages);
|
|
382
|
-
const
|
|
449
|
+
const projectedMessages = existingCheckpoint ? buildContextCompactionModelInput({
|
|
383
450
|
sessionId,
|
|
384
451
|
sessionMessages: ncpMessages
|
|
385
|
-
}) : ncpMessages.filter((message) => !isContextCompactionTimelineMessage(message))
|
|
452
|
+
}) : ncpMessages.filter((message) => !isContextCompactionTimelineMessage(message));
|
|
453
|
+
const messages = [...buildContextBlockMessage(contextBlocks), ...toLegacyMessages(projectedMessages)];
|
|
386
454
|
const budget = this.contextWindowBudgetService.evaluate({
|
|
387
455
|
messages,
|
|
388
456
|
contextTokens,
|
|
@@ -468,7 +536,7 @@ var ContextCompactionPreflightService = class {
|
|
|
468
536
|
generateSummary = async (params) => {
|
|
469
537
|
if (!this.providerManager) throw new Error("context compaction summary generation requires a provider manager");
|
|
470
538
|
const { messages, model } = params;
|
|
471
|
-
const
|
|
539
|
+
const response = await this.providerManager.chat({
|
|
472
540
|
model,
|
|
473
541
|
maxTokens: SUMMARY_MAX_TOKENS,
|
|
474
542
|
messages: [{
|
|
@@ -476,7 +544,10 @@ var ContextCompactionPreflightService = class {
|
|
|
476
544
|
content: [
|
|
477
545
|
"You are NextClaw's context compactor for a coding agent session.",
|
|
478
546
|
"Create a complete compressed working context that will replace all prior conversation messages in a future model request.",
|
|
479
|
-
"
|
|
547
|
+
"Only the latest current input may remain raw, so preserve the active task, latest user intent, latest assistant response, and recent turns with high fidelity inside the summary.",
|
|
548
|
+
"Always include a 'Continuation Contract' section that states what the next assistant response should remember and how it should continue the session.",
|
|
549
|
+
"Do not turn missing user profile, assistant nickname, or onboarding fields into blockers unless onboarding is the active user task in the latest turns.",
|
|
550
|
+
"If the latest user message is a short greeting, preserve the prior active task and last assistant stance so the next response does not restart as a fresh session.",
|
|
480
551
|
"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.",
|
|
481
552
|
"Do not invent facts. If something is uncertain, mark it as uncertain.",
|
|
482
553
|
"Return Markdown only. Start with '# Compressed Working Context'."
|
|
@@ -486,12 +557,14 @@ var ContextCompactionPreflightService = class {
|
|
|
486
557
|
content: [
|
|
487
558
|
"Compress these runtime messages into a reusable working context.",
|
|
488
559
|
"Include a 'Recent High-Fidelity Context' section for the latest important user/assistant turns.",
|
|
560
|
+
"Include a 'Continuation Contract' section after the recent context.",
|
|
489
561
|
"",
|
|
490
562
|
"Messages JSON:",
|
|
491
563
|
stringifyCompactionSource(messages)
|
|
492
564
|
].join("\n")
|
|
493
565
|
}]
|
|
494
|
-
})
|
|
566
|
+
});
|
|
567
|
+
const summary = response.content ? normalizeCompactionSummary(response.content) : "";
|
|
495
568
|
if (!summary) throw new Error("context compaction summary is empty");
|
|
496
569
|
return summary;
|
|
497
570
|
};
|
|
@@ -535,6 +608,7 @@ var AgentRunContextCompactionManager = class {
|
|
|
535
608
|
}
|
|
536
609
|
runPreflight = async (input) => {
|
|
537
610
|
const beginResult = this.preflightService.begin({
|
|
611
|
+
contextBlocks: input.contextBlocks,
|
|
538
612
|
inputMessages: [],
|
|
539
613
|
requestMetadata: input.metadata,
|
|
540
614
|
sessionId: input.sessionId,
|
|
@@ -561,6 +635,37 @@ var AgentRunContextCompactionManager = class {
|
|
|
561
635
|
};
|
|
562
636
|
};
|
|
563
637
|
//#endregion
|
|
638
|
+
//#region src/utils/agent-run-execution-metadata.utils.ts
|
|
639
|
+
const AGENT_RUN_EXECUTION_METADATA = {
|
|
640
|
+
contractVersion: 1,
|
|
641
|
+
modelProtocol: "ncp-agent-run",
|
|
642
|
+
terminalContracts: [
|
|
643
|
+
"chat.finish_reason",
|
|
644
|
+
"responses.response.completed",
|
|
645
|
+
"ncp.run.finished-or-error-or-abort"
|
|
646
|
+
],
|
|
647
|
+
retryPolicy: {
|
|
648
|
+
requestMaxAttempts: 3,
|
|
649
|
+
streamMaxAttemptsBeforeVisibleOutput: 3,
|
|
650
|
+
scope: "transport-or-missing-terminal-before-visible-output",
|
|
651
|
+
runtimeStreamRetry: {
|
|
652
|
+
attemptLimit: null,
|
|
653
|
+
backoffFactor: 2,
|
|
654
|
+
initialDelayMs: 2e3,
|
|
655
|
+
maxDelayMsWithoutHeaders: 3e4,
|
|
656
|
+
partialAttemptDisposition: "retain-visible-parts",
|
|
657
|
+
scope: "retryable-model-stream-failure",
|
|
658
|
+
statusFields: [
|
|
659
|
+
"attempt",
|
|
660
|
+
"message",
|
|
661
|
+
"action",
|
|
662
|
+
"next"
|
|
663
|
+
],
|
|
664
|
+
statusMetadataType: "retry"
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
//#endregion
|
|
564
669
|
//#region src/managers/agent-run-request.manager.ts
|
|
565
670
|
function toAgentRunRequest(envelope) {
|
|
566
671
|
const metadata = envelope.metadata ?? {};
|
|
@@ -712,7 +817,8 @@ function attachRunSpecMetadata(params) {
|
|
|
712
817
|
thinkingEffort: spec.thinkingEffort,
|
|
713
818
|
projectRoot: request.projectRoot ?? session.projectRoot ?? null,
|
|
714
819
|
workingDir: session.workingDir ?? null,
|
|
715
|
-
correlationId: spec.correlationId ?? null
|
|
820
|
+
correlationId: spec.correlationId ?? null,
|
|
821
|
+
execution: structuredClone(AGENT_RUN_EXECUTION_METADATA)
|
|
716
822
|
};
|
|
717
823
|
return {
|
|
718
824
|
...message,
|
|
@@ -748,7 +854,12 @@ var AgentRunRequestManager = class {
|
|
|
748
854
|
};
|
|
749
855
|
handleAbortRequest = async (envelope) => {
|
|
750
856
|
if (!envelope.payload?.sessionId) throw new Error("Invalid agent run abort request.");
|
|
751
|
-
await this.abort({
|
|
857
|
+
await this.abort({
|
|
858
|
+
sessionId: envelope.payload.sessionId,
|
|
859
|
+
runId: envelope.payload.runId,
|
|
860
|
+
correlationId: envelope.payload.correlationId,
|
|
861
|
+
reason: envelope.payload.reason
|
|
862
|
+
});
|
|
752
863
|
};
|
|
753
864
|
handleSessionMessageRequest = async (envelope) => {
|
|
754
865
|
if (!envelope.payload) throw new Error("Invalid agent run session message request.");
|
|
@@ -895,7 +1006,7 @@ var AgentRunRequestManager = class {
|
|
|
895
1006
|
});
|
|
896
1007
|
};
|
|
897
1008
|
abort = async (request) => {
|
|
898
|
-
this.sessionRunManager.getSessionRun(request.sessionId)?.abortRun(request.runId);
|
|
1009
|
+
this.sessionRunManager.getSessionRun(request.sessionId)?.abortRun(request.runId, request.reason);
|
|
899
1010
|
};
|
|
900
1011
|
};
|
|
901
1012
|
//#endregion
|
|
@@ -3887,12 +3998,12 @@ function createProjection(sessionId, preview) {
|
|
|
3887
3998
|
};
|
|
3888
3999
|
}
|
|
3889
4000
|
function formatErrorStatus(error) {
|
|
3890
|
-
if (typeof error === "string" && error.trim()) return
|
|
4001
|
+
if (typeof error === "string" && error.trim()) return `Run failed: ${truncatePreviewText(error)}`;
|
|
3891
4002
|
if (error && typeof error === "object" && "message" in error) {
|
|
3892
4003
|
const message = error.message;
|
|
3893
|
-
if (typeof message === "string" && message.trim()) return
|
|
4004
|
+
if (typeof message === "string" && message.trim()) return `Run failed: ${truncatePreviewText(message)}`;
|
|
3894
4005
|
}
|
|
3895
|
-
return "
|
|
4006
|
+
return "Run failed";
|
|
3896
4007
|
}
|
|
3897
4008
|
function readToolCallId(value) {
|
|
3898
4009
|
if (typeof value !== "string") return null;
|
|
@@ -3900,13 +4011,13 @@ function readToolCallId(value) {
|
|
|
3900
4011
|
return trimmed.length > 0 ? trimmed : null;
|
|
3901
4012
|
}
|
|
3902
4013
|
function formatToolDoneStatus(toolName) {
|
|
3903
|
-
return toolName ?
|
|
4014
|
+
return toolName ? `Tool call completed: ${toolName}` : "Tool call completed";
|
|
3904
4015
|
}
|
|
3905
4016
|
function createSessionActivityPreviewFromNcpEvent(event, timestamp, options = {}) {
|
|
3906
4017
|
switch (event.type) {
|
|
3907
4018
|
case NcpEventType.RunStarted: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3908
4019
|
state: "running",
|
|
3909
|
-
statusText: "
|
|
4020
|
+
statusText: "Thinking",
|
|
3910
4021
|
timestamp
|
|
3911
4022
|
});
|
|
3912
4023
|
case NcpEventType.RunFinished: return createProjection(readSessionId(event.payload.sessionId), {
|
|
@@ -3941,9 +4052,13 @@ function createSessionActivityPreviewFromNcpEvent(event, timestamp, options = {}
|
|
|
3941
4052
|
statusText: formatErrorStatus(event.payload.error),
|
|
3942
4053
|
timestamp
|
|
3943
4054
|
});
|
|
4055
|
+
case NcpEventType.MessageAbort: return createProjection(readSessionId(event.payload.sessionId), {
|
|
4056
|
+
state: "cancelled",
|
|
4057
|
+
timestamp
|
|
4058
|
+
});
|
|
3944
4059
|
case NcpEventType.MessageToolCallStart: return createProjection(readSessionId(event.payload.sessionId), {
|
|
3945
4060
|
state: "running",
|
|
3946
|
-
statusText:
|
|
4061
|
+
statusText: `Calling tool: ${event.payload.toolName}`,
|
|
3947
4062
|
timestamp
|
|
3948
4063
|
});
|
|
3949
4064
|
case NcpEventType.MessageToolCallEnd:
|
|
@@ -3966,6 +4081,7 @@ const SESSION_ACTIVITY_PREVIEW_STATES = new Set([
|
|
|
3966
4081
|
"running",
|
|
3967
4082
|
"completed",
|
|
3968
4083
|
"failed",
|
|
4084
|
+
"cancelled",
|
|
3969
4085
|
"idle"
|
|
3970
4086
|
]);
|
|
3971
4087
|
function isRecord$9(value) {
|
|
@@ -4053,7 +4169,7 @@ var SessionActivityPreviewEventService = class {
|
|
|
4053
4169
|
};
|
|
4054
4170
|
readToolName = (sessionId, toolCallId) => this.toolNames.get(this.createToolNameKey(sessionId, toolCallId)) ?? null;
|
|
4055
4171
|
clearFinishedRunToolNames = (event) => {
|
|
4056
|
-
if (event.type !== NcpEventType.RunFinished && event.type !== NcpEventType.RunError) return;
|
|
4172
|
+
if (event.type !== NcpEventType.RunFinished && event.type !== NcpEventType.RunError && event.type !== NcpEventType.MessageAbort) return;
|
|
4057
4173
|
const sessionId = event.payload.sessionId;
|
|
4058
4174
|
for (const key of this.toolNames.keys()) if (key.startsWith(`${sessionId}:`)) this.toolNames.delete(key);
|
|
4059
4175
|
};
|
|
@@ -6718,11 +6834,11 @@ var SessionRun = class {
|
|
|
6718
6834
|
signal: controller.signal
|
|
6719
6835
|
};
|
|
6720
6836
|
};
|
|
6721
|
-
abortRun = (runId) => {
|
|
6837
|
+
abortRun = (runId, reason) => {
|
|
6722
6838
|
if (!this.activeRunId || !this.activeRunController) return false;
|
|
6723
6839
|
if (runId && this.activeRunId !== runId) return false;
|
|
6724
6840
|
const wasRunning = this.isRunning();
|
|
6725
|
-
this.activeRunController.abort();
|
|
6841
|
+
this.activeRunController.abort(reason);
|
|
6726
6842
|
this.activeRunController = null;
|
|
6727
6843
|
this.activeRunId = null;
|
|
6728
6844
|
this.emitStatusChangeIfNeeded(wasRunning);
|
|
@@ -6731,7 +6847,11 @@ var SessionRun = class {
|
|
|
6731
6847
|
isRunning = () => this.activeRunId !== null;
|
|
6732
6848
|
dispose = () => {
|
|
6733
6849
|
const wasRunning = this.isRunning();
|
|
6734
|
-
this.activeRunController?.abort(
|
|
6850
|
+
this.activeRunController?.abort({
|
|
6851
|
+
code: "abort-error",
|
|
6852
|
+
message: "Session run owner was disposed; the current run was cancelled.",
|
|
6853
|
+
details: { source: "session-run-manager" }
|
|
6854
|
+
});
|
|
6735
6855
|
this.activeRunController = null;
|
|
6736
6856
|
this.activeRunId = null;
|
|
6737
6857
|
this.emitStatusChangeIfNeeded(wasRunning);
|
|
@@ -8392,7 +8512,61 @@ var AgentRunModelInputBudgeter = class {
|
|
|
8392
8512
|
};
|
|
8393
8513
|
};
|
|
8394
8514
|
//#endregion
|
|
8515
|
+
//#region src/utils/agent-onboarding-context.utils.ts
|
|
8516
|
+
const ALWAYS_SKIPPED_COMPACTED_BOOTSTRAP_FILES = new Set(["BOOT.MD", "BOOTSTRAP.MD"]);
|
|
8517
|
+
function normalizeBootstrapFilename(filename) {
|
|
8518
|
+
return filename.trim().toUpperCase();
|
|
8519
|
+
}
|
|
8520
|
+
function shouldSkipCompactedSessionBootstrapFile(filename, content) {
|
|
8521
|
+
const normalized = normalizeBootstrapFilename(filename);
|
|
8522
|
+
if (ALWAYS_SKIPPED_COMPACTED_BOOTSTRAP_FILES.has(normalized)) return true;
|
|
8523
|
+
if (normalized === "IDENTITY.MD") return /Fill this in during your first conversation/i.test(content);
|
|
8524
|
+
if (normalized === "USER.MD") return /Learn about the person you are helping/i.test(content);
|
|
8525
|
+
return false;
|
|
8526
|
+
}
|
|
8527
|
+
function stripCompactedSessionOnboardingSections(block) {
|
|
8528
|
+
const lines = block.split("\n");
|
|
8529
|
+
const output = [];
|
|
8530
|
+
let index = 0;
|
|
8531
|
+
while (index < lines.length) {
|
|
8532
|
+
const line = lines[index] ?? "";
|
|
8533
|
+
const heading = line.match(/^##\s+(.+?)\s*$/);
|
|
8534
|
+
if (!heading) {
|
|
8535
|
+
output.push(line);
|
|
8536
|
+
index += 1;
|
|
8537
|
+
continue;
|
|
8538
|
+
}
|
|
8539
|
+
const sectionLines = [line];
|
|
8540
|
+
index += 1;
|
|
8541
|
+
while (index < lines.length && !/^##\s+/.test(lines[index] ?? "")) {
|
|
8542
|
+
sectionLines.push(lines[index] ?? "");
|
|
8543
|
+
index += 1;
|
|
8544
|
+
}
|
|
8545
|
+
if (shouldSkipCompactedSessionBootstrapFile(heading[1] ?? "", sectionLines.join("\n"))) continue;
|
|
8546
|
+
output.push(...sectionLines);
|
|
8547
|
+
}
|
|
8548
|
+
return output.join("\n").trim();
|
|
8549
|
+
}
|
|
8550
|
+
//#endregion
|
|
8395
8551
|
//#region src/services/agent-run-model-input-builder.service.ts
|
|
8552
|
+
function readSystemContent(messages) {
|
|
8553
|
+
return messages.filter((message) => message.role === "system").map((message) => message.content.trim()).filter(Boolean);
|
|
8554
|
+
}
|
|
8555
|
+
function partitionProjectedMessages(messages) {
|
|
8556
|
+
const compressedContextBlocks = [];
|
|
8557
|
+
const conversationMessages = [];
|
|
8558
|
+
for (const message of messages) {
|
|
8559
|
+
if (!isContextCompactionProjectionMessage(message)) {
|
|
8560
|
+
conversationMessages.push(message);
|
|
8561
|
+
continue;
|
|
8562
|
+
}
|
|
8563
|
+
compressedContextBlocks.push(...readSystemContent(ncpMessageToOpenAiMessages(message)));
|
|
8564
|
+
}
|
|
8565
|
+
return {
|
|
8566
|
+
compressedContextBlocks,
|
|
8567
|
+
conversationMessages
|
|
8568
|
+
};
|
|
8569
|
+
}
|
|
8396
8570
|
var AgentRunModelInputBuilder = class {
|
|
8397
8571
|
constructor(messageProjector, modelInputBudgeter, assetStore = null) {
|
|
8398
8572
|
this.messageProjector = messageProjector;
|
|
@@ -8400,15 +8574,17 @@ var AgentRunModelInputBuilder = class {
|
|
|
8400
8574
|
this.assetStore = assetStore;
|
|
8401
8575
|
}
|
|
8402
8576
|
build = async (request) => {
|
|
8403
|
-
const
|
|
8577
|
+
const { compressedContextBlocks, conversationMessages: projectedConversationMessages } = partitionProjectedMessages(this.messageProjector.project({
|
|
8578
|
+
sessionId: request.sessionId,
|
|
8579
|
+
messages: request.messages
|
|
8580
|
+
}));
|
|
8581
|
+
const contextBlocks = compressedContextBlocks.length > 0 ? request.contextBlocks.map(stripCompactedSessionOnboardingSections) : request.contextBlocks;
|
|
8582
|
+
const contextContent = [...compressedContextBlocks, ...contextBlocks].map((block) => block.trim()).filter(Boolean).join("\n\n");
|
|
8404
8583
|
const contextMessages = contextContent ? [{
|
|
8405
8584
|
role: "system",
|
|
8406
8585
|
content: contextContent
|
|
8407
8586
|
}] : [];
|
|
8408
|
-
const conversationMessages =
|
|
8409
|
-
sessionId: request.sessionId,
|
|
8410
|
-
messages: request.messages
|
|
8411
|
-
}).flatMap((message) => ncpMessageToOpenAiMessages(message, { assetStore: this.assetStore }));
|
|
8587
|
+
const conversationMessages = projectedConversationMessages.flatMap((message) => ncpMessageToOpenAiMessages(message, { assetStore: this.assetStore }));
|
|
8412
8588
|
const pruned = await this.modelInputBudgeter.prune({
|
|
8413
8589
|
spec: request.spec,
|
|
8414
8590
|
messages: [...contextMessages, ...conversationMessages]
|
|
@@ -8440,22 +8616,28 @@ var NcpAgentRuntimeWrapper = class {
|
|
|
8440
8616
|
const { sessionRun, tools } = options;
|
|
8441
8617
|
this.currentTools = tools.map(this.toOpenAiTool);
|
|
8442
8618
|
const messages = sessionRun.inbox.drain();
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8619
|
+
try {
|
|
8620
|
+
for (const event of this.toMessageSentEvents(messages, spec, sessionRun.sessionId)) yield await this.applyEvent(sessionRun, event);
|
|
8621
|
+
const input = {
|
|
8622
|
+
sessionId: sessionRun.sessionId,
|
|
8623
|
+
runId: spec.runId,
|
|
8624
|
+
messages,
|
|
8625
|
+
correlationId: spec.correlationId,
|
|
8626
|
+
metadata: this.buildMetadata(options.session, spec),
|
|
8627
|
+
executionContext: { cwd: options.session.workingDir }
|
|
8628
|
+
};
|
|
8629
|
+
for await (const event of this.getRuntime().run(input, { signal: options.signal })) yield await this.applyEvent(sessionRun, event);
|
|
8630
|
+
} finally {
|
|
8631
|
+
this.currentTools = [];
|
|
8632
|
+
}
|
|
8454
8633
|
};
|
|
8455
8634
|
dispose = async () => {
|
|
8635
|
+
await this.disposeRuntimeInstance();
|
|
8636
|
+
this.currentTools = [];
|
|
8637
|
+
};
|
|
8638
|
+
disposeRuntimeInstance = async () => {
|
|
8456
8639
|
if (this.runtime && "dispose" in this.runtime && typeof this.runtime.dispose === "function") await this.runtime.dispose();
|
|
8457
8640
|
this.runtime = null;
|
|
8458
|
-
this.currentTools = [];
|
|
8459
8641
|
};
|
|
8460
8642
|
getRuntime = () => {
|
|
8461
8643
|
if (!this.runtime) this.runtime = this.params.createRuntime({
|
|
@@ -8522,10 +8704,11 @@ var AgentRunRuntimeContribution = class {
|
|
|
8522
8704
|
createRuntime: () => new DefaultNcpAgentRuntime({
|
|
8523
8705
|
llmApi: new ProviderManagerNcpLLMApi(this.kernel.llmProviders),
|
|
8524
8706
|
modelInputBuilder: this.modelInputBuilder,
|
|
8525
|
-
runPreflight: async ({ spec, sessionRun }) => {
|
|
8707
|
+
runPreflight: async ({ contextBlocks, spec, sessionRun }) => {
|
|
8526
8708
|
const session = await this.kernel.sessionManager.getAgentRunSession(sessionRun.sessionId);
|
|
8527
8709
|
return await this.kernel.contextCompactionManager.runPreflight({
|
|
8528
8710
|
agentId: spec.agentId,
|
|
8711
|
+
contextBlocks,
|
|
8529
8712
|
messages: sessionRun.getSnapshot().messages,
|
|
8530
8713
|
metadata: session.metadata,
|
|
8531
8714
|
sessionId: sessionRun.sessionId
|
|
@@ -8570,11 +8753,13 @@ var AgentBootstrapContextProvider = class {
|
|
|
8570
8753
|
provide = async (request) => {
|
|
8571
8754
|
const { contextConfig, projectContext, runContext } = await this.context.resolve(request);
|
|
8572
8755
|
const budget = this.createReadBudget(contextConfig.bootstrap);
|
|
8756
|
+
const compactedSession = this.hasCompressedContext(runContext.sessionMetadata);
|
|
8573
8757
|
const agentBootstrapRoot = projectContext.projectBootstrapRoot ?? projectContext.effectiveWorkspace;
|
|
8574
8758
|
const projectBootstrap = this.loadBootstrapFiles({
|
|
8575
8759
|
root: agentBootstrapRoot,
|
|
8576
8760
|
config: contextConfig.bootstrap,
|
|
8577
8761
|
sessionKey: runContext.sessionKey,
|
|
8762
|
+
compactedSession,
|
|
8578
8763
|
budget
|
|
8579
8764
|
});
|
|
8580
8765
|
const hasDistinctHostWorkspace = projectContext.hostWorkspace !== agentBootstrapRoot;
|
|
@@ -8582,6 +8767,7 @@ var AgentBootstrapContextProvider = class {
|
|
|
8582
8767
|
root: projectContext.hostWorkspace,
|
|
8583
8768
|
config: contextConfig.bootstrap,
|
|
8584
8769
|
sessionKey: runContext.sessionKey,
|
|
8770
|
+
compactedSession,
|
|
8585
8771
|
budget
|
|
8586
8772
|
}) : "";
|
|
8587
8773
|
const hasSoulFile = /##\s+SOUL\.md\b/i.test(`${projectBootstrap}\n${workspaceBootstrap}`);
|
|
@@ -8615,14 +8801,15 @@ var AgentBootstrapContextProvider = class {
|
|
|
8615
8801
|
return lines.join("\n");
|
|
8616
8802
|
};
|
|
8617
8803
|
loadBootstrapFiles = (params) => {
|
|
8618
|
-
const { budget, config, root, sessionKey } = params;
|
|
8804
|
+
const { budget, compactedSession, config, root, sessionKey } = params;
|
|
8619
8805
|
const parts = [];
|
|
8620
|
-
const fileList = this.selectBootstrapFiles(config, sessionKey);
|
|
8806
|
+
const fileList = this.selectBootstrapFiles(config, sessionKey, compactedSession);
|
|
8621
8807
|
for (const filename of fileList) {
|
|
8622
8808
|
const filePath = join(root, filename);
|
|
8623
8809
|
if (!existsSync(filePath)) continue;
|
|
8624
8810
|
const raw = readFileSync(filePath, "utf-8").trim();
|
|
8625
8811
|
if (!raw) continue;
|
|
8812
|
+
if (compactedSession && shouldSkipCompactedSessionBootstrapFile(filename, raw)) continue;
|
|
8626
8813
|
const perFileLimit = config.perFileChars > 0 ? config.perFileChars : raw.length;
|
|
8627
8814
|
const allowed = Math.min(perFileLimit, budget.remaining);
|
|
8628
8815
|
if (allowed <= 0) break;
|
|
@@ -8634,11 +8821,13 @@ var AgentBootstrapContextProvider = class {
|
|
|
8634
8821
|
return parts.join("\n\n");
|
|
8635
8822
|
};
|
|
8636
8823
|
createReadBudget = (config) => ({ remaining: config.totalChars > 0 ? config.totalChars : Number.POSITIVE_INFINITY });
|
|
8637
|
-
selectBootstrapFiles = (config, sessionKey) => {
|
|
8638
|
-
if (!sessionKey) return config.files;
|
|
8824
|
+
selectBootstrapFiles = (config, sessionKey, compactedSession = false) => {
|
|
8825
|
+
if (!sessionKey) return this.filterCompactedSessionFiles(config.files, compactedSession);
|
|
8639
8826
|
if (sessionKey.startsWith("cron:") || sessionKey.startsWith("subagent:")) return config.minimalFiles;
|
|
8640
|
-
return config.files;
|
|
8827
|
+
return this.filterCompactedSessionFiles(config.files, compactedSession);
|
|
8641
8828
|
};
|
|
8829
|
+
filterCompactedSessionFiles = (files, compactedSession) => compactedSession ? files.filter((filename) => !shouldSkipCompactedSessionBootstrapFile(filename, "")) : [...files];
|
|
8830
|
+
hasCompressedContext = (metadata) => Boolean(readCompressedContextCompactionCheckpoint(metadata?.[CONTEXT_COMPACTION_METADATA_KEY]));
|
|
8642
8831
|
};
|
|
8643
8832
|
//#endregion
|
|
8644
8833
|
//#region src/contributions/context-provider/providers/current-session-context.provider.ts
|
|
@@ -8720,7 +8909,7 @@ const createInlineInteractiveSurfaceContextProvider = () => staticBlock([
|
|
|
8720
8909
|
"Do not make every UI an inline card. Choose inline only when the intended result is a compact, immediately usable card or short interaction; use the side panel for normal Panel Apps, long reading, rich editing, file browsing, large tables, multi-page workflows, or sustained workspaces.",
|
|
8721
8910
|
"Inline Panel App display is Markdown-only: in the final reply, output a `nextclaw-inline` fenced JSON block so the display remains message content.",
|
|
8722
8911
|
"`show_panel_app` is side-panel only. Never call `show_panel_app` for inline display, including when the user asks which Panel Apps are suitable for inline display or says \"show/display them inline\".",
|
|
8723
|
-
"For ordinary local HTML files or page prototypes, call `show_file` with `path` and `viewer=\"rendered\"`; use `viewer=\"source\"` when the user needs to inspect source text. Do not convert a plain HTML file into a Panel App just to preview it.",
|
|
8912
|
+
"For ordinary local HTML files or page prototypes, call `show_file` with `path` and `viewer=\"rendered\"`; use `viewer=\"source\"` when the user needs to inspect source text. Markdown file links open source by default; append `?viewer=rendered` only when the link itself should open the rendered HTML view. Do not convert a plain HTML file into a Panel App just to preview it.",
|
|
8724
8913
|
"A Panel Card must be designed card-first: prefer a landscape composition where width carries the main information and the card is wider than it is tall; collapse to one column only in narrow containers. Core value must be visible in the first 220-420px, with no horizontal scrolling, no reliance on document-level internal scrolling, compact controls, at most one primary action, clear loading/empty/error states, and an obvious expand path for details.",
|
|
8725
8914
|
"Typical Panel Card fits: weather cards, calculators, timers, checklists, pickers, compact forms, previews, and small dashboards. If the UI needs more space than a card, use the side panel instead. Inline hosts may pass `nextclawDisplayMode=card` and `nextclawPlacement=inline`; use those hints to render a compact card layout instead of a full page."
|
|
8726
8915
|
]);
|
|
@@ -8877,7 +9066,7 @@ var ProjectContextProvider = class {
|
|
|
8877
9066
|
//#endregion
|
|
8878
9067
|
//#region src/contributions/context-provider/providers/reply-format-context.provider.ts
|
|
8879
9068
|
var ReplyFormatContextProvider = class {
|
|
8880
|
-
provide = (_request) => ["## Reply Formatting Contract\nGoal: openable files in user-visible replies must be clickable, and inert inline display declarations are only for content that should appear as part of the reply.\nFile links: 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). Use project-relative hrefs for files under the active/session project root, and absolute hrefs for local files outside it.\nInline display: when the final reply should include a non-clickable inline display placeholder, output a fenced `nextclaw-inline` JSON block:\n```nextclaw-inline\n{\"target\":{\"type\":\"panel_app\",\"payload\":{\"appId\":\"timer\"}},\"title\":\"Timer\"}\n```\nSupported targets are `panel_app`, `json`, `file`, and `url`. Prefer `panel_app` for inline Panel App display; use `file` and `url` only as non-clickable placeholders when a clickable link is not intended; use `json` for inert JSON snapshots.\nIt is display-only: no opening, executing, or tool action. Never call `show_panel_app` for inline display; `show_panel_app` is only for immediately opening a Panel App outside the final reply in the side panel. Use Markdown links for clickable resources and show_file/show_url/show_panel_app tools only when you want the UI to immediately show or run content outside the final reply.\nForbidden forms: bare file names or paths, inline-code file names, bold-only file names, code-styled link labels, code blocks for file references, action semantics inside `nextclaw-inline`, tool calls for inline display, 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 or intentionally represented by `nextclaw-inline`, remove the exact names and summarize instead."];
|
|
9069
|
+
provide = (_request) => ["## Reply Formatting Contract\nGoal: openable files in user-visible replies must be clickable, and inert inline display declarations are only for content that should appear as part of the reply.\nFile links: 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). Use project-relative hrefs for files under the active/session project root, and absolute hrefs for local files outside it. File links open source by default; use a viewer query such as [preview.html](preview.html?viewer=rendered) only when the link should open the rendered HTML view.\nInline display: when the final reply should include a non-clickable inline display placeholder, output a fenced `nextclaw-inline` JSON block:\n```nextclaw-inline\n{\"target\":{\"type\":\"panel_app\",\"payload\":{\"appId\":\"timer\"}},\"title\":\"Timer\"}\n```\nSupported targets are `panel_app`, `json`, `file`, and `url`. Prefer `panel_app` for inline Panel App display; use `file` and `url` only as non-clickable placeholders when a clickable link is not intended; use `json` for inert JSON snapshots.\nIt is display-only: no opening, executing, or tool action. Never call `show_panel_app` for inline display; `show_panel_app` is only for immediately opening a Panel App outside the final reply in the side panel. Use Markdown links for clickable resources and show_file/show_url/show_panel_app tools only when you want the UI to immediately show or run content outside the final reply.\nForbidden forms: bare file names or paths, inline-code file names, bold-only file names, code-styled link labels, code blocks for file references, action semantics inside `nextclaw-inline`, tool calls for inline display, 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 or intentionally represented by `nextclaw-inline`, remove the exact names and summarize instead."];
|
|
8881
9070
|
};
|
|
8882
9071
|
//#endregion
|
|
8883
9072
|
//#region src/contributions/context-provider/providers/skills-context.provider.ts
|
|
@@ -9993,7 +10182,7 @@ function normalizeShowFileArgs(args) {
|
|
|
9993
10182
|
path: readRequiredString(params.path, "path"),
|
|
9994
10183
|
line: readOptionalPositiveInteger(params.line, "line"),
|
|
9995
10184
|
column: readOptionalPositiveInteger(params.column, "column"),
|
|
9996
|
-
viewer: readOptionalEnum(params.viewer, "viewer", FILE_VIEWERS)
|
|
10185
|
+
viewer: readOptionalEnum(params.viewer, "viewer", FILE_VIEWERS) ?? "source"
|
|
9997
10186
|
}
|
|
9998
10187
|
},
|
|
9999
10188
|
...readCommonRequestFields(params, FILE_PURPOSES)
|
|
@@ -10062,7 +10251,7 @@ var ShowContentDisplayTool = class {
|
|
|
10062
10251
|
const SHOW_CONTENT_TOOL_SPECS = [
|
|
10063
10252
|
{
|
|
10064
10253
|
name: "show_file",
|
|
10065
|
-
description: "Show a local file in the current chat UI. Use viewer=\"rendered\" for rendered HTML/page previews and viewer=\"source\" for source text.",
|
|
10254
|
+
description: "Show a local file in the current chat UI. Defaults to source text. Use viewer=\"rendered\" for rendered HTML/page previews and viewer=\"source\" for source text.",
|
|
10066
10255
|
parameters: {
|
|
10067
10256
|
type: "object",
|
|
10068
10257
|
properties: {
|
|
@@ -10967,6 +11156,6 @@ function resolveLegacyEventType(message) {
|
|
|
10967
11156
|
return `message.${role || "other"}`;
|
|
10968
11157
|
}
|
|
10969
11158
|
//#endregion
|
|
10970
|
-
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, PreferenceError, PreferenceManager, 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, isPreferenceError, 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 };
|
|
11159
|
+
export { AccessManager, AgentManager, AgentRunClient, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_PROJECTION_KIND, CONTEXT_COMPACTION_PROJECTION_METADATA_KEY, 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, PreferenceError, PreferenceManager, 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, isContextCompactionProjectionMessage, isContextCompactionTimelineMessage, isContextWindowSnapshot, isPanelAppAgentCapability, isPanelAppError, isPreferenceError, 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 };
|
|
10971
11160
|
|
|
10972
11161
|
//# sourceMappingURL=index.js.map
|