@nextclaw/kernel 0.14.0 → 0.15.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +232 -49
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1495 -210
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AUTOMATIC_UPDATE_CHECK_INTERVAL_MS, getAutomaticUpdateCheckDelay, resolveAutomaticUpdateCheckIntervalMs } from "./utils/automatic-update-check.utils.js";
|
|
2
2
|
import { n as getUnsignedUpdateManifest, r as serializeUnsignedUpdateManifest, t as UpdateManifestReader } from "./update-manifest.types-C0qPrjGQ.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
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, DIAGNOSTIC_CORRELATION_METADATA_KEY, DiagnosticRuntime, EditFileTool, ExecTool, ExtensionChannelAdapter, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, LocalExecutionClaimService, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderModelDiscoveryService, ProviderRegistry, ReadFileTool,
|
|
4
|
+
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, DIAGNOSTIC_CORRELATION_METADATA_KEY, DiagnosticRuntime, EditFileTool, ExecTool, ExtensionChannelAdapter, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, LiteLLMProvider, LocalExecutionClaimService, MAX_SESSION_SEARCH_LIMIT, MemoryGetTool, MemorySearchTool, MemoryStore, MessageBus, MessageTool, ProviderModelDiscoveryService, ProviderRegistry, ReadFileTool, 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, estimateInputTokens, 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, resolveRuntimeCommandLaunch, resolveSecretRef, resolveSessionProjectContext, resolveSessionWorkspacePath, resolveThinkingLevel, safeFilename, sanitizeOutboundAssistantContent, saveConfig, summarizeSessionRequestTask, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
5
5
|
import { NCP_AI_EXECUTION_METADATA_KEY, NCP_INTERNAL_VISIBILITY_METADATA_KEY, NCP_RUN_TRIGGER_METADATA_KEY, NcpEventType, OBSERVATION_EVENT_EXTENSION_TYPE, createUnavailableNcpAiExecutionMetadata, isHiddenNcpMessage, normalizeAssistantText, parseNcpRunTriggerInput, readNcpAiExecutionMetadata, sanitizeAssistantReplyTags } from "@nextclaw/ncp";
|
|
6
6
|
import { LocalAssetStore, buildAssetContentPath, buildOpenAiFunctionTool, isTextLikeAsset, ncpMessageToOpenAiMessages, validateToolArgs } from "@nextclaw/ncp-agent-runtime";
|
|
7
7
|
import { CHAT_CONTINUATION_TARGET_MESSAGE_METADATA_KEY, CHAT_CONVERSATION_EXCERPT_TOKEN_KIND, CHAT_INLINE_TOKENS_METADATA_KEY, CHAT_INLINE_TOKENS_SCHEMA_VERSION, CHAT_PROJECT_TOKEN_KIND, CHAT_SESSION_MATERIALIZATION_METADATA_KEY, CHAT_SYSTEM_OBJECT_TOKEN_KIND, CHAT_UI_RESOURCE_TOKEN_KIND, CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND, CHAT_WORKSPACE_EXCERPT_TOKEN_KIND, CHAT_WORKSPACE_FILE_TOKEN_KIND, Contribution as Contribution$1, EventBus, EventBus as EventBus$1, Ingress, Ingress as Ingress$1, PANEL_APP_INLINE_HOST_CONTRACT, PANEL_APP_SCROLL_RESTORATION_CONTRACT, SYSTEM_OBJECT_REFERENCE_DEFAULT_LIMIT, SYSTEM_OBJECT_REFERENCE_MAX_LIMIT, SYSTEM_OBJECT_TYPE_CRON_JOB, SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, UI_CONTENT_PARAMS_HOST_CONTRACT, classifyDiagnosticError, createSystemObjectReferenceUri, createTypedKey, eventKeys, eventKeys as eventKeys$1, ingressKeys, ingressKeys as ingressKeys$1, isRuntimeDefaultModelValue, isSilentReplyNcpMessage, normalizeRuntimeModelSelectionMode, parseSystemObjectReferenceUri, readChatUiResourceReference, readInlineContentHeight, readSystemObjectResolvedReference, readUiContentParams } from "@nextclaw/shared";
|
|
@@ -10,7 +10,7 @@ import { catchError, filter, from, lastValueFrom, tap } from "rxjs";
|
|
|
10
10
|
import { DefaultNcpAgentConversationStateManager, insertMessageByTimeline, mergeToolExecutionTiming } from "@nextclaw/ncp-toolkit";
|
|
11
11
|
import { accessSync, appendFileSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
12
12
|
import path, { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
13
|
-
import { access, appendFile, chmod, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
13
|
+
import { access, appendFile, chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
14
14
|
import { AppHomeService, AppInstallationService, AppInstanceInventoryService, AppInstanceStorageService, AppManifestService, AppPlatformTargetService, AppRegistryService, AppServiceLaunchService, FileLockService, isAppComponentManifestBundle } from "@nextclaw/app-runtime";
|
|
15
15
|
import { execFileSync, spawn } from "node:child_process";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
@@ -1393,26 +1393,26 @@ const SESSION_ACTIVITY_PREVIEW_STATUS_KINDS = new Set([
|
|
|
1393
1393
|
"run-failed",
|
|
1394
1394
|
"run-interrupted"
|
|
1395
1395
|
]);
|
|
1396
|
-
function isRecord$
|
|
1396
|
+
function isRecord$22(value) {
|
|
1397
1397
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1398
1398
|
}
|
|
1399
|
-
function readOptionalString$
|
|
1399
|
+
function readOptionalString$16(value) {
|
|
1400
1400
|
if (typeof value !== "string") return;
|
|
1401
1401
|
const trimmed = value.trim();
|
|
1402
1402
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
1403
1403
|
}
|
|
1404
1404
|
function readSessionActivityPreviewMetadata(value) {
|
|
1405
|
-
if (!isRecord$
|
|
1405
|
+
if (!isRecord$22(value)) return null;
|
|
1406
1406
|
const state = value.state;
|
|
1407
|
-
const timestamp = readOptionalString$
|
|
1407
|
+
const timestamp = readOptionalString$16(value.timestamp);
|
|
1408
1408
|
if (!SESSION_ACTIVITY_PREVIEW_STATES.has(state) || !timestamp) return null;
|
|
1409
|
-
const statusKind = readOptionalString$
|
|
1409
|
+
const statusKind = readOptionalString$16(value.statusKind);
|
|
1410
1410
|
return {
|
|
1411
1411
|
state,
|
|
1412
1412
|
timestamp,
|
|
1413
1413
|
statusKind: SESSION_ACTIVITY_PREVIEW_STATUS_KINDS.has(statusKind) ? statusKind : void 0,
|
|
1414
|
-
statusText: readOptionalString$
|
|
1415
|
-
replyText: readOptionalString$
|
|
1414
|
+
statusText: readOptionalString$16(value.statusText),
|
|
1415
|
+
replyText: readOptionalString$16(value.replyText)
|
|
1416
1416
|
};
|
|
1417
1417
|
}
|
|
1418
1418
|
function compareIsoTimestamp(left, right) {
|
|
@@ -1496,7 +1496,7 @@ var SessionActivityPreviewEventService = class {
|
|
|
1496
1496
|
//#endregion
|
|
1497
1497
|
//#region src/managers/agent-run-session-command.manager.ts
|
|
1498
1498
|
const CONTINUATION_PROMPT = "Continue from where you stopped. Preserve completed work and avoid repeating it.";
|
|
1499
|
-
function isRecord$
|
|
1499
|
+
function isRecord$21(value) {
|
|
1500
1500
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1501
1501
|
}
|
|
1502
1502
|
function hasSendableMessageContent(message) {
|
|
@@ -1504,7 +1504,7 @@ function hasSendableMessageContent(message) {
|
|
|
1504
1504
|
}
|
|
1505
1505
|
function readSessionActivityState(metadata) {
|
|
1506
1506
|
const preview = metadata?.[SESSION_ACTIVITY_PREVIEW_METADATA_KEY];
|
|
1507
|
-
return isRecord$
|
|
1507
|
+
return isRecord$21(preview) && typeof preview.state === "string" ? preview.state : null;
|
|
1508
1508
|
}
|
|
1509
1509
|
var AgentRunSessionCommandManager = class {
|
|
1510
1510
|
pendingCommands = /* @__PURE__ */ new Map();
|
|
@@ -1879,13 +1879,13 @@ function buildRunMetadata(params) {
|
|
|
1879
1879
|
}
|
|
1880
1880
|
//#endregion
|
|
1881
1881
|
//#region src/utils/agent-run-request.utils.ts
|
|
1882
|
-
function readOptionalString$
|
|
1882
|
+
function readOptionalString$15(value) {
|
|
1883
1883
|
if (typeof value !== "string") return;
|
|
1884
1884
|
return value.trim() || void 0;
|
|
1885
1885
|
}
|
|
1886
1886
|
function toAgentRunRequest(envelope) {
|
|
1887
1887
|
const metadata = envelope.metadata ?? {};
|
|
1888
|
-
const peerId = readOptionalString$
|
|
1888
|
+
const peerId = readOptionalString$15(envelope.peerId);
|
|
1889
1889
|
const requestMetadata = {
|
|
1890
1890
|
agentRuntimeId: metadata.agentRuntimeId,
|
|
1891
1891
|
agentId: metadata.agentId,
|
|
@@ -1897,10 +1897,10 @@ function toAgentRunRequest(envelope) {
|
|
|
1897
1897
|
maxTokens: metadata.maxTokens,
|
|
1898
1898
|
thinkingEffort: metadata.thinkingEffort,
|
|
1899
1899
|
delivery: envelope.delivery,
|
|
1900
|
-
idempotencyKey: readOptionalString$
|
|
1900
|
+
idempotencyKey: readOptionalString$15(envelope.idempotencyKey)
|
|
1901
1901
|
};
|
|
1902
1902
|
if (Array.isArray(envelope.content)) {
|
|
1903
|
-
const sessionId = readOptionalString$
|
|
1903
|
+
const sessionId = readOptionalString$15(envelope.sessionId);
|
|
1904
1904
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
1905
1905
|
return {
|
|
1906
1906
|
...requestMetadata,
|
|
@@ -1918,8 +1918,8 @@ function toAgentRunRequest(envelope) {
|
|
|
1918
1918
|
}
|
|
1919
1919
|
const sourceMessage = envelope.message;
|
|
1920
1920
|
if (!sourceMessage) throw new Error("Invalid agent run send request.");
|
|
1921
|
-
const envelopeSessionId = readOptionalString$
|
|
1922
|
-
const messageSessionId = readOptionalString$
|
|
1921
|
+
const envelopeSessionId = readOptionalString$15(envelope.sessionId);
|
|
1922
|
+
const messageSessionId = readOptionalString$15(sourceMessage.sessionId);
|
|
1923
1923
|
const sessionId = envelopeSessionId ?? messageSessionId;
|
|
1924
1924
|
if (sessionId && peerId) throw new Error("agent-run.send cannot accept both sessionId and peerId.");
|
|
1925
1925
|
return {
|
|
@@ -1980,7 +1980,7 @@ function readSessionMaterialization(metadata) {
|
|
|
1980
1980
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
1981
1981
|
const materialization = value;
|
|
1982
1982
|
if (materialization.kind !== "child") throw new Error("session_materialization.kind must be \"child\".");
|
|
1983
|
-
const parentSessionId = readOptionalString$
|
|
1983
|
+
const parentSessionId = readOptionalString$15(materialization.parentSessionId);
|
|
1984
1984
|
if (!parentSessionId) throw new Error("session_materialization.parentSessionId is required.");
|
|
1985
1985
|
if (materialization.inheritContext !== true) throw new Error("session_materialization.inheritContext must be true.");
|
|
1986
1986
|
return {
|
|
@@ -2185,15 +2185,15 @@ var AgentRuntimeRunObserverService = class {
|
|
|
2185
2185
|
};
|
|
2186
2186
|
//#endregion
|
|
2187
2187
|
//#region src/utils/agent-run-trigger.utils.ts
|
|
2188
|
-
function isRecord$
|
|
2188
|
+
function isRecord$20(value) {
|
|
2189
2189
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2190
2190
|
}
|
|
2191
|
-
function readOptionalString$
|
|
2191
|
+
function readOptionalString$14(value) {
|
|
2192
2192
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2193
2193
|
}
|
|
2194
2194
|
function readSourceRunSpec(message) {
|
|
2195
2195
|
const value = message.metadata?.[AGENT_RUN_MESSAGE_RUN_SPEC_METADATA_KEY];
|
|
2196
|
-
return isRecord$
|
|
2196
|
+
return isRecord$20(value) ? value : {};
|
|
2197
2197
|
}
|
|
2198
2198
|
const SOURCE_CONTEXT_KEYS = [
|
|
2199
2199
|
"channel",
|
|
@@ -2222,9 +2222,9 @@ function readSourceContext(request) {
|
|
|
2222
2222
|
function createAgentToolRunTriggerInput(params) {
|
|
2223
2223
|
const { request, source } = params;
|
|
2224
2224
|
const runSpec = readSourceRunSpec(request.message);
|
|
2225
|
-
const sourceSessionId = readOptionalString$
|
|
2226
|
-
const sourceRunId = readOptionalString$
|
|
2227
|
-
const sourceModel = readOptionalString$
|
|
2225
|
+
const sourceSessionId = readOptionalString$14(request.sessionId);
|
|
2226
|
+
const sourceRunId = readOptionalString$14(runSpec.runId);
|
|
2227
|
+
const sourceModel = readOptionalString$14(runSpec.model);
|
|
2228
2228
|
const sourceContext = readSourceContext(request);
|
|
2229
2229
|
return {
|
|
2230
2230
|
actor: "agent",
|
|
@@ -2240,9 +2240,9 @@ function createAgentToolRunTriggerInput(params) {
|
|
|
2240
2240
|
function createIngressRunTriggerInput(params) {
|
|
2241
2241
|
const { request } = params;
|
|
2242
2242
|
const source = request.channel ? `channel:${request.channel}` : params.source.trim() || "internal";
|
|
2243
|
-
const sourceSessionId = readOptionalString$
|
|
2243
|
+
const sourceSessionId = readOptionalString$14(request.sessionId);
|
|
2244
2244
|
const sourceContext = readSourceContext(request);
|
|
2245
|
-
const cronJobId = readOptionalString$
|
|
2245
|
+
const cronJobId = readOptionalString$14(request.metadata?.cron_job_id);
|
|
2246
2246
|
const isCron = request.metadata?.session_origin === "cron" || Boolean(cronJobId);
|
|
2247
2247
|
return {
|
|
2248
2248
|
actor: isCron ? "automation" : request.message.role === "user" ? "human" : request.message.role === "service" ? "automation" : "system",
|
|
@@ -2296,7 +2296,7 @@ function createRunTriggerMetadataEvent(params) {
|
|
|
2296
2296
|
};
|
|
2297
2297
|
}
|
|
2298
2298
|
function attachSourceToolCall(trigger, sourceToolCallId) {
|
|
2299
|
-
const normalizedToolCallId = readOptionalString$
|
|
2299
|
+
const normalizedToolCallId = readOptionalString$14(sourceToolCallId);
|
|
2300
2300
|
return {
|
|
2301
2301
|
...structuredClone(trigger),
|
|
2302
2302
|
...normalizedToolCallId ? { sourceToolCallId: normalizedToolCallId } : {}
|
|
@@ -2698,7 +2698,7 @@ const BUILTIN_RUNTIME_PRESENTATION = {
|
|
|
2698
2698
|
}
|
|
2699
2699
|
}
|
|
2700
2700
|
};
|
|
2701
|
-
function readString$
|
|
2701
|
+
function readString$12(value) {
|
|
2702
2702
|
if (typeof value !== "string") return;
|
|
2703
2703
|
return value.trim() || void 0;
|
|
2704
2704
|
}
|
|
@@ -2707,7 +2707,7 @@ function readRecord$3(value) {
|
|
|
2707
2707
|
return value;
|
|
2708
2708
|
}
|
|
2709
2709
|
function resolveBuiltinRuntimePresentation(value) {
|
|
2710
|
-
const normalized = readString$
|
|
2710
|
+
const normalized = readString$12(value)?.toLowerCase();
|
|
2711
2711
|
if (!normalized) return null;
|
|
2712
2712
|
if (!(normalized in BUILTIN_RUNTIME_PRESENTATION)) return null;
|
|
2713
2713
|
return BUILTIN_RUNTIME_PRESENTATION[normalized] ?? null;
|
|
@@ -2728,13 +2728,13 @@ function resolveAgentRuntimeEntries(params) {
|
|
|
2728
2728
|
entries.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, buildNativeRuntimeEntry(params.config));
|
|
2729
2729
|
for (const [rawId, rawEntry] of Object.entries(params.config.agents.runtimes.entries ?? {})) {
|
|
2730
2730
|
const id = rawId.trim().toLowerCase();
|
|
2731
|
-
const type = readString$
|
|
2731
|
+
const type = readString$12(rawEntry.type)?.toLowerCase();
|
|
2732
2732
|
if (!id || !type) continue;
|
|
2733
2733
|
const explicitIcon = normalizeAgentRuntimeSessionTypeIcon(rawEntry.icon);
|
|
2734
2734
|
const builtinPresentation = resolveBuiltinRuntimePresentation(id) ?? resolveBuiltinRuntimePresentation(type);
|
|
2735
2735
|
entries.set(id, {
|
|
2736
2736
|
id,
|
|
2737
|
-
label: readString$
|
|
2737
|
+
label: readString$12(rawEntry.label) ?? builtinPresentation?.label ?? id,
|
|
2738
2738
|
...explicitIcon ?? builtinPresentation?.icon ? { icon: explicitIcon ?? builtinPresentation?.icon } : {},
|
|
2739
2739
|
type,
|
|
2740
2740
|
enabled: rawEntry.enabled !== false,
|
|
@@ -3807,10 +3807,10 @@ function parseServiceAppManifest(raw, options = {}) {
|
|
|
3807
3807
|
} catch (error) {
|
|
3808
3808
|
throw new Error(`service-app.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
3809
3809
|
}
|
|
3810
|
-
if (!isRecord$
|
|
3810
|
+
if (!isRecord$19(parsed)) throw new Error("service-app.json must contain an object.");
|
|
3811
3811
|
const id = readRequiredString$8(parsed, "id");
|
|
3812
3812
|
if (!SERVICE_APP_ID_PATTERN$1.test(id)) throw new Error("service app id must be kebab-case.");
|
|
3813
|
-
const protocol = readOptionalString$
|
|
3813
|
+
const protocol = readOptionalString$13(parsed, "protocol") ?? "mcp";
|
|
3814
3814
|
if (protocol !== "mcp" && protocol !== "wasi-component") throw new Error("service app protocol must be mcp or wasi-component.");
|
|
3815
3815
|
const launch = protocol === "mcp" ? new AppServiceLaunchService(options.platformTargetService).resolve(parsed, options.target) : void 0;
|
|
3816
3816
|
const componentEntry = protocol === "wasi-component" ? readPortableComponentEntry(parsed) : void 0;
|
|
@@ -3821,7 +3821,7 @@ function parseServiceAppManifest(raw, options = {}) {
|
|
|
3821
3821
|
return {
|
|
3822
3822
|
id,
|
|
3823
3823
|
title: readRequiredString$8(parsed, "title"),
|
|
3824
|
-
description: readOptionalString$
|
|
3824
|
+
description: readOptionalString$13(parsed, "description"),
|
|
3825
3825
|
enabled: readOptionalBoolean$2(parsed, "enabled") ?? true,
|
|
3826
3826
|
protocol,
|
|
3827
3827
|
command: launch?.command,
|
|
@@ -3836,14 +3836,14 @@ function parseServiceAppManifest(raw, options = {}) {
|
|
|
3836
3836
|
}
|
|
3837
3837
|
function readServiceAppProvides(value) {
|
|
3838
3838
|
if (value === void 0) return void 0;
|
|
3839
|
-
if (!isRecord$
|
|
3839
|
+
if (!isRecord$19(value)) throw new Error("service app provides must be an object.");
|
|
3840
3840
|
if (value.capabilities === void 0) return void 0;
|
|
3841
3841
|
if (!Array.isArray(value.capabilities)) throw new Error("service app provides.capabilities must be an array.");
|
|
3842
3842
|
const seen = /* @__PURE__ */ new Set();
|
|
3843
3843
|
const capabilities = value.capabilities.map((entry, index) => {
|
|
3844
|
-
if (!isRecord$
|
|
3844
|
+
if (!isRecord$19(entry)) throw new Error(`service app provides.capabilities[${index}] must be an object.`);
|
|
3845
3845
|
const id = readRequirementIdentifier(entry, "id", `provides.capabilities[${index}].id`);
|
|
3846
|
-
const version = readOptionalString$
|
|
3846
|
+
const version = readOptionalString$13(entry, "version");
|
|
3847
3847
|
if (!version) throw new Error(`service app provides.capabilities[${index}].version is required.`);
|
|
3848
3848
|
const key = `${id}@${version}`;
|
|
3849
3849
|
if (seen.has(key)) throw new Error(`service app provides.capabilities contains duplicate ${key}.`);
|
|
@@ -3869,7 +3869,7 @@ function readCapabilityResourceTypes(value, index) {
|
|
|
3869
3869
|
}
|
|
3870
3870
|
function readServiceAppRequirements(value, protocol) {
|
|
3871
3871
|
if (value === void 0) return void 0;
|
|
3872
|
-
if (!isRecord$
|
|
3872
|
+
if (!isRecord$19(value)) throw new Error("service app requires must be an object.");
|
|
3873
3873
|
const capabilities = readCapabilityRequirements(value.capabilities, protocol);
|
|
3874
3874
|
const resources = readResourceRequirements(value.resources);
|
|
3875
3875
|
const modelSlots = readModelCapabilitySlots(value.modelSlots);
|
|
@@ -3893,7 +3893,7 @@ function readCapabilitySlots(value, name, hasModelLimits) {
|
|
|
3893
3893
|
const seen = /* @__PURE__ */ new Set();
|
|
3894
3894
|
return value.map((entry, index) => {
|
|
3895
3895
|
const field = `requires.${name}[${index}]`;
|
|
3896
|
-
if (!isRecord$
|
|
3896
|
+
if (!isRecord$19(entry)) throw new Error(`service app ${field} must be an object.`);
|
|
3897
3897
|
const allowed = hasModelLimits ? [
|
|
3898
3898
|
"id",
|
|
3899
3899
|
"title",
|
|
@@ -3935,9 +3935,9 @@ function readCapabilityRequirements(value, protocol) {
|
|
|
3935
3935
|
if (!Array.isArray(value)) throw new Error("service app requires.capabilities must be an array.");
|
|
3936
3936
|
const seen = /* @__PURE__ */ new Set();
|
|
3937
3937
|
return value.map((entry, index) => {
|
|
3938
|
-
if (!isRecord$
|
|
3938
|
+
if (!isRecord$19(entry)) throw new Error(`service app requires.capabilities[${index}] must be an object.`);
|
|
3939
3939
|
const id = readRequirementIdentifier(entry, "id", `requires.capabilities[${index}].id`);
|
|
3940
|
-
const version = readOptionalString$
|
|
3940
|
+
const version = readOptionalString$13(entry, "version");
|
|
3941
3941
|
const key = `${id}@${version ?? "*"}`;
|
|
3942
3942
|
if (seen.has(key)) throw new Error(`service app requires.capabilities contains duplicate ${key}.`);
|
|
3943
3943
|
seen.add(key);
|
|
@@ -3950,19 +3950,19 @@ function readCapabilityRequirements(value, protocol) {
|
|
|
3950
3950
|
version,
|
|
3951
3951
|
provider,
|
|
3952
3952
|
wit,
|
|
3953
|
-
title: readOptionalString$
|
|
3954
|
-
description: readOptionalString$
|
|
3953
|
+
title: readOptionalString$13(entry, "title"),
|
|
3954
|
+
description: readOptionalString$13(entry, "description"),
|
|
3955
3955
|
remediation: readExternalRemediation(entry.remediation, `requires.capabilities[${index}]`)
|
|
3956
3956
|
};
|
|
3957
3957
|
});
|
|
3958
3958
|
}
|
|
3959
3959
|
function readWitContract(value, fieldName, role) {
|
|
3960
3960
|
if (value === void 0) return void 0;
|
|
3961
|
-
if (!isRecord$
|
|
3962
|
-
const packageName = readOptionalString$
|
|
3961
|
+
if (!isRecord$19(value)) throw new Error(`service app ${fieldName} must be an object.`);
|
|
3962
|
+
const packageName = readOptionalString$13(value, "package");
|
|
3963
3963
|
if (!packageName || !WIT_PACKAGE_PATTERN.test(packageName)) throw new Error(`service app ${fieldName}.package must be a WIT package identifier.`);
|
|
3964
3964
|
const interfaceName = readRequirementIdentifier(value, "interface", `${fieldName}.interface`);
|
|
3965
|
-
const version = readOptionalString$
|
|
3965
|
+
const version = readOptionalString$13(value, "version");
|
|
3966
3966
|
if (!version) throw new Error(`service app ${fieldName}.version is required.`);
|
|
3967
3967
|
if (role === "provider" && !SEMVER_VERSION_PATTERN.test(version)) throw new Error(`service app ${fieldName}.version must be an exact semver version for a Provider.`);
|
|
3968
3968
|
if (role === "consumer" && !isSemverRange(version)) throw new Error(`service app ${fieldName}.version must be a semver range for a Consumer.`);
|
|
@@ -3985,7 +3985,7 @@ function readResourceRequirements(value) {
|
|
|
3985
3985
|
if (!Array.isArray(value)) throw new Error("service app requires.resources must be an array.");
|
|
3986
3986
|
const seen = /* @__PURE__ */ new Set();
|
|
3987
3987
|
return value.map((entry, index) => {
|
|
3988
|
-
if (!isRecord$
|
|
3988
|
+
if (!isRecord$19(entry)) throw new Error(`service app requires.resources[${index}] must be an object.`);
|
|
3989
3989
|
const binding = readRequirementIdentifier(entry, "binding", `requires.resources[${index}].binding`);
|
|
3990
3990
|
if (seen.has(binding)) throw new Error(`service app requires.resources contains duplicate binding ${binding}.`);
|
|
3991
3991
|
seen.add(binding);
|
|
@@ -3993,21 +3993,21 @@ function readResourceRequirements(value) {
|
|
|
3993
3993
|
binding,
|
|
3994
3994
|
type: readRequirementIdentifier(entry, "type", `requires.resources[${index}].type`),
|
|
3995
3995
|
required: readOptionalBoolean$2(entry, "required") ?? true,
|
|
3996
|
-
title: readOptionalString$
|
|
3997
|
-
description: readOptionalString$
|
|
3996
|
+
title: readOptionalString$13(entry, "title"),
|
|
3997
|
+
description: readOptionalString$13(entry, "description"),
|
|
3998
3998
|
remediation: readExternalRemediation(entry.remediation, `requires.resources[${index}]`)
|
|
3999
3999
|
};
|
|
4000
4000
|
});
|
|
4001
4001
|
}
|
|
4002
4002
|
function readRequirementIdentifier(record, key, fieldName) {
|
|
4003
|
-
const value = readOptionalString$
|
|
4003
|
+
const value = readOptionalString$13(record, key);
|
|
4004
4004
|
if (!value || !/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/.test(value)) throw new Error(`service app ${fieldName} must be a lowercase identifier.`);
|
|
4005
4005
|
return value;
|
|
4006
4006
|
}
|
|
4007
4007
|
function readExternalRemediation(value, fieldPrefix) {
|
|
4008
4008
|
if (value === void 0) return void 0;
|
|
4009
|
-
if (!isRecord$
|
|
4010
|
-
const summary = readOptionalString$
|
|
4009
|
+
if (!isRecord$19(value) || value.kind !== "agent-setup") throw new Error(`service app ${fieldPrefix}.remediation.kind must be agent-setup.`);
|
|
4010
|
+
const summary = readOptionalString$13(value, "summary");
|
|
4011
4011
|
if (!summary) throw new Error(`service app ${fieldPrefix}.remediation.summary is required.`);
|
|
4012
4012
|
return {
|
|
4013
4013
|
kind: "agent-setup",
|
|
@@ -4017,8 +4017,8 @@ function readExternalRemediation(value, fieldPrefix) {
|
|
|
4017
4017
|
}
|
|
4018
4018
|
function readServiceAppLifecycle(value) {
|
|
4019
4019
|
if (value === void 0) return { mode: "action" };
|
|
4020
|
-
if (!isRecord$
|
|
4021
|
-
const mode = readOptionalString$
|
|
4020
|
+
if (!isRecord$19(value)) throw new Error("service app lifecycle must be an object.");
|
|
4021
|
+
const mode = readOptionalString$13(value, "mode") ?? "action";
|
|
4022
4022
|
if (mode === "action") return { mode };
|
|
4023
4023
|
if (mode === "provider") return { mode };
|
|
4024
4024
|
if (mode !== "resident") throw new Error("service app lifecycle.mode must be action, resident or provider.");
|
|
@@ -4039,13 +4039,13 @@ function readProviderIds(value) {
|
|
|
4039
4039
|
return Array.from(new Set(providerIds));
|
|
4040
4040
|
}
|
|
4041
4041
|
function readServiceAppId(record, key, fieldName) {
|
|
4042
|
-
const value = readOptionalString$
|
|
4042
|
+
const value = readOptionalString$13(record, key);
|
|
4043
4043
|
if (!value || !SERVICE_APP_ID_PATTERN$1.test(value)) throw new Error(`service app ${fieldName} must be a kebab-case service app id.`);
|
|
4044
4044
|
return value;
|
|
4045
4045
|
}
|
|
4046
4046
|
function readPortableComponentEntry(record) {
|
|
4047
4047
|
const component = record.component;
|
|
4048
|
-
if (!isRecord$
|
|
4048
|
+
if (!isRecord$19(component)) throw new Error("service app component is required for wasi-component.");
|
|
4049
4049
|
const entry = readRequiredString$8(component, "entry").replace(/\\/g, "/");
|
|
4050
4050
|
if (path.isAbsolute(entry) || entry.includes("\0") || entry.split("/").includes("..")) throw new Error("service app component.entry must be a package-relative path.");
|
|
4051
4051
|
if (!entry.endsWith(".wasm")) throw new Error("service app component.entry must reference a .wasm file.");
|
|
@@ -4053,22 +4053,22 @@ function readPortableComponentEntry(record) {
|
|
|
4053
4053
|
}
|
|
4054
4054
|
function readManifestActions(value) {
|
|
4055
4055
|
if (value === void 0) throw new Error("service app actions are required.");
|
|
4056
|
-
if (!isRecord$
|
|
4056
|
+
if (!isRecord$19(value)) throw new Error("service app actions must be an object.");
|
|
4057
4057
|
if (Object.keys(value).length === 0) throw new Error("service app actions cannot be empty.");
|
|
4058
4058
|
const actions = {};
|
|
4059
4059
|
for (const [name, action] of Object.entries(value)) {
|
|
4060
4060
|
if (!name.trim()) throw new Error("service app action name cannot be empty.");
|
|
4061
|
-
if (!isRecord$
|
|
4062
|
-
const risk = readOptionalString$
|
|
4061
|
+
if (!isRecord$19(action)) throw new Error(`service app action ${name} must be an object.`);
|
|
4062
|
+
const risk = readOptionalString$13(action, "risk");
|
|
4063
4063
|
if (risk !== void 0 && !SERVICE_ACTION_RISKS.has(risk)) throw new Error(`service app action ${name} has invalid risk.`);
|
|
4064
4064
|
const inputSchema = action.inputSchema;
|
|
4065
|
-
if (inputSchema !== void 0 && !isRecord$
|
|
4065
|
+
if (inputSchema !== void 0 && !isRecord$19(inputSchema)) throw new Error(`service app action ${name} inputSchema must be an object.`);
|
|
4066
4066
|
const timeoutMs = readOptionalNumber$1(action, "timeoutMs");
|
|
4067
4067
|
if (timeoutMs !== void 0 && (!Number.isInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 3e5)) throw new Error(`service app action ${name} timeoutMs must be an integer between 100 and 300000.`);
|
|
4068
4068
|
actions[name] = {
|
|
4069
4069
|
risk,
|
|
4070
|
-
title: readOptionalString$
|
|
4071
|
-
description: readOptionalString$
|
|
4070
|
+
title: readOptionalString$13(action, "title"),
|
|
4071
|
+
description: readOptionalString$13(action, "description"),
|
|
4072
4072
|
inputSchema,
|
|
4073
4073
|
timeoutMs
|
|
4074
4074
|
};
|
|
@@ -4076,7 +4076,7 @@ function readManifestActions(value) {
|
|
|
4076
4076
|
return actions;
|
|
4077
4077
|
}
|
|
4078
4078
|
function readRequiredString$8(record, key) {
|
|
4079
|
-
const value = readOptionalString$
|
|
4079
|
+
const value = readOptionalString$13(record, key);
|
|
4080
4080
|
if (!value) throw new Error(`service app ${key} is required.`);
|
|
4081
4081
|
return value;
|
|
4082
4082
|
}
|
|
@@ -4084,7 +4084,7 @@ function readRequiredBoolean(record, key) {
|
|
|
4084
4084
|
if (typeof record[key] !== "boolean") throw new Error(`service app ${key} is required and must be a boolean.`);
|
|
4085
4085
|
return record[key];
|
|
4086
4086
|
}
|
|
4087
|
-
function readOptionalString$
|
|
4087
|
+
function readOptionalString$13(record, key) {
|
|
4088
4088
|
return typeof record[key] === "string" && record[key].trim() ? record[key].trim() : void 0;
|
|
4089
4089
|
}
|
|
4090
4090
|
function readOptionalBoolean$2(record, key) {
|
|
@@ -4097,7 +4097,7 @@ function readOptionalNumber$1(record, key) {
|
|
|
4097
4097
|
if (typeof record[key] !== "number") throw new Error(`service app ${key} must be number.`);
|
|
4098
4098
|
return record[key];
|
|
4099
4099
|
}
|
|
4100
|
-
function isRecord$
|
|
4100
|
+
function isRecord$19(value) {
|
|
4101
4101
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4102
4102
|
}
|
|
4103
4103
|
//#endregion
|
|
@@ -5856,14 +5856,14 @@ var ExtensionLifecycleService = class {
|
|
|
5856
5856
|
};
|
|
5857
5857
|
//#endregion
|
|
5858
5858
|
//#region src/features/extension-runtime/utils/extension-runtime-payload.utils.ts
|
|
5859
|
-
function readString$
|
|
5859
|
+
function readString$11(value) {
|
|
5860
5860
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
5861
5861
|
}
|
|
5862
5862
|
function readRecord$2(value) {
|
|
5863
5863
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5864
5864
|
}
|
|
5865
5865
|
function readRequiredString$7(value, name) {
|
|
5866
|
-
const trimmed = readString$
|
|
5866
|
+
const trimmed = readString$11(value);
|
|
5867
5867
|
if (!trimmed) throw new Error(`${name} is required`);
|
|
5868
5868
|
return trimmed;
|
|
5869
5869
|
}
|
|
@@ -5878,16 +5878,16 @@ function readTextContent(value) {
|
|
|
5878
5878
|
function readInboundAttachments(value) {
|
|
5879
5879
|
if (!Array.isArray(value)) return [];
|
|
5880
5880
|
return value.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))).map((entry) => ({
|
|
5881
|
-
...readString$
|
|
5882
|
-
...readString$
|
|
5883
|
-
...readString$
|
|
5884
|
-
...readString$
|
|
5885
|
-
...readString$
|
|
5886
|
-
...readString$
|
|
5881
|
+
...readString$11(entry.id) ? { id: readString$11(entry.id) } : {},
|
|
5882
|
+
...readString$11(entry.name) ? { name: readString$11(entry.name) } : {},
|
|
5883
|
+
...readString$11(entry.path) ? { path: readString$11(entry.path) } : {},
|
|
5884
|
+
...readString$11(entry.url) ? { url: readString$11(entry.url) } : {},
|
|
5885
|
+
...readString$11(entry.assetUri) ? { assetUri: readString$11(entry.assetUri) } : {},
|
|
5886
|
+
...readString$11(entry.mimeType) ? { mimeType: readString$11(entry.mimeType) } : {},
|
|
5887
5887
|
...readOptionalNumber(entry.size) !== void 0 ? { size: readOptionalNumber(entry.size) } : {},
|
|
5888
|
-
...readString$
|
|
5888
|
+
...readString$11(entry.source) ? { source: readString$11(entry.source) } : {},
|
|
5889
5889
|
...entry.status === "ready" || entry.status === "remote-only" ? { status: entry.status } : {},
|
|
5890
|
-
...readString$
|
|
5890
|
+
...readString$11(entry.errorCode) ? { errorCode: readString$11(entry.errorCode) } : {}
|
|
5891
5891
|
}));
|
|
5892
5892
|
}
|
|
5893
5893
|
function toInboundMessage(value) {
|
|
@@ -5919,7 +5919,7 @@ function normalizeAuthPollResult(value) {
|
|
|
5919
5919
|
return {
|
|
5920
5920
|
channel: readRequiredString$7(record.channel, "channel"),
|
|
5921
5921
|
status: record.status,
|
|
5922
|
-
message: readString$
|
|
5922
|
+
message: readString$11(record.message),
|
|
5923
5923
|
nextPollMs: readOptionalNumber(record.nextPollMs),
|
|
5924
5924
|
accountId: typeof record.accountId === "string" ? record.accountId : null,
|
|
5925
5925
|
notes: Array.isArray(record.notes) ? record.notes.filter((note) => typeof note === "string") : [],
|
|
@@ -5953,10 +5953,10 @@ var ExtensionIngressDiagnosticsService = class {
|
|
|
5953
5953
|
event: readRequiredString$7(payload.event, "event"),
|
|
5954
5954
|
component: readRequiredString$7(payload.component, "component"),
|
|
5955
5955
|
outcome: readRequiredString$7(payload.outcome, "outcome"),
|
|
5956
|
-
correlationId: readString$
|
|
5957
|
-
parentCorrelationId: readString$
|
|
5958
|
-
reasonCode: readString$
|
|
5959
|
-
providerCode: readString$
|
|
5956
|
+
correlationId: readString$11(payload.correlationId),
|
|
5957
|
+
parentCorrelationId: readString$11(payload.parentCorrelationId),
|
|
5958
|
+
reasonCode: readString$11(payload.reasonCode),
|
|
5959
|
+
providerCode: readString$11(payload.providerCode),
|
|
5960
5960
|
durationMs: readOptionalNumber(payload.durationMs),
|
|
5961
5961
|
attempt: readOptionalNumber(payload.attempt),
|
|
5962
5962
|
facts: {
|
|
@@ -6100,12 +6100,12 @@ var ExtensionAuthLeaseService = class {
|
|
|
6100
6100
|
if (kind === "channel.auth.poll") {
|
|
6101
6101
|
const sessionId = readRequiredString$7(payload.sessionId, "sessionId");
|
|
6102
6102
|
const result = value ? readRecord$2(value) : null;
|
|
6103
|
-
const status = result ? readString$
|
|
6103
|
+
const status = result ? readString$11(result.status) : null;
|
|
6104
6104
|
if (status === "authorized") await this.retainHandoff(extensionId, channelId, generation);
|
|
6105
6105
|
if (!result || status === "authorized" || status === "expired" || status === "error") this.releaseSession(extensionId, sessionId);
|
|
6106
6106
|
return;
|
|
6107
6107
|
}
|
|
6108
|
-
if (kind === "channel.auth.connect" && readString$
|
|
6108
|
+
if (kind === "channel.auth.connect" && readString$11(readRecord$2(value).status) === "authorized") {
|
|
6109
6109
|
await this.retainHandoff(extensionId, channelId, generation);
|
|
6110
6110
|
return;
|
|
6111
6111
|
}
|
|
@@ -6224,7 +6224,7 @@ const BUILTIN_EXTENSION_PACKAGES = [
|
|
|
6224
6224
|
"@nextclaw/channel-extension-weixin"
|
|
6225
6225
|
];
|
|
6226
6226
|
const runtimeRequire = createRequire(import.meta.url);
|
|
6227
|
-
function readString$
|
|
6227
|
+
function readString$10(value) {
|
|
6228
6228
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
6229
6229
|
}
|
|
6230
6230
|
function readStringArray$1(value) {
|
|
@@ -6273,16 +6273,16 @@ function toManifest(value, rootDir) {
|
|
|
6273
6273
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("extension manifest must be an object");
|
|
6274
6274
|
const record = value;
|
|
6275
6275
|
const server = readRecord$1(record.server);
|
|
6276
|
-
const id = readString$
|
|
6277
|
-
const command = readString$
|
|
6276
|
+
const id = readString$10(record.id);
|
|
6277
|
+
const command = readString$10(server.command);
|
|
6278
6278
|
if (!id) throw new Error("extension manifest id is required");
|
|
6279
6279
|
if (server.type !== "stdio") throw new Error("extension server.type must be stdio");
|
|
6280
6280
|
if (!command) throw new Error("extension server.command is required");
|
|
6281
6281
|
return {
|
|
6282
6282
|
id,
|
|
6283
6283
|
rootDir,
|
|
6284
|
-
...readString$
|
|
6285
|
-
...readString$
|
|
6284
|
+
...readString$10(record.name) ? { name: readString$10(record.name) } : {},
|
|
6285
|
+
...readString$10(record.version) ? { version: readString$10(record.version) } : {},
|
|
6286
6286
|
server: {
|
|
6287
6287
|
type: "stdio",
|
|
6288
6288
|
command,
|
|
@@ -6478,13 +6478,13 @@ var ExtensionObservationRuntimeService = class {
|
|
|
6478
6478
|
eventId,
|
|
6479
6479
|
eventType,
|
|
6480
6480
|
occurredAt,
|
|
6481
|
-
observedAt: readString$
|
|
6482
|
-
...readString$
|
|
6483
|
-
...readString$
|
|
6481
|
+
observedAt: readString$11(event.observedAt) ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
6482
|
+
...readString$11(event.cursor) ? { cursor: readString$11(event.cursor) } : {},
|
|
6483
|
+
...readString$11(event.dedupeKey) ? { dedupeKey: readString$11(event.dedupeKey) } : {},
|
|
6484
6484
|
payload: event.payload,
|
|
6485
6485
|
...Array.isArray(event.sourceRefs) && event.sourceRefs.every((value) => typeof value === "string") ? { sourceRefs: event.sourceRefs } : {},
|
|
6486
|
-
...readString$
|
|
6487
|
-
...readString$
|
|
6486
|
+
...readString$11(event.causationId) ? { causationId: readString$11(event.causationId) } : {},
|
|
6487
|
+
...readString$11(event.correlationId) ? { correlationId: readString$11(event.correlationId) } : {}
|
|
6488
6488
|
}
|
|
6489
6489
|
}) ?? { accepted: false };
|
|
6490
6490
|
};
|
|
@@ -6569,13 +6569,13 @@ function stableStringify(value) {
|
|
|
6569
6569
|
}
|
|
6570
6570
|
function sortValue(value) {
|
|
6571
6571
|
if (Array.isArray(value)) return value.map(sortValue);
|
|
6572
|
-
if (!isRecord$
|
|
6572
|
+
if (!isRecord$18(value)) return value;
|
|
6573
6573
|
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortValue(value[key])]));
|
|
6574
6574
|
}
|
|
6575
6575
|
function normalizeJsonValue(value) {
|
|
6576
6576
|
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
|
|
6577
6577
|
if (Array.isArray(value)) return value.map(normalizeJsonValue);
|
|
6578
|
-
if (isRecord$
|
|
6578
|
+
if (isRecord$18(value)) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, normalizeJsonValue(item)]));
|
|
6579
6579
|
throw new Error("Capability grant target must be JSON-compatible.");
|
|
6580
6580
|
}
|
|
6581
6581
|
function requireString$1(value, field) {
|
|
@@ -6583,7 +6583,7 @@ function requireString$1(value, field) {
|
|
|
6583
6583
|
if (!normalized) throw new Error(`Capability grant ${field} is required.`);
|
|
6584
6584
|
return normalized;
|
|
6585
6585
|
}
|
|
6586
|
-
function isRecord$
|
|
6586
|
+
function isRecord$18(value) {
|
|
6587
6587
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6588
6588
|
}
|
|
6589
6589
|
//#endregion
|
|
@@ -7063,10 +7063,10 @@ function toGrantRecord(grants) {
|
|
|
7063
7063
|
}));
|
|
7064
7064
|
}
|
|
7065
7065
|
function normalizeStoreData(value) {
|
|
7066
|
-
if (!isRecord$
|
|
7066
|
+
if (!isRecord$17(value) || value.version !== 1 || !isRecord$17(value.grants)) throw new Error("Capability grant store is invalid.");
|
|
7067
7067
|
const grants = [];
|
|
7068
7068
|
for (const grant of Object.values(value.grants)) {
|
|
7069
|
-
if (!isRecord$
|
|
7069
|
+
if (!isRecord$17(grant) || !isRecord$17(grant.subject) || !isRecord$17(grant.resource) || !Array.isArray(grant.access) || !grant.access.every((item) => typeof item === "string") || typeof grant.declarationFingerprint !== "string" || typeof grant.grantedAt !== "string") throw new Error("Capability grant store contains an invalid grant.");
|
|
7070
7070
|
const request = normalizeCapabilityGrantRequest({
|
|
7071
7071
|
subject: {
|
|
7072
7072
|
type: String(grant.subject.type ?? ""),
|
|
@@ -7090,11 +7090,11 @@ function normalizeStoreData(value) {
|
|
|
7090
7090
|
grants: toGrantRecord(grants)
|
|
7091
7091
|
};
|
|
7092
7092
|
}
|
|
7093
|
-
function isRecord$
|
|
7093
|
+
function isRecord$17(value) {
|
|
7094
7094
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
7095
7095
|
}
|
|
7096
7096
|
function isMissingFileError$1(error) {
|
|
7097
|
-
return isRecord$
|
|
7097
|
+
return isRecord$17(error) && error.code === "ENOENT";
|
|
7098
7098
|
}
|
|
7099
7099
|
//#endregion
|
|
7100
7100
|
//#region src/features/capability-grants/managers/capability-grant.manager.ts
|
|
@@ -7598,10 +7598,10 @@ var DesktopNodeReplService = class {
|
|
|
7598
7598
|
}
|
|
7599
7599
|
async handleWorkerMessage(key, worker, value) {
|
|
7600
7600
|
const message = asRecord$1(value);
|
|
7601
|
-
const executionId = readString$
|
|
7601
|
+
const executionId = readString$9(message.executionId);
|
|
7602
7602
|
if (!executionId || !worker.pending.has(executionId)) return;
|
|
7603
7603
|
if (message.type === "desktop.request") {
|
|
7604
|
-
const requestId = readString$
|
|
7604
|
+
const requestId = readString$9(message.requestId);
|
|
7605
7605
|
if (!requestId) return;
|
|
7606
7606
|
try {
|
|
7607
7607
|
const result = await this.invokeDesktop(worker.pending.get(executionId).caller, message.operation, message.args);
|
|
@@ -7632,7 +7632,7 @@ var DesktopNodeReplService = class {
|
|
|
7632
7632
|
}
|
|
7633
7633
|
if (message.type === "error") {
|
|
7634
7634
|
const error = asRecord$1(message.error);
|
|
7635
|
-
this.reject(worker, executionId, replError(readString$
|
|
7635
|
+
this.reject(worker, executionId, replError(readString$9(error.code) ?? "repl_execution_failed", readString$9(error.message) ?? "node_repl execution failed."));
|
|
7636
7636
|
return;
|
|
7637
7637
|
}
|
|
7638
7638
|
this.stopWorker(key, worker);
|
|
@@ -7778,7 +7778,7 @@ function readKeyboardModifiers(value) {
|
|
|
7778
7778
|
if (new Set(value).size !== value.length) throw replError("invalid_tool_arguments", "modifiers cannot contain duplicates.");
|
|
7779
7779
|
return value;
|
|
7780
7780
|
}
|
|
7781
|
-
function readString$
|
|
7781
|
+
function readString$9(value) {
|
|
7782
7782
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
7783
7783
|
}
|
|
7784
7784
|
function trimOutput(value) {
|
|
@@ -8249,9 +8249,9 @@ var ExtensionDesktopRuntimeService = class {
|
|
|
8249
8249
|
method: readRequiredString$7(payload.method, "method"),
|
|
8250
8250
|
payload: readRecord$2(payload.payload),
|
|
8251
8251
|
caller: {
|
|
8252
|
-
...readString$
|
|
8253
|
-
...readString$
|
|
8254
|
-
...readString$
|
|
8252
|
+
...readString$11(caller.sessionId) ? { sessionId: readString$11(caller.sessionId) } : {},
|
|
8253
|
+
...readString$11(caller.agentRunId) ? { agentRunId: readString$11(caller.agentRunId) } : {},
|
|
8254
|
+
...readString$11(caller.subscriptionId) ? { subscriptionId: readString$11(caller.subscriptionId) } : {}
|
|
8255
8255
|
}
|
|
8256
8256
|
});
|
|
8257
8257
|
};
|
|
@@ -8392,7 +8392,7 @@ var ExtensionRuntimeService = class {
|
|
|
8392
8392
|
const desired = /* @__PURE__ */ new Map();
|
|
8393
8393
|
const channelConfig = readRecord$2(config.channels);
|
|
8394
8394
|
for (const manifest of this.manifests) for (const channel of manifest.contributes?.channels ?? []) {
|
|
8395
|
-
const channelId = readString$
|
|
8395
|
+
const channelId = readString$11(channel.id);
|
|
8396
8396
|
if (!channelId || readRecord$2(channelConfig[channelId]).enabled !== true) continue;
|
|
8397
8397
|
desired.set(this.persistentLeaseKey(manifest.id, channelId), {
|
|
8398
8398
|
manifest,
|
|
@@ -8469,15 +8469,15 @@ var ExtensionRuntimeService = class {
|
|
|
8469
8469
|
channel,
|
|
8470
8470
|
chatId,
|
|
8471
8471
|
senderId,
|
|
8472
|
-
content: readString$
|
|
8472
|
+
content: readString$11(payload.rawText) ?? readString$11(payload.commandName) ?? "",
|
|
8473
8473
|
timestamp: /* @__PURE__ */ new Date(),
|
|
8474
8474
|
attachments: [],
|
|
8475
8475
|
metadata
|
|
8476
8476
|
},
|
|
8477
|
-
forcedAgentId: readString$
|
|
8478
|
-
sessionKeyOverride: readString$
|
|
8477
|
+
forcedAgentId: readString$11(metadata.target_agent_id),
|
|
8478
|
+
sessionKeyOverride: readString$11(metadata.session_key_override)
|
|
8479
8479
|
});
|
|
8480
|
-
const rawText = readString$
|
|
8480
|
+
const rawText = readString$11(payload.rawText);
|
|
8481
8481
|
if (rawText) return await registry.executeText(rawText, {
|
|
8482
8482
|
channel,
|
|
8483
8483
|
chatId,
|
|
@@ -8510,7 +8510,7 @@ var ExtensionRuntimeService = class {
|
|
|
8510
8510
|
this.pendingRequests.delete(requestId);
|
|
8511
8511
|
pending.cleanup();
|
|
8512
8512
|
if (payload.ok === false) {
|
|
8513
|
-
const message = readString$
|
|
8513
|
+
const message = readString$11(readRecord$2(payload.error).message) ?? "Extension request failed";
|
|
8514
8514
|
pending.reject(new Error(message));
|
|
8515
8515
|
return { accepted: true };
|
|
8516
8516
|
}
|
|
@@ -8621,9 +8621,9 @@ var ExtensionRuntimeService = class {
|
|
|
8621
8621
|
};
|
|
8622
8622
|
assertAuthorized = (envelope, context) => {
|
|
8623
8623
|
const credential = this.lifecycle.authenticateCredential({
|
|
8624
|
-
extensionId: readString$
|
|
8625
|
-
generation: readString$
|
|
8626
|
-
token: readString$
|
|
8624
|
+
extensionId: readString$11(envelope.extensionId) ?? null,
|
|
8625
|
+
generation: readString$11(envelope.generation) ?? null,
|
|
8626
|
+
token: readString$11(context.token) ?? null
|
|
8627
8627
|
});
|
|
8628
8628
|
if (!credential) throw new Error("Unauthorized ingress token");
|
|
8629
8629
|
return credential;
|
|
@@ -8765,11 +8765,11 @@ var ExtensionManager = class {
|
|
|
8765
8765
|
//#endregion
|
|
8766
8766
|
//#region src/utils/model-message-vision.utils.ts
|
|
8767
8767
|
const IMAGE_OMITTED_TEXT = "[Image omitted: the selected model is not configured for vision input.]";
|
|
8768
|
-
function isRecord$
|
|
8768
|
+
function isRecord$16(value) {
|
|
8769
8769
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8770
8770
|
}
|
|
8771
8771
|
function isImageContentPart(value) {
|
|
8772
|
-
if (!isRecord$
|
|
8772
|
+
if (!isRecord$16(value)) return false;
|
|
8773
8773
|
const type = value.type;
|
|
8774
8774
|
return type === "image_url" || type === "input_image";
|
|
8775
8775
|
}
|
|
@@ -8785,7 +8785,7 @@ function normalizeContentWithoutVision(content) {
|
|
|
8785
8785
|
};
|
|
8786
8786
|
});
|
|
8787
8787
|
if (!sawImage) return content;
|
|
8788
|
-
const textParts = parts.filter((part) => isRecord$
|
|
8788
|
+
const textParts = parts.filter((part) => isRecord$16(part) && part.type === "text" && typeof part.text === "string").map((part) => part.text.trim()).filter(Boolean);
|
|
8789
8789
|
if (textParts.length === parts.length) return textParts.join("\n\n");
|
|
8790
8790
|
return parts;
|
|
8791
8791
|
}
|
|
@@ -10344,14 +10344,14 @@ function parsePanelAppFolderManifest(raw) {
|
|
|
10344
10344
|
} catch (error) {
|
|
10345
10345
|
throw new Error(`panel-app.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
10346
10346
|
}
|
|
10347
|
-
if (!isRecord$
|
|
10348
|
-
const id = readOptionalString$
|
|
10347
|
+
if (!isRecord$15(parsed)) throw new Error("panel-app.json must contain an object.");
|
|
10348
|
+
const id = readOptionalString$12(parsed, "id");
|
|
10349
10349
|
if (id && !PANEL_APP_ID_PATTERN.test(id)) throw new Error("panel app id must be kebab-case.");
|
|
10350
10350
|
return {
|
|
10351
10351
|
id,
|
|
10352
10352
|
title: readRequiredString$6(parsed, "title"),
|
|
10353
|
-
description: readOptionalString$
|
|
10354
|
-
icon: readOptionalString$
|
|
10353
|
+
description: readOptionalString$12(parsed, "description"),
|
|
10354
|
+
icon: readOptionalString$12(parsed, "icon"),
|
|
10355
10355
|
entry: readRequiredString$6(parsed, "entry"),
|
|
10356
10356
|
capabilities: readStringArray(parsed.capabilities, "capabilities"),
|
|
10357
10357
|
client: readOptionalBoolean$1(parsed, "client"),
|
|
@@ -10413,11 +10413,11 @@ function parseTokenList(content) {
|
|
|
10413
10413
|
return [...new Set(content.split(/[,\s]+/).map((entry) => entry.trim()).filter(Boolean))];
|
|
10414
10414
|
}
|
|
10415
10415
|
function readRequiredString$6(record, key) {
|
|
10416
|
-
const value = readOptionalString$
|
|
10416
|
+
const value = readOptionalString$12(record, key);
|
|
10417
10417
|
if (!value) throw new Error(`panel app ${key} is required.`);
|
|
10418
10418
|
return value;
|
|
10419
10419
|
}
|
|
10420
|
-
function readOptionalString$
|
|
10420
|
+
function readOptionalString$12(record, key) {
|
|
10421
10421
|
return typeof record[key] === "string" && record[key].trim() ? record[key].trim() : void 0;
|
|
10422
10422
|
}
|
|
10423
10423
|
function readOptionalBoolean$1(record, key) {
|
|
@@ -10431,7 +10431,7 @@ function readStringArray(value, key) {
|
|
|
10431
10431
|
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new Error(`panel app ${key} must be a string array.`);
|
|
10432
10432
|
return [...new Set(value.map((entry) => entry.trim()).filter(Boolean))];
|
|
10433
10433
|
}
|
|
10434
|
-
function isRecord$
|
|
10434
|
+
function isRecord$15(value) {
|
|
10435
10435
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
10436
10436
|
}
|
|
10437
10437
|
function normalizeTextValue(value) {
|
|
@@ -10931,7 +10931,7 @@ const PANEL_APP_AGENT_MAX_CONTEXT_CHARS = 8e4;
|
|
|
10931
10931
|
function normalizePanelAppGenerateObjectInput(input) {
|
|
10932
10932
|
const peerId = input.peerId.trim();
|
|
10933
10933
|
const prompt = input.prompt.trim();
|
|
10934
|
-
if (!peerId || !prompt || !isRecord$
|
|
10934
|
+
if (!peerId || !prompt || !isRecord$14(input.schema)) throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "invalid generateObject request");
|
|
10935
10935
|
if (prompt.length > PANEL_APP_AGENT_MAX_PROMPT_CHARS) throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "generateObject prompt is too large");
|
|
10936
10936
|
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");
|
|
10937
10937
|
return {
|
|
@@ -11072,7 +11072,7 @@ function readStructuredResultEvent(event, resultToolCallId) {
|
|
|
11072
11072
|
};
|
|
11073
11073
|
}
|
|
11074
11074
|
function assertToolResultContent(content) {
|
|
11075
|
-
if (!isRecord$
|
|
11075
|
+
if (!isRecord$14(content) || content.ok !== false || !isRecord$14(content.error)) return;
|
|
11076
11076
|
if (content.error.code === "invalid_tool_arguments") throw new PanelAppError("AGENT_OBJECT_RESULT_SCHEMA_INVALID", "agent object result did not match the schema");
|
|
11077
11077
|
throw new PanelAppError("AGENT_OBJECT_REQUEST_FAILED", typeof content.error.message === "string" ? content.error.message : "agent object request failed");
|
|
11078
11078
|
}
|
|
@@ -11088,7 +11088,7 @@ function stringifyJsonValue(value) {
|
|
|
11088
11088
|
throw new PanelAppError("PANEL_APP_AGENT_REQUEST_INVALID", "value is not JSON serializable");
|
|
11089
11089
|
}
|
|
11090
11090
|
}
|
|
11091
|
-
function isRecord$
|
|
11091
|
+
function isRecord$14(value) {
|
|
11092
11092
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
11093
11093
|
}
|
|
11094
11094
|
//#endregion
|
|
@@ -12509,12 +12509,12 @@ function parseSkillFrontmatter(raw) {
|
|
|
12509
12509
|
const summaryI18n = readLocalizedTextMap(parsed, "summaryi18n", "summary_i18n");
|
|
12510
12510
|
const descriptionI18n = readLocalizedTextMap(parsed, "descriptioni18n", "description_i18n");
|
|
12511
12511
|
return {
|
|
12512
|
-
name: readString$
|
|
12513
|
-
summary: readString$
|
|
12514
|
-
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$
|
|
12515
|
-
description: readString$
|
|
12516
|
-
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$
|
|
12517
|
-
author: readString$
|
|
12512
|
+
name: readString$8(parsed, "name"),
|
|
12513
|
+
summary: readString$8(parsed, "summary"),
|
|
12514
|
+
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: readString$8(parsed, "summaryzh", "summary_zh") }),
|
|
12515
|
+
description: readString$8(parsed, "description"),
|
|
12516
|
+
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: readString$8(parsed, "descriptionzh", "description_zh") }),
|
|
12517
|
+
author: readString$8(parsed, "author"),
|
|
12518
12518
|
tags: readTags(parsed)
|
|
12519
12519
|
};
|
|
12520
12520
|
}
|
|
@@ -12535,19 +12535,19 @@ function parseFrontmatterBlock(raw) {
|
|
|
12535
12535
|
function parseYamlFrontmatter(raw) {
|
|
12536
12536
|
try {
|
|
12537
12537
|
const parsed = parse(raw);
|
|
12538
|
-
return isRecord$
|
|
12538
|
+
return isRecord$13(parsed) ? parsed : {};
|
|
12539
12539
|
} catch (error) {
|
|
12540
12540
|
const message = error instanceof Error ? error.message : String(error);
|
|
12541
12541
|
throw new Error(`Invalid SKILL.md frontmatter: ${message}`);
|
|
12542
12542
|
}
|
|
12543
12543
|
}
|
|
12544
|
-
function readString$
|
|
12544
|
+
function readString$8(record, ...names) {
|
|
12545
12545
|
const value = readValue(record, names);
|
|
12546
12546
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
12547
12547
|
}
|
|
12548
12548
|
function readLocalizedTextMap(record, ...names) {
|
|
12549
12549
|
const value = readValue(record, names);
|
|
12550
|
-
if (!isRecord$
|
|
12550
|
+
if (!isRecord$13(value)) return;
|
|
12551
12551
|
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()]));
|
|
12552
12552
|
return Object.keys(localized).length > 0 ? localized : void 0;
|
|
12553
12553
|
}
|
|
@@ -12571,7 +12571,7 @@ function normalizeFrontmatterKey(raw) {
|
|
|
12571
12571
|
function normalizeLocaleTag(raw) {
|
|
12572
12572
|
return raw.trim().toLowerCase();
|
|
12573
12573
|
}
|
|
12574
|
-
function isRecord$
|
|
12574
|
+
function isRecord$13(value) {
|
|
12575
12575
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12576
12576
|
}
|
|
12577
12577
|
//#endregion
|
|
@@ -12791,11 +12791,11 @@ function createAgentPeerSessionIdentity(params) {
|
|
|
12791
12791
|
}
|
|
12792
12792
|
function resolveAgentPeerScope(params) {
|
|
12793
12793
|
const metadata = params.metadata ?? {};
|
|
12794
|
-
const explicitScope = readOptionalString$
|
|
12794
|
+
const explicitScope = readOptionalString$11(metadata["agent_peer_scope"]) ?? readOptionalString$11(metadata.agentPeerScope);
|
|
12795
12795
|
if (explicitScope) return explicitScope;
|
|
12796
|
-
return `agent:${readOptionalString$
|
|
12796
|
+
return `agent:${readOptionalString$11(params.agentId) ?? BUILTIN_MAIN_AGENT_ID}:${readOptionalString$11(params.channel) ?? readOptionalString$11(metadata.channel) ?? "agent-run"}:${readOptionalString$11(metadata.accountId) ?? readOptionalString$11(metadata.account_id) ?? "default"}`;
|
|
12797
12797
|
}
|
|
12798
|
-
function readOptionalString$
|
|
12798
|
+
function readOptionalString$11(value) {
|
|
12799
12799
|
if (typeof value !== "string") return;
|
|
12800
12800
|
return value.trim() || void 0;
|
|
12801
12801
|
}
|
|
@@ -12855,20 +12855,20 @@ function readEventMessageId(event) {
|
|
|
12855
12855
|
if (event.type === "session.snapshot.message") return null;
|
|
12856
12856
|
const streamingMessageId = readStreamingMessageId(event);
|
|
12857
12857
|
if (streamingMessageId) return streamingMessageId;
|
|
12858
|
-
const messageId = ("payload" in event && isRecord$
|
|
12858
|
+
const messageId = ("payload" in event && isRecord$12(event.payload) ? event.payload : null)?.messageId;
|
|
12859
12859
|
if (typeof messageId === "string" && messageId.trim()) return messageId.trim();
|
|
12860
12860
|
return null;
|
|
12861
12861
|
}
|
|
12862
12862
|
function readEventRunId(event) {
|
|
12863
12863
|
if (isJournalOnlyEvent(event)) return null;
|
|
12864
12864
|
if (event.type === "session.snapshot.message") return null;
|
|
12865
|
-
const runId = ("payload" in event && isRecord$
|
|
12865
|
+
const runId = ("payload" in event && isRecord$12(event.payload) ? event.payload : null)?.runId;
|
|
12866
12866
|
if (typeof runId === "string" && runId.trim()) return runId.trim();
|
|
12867
12867
|
return null;
|
|
12868
12868
|
}
|
|
12869
12869
|
function readEventToolCallId(event) {
|
|
12870
12870
|
if (isJournalOnlyEvent(event)) return null;
|
|
12871
|
-
const toolCallId = ("payload" in event && isRecord$
|
|
12871
|
+
const toolCallId = ("payload" in event && isRecord$12(event.payload) ? event.payload : null)?.toolCallId;
|
|
12872
12872
|
return typeof toolCallId === "string" && toolCallId.trim() ? toolCallId.trim() : null;
|
|
12873
12873
|
}
|
|
12874
12874
|
function createReplayEvent(event, toolResultsByCallId) {
|
|
@@ -12913,7 +12913,7 @@ function mergeReplayCompletedToolResults(message, toolResultsByCallId) {
|
|
|
12913
12913
|
} : message;
|
|
12914
12914
|
}
|
|
12915
12915
|
function readLegacyContextCompactionMessageId(message) {
|
|
12916
|
-
const checkpoint = isRecord$
|
|
12916
|
+
const checkpoint = isRecord$12(message?.metadata?.checkpoint) ? message.metadata.checkpoint : null;
|
|
12917
12917
|
const checkpointId = typeof checkpoint?.id === "string" ? checkpoint.id : "";
|
|
12918
12918
|
const coveredCount = checkpoint?.coveredSessionMessageCount;
|
|
12919
12919
|
const legacyId = `${message?.sessionId}:service:context-compaction:${checkpointId}`;
|
|
@@ -12945,11 +12945,11 @@ function readReplayMessageId(event) {
|
|
|
12945
12945
|
return readMessageFromSummaryEvent$1(event)?.id ?? null;
|
|
12946
12946
|
}
|
|
12947
12947
|
function readEventSessionId$1(event) {
|
|
12948
|
-
const sessionId = ("payload" in event && isRecord$
|
|
12948
|
+
const sessionId = ("payload" in event && isRecord$12(event.payload) ? event.payload : null)?.sessionId;
|
|
12949
12949
|
return typeof sessionId === "string" ? sessionId : "";
|
|
12950
12950
|
}
|
|
12951
12951
|
function readReplayPayloadTimestamp(event) {
|
|
12952
|
-
const payload = "payload" in event && isRecord$
|
|
12952
|
+
const payload = "payload" in event && isRecord$12(event.payload) ? event.payload : null;
|
|
12953
12953
|
const timestamp = typeof payload?.timestamp === "string" ? payload.timestamp : "";
|
|
12954
12954
|
return Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
|
|
12955
12955
|
}
|
|
@@ -12970,7 +12970,7 @@ function readStreamingMessageId(event) {
|
|
|
12970
12970
|
function isJournalOnlyEvent(event) {
|
|
12971
12971
|
return event.type === "session.request.accepted" || event.type === "session.request.completed" || event.type === "session.request.failed";
|
|
12972
12972
|
}
|
|
12973
|
-
function isRecord$
|
|
12973
|
+
function isRecord$12(value) {
|
|
12974
12974
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
12975
12975
|
}
|
|
12976
12976
|
function readMessageFromSummaryEvent$1(event) {
|
|
@@ -13077,7 +13077,7 @@ function safeNcpSessionFilename(value) {
|
|
|
13077
13077
|
function normalizeNcpAgentId(agentId) {
|
|
13078
13078
|
return agentId?.trim().toLowerCase() || void 0;
|
|
13079
13079
|
}
|
|
13080
|
-
function isRecord$
|
|
13080
|
+
function isRecord$11(value) {
|
|
13081
13081
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13082
13082
|
}
|
|
13083
13083
|
function toIsoString(value, fallback) {
|
|
@@ -13685,7 +13685,7 @@ function applyLimit(items, limit) {
|
|
|
13685
13685
|
if (!Number.isFinite(limit) || typeof limit !== "number" || limit <= 0) return items;
|
|
13686
13686
|
return items.slice(0, Math.trunc(limit));
|
|
13687
13687
|
}
|
|
13688
|
-
function readOptionalString$
|
|
13688
|
+
function readOptionalString$10(value) {
|
|
13689
13689
|
if (typeof value !== "string") return null;
|
|
13690
13690
|
const trimmed = value.trim();
|
|
13691
13691
|
return trimmed.length > 0 ? trimmed : null;
|
|
@@ -13731,7 +13731,6 @@ function cloneInheritedMetadata(sourceMetadata) {
|
|
|
13731
13731
|
"preferred_model",
|
|
13732
13732
|
"preferred_thinking",
|
|
13733
13733
|
"project_root",
|
|
13734
|
-
"requested_skill_refs",
|
|
13735
13734
|
"codex_runtime_backend",
|
|
13736
13735
|
"reasoningNormalizationMode",
|
|
13737
13736
|
"reasoning_normalization_mode"
|
|
@@ -13746,7 +13745,7 @@ function mergeMetadataOverrides(metadata, overrides) {
|
|
|
13746
13745
|
}
|
|
13747
13746
|
function resolveSessionType(params) {
|
|
13748
13747
|
const { metadata, runtime, sessionType } = params;
|
|
13749
|
-
return readOptionalString$
|
|
13748
|
+
return readOptionalString$10(runtime) ?? readOptionalString$10(metadata.runtime) ?? readOptionalString$10(sessionType) ?? readOptionalString$10(metadata.session_type) ?? "native";
|
|
13750
13749
|
}
|
|
13751
13750
|
function applySessionOverrides(params) {
|
|
13752
13751
|
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
@@ -13756,15 +13755,15 @@ function applySessionOverrides(params) {
|
|
|
13756
13755
|
metadata[CHILD_SESSION_LIFECYCLE_METADATA_KEY] = lifecycle;
|
|
13757
13756
|
if (parentSessionId) metadata[CHILD_SESSION_PARENT_METADATA_KEY] = parentSessionId;
|
|
13758
13757
|
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
13759
|
-
if (readOptionalString$
|
|
13758
|
+
if (readOptionalString$10(model)) {
|
|
13760
13759
|
metadata.model = model?.trim();
|
|
13761
13760
|
metadata.preferred_model = model?.trim();
|
|
13762
13761
|
}
|
|
13763
|
-
if (readOptionalString$
|
|
13762
|
+
if (readOptionalString$10(thinkingLevel)) {
|
|
13764
13763
|
metadata.thinking = thinkingLevel?.trim();
|
|
13765
13764
|
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
13766
13765
|
}
|
|
13767
|
-
if (readOptionalString$
|
|
13766
|
+
if (readOptionalString$10(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
13768
13767
|
}
|
|
13769
13768
|
//#endregion
|
|
13770
13769
|
//#region src/app/kernel-storage-paths.ts
|
|
@@ -16051,7 +16050,7 @@ var ServiceAppAiCapabilityService = class {
|
|
|
16051
16050
|
const payload = requireHostCallObject(call.request.input);
|
|
16052
16051
|
if (call.request.capability === "model-complete") {
|
|
16053
16052
|
const messages = payload.messages;
|
|
16054
|
-
if (!Array.isArray(messages) || !messages.every(isRecord$
|
|
16053
|
+
if (!Array.isArray(messages) || !messages.every(isRecord$10)) throw new ServiceAppError("SERVICE_APP_RUNTIME_FAILED", "AI model messages must be an array of objects.");
|
|
16055
16054
|
return await this.modelComplete({
|
|
16056
16055
|
app: call.app,
|
|
16057
16056
|
manifest: call.manifest,
|
|
@@ -16063,7 +16062,7 @@ var ServiceAppAiCapabilityService = class {
|
|
|
16063
16062
|
}
|
|
16064
16063
|
if (call.request.capability === "agent-start") {
|
|
16065
16064
|
const input = payload.input;
|
|
16066
|
-
if (!isRecord$
|
|
16065
|
+
if (!isRecord$10(input)) throw new ServiceAppError("SERVICE_APP_RUNTIME_FAILED", "AI Agent input must be an object.");
|
|
16067
16066
|
const execution = await this.agentStart({
|
|
16068
16067
|
app: call.app,
|
|
16069
16068
|
manifest: call.manifest,
|
|
@@ -16188,11 +16187,11 @@ var ServiceAppAiCapabilityService = class {
|
|
|
16188
16187
|
};
|
|
16189
16188
|
};
|
|
16190
16189
|
};
|
|
16191
|
-
function isRecord$
|
|
16190
|
+
function isRecord$10(value) {
|
|
16192
16191
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16193
16192
|
}
|
|
16194
16193
|
function requireHostCallObject(value) {
|
|
16195
|
-
if (!isRecord$
|
|
16194
|
+
if (!isRecord$10(value)) throw new ServiceAppError("SERVICE_APP_RUNTIME_FAILED", "Portable host call input must be an object.");
|
|
16196
16195
|
return value;
|
|
16197
16196
|
}
|
|
16198
16197
|
function requireHostCallString(value, key) {
|
|
@@ -18609,7 +18608,7 @@ function hasToolCall(message, toolCallId) {
|
|
|
18609
18608
|
return message.parts.some((part) => part.type === "tool-invocation" && part.toolCallId === toolCallId);
|
|
18610
18609
|
}
|
|
18611
18610
|
function findContextInheritanceAnchor(params) {
|
|
18612
|
-
const anchorToolCallId = readOptionalString$
|
|
18611
|
+
const anchorToolCallId = readOptionalString$10(params.anchorToolCallId);
|
|
18613
18612
|
if (!anchorToolCallId) return null;
|
|
18614
18613
|
const index = params.messages.findIndex((message) => hasToolCall(message, anchorToolCallId));
|
|
18615
18614
|
const message = index >= 0 ? params.messages[index] : void 0;
|
|
@@ -18649,7 +18648,7 @@ function createInheritedContextSnapshot(params) {
|
|
|
18649
18648
|
enabled: true,
|
|
18650
18649
|
sourceSessionId: sourceRecord.sessionId,
|
|
18651
18650
|
anchorKind: anchor ? "tool_call" : "latest_persisted",
|
|
18652
|
-
anchorToolCallId: readOptionalString$
|
|
18651
|
+
anchorToolCallId: readOptionalString$10(anchorToolCallId),
|
|
18653
18652
|
anchorMessageId: anchor?.message.id,
|
|
18654
18653
|
inheritedMessageCount: messages.length
|
|
18655
18654
|
}
|
|
@@ -18937,7 +18936,7 @@ var SessionWorkingDirResolver = class {
|
|
|
18937
18936
|
return this.resolveContext(params).effectiveWorkspace;
|
|
18938
18937
|
};
|
|
18939
18938
|
resolveContext = (params) => {
|
|
18940
|
-
const profile = this.agentManager.resolveAgentProfile(readOptionalString$
|
|
18939
|
+
const profile = this.agentManager.resolveAgentProfile(readOptionalString$10(params.agentId));
|
|
18941
18940
|
return resolveSessionProjectContext({
|
|
18942
18941
|
sessionMetadata: params.metadata,
|
|
18943
18942
|
workspace: profile.workspace
|
|
@@ -18985,10 +18984,10 @@ var SessionManager = class {
|
|
|
18985
18984
|
const { agentId: requestedAgentId, contextInheritance, metadataOverrides, model, parentSessionId: rawParentSessionId, projectRoot, requestId: rawRequestId, runtime, sessionId: requestedSessionId, sessionType: requestedSessionType, sourceSessionId, sourceSessionMetadata, task, thinkingLevel, title: requestedTitle } = params;
|
|
18986
18985
|
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
18987
18986
|
const metadata = cloneInheritedMetadata(sourceSessionMetadata);
|
|
18988
|
-
const title = readOptionalString$
|
|
18989
|
-
const parentSessionId = readOptionalString$
|
|
18987
|
+
const title = readOptionalString$10(requestedTitle) ?? summarizeTask(task);
|
|
18988
|
+
const parentSessionId = readOptionalString$10(rawParentSessionId);
|
|
18990
18989
|
await assertCanCreateSessionFromLineage(parentSessionId, sourceRecord, metadataOverrides, this.getSessionRecord);
|
|
18991
|
-
const requestId = readOptionalString$
|
|
18990
|
+
const requestId = readOptionalString$10(rawRequestId);
|
|
18992
18991
|
const sessionType = resolveSessionType({
|
|
18993
18992
|
runtime,
|
|
18994
18993
|
sessionType: requestedSessionType,
|
|
@@ -19014,8 +19013,8 @@ var SessionManager = class {
|
|
|
19014
19013
|
if (normalizedProjectRoot) nextMetadata.project_root = normalizedProjectRoot;
|
|
19015
19014
|
else delete nextMetadata.project_root;
|
|
19016
19015
|
}
|
|
19017
|
-
const agentId = readOptionalString$
|
|
19018
|
-
const sessionId = readOptionalString$
|
|
19016
|
+
const agentId = readOptionalString$10(requestedAgentId) ?? readOptionalString$10(sourceRecord?.agentId) ?? BUILTIN_MAIN_AGENT_ID;
|
|
19017
|
+
const sessionId = readOptionalString$10(requestedSessionId) ?? buildSessionId();
|
|
19019
19018
|
const inheritedContext = createSessionContextInheritance({
|
|
19020
19019
|
childSessionId: sessionId,
|
|
19021
19020
|
contextInheritance,
|
|
@@ -19101,7 +19100,7 @@ var SessionManager = class {
|
|
|
19101
19100
|
listSessions = async (options) => {
|
|
19102
19101
|
const { limit, peerId: rawPeerId } = options ?? {};
|
|
19103
19102
|
const { journalStore } = this.options;
|
|
19104
|
-
const peerId = readOptionalString$
|
|
19103
|
+
const peerId = readOptionalString$10(rawPeerId);
|
|
19105
19104
|
const summaryReadOptions = !peerId && limit !== void 0 ? { limit } : void 0;
|
|
19106
19105
|
return applyLimit((await journalStore.listSessionSummaries(summaryReadOptions)).filter((summary) => !peerId || summary.peerId === peerId).map(this.workingDirResolver.withWorkingDir), limit);
|
|
19107
19106
|
};
|
|
@@ -19160,9 +19159,9 @@ var SessionManager = class {
|
|
|
19160
19159
|
};
|
|
19161
19160
|
createAgentRunSession = async (params) => {
|
|
19162
19161
|
const { agentId, agentRuntimeId: requestedAgentRuntimeId, channel, contextInheritance, metadata, model, parentSessionId: rawParentSessionId, peerId: rawPeerId, projectRoot, sessionId, sourceSessionId: rawSourceSessionId, sourceSessionMetadata: requestedSourceSessionMetadata, task, thinkingEffort } = params;
|
|
19163
|
-
const peerId = readOptionalString$
|
|
19164
|
-
const parentSessionId = readOptionalString$
|
|
19165
|
-
const sourceSessionId = readOptionalString$
|
|
19162
|
+
const peerId = readOptionalString$10(rawPeerId);
|
|
19163
|
+
const parentSessionId = readOptionalString$10(rawParentSessionId);
|
|
19164
|
+
const sourceSessionId = readOptionalString$10(rawSourceSessionId);
|
|
19166
19165
|
const sourceRecord = sourceSessionId ? await this.getSessionRecord(sourceSessionId) : null;
|
|
19167
19166
|
const sourceSessionMetadata = requestedSourceSessionMetadata ?? sourceRecord?.metadata ?? {};
|
|
19168
19167
|
const agentRuntimeId = requestedAgentRuntimeId ?? readAgentRuntimeId(sourceSessionMetadata) ?? "native";
|
|
@@ -19172,7 +19171,7 @@ var SessionManager = class {
|
|
|
19172
19171
|
metadata,
|
|
19173
19172
|
peerId
|
|
19174
19173
|
}) : void 0;
|
|
19175
|
-
const requestedSessionId = readOptionalString$
|
|
19174
|
+
const requestedSessionId = readOptionalString$10(sessionId);
|
|
19176
19175
|
const created = await this.createSession({
|
|
19177
19176
|
contextInheritance,
|
|
19178
19177
|
parentSessionId: parentSessionId ?? void 0,
|
|
@@ -20206,8 +20205,11 @@ var ObservationManager = class {
|
|
|
20206
20205
|
};
|
|
20207
20206
|
};
|
|
20208
20207
|
//#endregion
|
|
20209
|
-
//#region src/stores/project.store.ts
|
|
20210
|
-
const PROJECT_STORE_VERSION =
|
|
20208
|
+
//#region src/features/projects/stores/project.store.ts
|
|
20209
|
+
const PROJECT_STORE_VERSION = 2;
|
|
20210
|
+
function createProjectId() {
|
|
20211
|
+
return randomBytes(9).toString("base64url");
|
|
20212
|
+
}
|
|
20211
20213
|
var ProjectStoreError = class extends Error {
|
|
20212
20214
|
constructor(message) {
|
|
20213
20215
|
super(message);
|
|
@@ -20227,6 +20229,28 @@ var ProjectStore = class {
|
|
|
20227
20229
|
throw error;
|
|
20228
20230
|
}
|
|
20229
20231
|
};
|
|
20232
|
+
migrateLegacyRecords = async () => {
|
|
20233
|
+
let source;
|
|
20234
|
+
try {
|
|
20235
|
+
source = await readFile(this.storePath, "utf8");
|
|
20236
|
+
} catch (error) {
|
|
20237
|
+
if (this.isMissingFileError(error)) return false;
|
|
20238
|
+
throw error;
|
|
20239
|
+
}
|
|
20240
|
+
let storeFile;
|
|
20241
|
+
try {
|
|
20242
|
+
storeFile = this.parseStoredFile(source);
|
|
20243
|
+
} catch (error) {
|
|
20244
|
+
if (error instanceof SyntaxError) throw new ProjectStoreError("project registry contains invalid JSON");
|
|
20245
|
+
throw error;
|
|
20246
|
+
}
|
|
20247
|
+
if (storeFile.version === PROJECT_STORE_VERSION) return false;
|
|
20248
|
+
await this.save(storeFile.projects.map((project) => ({
|
|
20249
|
+
id: createProjectId(),
|
|
20250
|
+
...project
|
|
20251
|
+
})));
|
|
20252
|
+
return true;
|
|
20253
|
+
};
|
|
20230
20254
|
save = async (projects) => {
|
|
20231
20255
|
const tempPath = `${this.storePath}.${randomUUID()}.tmp`;
|
|
20232
20256
|
const storeFile = {
|
|
@@ -20243,25 +20267,46 @@ var ProjectStore = class {
|
|
|
20243
20267
|
}
|
|
20244
20268
|
};
|
|
20245
20269
|
parseStoreFile = (source) => {
|
|
20246
|
-
const value =
|
|
20247
|
-
if (
|
|
20270
|
+
const value = this.parseStoredFile(source);
|
|
20271
|
+
if (value.version !== PROJECT_STORE_VERSION || !value.projects.every(this.isProjectRecord)) throw new ProjectStoreError("project registry has an unsupported structure");
|
|
20248
20272
|
return {
|
|
20249
20273
|
version: PROJECT_STORE_VERSION,
|
|
20250
20274
|
projects: value.projects.map((project) => structuredClone(project))
|
|
20251
20275
|
};
|
|
20252
20276
|
};
|
|
20277
|
+
parseStoredFile = (source) => {
|
|
20278
|
+
const value = JSON.parse(source);
|
|
20279
|
+
if (!this.isRecord(value) || !Array.isArray(value.projects)) throw new ProjectStoreError("project registry has an unsupported structure");
|
|
20280
|
+
if (value.version === PROJECT_STORE_VERSION && value.projects.every(this.isProjectRecord)) return {
|
|
20281
|
+
version: PROJECT_STORE_VERSION,
|
|
20282
|
+
projects: value.projects.map((project) => structuredClone(project))
|
|
20283
|
+
};
|
|
20284
|
+
if (value.version === 1 && value.projects.every(this.isLegacyProjectRecord)) return {
|
|
20285
|
+
version: 1,
|
|
20286
|
+
projects: value.projects.map((project) => structuredClone(project))
|
|
20287
|
+
};
|
|
20288
|
+
throw new ProjectStoreError("project registry has an unsupported structure");
|
|
20289
|
+
};
|
|
20253
20290
|
isProjectRecord = (value) => {
|
|
20254
20291
|
if (!this.isRecord(value)) return false;
|
|
20255
|
-
return typeof value.name === "string" && typeof value.rootPath === "string" && (value.template === void 0 || value.template === "empty" || value.template === "knowledge-base") && typeof value.createdAt === "string" && typeof value.updatedAt === "string";
|
|
20292
|
+
return typeof value.id === "string" && value.id.length > 0 && typeof value.name === "string" && typeof value.rootPath === "string" && (value.template === void 0 || value.template === "empty" || value.template === "knowledge-base") && typeof value.createdAt === "string" && typeof value.updatedAt === "string";
|
|
20293
|
+
};
|
|
20294
|
+
isLegacyProjectRecord = (value) => {
|
|
20295
|
+
if (!this.isRecord(value)) return false;
|
|
20296
|
+
const { id: _id, ...legacy } = value;
|
|
20297
|
+
return this.isProjectRecord({
|
|
20298
|
+
id: "legacy",
|
|
20299
|
+
...legacy
|
|
20300
|
+
});
|
|
20256
20301
|
};
|
|
20257
20302
|
isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20258
20303
|
isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
20259
20304
|
};
|
|
20260
20305
|
//#endregion
|
|
20261
|
-
//#region src/types/project.types.ts
|
|
20306
|
+
//#region src/features/projects/types/project.types.ts
|
|
20262
20307
|
const PROJECT_TEMPLATE_IDS = ["empty", "knowledge-base"];
|
|
20263
20308
|
//#endregion
|
|
20264
|
-
//#region src/managers/project.manager.ts
|
|
20309
|
+
//#region src/features/projects/managers/project.manager.ts
|
|
20265
20310
|
const PROJECT_TEMPLATES = [{
|
|
20266
20311
|
id: "empty",
|
|
20267
20312
|
name: "Empty project",
|
|
@@ -20288,6 +20333,17 @@ var ProjectManager = class {
|
|
|
20288
20333
|
this.store = new ProjectStore(options.storePath);
|
|
20289
20334
|
}
|
|
20290
20335
|
listProjects = async () => (await this.store.list()).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || left.name.localeCompare(right.name));
|
|
20336
|
+
migrateLegacyProjects = async () => await this.store.migrateLegacyRecords();
|
|
20337
|
+
getProjectById = async (projectId) => {
|
|
20338
|
+
const project = (await this.store.list()).find((entry) => entry.id === projectId);
|
|
20339
|
+
return project ? structuredClone(project) : null;
|
|
20340
|
+
};
|
|
20341
|
+
getRegisteredProject = async (rootPath) => {
|
|
20342
|
+
const canonicalPath = await this.resolveExistingProjectRoot(rootPath);
|
|
20343
|
+
if (!canonicalPath) return null;
|
|
20344
|
+
const project = (await this.store.list()).find((entry) => entry.rootPath === canonicalPath);
|
|
20345
|
+
return project ? structuredClone(project) : null;
|
|
20346
|
+
};
|
|
20291
20347
|
listTemplates = () => structuredClone(PROJECT_TEMPLATES);
|
|
20292
20348
|
createProject = async (input) => {
|
|
20293
20349
|
const name = this.normalizeName(input.name);
|
|
@@ -20357,6 +20413,7 @@ var ProjectManager = class {
|
|
|
20357
20413
|
if (existing) return existing;
|
|
20358
20414
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20359
20415
|
const project = {
|
|
20416
|
+
id: createProjectId(),
|
|
20360
20417
|
name: input.name,
|
|
20361
20418
|
rootPath: input.rootPath,
|
|
20362
20419
|
...input.template ? { template: input.template } : {},
|
|
@@ -20421,6 +20478,1232 @@ var ProjectManager = class {
|
|
|
20421
20478
|
isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
20422
20479
|
};
|
|
20423
20480
|
//#endregion
|
|
20481
|
+
//#region src/features/projects/types/project-observation.types.ts
|
|
20482
|
+
const PROJECT_OBSERVATION_PROTOCOL = "nextclaw.project/v1";
|
|
20483
|
+
var ProjectObservationError = class extends Error {
|
|
20484
|
+
constructor(code, message) {
|
|
20485
|
+
super(message);
|
|
20486
|
+
this.code = code;
|
|
20487
|
+
this.name = "ProjectObservationError";
|
|
20488
|
+
}
|
|
20489
|
+
};
|
|
20490
|
+
function isProjectObservationError(error) {
|
|
20491
|
+
return error instanceof ProjectObservationError;
|
|
20492
|
+
}
|
|
20493
|
+
//#endregion
|
|
20494
|
+
//#region src/features/projects/utils/project-observation-config.utils.ts
|
|
20495
|
+
const isRecord$9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20496
|
+
const readString$7 = (value) => {
|
|
20497
|
+
if (typeof value !== "string") return null;
|
|
20498
|
+
return value.trim() || null;
|
|
20499
|
+
};
|
|
20500
|
+
const collectUnknownKeyIssues = (value, allowed, owner) => Object.keys(value).flatMap((key) => allowed.includes(key) ? [] : [{
|
|
20501
|
+
code: "PROJECT_CONFIG_UNKNOWN_FIELD",
|
|
20502
|
+
message: `${owner} contains unknown field '${key}'.`
|
|
20503
|
+
}]);
|
|
20504
|
+
function parseContext(value) {
|
|
20505
|
+
if (value === void 0) return {
|
|
20506
|
+
value: [],
|
|
20507
|
+
issues: []
|
|
20508
|
+
};
|
|
20509
|
+
if (!Array.isArray(value)) return {
|
|
20510
|
+
value: [],
|
|
20511
|
+
issues: [{
|
|
20512
|
+
code: "PROJECT_CONFIG_CONTEXT_INVALID",
|
|
20513
|
+
message: "project.context must be an array."
|
|
20514
|
+
}]
|
|
20515
|
+
};
|
|
20516
|
+
const issues = [];
|
|
20517
|
+
return {
|
|
20518
|
+
value: value.flatMap((entry, index) => {
|
|
20519
|
+
if (!isRecord$9(entry)) {
|
|
20520
|
+
issues.push({
|
|
20521
|
+
code: "PROJECT_CONFIG_CONTEXT_INVALID",
|
|
20522
|
+
message: `project.context[${index}] must be an object.`
|
|
20523
|
+
});
|
|
20524
|
+
return [];
|
|
20525
|
+
}
|
|
20526
|
+
issues.push(...collectUnknownKeyIssues(entry, [
|
|
20527
|
+
"id",
|
|
20528
|
+
"role",
|
|
20529
|
+
"source"
|
|
20530
|
+
], `project.context[${index}]`));
|
|
20531
|
+
const id = readString$7(entry.id);
|
|
20532
|
+
const role = readString$7(entry.role);
|
|
20533
|
+
const source = readString$7(entry.source);
|
|
20534
|
+
if (!id || !role || !source) {
|
|
20535
|
+
issues.push({
|
|
20536
|
+
code: "PROJECT_CONFIG_CONTEXT_INVALID",
|
|
20537
|
+
message: `project.context[${index}] requires id, role and source.`
|
|
20538
|
+
});
|
|
20539
|
+
return [];
|
|
20540
|
+
}
|
|
20541
|
+
return [{
|
|
20542
|
+
id,
|
|
20543
|
+
role,
|
|
20544
|
+
source
|
|
20545
|
+
}];
|
|
20546
|
+
}),
|
|
20547
|
+
issues
|
|
20548
|
+
};
|
|
20549
|
+
}
|
|
20550
|
+
function parseWorkflows(value) {
|
|
20551
|
+
if (value === void 0) return {
|
|
20552
|
+
value: [],
|
|
20553
|
+
issues: []
|
|
20554
|
+
};
|
|
20555
|
+
if (!Array.isArray(value)) return {
|
|
20556
|
+
value: [],
|
|
20557
|
+
issues: [{
|
|
20558
|
+
code: "PROJECT_CONFIG_WORKFLOWS_INVALID",
|
|
20559
|
+
message: "workflows must be an array."
|
|
20560
|
+
}]
|
|
20561
|
+
};
|
|
20562
|
+
const issues = [];
|
|
20563
|
+
return {
|
|
20564
|
+
value: value.flatMap((entry, workflowIndex) => {
|
|
20565
|
+
if (!isRecord$9(entry) || !Array.isArray(entry.stages)) {
|
|
20566
|
+
issues.push({
|
|
20567
|
+
code: "PROJECT_CONFIG_WORKFLOW_INVALID",
|
|
20568
|
+
message: `workflows[${workflowIndex}] requires a stages array.`
|
|
20569
|
+
});
|
|
20570
|
+
return [];
|
|
20571
|
+
}
|
|
20572
|
+
issues.push(...collectUnknownKeyIssues(entry, [
|
|
20573
|
+
"id",
|
|
20574
|
+
"label",
|
|
20575
|
+
"stages"
|
|
20576
|
+
], `workflows[${workflowIndex}]`));
|
|
20577
|
+
const id = readString$7(entry.id);
|
|
20578
|
+
const label = readString$7(entry.label);
|
|
20579
|
+
const stages = entry.stages.flatMap((stage, stageIndex) => {
|
|
20580
|
+
if (!isRecord$9(stage)) {
|
|
20581
|
+
issues.push({
|
|
20582
|
+
code: "PROJECT_CONFIG_STAGE_INVALID",
|
|
20583
|
+
message: `workflows[${workflowIndex}].stages[${stageIndex}] must be an object.`
|
|
20584
|
+
});
|
|
20585
|
+
return [];
|
|
20586
|
+
}
|
|
20587
|
+
issues.push(...collectUnknownKeyIssues(stage, ["id", "label"], `workflows[${workflowIndex}].stages[${stageIndex}]`));
|
|
20588
|
+
const stageId = readString$7(stage.id);
|
|
20589
|
+
const stageLabel = readString$7(stage.label);
|
|
20590
|
+
if (!stageId || !stageLabel) {
|
|
20591
|
+
issues.push({
|
|
20592
|
+
code: "PROJECT_CONFIG_STAGE_INVALID",
|
|
20593
|
+
message: `workflows[${workflowIndex}].stages[${stageIndex}] requires id and label.`
|
|
20594
|
+
});
|
|
20595
|
+
return [];
|
|
20596
|
+
}
|
|
20597
|
+
return [{
|
|
20598
|
+
id: stageId,
|
|
20599
|
+
label: stageLabel
|
|
20600
|
+
}];
|
|
20601
|
+
});
|
|
20602
|
+
if (!id || !label) {
|
|
20603
|
+
issues.push({
|
|
20604
|
+
code: "PROJECT_CONFIG_WORKFLOW_INVALID",
|
|
20605
|
+
message: `workflows[${workflowIndex}] requires id and label.`
|
|
20606
|
+
});
|
|
20607
|
+
return [];
|
|
20608
|
+
}
|
|
20609
|
+
return [{
|
|
20610
|
+
id,
|
|
20611
|
+
label,
|
|
20612
|
+
stages
|
|
20613
|
+
}];
|
|
20614
|
+
}),
|
|
20615
|
+
issues
|
|
20616
|
+
};
|
|
20617
|
+
}
|
|
20618
|
+
function parseArtifactCategories(value) {
|
|
20619
|
+
if (value === void 0) return {
|
|
20620
|
+
value: [],
|
|
20621
|
+
issues: []
|
|
20622
|
+
};
|
|
20623
|
+
if (!Array.isArray(value)) return {
|
|
20624
|
+
value: [],
|
|
20625
|
+
issues: [{
|
|
20626
|
+
code: "PROJECT_CONFIG_ARTIFACTS_INVALID",
|
|
20627
|
+
message: "observation.artifacts must be an array."
|
|
20628
|
+
}]
|
|
20629
|
+
};
|
|
20630
|
+
const issues = [];
|
|
20631
|
+
return {
|
|
20632
|
+
value: value.flatMap((entry, index) => {
|
|
20633
|
+
if (!isRecord$9(entry) || !Array.isArray(entry.include)) {
|
|
20634
|
+
issues.push({
|
|
20635
|
+
code: "PROJECT_CONFIG_ARTIFACT_INVALID",
|
|
20636
|
+
message: `observation.artifacts[${index}] requires an include array.`
|
|
20637
|
+
});
|
|
20638
|
+
return [];
|
|
20639
|
+
}
|
|
20640
|
+
issues.push(...collectUnknownKeyIssues(entry, [
|
|
20641
|
+
"id",
|
|
20642
|
+
"label",
|
|
20643
|
+
"include"
|
|
20644
|
+
], `observation.artifacts[${index}]`));
|
|
20645
|
+
const id = readString$7(entry.id);
|
|
20646
|
+
const label = readString$7(entry.label);
|
|
20647
|
+
const include = entry.include.map(readString$7).filter((pattern) => pattern !== null);
|
|
20648
|
+
if (!id || !label || include.length !== entry.include.length || include.length === 0) {
|
|
20649
|
+
issues.push({
|
|
20650
|
+
code: "PROJECT_CONFIG_ARTIFACT_INVALID",
|
|
20651
|
+
message: `observation.artifacts[${index}] requires id, label and non-empty string patterns.`
|
|
20652
|
+
});
|
|
20653
|
+
return [];
|
|
20654
|
+
}
|
|
20655
|
+
return [{
|
|
20656
|
+
id,
|
|
20657
|
+
label,
|
|
20658
|
+
include
|
|
20659
|
+
}];
|
|
20660
|
+
}),
|
|
20661
|
+
issues
|
|
20662
|
+
};
|
|
20663
|
+
}
|
|
20664
|
+
function parseSkillRoots(value) {
|
|
20665
|
+
if (value === void 0) return {
|
|
20666
|
+
value: [".agents/skills"],
|
|
20667
|
+
issues: []
|
|
20668
|
+
};
|
|
20669
|
+
if (!Array.isArray(value)) return {
|
|
20670
|
+
value: [],
|
|
20671
|
+
issues: [{
|
|
20672
|
+
code: "PROJECT_CONFIG_SKILLS_INVALID",
|
|
20673
|
+
message: "observation.skills must be an array."
|
|
20674
|
+
}]
|
|
20675
|
+
};
|
|
20676
|
+
const issues = [];
|
|
20677
|
+
return {
|
|
20678
|
+
value: value.flatMap((entry, index) => {
|
|
20679
|
+
if (!isRecord$9(entry)) {
|
|
20680
|
+
issues.push({
|
|
20681
|
+
code: "PROJECT_CONFIG_SKILL_INVALID",
|
|
20682
|
+
message: `observation.skills[${index}] must be an object.`
|
|
20683
|
+
});
|
|
20684
|
+
return [];
|
|
20685
|
+
}
|
|
20686
|
+
issues.push(...collectUnknownKeyIssues(entry, ["root"], `observation.skills[${index}]`));
|
|
20687
|
+
const root = readString$7(entry.root);
|
|
20688
|
+
if (!root) {
|
|
20689
|
+
issues.push({
|
|
20690
|
+
code: "PROJECT_CONFIG_SKILL_INVALID",
|
|
20691
|
+
message: `observation.skills[${index}] requires root.`
|
|
20692
|
+
});
|
|
20693
|
+
return [];
|
|
20694
|
+
}
|
|
20695
|
+
return [root];
|
|
20696
|
+
}),
|
|
20697
|
+
issues
|
|
20698
|
+
};
|
|
20699
|
+
}
|
|
20700
|
+
function parseProjectObservationConfig(source) {
|
|
20701
|
+
const issues = [];
|
|
20702
|
+
let parsed;
|
|
20703
|
+
try {
|
|
20704
|
+
parsed = parse(source);
|
|
20705
|
+
} catch (error) {
|
|
20706
|
+
return {
|
|
20707
|
+
config: null,
|
|
20708
|
+
issues: [{
|
|
20709
|
+
code: "PROJECT_CONFIG_YAML_INVALID",
|
|
20710
|
+
message: error instanceof Error ? error.message : "project.yaml is invalid YAML."
|
|
20711
|
+
}]
|
|
20712
|
+
};
|
|
20713
|
+
}
|
|
20714
|
+
if (!isRecord$9(parsed)) return {
|
|
20715
|
+
config: null,
|
|
20716
|
+
issues: [{
|
|
20717
|
+
code: "PROJECT_CONFIG_INVALID",
|
|
20718
|
+
message: "project.yaml must contain an object."
|
|
20719
|
+
}]
|
|
20720
|
+
};
|
|
20721
|
+
issues.push(...collectUnknownKeyIssues(parsed, [
|
|
20722
|
+
"schema_version",
|
|
20723
|
+
"project",
|
|
20724
|
+
"workflows",
|
|
20725
|
+
"observation"
|
|
20726
|
+
], "project.yaml"));
|
|
20727
|
+
if (parsed.schema_version !== 1) return {
|
|
20728
|
+
config: null,
|
|
20729
|
+
issues: [{
|
|
20730
|
+
code: "PROJECT_CONFIG_VERSION_UNSUPPORTED",
|
|
20731
|
+
message: "Only schema_version 1 is supported."
|
|
20732
|
+
}, ...issues]
|
|
20733
|
+
};
|
|
20734
|
+
const project = isRecord$9(parsed.project) ? parsed.project : {};
|
|
20735
|
+
const observation = isRecord$9(parsed.observation) ? parsed.observation : {};
|
|
20736
|
+
if (parsed.project !== void 0 && !isRecord$9(parsed.project)) issues.push({
|
|
20737
|
+
code: "PROJECT_CONFIG_PROJECT_INVALID",
|
|
20738
|
+
message: "project must be an object."
|
|
20739
|
+
});
|
|
20740
|
+
if (parsed.observation !== void 0 && !isRecord$9(parsed.observation)) issues.push({
|
|
20741
|
+
code: "PROJECT_CONFIG_OBSERVATION_INVALID",
|
|
20742
|
+
message: "observation must be an object."
|
|
20743
|
+
});
|
|
20744
|
+
issues.push(...collectUnknownKeyIssues(project, ["summary", "context"], "project"));
|
|
20745
|
+
issues.push(...collectUnknownKeyIssues(observation, [
|
|
20746
|
+
"markers",
|
|
20747
|
+
"work_items",
|
|
20748
|
+
"artifacts",
|
|
20749
|
+
"skills"
|
|
20750
|
+
], "observation"));
|
|
20751
|
+
if (observation.markers !== void 0) {
|
|
20752
|
+
if (!(Array.isArray(observation.markers) ? observation.markers : []).some((marker) => isRecord$9(marker) && marker.protocol === "nextclaw.project/v1")) issues.push({
|
|
20753
|
+
code: "PROJECT_CONFIG_MARKERS_INVALID",
|
|
20754
|
+
message: `observation.markers must enable protocol '${PROJECT_OBSERVATION_PROTOCOL}'.`
|
|
20755
|
+
});
|
|
20756
|
+
}
|
|
20757
|
+
const context = parseContext(project.context);
|
|
20758
|
+
const workflows = parseWorkflows(parsed.workflows);
|
|
20759
|
+
const artifactCategories = parseArtifactCategories(observation.artifacts);
|
|
20760
|
+
const skillRoots = parseSkillRoots(observation.skills);
|
|
20761
|
+
issues.push(...context.issues, ...workflows.issues, ...artifactCategories.issues, ...skillRoots.issues);
|
|
20762
|
+
return {
|
|
20763
|
+
config: {
|
|
20764
|
+
...readString$7(project.summary) ? { summary: readString$7(project.summary) } : {},
|
|
20765
|
+
context: context.value,
|
|
20766
|
+
workflows: workflows.value,
|
|
20767
|
+
artifactCategories: artifactCategories.value,
|
|
20768
|
+
skillRoots: skillRoots.value
|
|
20769
|
+
},
|
|
20770
|
+
issues
|
|
20771
|
+
};
|
|
20772
|
+
}
|
|
20773
|
+
//#endregion
|
|
20774
|
+
//#region src/features/projects/utils/project-observation-files.utils.ts
|
|
20775
|
+
const IGNORED_DIRECTORIES = new Set([
|
|
20776
|
+
".git",
|
|
20777
|
+
".hg",
|
|
20778
|
+
".svn",
|
|
20779
|
+
"node_modules"
|
|
20780
|
+
]);
|
|
20781
|
+
const MAX_ARTIFACT_FILES = 1e4;
|
|
20782
|
+
const MAX_DEPTH = 12;
|
|
20783
|
+
const toPortablePath = (value) => value.split(sep).join("/");
|
|
20784
|
+
function globSearchBase(pattern) {
|
|
20785
|
+
const segments = pattern.split("/");
|
|
20786
|
+
const firstDynamicSegment = segments.findIndex((segment) => segment.includes("*") || segment.includes("?"));
|
|
20787
|
+
if (firstDynamicSegment >= 0) return segments.slice(0, firstDynamicSegment).join("/");
|
|
20788
|
+
return segments.slice(0, -1).join("/");
|
|
20789
|
+
}
|
|
20790
|
+
function shouldVisitDirectory(relativeDirectory, searchBases) {
|
|
20791
|
+
if (!relativeDirectory) return true;
|
|
20792
|
+
return searchBases.some((base) => !base || base === relativeDirectory || base.startsWith(`${relativeDirectory}/`) || relativeDirectory.startsWith(`${base}/`));
|
|
20793
|
+
}
|
|
20794
|
+
function compareFileRecency(left, right) {
|
|
20795
|
+
return left.updatedAt.localeCompare(right.updatedAt) || left.relativePath.localeCompare(right.relativePath);
|
|
20796
|
+
}
|
|
20797
|
+
function siftOldestFileDown(files, index) {
|
|
20798
|
+
let parent = index;
|
|
20799
|
+
while (true) {
|
|
20800
|
+
const left = parent * 2 + 1;
|
|
20801
|
+
const right = left + 1;
|
|
20802
|
+
let oldest = parent;
|
|
20803
|
+
if (left < files.length && compareFileRecency(files[left], files[oldest]) < 0) oldest = left;
|
|
20804
|
+
if (right < files.length && compareFileRecency(files[right], files[oldest]) < 0) oldest = right;
|
|
20805
|
+
if (oldest === parent) return;
|
|
20806
|
+
[files[parent], files[oldest]] = [files[oldest], files[parent]];
|
|
20807
|
+
parent = oldest;
|
|
20808
|
+
}
|
|
20809
|
+
}
|
|
20810
|
+
function keepMostRecentArtifactFile(files, file, maxArtifactFiles) {
|
|
20811
|
+
if (files.length < maxArtifactFiles) {
|
|
20812
|
+
files.push(file);
|
|
20813
|
+
let child = files.length - 1;
|
|
20814
|
+
while (child > 0) {
|
|
20815
|
+
const parent = Math.floor((child - 1) / 2);
|
|
20816
|
+
if (compareFileRecency(files[child], files[parent]) >= 0) break;
|
|
20817
|
+
[files[child], files[parent]] = [files[parent], files[child]];
|
|
20818
|
+
child = parent;
|
|
20819
|
+
}
|
|
20820
|
+
return;
|
|
20821
|
+
}
|
|
20822
|
+
if (compareFileRecency(file, files[0]) <= 0) return;
|
|
20823
|
+
files[0] = file;
|
|
20824
|
+
siftOldestFileDown(files, 0);
|
|
20825
|
+
}
|
|
20826
|
+
function normalizeProjectRelativePath(value) {
|
|
20827
|
+
const normalized = value.trim().replaceAll("\\", "/").replace(/^\.\//, "");
|
|
20828
|
+
if (!normalized || normalized.startsWith("/") || isAbsolute(normalized)) return null;
|
|
20829
|
+
const segments = normalized.split("/");
|
|
20830
|
+
if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) return null;
|
|
20831
|
+
return segments.join("/");
|
|
20832
|
+
}
|
|
20833
|
+
function resolveInsideProject(rootPath, projectRelativePath) {
|
|
20834
|
+
const normalized = normalizeProjectRelativePath(projectRelativePath);
|
|
20835
|
+
if (!normalized) return null;
|
|
20836
|
+
const target = resolve(rootPath, normalized);
|
|
20837
|
+
const targetRelative = relative(rootPath, target);
|
|
20838
|
+
return targetRelative && !targetRelative.startsWith(`..${sep}`) && targetRelative !== ".." ? target : null;
|
|
20839
|
+
}
|
|
20840
|
+
async function observeProjectFile(rootPath, projectRelativePath) {
|
|
20841
|
+
const target = resolveInsideProject(rootPath, projectRelativePath);
|
|
20842
|
+
if (!target) return null;
|
|
20843
|
+
try {
|
|
20844
|
+
const targetLstat = await lstat(target);
|
|
20845
|
+
if (targetLstat.isSymbolicLink() || !targetLstat.isFile()) return null;
|
|
20846
|
+
const canonicalRoot = await realpath(rootPath);
|
|
20847
|
+
const canonicalTarget = await realpath(target);
|
|
20848
|
+
const canonicalRelative = relative(canonicalRoot, canonicalTarget);
|
|
20849
|
+
if (canonicalRelative.startsWith(`..${sep}`) || canonicalRelative === "..") return null;
|
|
20850
|
+
const targetStat = await stat(canonicalTarget);
|
|
20851
|
+
return {
|
|
20852
|
+
createdAt: targetStat.birthtime.toISOString(),
|
|
20853
|
+
relativePath: normalizeProjectRelativePath(projectRelativePath),
|
|
20854
|
+
size: targetStat.size,
|
|
20855
|
+
updatedAt: targetStat.mtime.toISOString()
|
|
20856
|
+
};
|
|
20857
|
+
} catch {
|
|
20858
|
+
return null;
|
|
20859
|
+
}
|
|
20860
|
+
}
|
|
20861
|
+
function globToRegExp(pattern) {
|
|
20862
|
+
const normalized = normalizeProjectRelativePath(pattern);
|
|
20863
|
+
if (!normalized) return null;
|
|
20864
|
+
let source = "^";
|
|
20865
|
+
for (let index = 0; index < normalized.length; index += 1) {
|
|
20866
|
+
const character = normalized[index];
|
|
20867
|
+
const next = normalized[index + 1];
|
|
20868
|
+
if (character === "*" && next === "*") {
|
|
20869
|
+
const after = normalized[index + 2];
|
|
20870
|
+
source += after === "/" ? "(?:.*/)?" : ".*";
|
|
20871
|
+
index += after === "/" ? 2 : 1;
|
|
20872
|
+
continue;
|
|
20873
|
+
}
|
|
20874
|
+
if (character === "*") {
|
|
20875
|
+
source += "[^/]*";
|
|
20876
|
+
continue;
|
|
20877
|
+
}
|
|
20878
|
+
if (character === "?") {
|
|
20879
|
+
source += "[^/]";
|
|
20880
|
+
continue;
|
|
20881
|
+
}
|
|
20882
|
+
source += /[|\\{}()[\]^$+?.]/.test(character) ? `\\${character}` : character;
|
|
20883
|
+
}
|
|
20884
|
+
return new RegExp(`${source}$`);
|
|
20885
|
+
}
|
|
20886
|
+
async function scanProjectArtifactFiles(rootPath, categories, options = {}) {
|
|
20887
|
+
const issues = [];
|
|
20888
|
+
const compiled = categories.flatMap((category) => category.include.flatMap((pattern) => {
|
|
20889
|
+
const matcher = globToRegExp(pattern);
|
|
20890
|
+
if (!matcher) {
|
|
20891
|
+
issues.push({
|
|
20892
|
+
code: "PROJECT_ARTIFACT_PATTERN_INVALID",
|
|
20893
|
+
message: `Artifact pattern '${pattern}' is not a safe project-relative glob.`,
|
|
20894
|
+
projectRelativePath: pattern
|
|
20895
|
+
});
|
|
20896
|
+
return [];
|
|
20897
|
+
}
|
|
20898
|
+
return [{
|
|
20899
|
+
...category,
|
|
20900
|
+
pattern,
|
|
20901
|
+
matcher
|
|
20902
|
+
}];
|
|
20903
|
+
}));
|
|
20904
|
+
if (compiled.length === 0) return {
|
|
20905
|
+
matches: [],
|
|
20906
|
+
issues
|
|
20907
|
+
};
|
|
20908
|
+
const files = [];
|
|
20909
|
+
let matchedFileCount = 0;
|
|
20910
|
+
const maxArtifactFiles = options.maxArtifactFiles ?? MAX_ARTIFACT_FILES;
|
|
20911
|
+
const searchBases = [...new Set(compiled.map((rule) => globSearchBase(rule.pattern)))];
|
|
20912
|
+
const visit = async (directory, depth) => {
|
|
20913
|
+
if (depth > MAX_DEPTH) return;
|
|
20914
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
20915
|
+
for (const entry of entries) {
|
|
20916
|
+
if (entry.isSymbolicLink()) continue;
|
|
20917
|
+
const absolutePath = resolve(directory, entry.name);
|
|
20918
|
+
if (entry.isDirectory()) {
|
|
20919
|
+
const relativeDirectory = toPortablePath(relative(rootPath, absolutePath));
|
|
20920
|
+
if (!IGNORED_DIRECTORIES.has(entry.name) && shouldVisitDirectory(relativeDirectory, searchBases)) await visit(absolutePath, depth + 1);
|
|
20921
|
+
continue;
|
|
20922
|
+
}
|
|
20923
|
+
if (!entry.isFile()) continue;
|
|
20924
|
+
const relativePath = toPortablePath(relative(rootPath, absolutePath));
|
|
20925
|
+
if (!compiled.some((rule) => rule.matcher.test(relativePath))) continue;
|
|
20926
|
+
const fileStat = await stat(absolutePath);
|
|
20927
|
+
matchedFileCount += 1;
|
|
20928
|
+
keepMostRecentArtifactFile(files, {
|
|
20929
|
+
createdAt: fileStat.birthtime.toISOString(),
|
|
20930
|
+
relativePath,
|
|
20931
|
+
size: fileStat.size,
|
|
20932
|
+
updatedAt: fileStat.mtime.toISOString()
|
|
20933
|
+
}, maxArtifactFiles);
|
|
20934
|
+
}
|
|
20935
|
+
};
|
|
20936
|
+
try {
|
|
20937
|
+
await visit(rootPath, 0);
|
|
20938
|
+
} catch (error) {
|
|
20939
|
+
issues.push({
|
|
20940
|
+
code: "PROJECT_ARTIFACT_SCAN_FAILED",
|
|
20941
|
+
message: error instanceof Error ? error.message : "Project artifact scan failed."
|
|
20942
|
+
});
|
|
20943
|
+
}
|
|
20944
|
+
if (matchedFileCount > maxArtifactFiles) issues.push({
|
|
20945
|
+
code: "PROJECT_ARTIFACT_SCAN_LIMIT",
|
|
20946
|
+
message: `Showing the ${maxArtifactFiles} most recently updated files out of ${matchedFileCount} matched artifacts.`
|
|
20947
|
+
});
|
|
20948
|
+
const matchesByPath = /* @__PURE__ */ new Map();
|
|
20949
|
+
for (const rule of compiled) for (const file of files) {
|
|
20950
|
+
if (!rule.matcher.test(file.relativePath) || matchesByPath.has(file.relativePath)) continue;
|
|
20951
|
+
matchesByPath.set(file.relativePath, {
|
|
20952
|
+
...file,
|
|
20953
|
+
categoryId: rule.id,
|
|
20954
|
+
categoryLabel: rule.label
|
|
20955
|
+
});
|
|
20956
|
+
}
|
|
20957
|
+
return {
|
|
20958
|
+
matches: [...matchesByPath.values()],
|
|
20959
|
+
issues
|
|
20960
|
+
};
|
|
20961
|
+
}
|
|
20962
|
+
//#endregion
|
|
20963
|
+
//#region src/features/projects/utils/project-observation-projection.utils.ts
|
|
20964
|
+
const projectObservationConfigReference = (asOf) => ({
|
|
20965
|
+
kind: "project-config",
|
|
20966
|
+
label: "项目配置",
|
|
20967
|
+
observedAt: asOf,
|
|
20968
|
+
projectRelativePath: ".nextclaw/project.yaml"
|
|
20969
|
+
});
|
|
20970
|
+
const projectObservationFileReference = (path, observedAt) => ({
|
|
20971
|
+
kind: "file-observation",
|
|
20972
|
+
label: "文件观测",
|
|
20973
|
+
observedAt,
|
|
20974
|
+
projectRelativePath: path
|
|
20975
|
+
});
|
|
20976
|
+
const markerReference = (marker) => ({
|
|
20977
|
+
kind: "ai-report",
|
|
20978
|
+
label: "AI 报告",
|
|
20979
|
+
observedAt: marker.timestamp,
|
|
20980
|
+
sessionId: marker.sessionId,
|
|
20981
|
+
messageId: marker.messageId
|
|
20982
|
+
});
|
|
20983
|
+
const markerActivityMessage = (marker) => {
|
|
20984
|
+
switch (marker.kind) {
|
|
20985
|
+
case "work-item": return `AI 报告工作项“${marker.name}”为 ${marker.status}`;
|
|
20986
|
+
case "artifact": return `AI 报告产物 ${marker.path}`;
|
|
20987
|
+
case "schedule": return `AI 报告 ${marker.itemId} 的计划信息`;
|
|
20988
|
+
case "signal": return marker.message;
|
|
20989
|
+
case "request": return marker.prompt;
|
|
20990
|
+
}
|
|
20991
|
+
};
|
|
20992
|
+
const readOptionalString$9 = (value) => {
|
|
20993
|
+
if (typeof value !== "string") return void 0;
|
|
20994
|
+
return value.trim() || void 0;
|
|
20995
|
+
};
|
|
20996
|
+
const readProjectRunState = (session) => {
|
|
20997
|
+
const state = (session.metadata?.last_activity_preview)?.state;
|
|
20998
|
+
if (state === "running" || state === "completed" || state === "failed" || state === "cancelled" || state === "idle") return state;
|
|
20999
|
+
return session.status === "running" ? "running" : "idle";
|
|
21000
|
+
};
|
|
21001
|
+
function projectObservedRuns(sessions, markers) {
|
|
21002
|
+
const latestWorkItemIdBySession = /* @__PURE__ */ new Map();
|
|
21003
|
+
for (const marker of markers) if (marker.kind === "work-item") latestWorkItemIdBySession.set(marker.sessionId, marker.id);
|
|
21004
|
+
return sessions.map((session) => {
|
|
21005
|
+
const preview = session.metadata?.last_activity_preview;
|
|
21006
|
+
const updatedAt = readOptionalString$9(preview?.timestamp) ?? session.lastMessageAt ?? session.updatedAt;
|
|
21007
|
+
const model = readOptionalString$9(session.metadata?.preferred_model) ?? readOptionalString$9(session.metadata?.preferredModel) ?? readOptionalString$9(session.metadata?.model);
|
|
21008
|
+
const label = readOptionalString$9(session.metadata?.label);
|
|
21009
|
+
const statusText = readOptionalString$9(preview?.statusText);
|
|
21010
|
+
const workItemId = latestWorkItemIdBySession.get(session.sessionId);
|
|
21011
|
+
return {
|
|
21012
|
+
sessionId: session.sessionId,
|
|
21013
|
+
state: readProjectRunState(session),
|
|
21014
|
+
updatedAt,
|
|
21015
|
+
...session.agentId ? { agentId: session.agentId } : {},
|
|
21016
|
+
...model ? { model } : {},
|
|
21017
|
+
...label ? { label } : {},
|
|
21018
|
+
...statusText ? { statusText } : {},
|
|
21019
|
+
...workItemId ? { workItemId } : {},
|
|
21020
|
+
reference: {
|
|
21021
|
+
kind: "system-record",
|
|
21022
|
+
label: "会话运行",
|
|
21023
|
+
observedAt: updatedAt,
|
|
21024
|
+
sessionId: session.sessionId
|
|
21025
|
+
}
|
|
21026
|
+
};
|
|
21027
|
+
}).sort((left, right) => {
|
|
21028
|
+
return Number(right.state === "running") - Number(left.state === "running") || right.updatedAt.localeCompare(left.updatedAt);
|
|
21029
|
+
});
|
|
21030
|
+
}
|
|
21031
|
+
function projectObservedWorkItems(markers, workflows, addDiagnostic) {
|
|
21032
|
+
const workItems = /* @__PURE__ */ new Map();
|
|
21033
|
+
const schedules = /* @__PURE__ */ new Map();
|
|
21034
|
+
for (const marker of markers) {
|
|
21035
|
+
if (marker.kind === "work-item") workItems.set(marker.id, marker);
|
|
21036
|
+
if (marker.kind === "schedule") schedules.set(marker.itemId, marker);
|
|
21037
|
+
}
|
|
21038
|
+
return [...workItems.values()].map((marker) => {
|
|
21039
|
+
const inferredWorkflows = marker.stageId ? workflows.filter((entry) => entry.stages.some((stage) => stage.id === marker.stageId)) : [];
|
|
21040
|
+
const workflow = marker.workflowId ? workflows.find((entry) => entry.id === marker.workflowId) : inferredWorkflows.length === 1 ? inferredWorkflows[0] : void 0;
|
|
21041
|
+
if (marker.workflowId && !workflow) addDiagnostic("sessions", "warning", "PROJECT_MARKER_WORKFLOW_UNKNOWN", `Work item '${marker.id}' references unknown workflow '${marker.workflowId}'.`, {
|
|
21042
|
+
sessionId: marker.sessionId,
|
|
21043
|
+
messageId: marker.messageId
|
|
21044
|
+
});
|
|
21045
|
+
if (marker.stageId && (!workflow || !workflow.stages.some((stage) => stage.id === marker.stageId))) addDiagnostic("sessions", "warning", "PROJECT_MARKER_STAGE_UNKNOWN", `Work item '${marker.id}' references unknown stage '${marker.stageId}'.`, {
|
|
21046
|
+
sessionId: marker.sessionId,
|
|
21047
|
+
messageId: marker.messageId
|
|
21048
|
+
});
|
|
21049
|
+
const schedule = schedules.get(marker.id);
|
|
21050
|
+
return {
|
|
21051
|
+
id: marker.id,
|
|
21052
|
+
name: marker.name,
|
|
21053
|
+
status: marker.status,
|
|
21054
|
+
...workflow ? { workflowId: workflow.id } : {},
|
|
21055
|
+
...workflow && marker.stageId && workflow.stages.some((stage) => stage.id === marker.stageId) ? { stageId: marker.stageId } : {},
|
|
21056
|
+
...schedule ? { schedule: {
|
|
21057
|
+
...schedule.start ? { start: schedule.start } : {},
|
|
21058
|
+
...schedule.end ? { end: schedule.end } : {},
|
|
21059
|
+
milestone: schedule.milestone,
|
|
21060
|
+
dependsOn: schedule.dependsOn
|
|
21061
|
+
} } : {},
|
|
21062
|
+
updatedAt: marker.timestamp,
|
|
21063
|
+
reference: markerReference(marker)
|
|
21064
|
+
};
|
|
21065
|
+
}).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
21066
|
+
}
|
|
21067
|
+
async function mergeProjectObservedArtifacts(rootPath, observed, config, markers, addDiagnostic) {
|
|
21068
|
+
const artifacts = new Map(observed.map((artifact) => [`${artifact.categoryId}:${artifact.path}`, artifact]));
|
|
21069
|
+
for (const marker of markers) {
|
|
21070
|
+
if (marker.kind !== "artifact") continue;
|
|
21071
|
+
const category = config?.artifactCategories.find((entry) => entry.id === marker.categoryId);
|
|
21072
|
+
const path = normalizeProjectRelativePath(marker.path);
|
|
21073
|
+
const file = path ? await observeProjectFile(rootPath, path) : null;
|
|
21074
|
+
if (!category) addDiagnostic("sessions", "warning", "PROJECT_MARKER_CATEGORY_UNKNOWN", `Artifact marker references unknown category '${marker.categoryId}'.`, {
|
|
21075
|
+
sessionId: marker.sessionId,
|
|
21076
|
+
messageId: marker.messageId
|
|
21077
|
+
});
|
|
21078
|
+
if (!file) addDiagnostic("files", "warning", "PROJECT_MARKER_ARTIFACT_UNAVAILABLE", `Artifact '${marker.path}' is missing or outside the project.`, {
|
|
21079
|
+
projectRelativePath: marker.path,
|
|
21080
|
+
sessionId: marker.sessionId,
|
|
21081
|
+
messageId: marker.messageId
|
|
21082
|
+
});
|
|
21083
|
+
const normalizedPath = path ?? marker.path;
|
|
21084
|
+
const key = `${marker.categoryId}:${normalizedPath}`;
|
|
21085
|
+
const existing = artifacts.get(key);
|
|
21086
|
+
if (existing) {
|
|
21087
|
+
artifacts.set(key, {
|
|
21088
|
+
...existing,
|
|
21089
|
+
itemId: marker.itemId,
|
|
21090
|
+
references: [...existing.references, markerReference(marker)]
|
|
21091
|
+
});
|
|
21092
|
+
continue;
|
|
21093
|
+
}
|
|
21094
|
+
artifacts.set(key, {
|
|
21095
|
+
id: key,
|
|
21096
|
+
path: normalizedPath,
|
|
21097
|
+
categoryId: marker.categoryId,
|
|
21098
|
+
categoryLabel: category?.label ?? marker.categoryId,
|
|
21099
|
+
exists: file !== null,
|
|
21100
|
+
itemId: marker.itemId,
|
|
21101
|
+
...file ? {
|
|
21102
|
+
size: file.size,
|
|
21103
|
+
fileCreatedAt: file.createdAt,
|
|
21104
|
+
fileUpdatedAt: file.updatedAt
|
|
21105
|
+
} : {},
|
|
21106
|
+
references: [markerReference(marker), ...file ? [projectObservationFileReference(file.relativePath, file.updatedAt)] : []]
|
|
21107
|
+
});
|
|
21108
|
+
}
|
|
21109
|
+
return [...artifacts.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
21110
|
+
}
|
|
21111
|
+
function projectObservedSignals(markers) {
|
|
21112
|
+
const signals = /* @__PURE__ */ new Map();
|
|
21113
|
+
for (const marker of markers) if (marker.kind === "signal") signals.set(marker.id, marker);
|
|
21114
|
+
return [...signals.values()].map((marker) => ({
|
|
21115
|
+
id: marker.id,
|
|
21116
|
+
...marker.itemId ? { itemId: marker.itemId } : {},
|
|
21117
|
+
status: marker.status,
|
|
21118
|
+
level: marker.level,
|
|
21119
|
+
message: marker.message,
|
|
21120
|
+
updatedAt: marker.timestamp,
|
|
21121
|
+
reference: markerReference(marker)
|
|
21122
|
+
})).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
21123
|
+
}
|
|
21124
|
+
function projectObservedRequests(markers, responses) {
|
|
21125
|
+
const requests = /* @__PURE__ */ new Map();
|
|
21126
|
+
for (const marker of markers) if (marker.kind === "request") requests.set(marker.id, marker);
|
|
21127
|
+
return [...requests.values()].map((marker) => ({
|
|
21128
|
+
id: marker.id,
|
|
21129
|
+
...marker.itemId ? { itemId: marker.itemId } : {},
|
|
21130
|
+
status: marker.status,
|
|
21131
|
+
response: marker.response,
|
|
21132
|
+
prompt: marker.prompt,
|
|
21133
|
+
updatedAt: marker.timestamp,
|
|
21134
|
+
...responses.get(marker.id) ? { reply: responses.get(marker.id) } : {},
|
|
21135
|
+
reference: markerReference(marker)
|
|
21136
|
+
})).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
21137
|
+
}
|
|
21138
|
+
const projectObservedActivity = (markers) => markers.map((marker) => ({
|
|
21139
|
+
id: `${marker.messageId}:${marker.line}:${marker.kind}`,
|
|
21140
|
+
kind: marker.kind,
|
|
21141
|
+
message: markerActivityMessage(marker),
|
|
21142
|
+
at: marker.timestamp,
|
|
21143
|
+
...marker.kind === "work-item" ? { itemId: marker.id } : marker.kind === "artifact" || marker.kind === "schedule" ? { itemId: marker.itemId } : marker.itemId ? { itemId: marker.itemId } : {},
|
|
21144
|
+
reference: markerReference(marker)
|
|
21145
|
+
})).sort((left, right) => right.at.localeCompare(left.at));
|
|
21146
|
+
//#endregion
|
|
21147
|
+
//#region src/features/projects/utils/project-observation-marker.utils.ts
|
|
21148
|
+
function createProjectObservationMarkerParseState() {
|
|
21149
|
+
return {
|
|
21150
|
+
currentWorkItemIdBySession: /* @__PURE__ */ new Map(),
|
|
21151
|
+
requestsById: /* @__PURE__ */ new Map(),
|
|
21152
|
+
workItemsById: /* @__PURE__ */ new Map()
|
|
21153
|
+
};
|
|
21154
|
+
}
|
|
21155
|
+
const ID_VALUE = "[a-z0-9][a-z0-9._-]*";
|
|
21156
|
+
const ID = `(${ID_VALUE})`;
|
|
21157
|
+
const OPTIONAL_ID = `(${ID_VALUE}|none)`;
|
|
21158
|
+
const TEXT = "([^\"\\]\\r\\n]{1,240})";
|
|
21159
|
+
const DATE = "(\\d{4}-\\d{2}-\\d{2}|none)";
|
|
21160
|
+
const PREFIX = "\\[nextclaw\\.project/v1 ";
|
|
21161
|
+
const LEGACY_WORK_ITEM_PATTERN = new RegExp(`^${PREFIX}kind=work-item id=${ID} title="${TEXT}" workflow=${OPTIONAL_ID} stage=${OPTIONAL_ID} status=(active|blocked|completed|cancelled)\\]$`);
|
|
21162
|
+
const LEGACY_ARTIFACT_PATTERN = new RegExp(`^${PREFIX}kind=artifact item=${ID} path="${TEXT}" category=${ID}\\]$`);
|
|
21163
|
+
const LEGACY_SCHEDULE_PATTERN = new RegExp(`^${PREFIX}kind=schedule item=${ID} start=${DATE} end=${DATE} milestone=(true|false) depends-on=([a-z0-9._,-]+|none)\\]$`);
|
|
21164
|
+
const LEGACY_SIGNAL_PATTERN = new RegExp(`^${PREFIX}kind=signal id=${ID} item=${OPTIONAL_ID} status=(open|resolved) level=(info|attention|warning) message="${TEXT}"\\]$`);
|
|
21165
|
+
const LEGACY_REQUEST_PATTERN = new RegExp(`^${PREFIX}kind=request id=${ID} item=${OPTIONAL_ID} status=(open|resolved|expired) response=(confirm-reject|open-session) prompt="${TEXT}"\\]$`);
|
|
21166
|
+
const ID_PATTERN = new RegExp(`^${ID_VALUE}$`);
|
|
21167
|
+
const FIELD_PATTERN = /([a-z][a-z-]*)=(?:"([^"\\\]\r\n]{1,240})"|([^\s\]]+))/y;
|
|
21168
|
+
const WORK_ITEM_STATUSES = new Set([
|
|
21169
|
+
"active",
|
|
21170
|
+
"blocked",
|
|
21171
|
+
"completed",
|
|
21172
|
+
"cancelled"
|
|
21173
|
+
]);
|
|
21174
|
+
const REQUEST_STATUSES = new Set([
|
|
21175
|
+
"open",
|
|
21176
|
+
"resolved",
|
|
21177
|
+
"expired"
|
|
21178
|
+
]);
|
|
21179
|
+
const REQUEST_RESPONSES = new Set(["confirm-reject", "open-session"]);
|
|
21180
|
+
const optional = (value) => value === "none" ? void 0 : value;
|
|
21181
|
+
function parseFields(value) {
|
|
21182
|
+
const fields = /* @__PURE__ */ new Map();
|
|
21183
|
+
let cursor = 0;
|
|
21184
|
+
while (cursor < value.length) {
|
|
21185
|
+
FIELD_PATTERN.lastIndex = cursor;
|
|
21186
|
+
const match = FIELD_PATTERN.exec(value);
|
|
21187
|
+
if (!match || fields.has(match[1])) return null;
|
|
21188
|
+
fields.set(match[1], match[2] ?? match[3]);
|
|
21189
|
+
cursor = FIELD_PATTERN.lastIndex;
|
|
21190
|
+
if (cursor === value.length) break;
|
|
21191
|
+
if (value[cursor] !== " ") return null;
|
|
21192
|
+
cursor += 1;
|
|
21193
|
+
}
|
|
21194
|
+
return fields;
|
|
21195
|
+
}
|
|
21196
|
+
function hasOnlyFields(fields, allowed) {
|
|
21197
|
+
const allowedSet = new Set(allowed);
|
|
21198
|
+
return [...fields.keys()].every((key) => allowedSet.has(key));
|
|
21199
|
+
}
|
|
21200
|
+
function rememberWorkItem(marker, state) {
|
|
21201
|
+
state.currentWorkItemIdBySession.set(marker.sessionId, marker.id);
|
|
21202
|
+
state.workItemsById.set(marker.id, {
|
|
21203
|
+
id: marker.id,
|
|
21204
|
+
name: marker.name,
|
|
21205
|
+
...marker.workflowId ? { workflowId: marker.workflowId } : {},
|
|
21206
|
+
...marker.stageId ? { stageId: marker.stageId } : {},
|
|
21207
|
+
status: marker.status
|
|
21208
|
+
});
|
|
21209
|
+
}
|
|
21210
|
+
function rememberRequest(marker, state) {
|
|
21211
|
+
state.requestsById.set(marker.id, {
|
|
21212
|
+
id: marker.id,
|
|
21213
|
+
...marker.itemId ? { itemId: marker.itemId } : {},
|
|
21214
|
+
status: marker.status,
|
|
21215
|
+
response: marker.response,
|
|
21216
|
+
prompt: marker.prompt
|
|
21217
|
+
});
|
|
21218
|
+
}
|
|
21219
|
+
function parseLegacyMarkerLine(line, source, state) {
|
|
21220
|
+
let match = LEGACY_WORK_ITEM_PATTERN.exec(line);
|
|
21221
|
+
if (match) {
|
|
21222
|
+
const marker = {
|
|
21223
|
+
...source,
|
|
21224
|
+
kind: "work-item",
|
|
21225
|
+
id: match[1],
|
|
21226
|
+
name: match[2],
|
|
21227
|
+
...optional(match[3]) ? { workflowId: optional(match[3]) } : {},
|
|
21228
|
+
...optional(match[4]) ? { stageId: optional(match[4]) } : {},
|
|
21229
|
+
status: match[5]
|
|
21230
|
+
};
|
|
21231
|
+
rememberWorkItem(marker, state);
|
|
21232
|
+
return marker;
|
|
21233
|
+
}
|
|
21234
|
+
match = LEGACY_ARTIFACT_PATTERN.exec(line);
|
|
21235
|
+
if (match) return {
|
|
21236
|
+
...source,
|
|
21237
|
+
kind: "artifact",
|
|
21238
|
+
itemId: match[1],
|
|
21239
|
+
path: match[2],
|
|
21240
|
+
categoryId: match[3]
|
|
21241
|
+
};
|
|
21242
|
+
match = LEGACY_SCHEDULE_PATTERN.exec(line);
|
|
21243
|
+
if (match) return {
|
|
21244
|
+
...source,
|
|
21245
|
+
kind: "schedule",
|
|
21246
|
+
itemId: match[1],
|
|
21247
|
+
...optional(match[2]) ? { start: optional(match[2]) } : {},
|
|
21248
|
+
...optional(match[3]) ? { end: optional(match[3]) } : {},
|
|
21249
|
+
milestone: match[4] === "true",
|
|
21250
|
+
dependsOn: match[5] === "none" ? [] : match[5].split(",")
|
|
21251
|
+
};
|
|
21252
|
+
match = LEGACY_SIGNAL_PATTERN.exec(line);
|
|
21253
|
+
if (match) return {
|
|
21254
|
+
...source,
|
|
21255
|
+
kind: "signal",
|
|
21256
|
+
id: match[1],
|
|
21257
|
+
...optional(match[2]) ? { itemId: optional(match[2]) } : {},
|
|
21258
|
+
status: match[3],
|
|
21259
|
+
level: match[4],
|
|
21260
|
+
message: match[5]
|
|
21261
|
+
};
|
|
21262
|
+
match = LEGACY_REQUEST_PATTERN.exec(line);
|
|
21263
|
+
if (match) {
|
|
21264
|
+
const marker = {
|
|
21265
|
+
...source,
|
|
21266
|
+
kind: "request",
|
|
21267
|
+
id: match[1],
|
|
21268
|
+
...optional(match[2]) ? { itemId: optional(match[2]) } : {},
|
|
21269
|
+
status: match[3],
|
|
21270
|
+
response: match[4],
|
|
21271
|
+
prompt: match[5]
|
|
21272
|
+
};
|
|
21273
|
+
rememberRequest(marker, state);
|
|
21274
|
+
return marker;
|
|
21275
|
+
}
|
|
21276
|
+
return null;
|
|
21277
|
+
}
|
|
21278
|
+
function parseCompactWorkItem(body, source, state) {
|
|
21279
|
+
const fields = parseFields(body);
|
|
21280
|
+
if (!fields || fields.size === 0 || !hasOnlyFields(fields, [
|
|
21281
|
+
"id",
|
|
21282
|
+
"name",
|
|
21283
|
+
"workflow",
|
|
21284
|
+
"stage",
|
|
21285
|
+
"status"
|
|
21286
|
+
])) return null;
|
|
21287
|
+
const explicitId = fields.get("id");
|
|
21288
|
+
if (explicitId && !ID_PATTERN.test(explicitId)) return null;
|
|
21289
|
+
const id = explicitId ?? state.currentWorkItemIdBySession.get(source.sessionId);
|
|
21290
|
+
if (!id) return null;
|
|
21291
|
+
const previous = state.workItemsById.get(id);
|
|
21292
|
+
const explicitName = fields.get("name");
|
|
21293
|
+
if (!previous && (!explicitName || !fields.has("stage"))) return null;
|
|
21294
|
+
if (previous && explicitName && explicitName !== previous.name) return null;
|
|
21295
|
+
const statusValue = fields.get("status");
|
|
21296
|
+
if (statusValue && !WORK_ITEM_STATUSES.has(statusValue)) return null;
|
|
21297
|
+
const workflowValue = fields.get("workflow");
|
|
21298
|
+
const stageValue = fields.get("stage");
|
|
21299
|
+
if (workflowValue && workflowValue !== "none" && !ID_PATTERN.test(workflowValue) || stageValue && stageValue !== "none" && !ID_PATTERN.test(stageValue)) return null;
|
|
21300
|
+
const workflowId = workflowValue === void 0 ? previous?.workflowId : optional(workflowValue);
|
|
21301
|
+
const stageId = stageValue === void 0 ? previous?.stageId : optional(stageValue);
|
|
21302
|
+
const marker = {
|
|
21303
|
+
...source,
|
|
21304
|
+
kind: "work-item",
|
|
21305
|
+
id,
|
|
21306
|
+
name: explicitName ?? previous.name,
|
|
21307
|
+
...workflowId ? { workflowId } : {},
|
|
21308
|
+
...stageId ? { stageId } : {},
|
|
21309
|
+
status: statusValue ?? (fields.has("stage") ? "active" : previous?.status ?? "active")
|
|
21310
|
+
};
|
|
21311
|
+
rememberWorkItem(marker, state);
|
|
21312
|
+
return marker;
|
|
21313
|
+
}
|
|
21314
|
+
function parseCompactArtifact(body, source, state) {
|
|
21315
|
+
const fields = parseFields(body);
|
|
21316
|
+
if (!fields || !hasOnlyFields(fields, [
|
|
21317
|
+
"path",
|
|
21318
|
+
"category",
|
|
21319
|
+
"work-id"
|
|
21320
|
+
])) return null;
|
|
21321
|
+
const path = fields.get("path");
|
|
21322
|
+
const categoryId = fields.get("category");
|
|
21323
|
+
const itemId = fields.get("work-id") ?? state.currentWorkItemIdBySession.get(source.sessionId);
|
|
21324
|
+
if (!path || !categoryId || !itemId || !ID_PATTERN.test(categoryId) || !ID_PATTERN.test(itemId)) return null;
|
|
21325
|
+
return {
|
|
21326
|
+
...source,
|
|
21327
|
+
kind: "artifact",
|
|
21328
|
+
itemId,
|
|
21329
|
+
path,
|
|
21330
|
+
categoryId
|
|
21331
|
+
};
|
|
21332
|
+
}
|
|
21333
|
+
function parseCompactRequest(body, source, state) {
|
|
21334
|
+
const fields = parseFields(body);
|
|
21335
|
+
if (!fields || !hasOnlyFields(fields, [
|
|
21336
|
+
"request",
|
|
21337
|
+
"work-id",
|
|
21338
|
+
"status",
|
|
21339
|
+
"response",
|
|
21340
|
+
"prompt"
|
|
21341
|
+
])) return null;
|
|
21342
|
+
const id = fields.get("request");
|
|
21343
|
+
if (!id || !ID_PATTERN.test(id)) return null;
|
|
21344
|
+
const previous = state.requestsById.get(id);
|
|
21345
|
+
const itemId = fields.get("work-id") ?? previous?.itemId ?? state.currentWorkItemIdBySession.get(source.sessionId);
|
|
21346
|
+
const statusValue = fields.get("status") ?? previous?.status ?? "open";
|
|
21347
|
+
const responseValue = fields.get("response") ?? previous?.response;
|
|
21348
|
+
const prompt = fields.get("prompt") ?? previous?.prompt;
|
|
21349
|
+
if (!responseValue || !prompt || !REQUEST_STATUSES.has(statusValue) || !REQUEST_RESPONSES.has(responseValue) || itemId && !ID_PATTERN.test(itemId)) return null;
|
|
21350
|
+
const marker = {
|
|
21351
|
+
...source,
|
|
21352
|
+
kind: "request",
|
|
21353
|
+
id,
|
|
21354
|
+
...itemId ? { itemId } : {},
|
|
21355
|
+
status: statusValue,
|
|
21356
|
+
response: responseValue,
|
|
21357
|
+
prompt
|
|
21358
|
+
};
|
|
21359
|
+
rememberRequest(marker, state);
|
|
21360
|
+
return marker;
|
|
21361
|
+
}
|
|
21362
|
+
function parseCompactMarkerLine(line, source, state) {
|
|
21363
|
+
const prefix = `[${PROJECT_OBSERVATION_PROTOCOL} `;
|
|
21364
|
+
if (!line.startsWith(prefix) || !line.endsWith("]")) return null;
|
|
21365
|
+
const body = line.slice(prefix.length, -1);
|
|
21366
|
+
if (body.startsWith("artifact ")) return parseCompactArtifact(body.slice(9), source, state);
|
|
21367
|
+
if (body.startsWith("request=")) return parseCompactRequest(body, source, state);
|
|
21368
|
+
return parseCompactWorkItem(body, source, state);
|
|
21369
|
+
}
|
|
21370
|
+
function parseProjectObservationMarkers(params) {
|
|
21371
|
+
const markers = [];
|
|
21372
|
+
const issues = [];
|
|
21373
|
+
const state = params.state ?? createProjectObservationMarkerParseState();
|
|
21374
|
+
let insideFencedCodeBlock = false;
|
|
21375
|
+
params.text.split(/\r?\n/).forEach((rawLine, index) => {
|
|
21376
|
+
const line = rawLine.trim();
|
|
21377
|
+
if (line.startsWith("```")) {
|
|
21378
|
+
insideFencedCodeBlock = !insideFencedCodeBlock;
|
|
21379
|
+
return;
|
|
21380
|
+
}
|
|
21381
|
+
if (insideFencedCodeBlock) return;
|
|
21382
|
+
if (!line.startsWith(`[nextclaw.project/v1`)) return;
|
|
21383
|
+
const source = {
|
|
21384
|
+
sessionId: params.sessionId,
|
|
21385
|
+
messageId: params.messageId,
|
|
21386
|
+
timestamp: params.timestamp,
|
|
21387
|
+
line: index + 1
|
|
21388
|
+
};
|
|
21389
|
+
const marker = line.includes(" kind=") ? parseLegacyMarkerLine(line, source, state) : parseCompactMarkerLine(line, source, state);
|
|
21390
|
+
if (marker) {
|
|
21391
|
+
markers.push(marker);
|
|
21392
|
+
return;
|
|
21393
|
+
}
|
|
21394
|
+
if (params.reportInvalid !== false) issues.push({
|
|
21395
|
+
code: "PROJECT_MARKER_INVALID",
|
|
21396
|
+
message: `Invalid ${PROJECT_OBSERVATION_PROTOCOL} marker at line ${index + 1}.`,
|
|
21397
|
+
line: index + 1
|
|
21398
|
+
});
|
|
21399
|
+
});
|
|
21400
|
+
return {
|
|
21401
|
+
markers,
|
|
21402
|
+
issues
|
|
21403
|
+
};
|
|
21404
|
+
}
|
|
21405
|
+
const isRecord$8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21406
|
+
function readProjectObservationResponseMetadata(metadata) {
|
|
21407
|
+
const response = metadata?.project_observation_response;
|
|
21408
|
+
if (!isRecord$8(response) || response.protocol !== "nextclaw.project/v1" || typeof response.requestId !== "string" || response.decision !== "confirmed" && response.decision !== "rejected") return null;
|
|
21409
|
+
return {
|
|
21410
|
+
protocol: PROJECT_OBSERVATION_PROTOCOL,
|
|
21411
|
+
requestId: response.requestId,
|
|
21412
|
+
decision: response.decision
|
|
21413
|
+
};
|
|
21414
|
+
}
|
|
21415
|
+
//#endregion
|
|
21416
|
+
//#region src/features/projects/services/project-observation.service.ts
|
|
21417
|
+
const SOURCE_LABELS = {
|
|
21418
|
+
config: "项目配置",
|
|
21419
|
+
files: "项目文件",
|
|
21420
|
+
sessions: "项目会话",
|
|
21421
|
+
skills: "项目 Skills"
|
|
21422
|
+
};
|
|
21423
|
+
const readOptionalString$8 = (value) => {
|
|
21424
|
+
if (typeof value !== "string") return;
|
|
21425
|
+
return value.trim() || void 0;
|
|
21426
|
+
};
|
|
21427
|
+
const readSessionProjectRoot$1 = (session) => readOptionalString$8(session.metadata?.project_root) ?? readOptionalString$8(session.metadata?.projectRoot);
|
|
21428
|
+
const readMessageText = (message) => message.parts.flatMap((part) => part.type === "text" || part.type === "rich-text" ? [part.text] : []).join("\n");
|
|
21429
|
+
const compareMarkerSource = (left, right) => left.timestamp.localeCompare(right.timestamp) || left.sessionId.localeCompare(right.sessionId) || left.messageId.localeCompare(right.messageId) || left.line - right.line;
|
|
21430
|
+
const markerConflictKey = (marker) => {
|
|
21431
|
+
switch (marker.kind) {
|
|
21432
|
+
case "work-item":
|
|
21433
|
+
case "signal":
|
|
21434
|
+
case "request": return `${marker.kind}:${marker.id}`;
|
|
21435
|
+
case "schedule": return `${marker.kind}:${marker.itemId}`;
|
|
21436
|
+
case "artifact": return null;
|
|
21437
|
+
}
|
|
21438
|
+
};
|
|
21439
|
+
const markerSemanticValue = (marker) => {
|
|
21440
|
+
const { line: _line, messageId: _messageId, sessionId: _sessionId, timestamp: _timestamp, ...semantic } = marker;
|
|
21441
|
+
return JSON.stringify(semantic);
|
|
21442
|
+
};
|
|
21443
|
+
const parseProjectSessionMessage = (sessionId, message, state) => {
|
|
21444
|
+
if (message.role === "assistant") {
|
|
21445
|
+
const parsed = parseProjectObservationMarkers({
|
|
21446
|
+
text: readMessageText(message),
|
|
21447
|
+
sessionId,
|
|
21448
|
+
messageId: message.id,
|
|
21449
|
+
timestamp: message.timestamp,
|
|
21450
|
+
reportInvalid: message.status === "final" || message.status === "error",
|
|
21451
|
+
state
|
|
21452
|
+
});
|
|
21453
|
+
return {
|
|
21454
|
+
markers: parsed.markers,
|
|
21455
|
+
markerIssues: parsed.issues
|
|
21456
|
+
};
|
|
21457
|
+
}
|
|
21458
|
+
if (message.role !== "user") return {
|
|
21459
|
+
markers: [],
|
|
21460
|
+
markerIssues: []
|
|
21461
|
+
};
|
|
21462
|
+
const response = readProjectObservationResponseMetadata(message.metadata);
|
|
21463
|
+
return {
|
|
21464
|
+
markers: [],
|
|
21465
|
+
markerIssues: [],
|
|
21466
|
+
...response ? { response: {
|
|
21467
|
+
requestId: response.requestId,
|
|
21468
|
+
decision: response.decision,
|
|
21469
|
+
sentAt: message.timestamp,
|
|
21470
|
+
messageId: message.id
|
|
21471
|
+
} } : {}
|
|
21472
|
+
};
|
|
21473
|
+
};
|
|
21474
|
+
const mergeLatestResponse = (responses, response) => {
|
|
21475
|
+
const next = new Map(responses);
|
|
21476
|
+
const current = next.get(response.requestId);
|
|
21477
|
+
if (!current || current.sentAt.localeCompare(response.sentAt) <= 0) {
|
|
21478
|
+
const { requestId, ...value } = response;
|
|
21479
|
+
next.set(requestId, value);
|
|
21480
|
+
}
|
|
21481
|
+
return next;
|
|
21482
|
+
};
|
|
21483
|
+
var ProjectObservationService = class {
|
|
21484
|
+
now;
|
|
21485
|
+
constructor(options) {
|
|
21486
|
+
this.options = options;
|
|
21487
|
+
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
21488
|
+
}
|
|
21489
|
+
observe = async (rootPath) => {
|
|
21490
|
+
let project;
|
|
21491
|
+
try {
|
|
21492
|
+
project = await this.options.projectManager.getRegisteredProject(rootPath);
|
|
21493
|
+
} catch (error) {
|
|
21494
|
+
throw new ProjectObservationError("PROJECT_OBSERVATION_INVALID_ROOT", error instanceof Error ? error.message : "Project root is invalid.");
|
|
21495
|
+
}
|
|
21496
|
+
if (!project) throw new ProjectObservationError("PROJECT_NOT_REGISTERED", "Project is not registered.");
|
|
21497
|
+
const asOf = this.now().toISOString();
|
|
21498
|
+
const diagnostics = [];
|
|
21499
|
+
const sourceCounts = /* @__PURE__ */ new Map();
|
|
21500
|
+
const sourceErrors = /* @__PURE__ */ new Set();
|
|
21501
|
+
const addDiagnostic = (source, level, code, message, details = {}) => {
|
|
21502
|
+
if (level === "error") sourceErrors.add(source);
|
|
21503
|
+
diagnostics.push({
|
|
21504
|
+
id: `${source}:${code}:${diagnostics.filter((entry) => entry.source === source && entry.code === code).length + 1}`,
|
|
21505
|
+
source,
|
|
21506
|
+
level,
|
|
21507
|
+
code,
|
|
21508
|
+
message,
|
|
21509
|
+
...details
|
|
21510
|
+
});
|
|
21511
|
+
};
|
|
21512
|
+
const addSourceCount = (source, count) => {
|
|
21513
|
+
sourceCounts.set(source, (sourceCounts.get(source) ?? 0) + count);
|
|
21514
|
+
};
|
|
21515
|
+
const config = await this.readConfig(project.rootPath, addDiagnostic);
|
|
21516
|
+
const context = await this.observeContext(project.rootPath, config, asOf, addDiagnostic);
|
|
21517
|
+
addSourceCount("config", (config ? 1 : 0) + context.length + (config?.workflows.length ?? 0));
|
|
21518
|
+
const artifacts = await this.observeArtifacts(project.rootPath, config, asOf, addDiagnostic);
|
|
21519
|
+
addSourceCount("files", artifacts.length);
|
|
21520
|
+
const sessionObservation = await this.observeSessions(project.rootPath, addDiagnostic);
|
|
21521
|
+
addSourceCount("sessions", sessionObservation.sessions.length);
|
|
21522
|
+
const skills = this.observeSkills(project.rootPath, config, asOf, addDiagnostic);
|
|
21523
|
+
addSourceCount("skills", skills.length);
|
|
21524
|
+
const workflows = (config?.workflows ?? []).map((workflow) => ({
|
|
21525
|
+
...workflow,
|
|
21526
|
+
reference: projectObservationConfigReference(asOf)
|
|
21527
|
+
}));
|
|
21528
|
+
const workItems = projectObservedWorkItems(sessionObservation.markers, workflows, addDiagnostic);
|
|
21529
|
+
const runs = projectObservedRuns(sessionObservation.sessions, sessionObservation.markers);
|
|
21530
|
+
const mergedArtifacts = await mergeProjectObservedArtifacts(project.rootPath, artifacts, config, sessionObservation.markers, addDiagnostic);
|
|
21531
|
+
const signals = projectObservedSignals(sessionObservation.markers);
|
|
21532
|
+
const requests = projectObservedRequests(sessionObservation.markers, sessionObservation.responses);
|
|
21533
|
+
const activity = projectObservedActivity(sessionObservation.markers);
|
|
21534
|
+
const sources = Object.keys(SOURCE_LABELS).map((source) => this.createSourceStatus(source, asOf, sourceCounts.get(source) ?? 0, sourceErrors.has(source), diagnostics));
|
|
21535
|
+
const errorSourceCount = sources.filter((source) => source.status === "error").length;
|
|
21536
|
+
return {
|
|
21537
|
+
asOf,
|
|
21538
|
+
project: {
|
|
21539
|
+
name: project.name,
|
|
21540
|
+
rootPath: project.rootPath,
|
|
21541
|
+
...config?.summary ? { summary: config.summary } : {},
|
|
21542
|
+
context
|
|
21543
|
+
},
|
|
21544
|
+
sources,
|
|
21545
|
+
workflows,
|
|
21546
|
+
runs,
|
|
21547
|
+
workItems,
|
|
21548
|
+
artifactCategories: (config?.artifactCategories ?? []).map(({ id, label }) => ({
|
|
21549
|
+
id,
|
|
21550
|
+
label
|
|
21551
|
+
})),
|
|
21552
|
+
artifacts: mergedArtifacts,
|
|
21553
|
+
signals,
|
|
21554
|
+
requests,
|
|
21555
|
+
activity,
|
|
21556
|
+
skills,
|
|
21557
|
+
diagnostics,
|
|
21558
|
+
dataQuality: errorSourceCount === sources.length ? "unavailable" : diagnostics.some((entry) => entry.level === "error" || entry.level === "warning") ? "partial" : "complete"
|
|
21559
|
+
};
|
|
21560
|
+
};
|
|
21561
|
+
readConfig = async (rootPath, addDiagnostic) => {
|
|
21562
|
+
const path = ".nextclaw/project.yaml";
|
|
21563
|
+
if (!await observeProjectFile(rootPath, path)) {
|
|
21564
|
+
addDiagnostic("config", "info", "PROJECT_CONFIG_NOT_FOUND", "No .nextclaw/project.yaml was found.", { projectRelativePath: path });
|
|
21565
|
+
return null;
|
|
21566
|
+
}
|
|
21567
|
+
try {
|
|
21568
|
+
const result = parseProjectObservationConfig(await readFile(join(rootPath, path), "utf8"));
|
|
21569
|
+
for (const issue of result.issues) addDiagnostic("config", result.config ? "warning" : "error", issue.code, issue.message, { projectRelativePath: path });
|
|
21570
|
+
return result.config;
|
|
21571
|
+
} catch (error) {
|
|
21572
|
+
addDiagnostic("config", "error", "PROJECT_CONFIG_READ_FAILED", error instanceof Error ? error.message : "Project config could not be read.", { projectRelativePath: path });
|
|
21573
|
+
return null;
|
|
21574
|
+
}
|
|
21575
|
+
};
|
|
21576
|
+
observeContext = async (rootPath, config, asOf, addDiagnostic) => await Promise.all((config?.context ?? []).map(async (entry) => {
|
|
21577
|
+
const path = normalizeProjectRelativePath(entry.source);
|
|
21578
|
+
const observed = path ? await observeProjectFile(rootPath, path) : null;
|
|
21579
|
+
if (!observed) addDiagnostic("files", "warning", "PROJECT_CONTEXT_SOURCE_UNAVAILABLE", `Context source '${entry.source}' is unavailable or outside the project.`, { projectRelativePath: entry.source });
|
|
21580
|
+
return {
|
|
21581
|
+
...entry,
|
|
21582
|
+
accessible: observed !== null,
|
|
21583
|
+
reference: observed ? projectObservationFileReference(observed.relativePath, asOf) : projectObservationConfigReference(asOf)
|
|
21584
|
+
};
|
|
21585
|
+
}));
|
|
21586
|
+
observeArtifacts = async (rootPath, config, asOf, addDiagnostic) => {
|
|
21587
|
+
const result = await scanProjectArtifactFiles(rootPath, config?.artifactCategories ?? []);
|
|
21588
|
+
for (const issue of result.issues) addDiagnostic("files", "warning", issue.code, issue.message, { ...issue.projectRelativePath ? { projectRelativePath: issue.projectRelativePath } : {} });
|
|
21589
|
+
return result.matches.map((match) => ({
|
|
21590
|
+
id: `${match.categoryId}:${match.relativePath}`,
|
|
21591
|
+
path: match.relativePath,
|
|
21592
|
+
categoryId: match.categoryId,
|
|
21593
|
+
categoryLabel: match.categoryLabel,
|
|
21594
|
+
exists: true,
|
|
21595
|
+
size: match.size,
|
|
21596
|
+
fileCreatedAt: match.createdAt,
|
|
21597
|
+
fileUpdatedAt: match.updatedAt,
|
|
21598
|
+
references: [projectObservationFileReference(match.relativePath, asOf)]
|
|
21599
|
+
}));
|
|
21600
|
+
};
|
|
21601
|
+
observeSessions = async (rootPath, addDiagnostic) => {
|
|
21602
|
+
const markers = [];
|
|
21603
|
+
let responses = /* @__PURE__ */ new Map();
|
|
21604
|
+
let sessions;
|
|
21605
|
+
try {
|
|
21606
|
+
sessions = (await this.options.sessionManager.listSessions()).filter((session) => readSessionProjectRoot$1(session) === rootPath);
|
|
21607
|
+
} catch (error) {
|
|
21608
|
+
addDiagnostic("sessions", "error", "PROJECT_SESSIONS_READ_FAILED", error instanceof Error ? error.message : "Project sessions could not be listed.");
|
|
21609
|
+
return {
|
|
21610
|
+
markers,
|
|
21611
|
+
responses,
|
|
21612
|
+
sessions: []
|
|
21613
|
+
};
|
|
21614
|
+
}
|
|
21615
|
+
const messages = [];
|
|
21616
|
+
for (const session of sessions) try {
|
|
21617
|
+
messages.push(...(await this.options.sessionManager.listSessionMessages(session.sessionId)).map((message) => ({
|
|
21618
|
+
message,
|
|
21619
|
+
sessionId: session.sessionId
|
|
21620
|
+
})));
|
|
21621
|
+
} catch (error) {
|
|
21622
|
+
addDiagnostic("sessions", "error", "PROJECT_SESSION_MESSAGES_READ_FAILED", error instanceof Error ? error.message : "Project session messages could not be read.", { sessionId: session.sessionId });
|
|
21623
|
+
}
|
|
21624
|
+
messages.sort((left, right) => left.message.timestamp.localeCompare(right.message.timestamp) || left.sessionId.localeCompare(right.sessionId) || left.message.id.localeCompare(right.message.id));
|
|
21625
|
+
const parseState = createProjectObservationMarkerParseState();
|
|
21626
|
+
for (const { message, sessionId } of messages) {
|
|
21627
|
+
const parsed = parseProjectSessionMessage(sessionId, message, parseState);
|
|
21628
|
+
markers.push(...parsed.markers);
|
|
21629
|
+
for (const issue of parsed.markerIssues) addDiagnostic("sessions", "warning", issue.code, issue.message, {
|
|
21630
|
+
sessionId,
|
|
21631
|
+
messageId: message.id
|
|
21632
|
+
});
|
|
21633
|
+
if (parsed.response) responses = mergeLatestResponse(responses, parsed.response);
|
|
21634
|
+
}
|
|
21635
|
+
markers.sort(compareMarkerSource);
|
|
21636
|
+
this.addMarkerConflictDiagnostics(markers, addDiagnostic);
|
|
21637
|
+
return {
|
|
21638
|
+
markers,
|
|
21639
|
+
responses,
|
|
21640
|
+
sessions
|
|
21641
|
+
};
|
|
21642
|
+
};
|
|
21643
|
+
addMarkerConflictDiagnostics = (markers, addDiagnostic) => {
|
|
21644
|
+
const latestAtByKey = /* @__PURE__ */ new Map();
|
|
21645
|
+
for (const marker of markers) {
|
|
21646
|
+
const key = markerConflictKey(marker);
|
|
21647
|
+
if (!key) continue;
|
|
21648
|
+
const current = latestAtByKey.get(key);
|
|
21649
|
+
const value = markerSemanticValue(marker);
|
|
21650
|
+
if (current?.timestamp === marker.timestamp && (current.sessionId !== marker.sessionId || current.messageId !== marker.messageId) && current.value !== value) addDiagnostic("sessions", "warning", "PROJECT_MARKER_CONFLICT", `Conflicting '${key}' markers share the same observation time; a deterministic source order was used.`, {
|
|
21651
|
+
sessionId: marker.sessionId,
|
|
21652
|
+
messageId: marker.messageId
|
|
21653
|
+
});
|
|
21654
|
+
latestAtByKey.set(key, {
|
|
21655
|
+
messageId: marker.messageId,
|
|
21656
|
+
sessionId: marker.sessionId,
|
|
21657
|
+
timestamp: marker.timestamp,
|
|
21658
|
+
value
|
|
21659
|
+
});
|
|
21660
|
+
}
|
|
21661
|
+
};
|
|
21662
|
+
observeSkills = (rootPath, config, asOf, addDiagnostic) => {
|
|
21663
|
+
const output = /* @__PURE__ */ new Map();
|
|
21664
|
+
for (const skillRoot of config?.skillRoots ?? [".agents/skills"]) {
|
|
21665
|
+
const normalizedRoot = normalizeProjectRelativePath(skillRoot);
|
|
21666
|
+
if (!normalizedRoot) {
|
|
21667
|
+
addDiagnostic("skills", "warning", "PROJECT_SKILL_ROOT_INVALID", `Skill root '${skillRoot}' is outside the project.`, { projectRelativePath: skillRoot });
|
|
21668
|
+
continue;
|
|
21669
|
+
}
|
|
21670
|
+
try {
|
|
21671
|
+
const loader = new SkillsLoader({
|
|
21672
|
+
workspace: this.options.workspacePath,
|
|
21673
|
+
projectRoot: rootPath,
|
|
21674
|
+
projectSkillsDirName: normalizedRoot,
|
|
21675
|
+
includeBuiltin: false,
|
|
21676
|
+
includeGlobal: false
|
|
21677
|
+
});
|
|
21678
|
+
for (const skill of loader.listSkills(false).filter((entry) => entry.scope === "project")) {
|
|
21679
|
+
const metadata = loader.getSkillMetadata(skill) ?? {};
|
|
21680
|
+
const relativePath = normalizeProjectRelativePath(skill.path.slice(rootPath.length + 1)) ?? `${normalizedRoot}/${skill.name}/SKILL.md`;
|
|
21681
|
+
output.set(skill.ref, {
|
|
21682
|
+
ref: skill.ref,
|
|
21683
|
+
name: skill.name,
|
|
21684
|
+
...metadata.description ? { description: metadata.description } : {},
|
|
21685
|
+
source: "project",
|
|
21686
|
+
path: relativePath,
|
|
21687
|
+
readable: true,
|
|
21688
|
+
reference: projectObservationFileReference(relativePath, asOf)
|
|
21689
|
+
});
|
|
21690
|
+
}
|
|
21691
|
+
} catch (error) {
|
|
21692
|
+
addDiagnostic("skills", "error", "PROJECT_SKILLS_READ_FAILED", error instanceof Error ? error.message : "Project skills could not be read.", { projectRelativePath: normalizedRoot });
|
|
21693
|
+
}
|
|
21694
|
+
}
|
|
21695
|
+
return [...output.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
21696
|
+
};
|
|
21697
|
+
createSourceStatus = (source, asOf, itemCount, hasError, diagnostics) => ({
|
|
21698
|
+
id: source,
|
|
21699
|
+
label: SOURCE_LABELS[source],
|
|
21700
|
+
status: hasError ? "error" : itemCount > 0 ? "available" : "empty",
|
|
21701
|
+
itemCount,
|
|
21702
|
+
observedAt: asOf,
|
|
21703
|
+
diagnosticIds: diagnostics.filter((entry) => entry.source === source).map((entry) => entry.id)
|
|
21704
|
+
});
|
|
21705
|
+
};
|
|
21706
|
+
//#endregion
|
|
20424
21707
|
//#region src/stores/ncp-agent-session-journal-summary-recovery.store.ts
|
|
20425
21708
|
async function loadNcpAgentSessionSummary(params) {
|
|
20426
21709
|
const journalStat = await stat(params.journalPath);
|
|
@@ -20501,18 +21784,18 @@ function applyJournalSummaryLine(state, line) {
|
|
|
20501
21784
|
if (parsed._type === "metadata") {
|
|
20502
21785
|
state.createdAt = toIsoString(parsed.created_at, state.createdAt);
|
|
20503
21786
|
state.agentId = typeof parsed.agent_id === "string" ? parsed.agent_id : state.agentId;
|
|
20504
|
-
if (isRecord$
|
|
21787
|
+
if (isRecord$11(parsed.metadata)) state.metadata = structuredClone(parsed.metadata);
|
|
20505
21788
|
return;
|
|
20506
21789
|
}
|
|
20507
|
-
if (parsed._type !== "event" || !isRecord$
|
|
21790
|
+
if (parsed._type !== "event" || !isRecord$11(parsed.event)) return;
|
|
20508
21791
|
const event = parsed.event;
|
|
20509
|
-
const payload = isRecord$
|
|
20510
|
-
const message = payload && isRecord$
|
|
21792
|
+
const payload = isRecord$11(event.payload) ? event.payload : null;
|
|
21793
|
+
const message = payload && isRecord$11(payload.message) ? payload.message : null;
|
|
20511
21794
|
const messageId = typeof message?.id === "string" ? message.id : typeof payload?.messageId === "string" ? payload.messageId : null;
|
|
20512
21795
|
if (!isMessageStartEvent(event.type) || !messageId || state.messageIds.has(messageId)) return;
|
|
20513
21796
|
state.messageIds.add(messageId);
|
|
20514
21797
|
state.messageCount += 1;
|
|
20515
|
-
if (isRecord$
|
|
21798
|
+
if (isRecord$11(message?.metadata) && message.metadata.nextclaw_timeline_kind === "context_compaction") state.requiresReplay = true;
|
|
20516
21799
|
if (!isFinalMessageEvent(event.type)) return;
|
|
20517
21800
|
const timestamp = toIsoString(message?.timestamp, "");
|
|
20518
21801
|
if (timestamp && (!state.lastMessageAt || timestamp > state.lastMessageAt)) state.lastMessageAt = timestamp;
|
|
@@ -20521,7 +21804,7 @@ function parseJournalLine(line) {
|
|
|
20521
21804
|
if (!line.trim()) return null;
|
|
20522
21805
|
try {
|
|
20523
21806
|
const parsed = JSON.parse(line);
|
|
20524
|
-
return isRecord$
|
|
21807
|
+
return isRecord$11(parsed) ? parsed : null;
|
|
20525
21808
|
} catch {
|
|
20526
21809
|
return null;
|
|
20527
21810
|
}
|
|
@@ -20575,7 +21858,7 @@ var NcpAgentUnfinishedRunStore = class {
|
|
|
20575
21858
|
} catch {
|
|
20576
21859
|
continue;
|
|
20577
21860
|
}
|
|
20578
|
-
if (!isRecord$
|
|
21861
|
+
if (!isRecord$11(parsed) || parsed._type !== "event" || !isRecord$11(parsed.event)) continue;
|
|
20579
21862
|
activeRun = applyNcpAgentRunLifecycleEvent(sessionId, activeRun, parsed.event);
|
|
20580
21863
|
}
|
|
20581
21864
|
return activeRun;
|
|
@@ -20596,11 +21879,11 @@ function isNcpAgentSessionMessageProjectionBoundaryEvent(event) {
|
|
|
20596
21879
|
function serializeNcpAgentSessionJournalEntry(entry) {
|
|
20597
21880
|
const serialized = JSON.stringify(entry);
|
|
20598
21881
|
if (!serialized) throw new Error("ncp agent session journal entry serialization produced empty output");
|
|
20599
|
-
if (!isRecord$
|
|
21882
|
+
if (!isRecord$11(JSON.parse(serialized))) throw new Error("ncp agent session journal entry serialization produced a non-object entry");
|
|
20600
21883
|
return serialized;
|
|
20601
21884
|
}
|
|
20602
21885
|
function attachNcpAgentSessionJournalTimestamp(event, timestamp) {
|
|
20603
|
-
if (!("payload" in event) || !isRecord$
|
|
21886
|
+
if (!("payload" in event) || !isRecord$11(event.payload)) return event;
|
|
20604
21887
|
return {
|
|
20605
21888
|
...event,
|
|
20606
21889
|
payload: {
|
|
@@ -20625,7 +21908,7 @@ var NcpAgentSessionJournalParser = class {
|
|
|
20625
21908
|
this.applyMetadata(parsed);
|
|
20626
21909
|
return;
|
|
20627
21910
|
}
|
|
20628
|
-
if (parsed._type === "event" && isRecord$
|
|
21911
|
+
if (parsed._type === "event" && isRecord$11(parsed.event)) this.applyEvent(parsed, lineEndOffset);
|
|
20629
21912
|
};
|
|
20630
21913
|
finish = () => ({
|
|
20631
21914
|
metadata: this.metadata,
|
|
@@ -20639,14 +21922,14 @@ var NcpAgentSessionJournalParser = class {
|
|
|
20639
21922
|
parseLine = (line, index) => {
|
|
20640
21923
|
try {
|
|
20641
21924
|
const parsed = JSON.parse(line);
|
|
20642
|
-
return isRecord$
|
|
21925
|
+
return isRecord$11(parsed) ? parsed : null;
|
|
20643
21926
|
} catch (error) {
|
|
20644
21927
|
console.warn(`[ncp-agent-session-journal] skipped corrupted journal line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);
|
|
20645
21928
|
return null;
|
|
20646
21929
|
}
|
|
20647
21930
|
};
|
|
20648
21931
|
applyMetadata = (entry) => {
|
|
20649
|
-
this.metadata = isRecord$
|
|
21932
|
+
this.metadata = isRecord$11(entry.metadata) ? structuredClone(entry.metadata) : {};
|
|
20650
21933
|
this.agentId = normalizeNcpAgentId(typeof entry.agent_id === "string" ? entry.agent_id : void 0);
|
|
20651
21934
|
this.createdAt = toIsoString(entry.created_at, this.createdAt);
|
|
20652
21935
|
this.updatedAt = toIsoString(entry.updated_at, this.updatedAt);
|
|
@@ -20693,7 +21976,7 @@ var NcpAgentSessionMetadataStore = class {
|
|
|
20693
21976
|
read = async (sessionId, activitySnapshot) => {
|
|
20694
21977
|
try {
|
|
20695
21978
|
const parsed = JSON.parse(await readFile(this.metadataPath(sessionId), "utf-8"));
|
|
20696
|
-
if (!isRecord$
|
|
21979
|
+
if (!isRecord$11(parsed) || parsed._type !== "metadata" || !isRecord$11(parsed.metadata)) throw new Error(`invalid ncp agent session metadata sidecar: ${sessionId}`);
|
|
20697
21980
|
const createdAt = toIsoString(parsed.created_at, activitySnapshot.createdAt);
|
|
20698
21981
|
const agentId = normalizeNcpAgentId(typeof parsed.agent_id === "string" ? parsed.agent_id : void 0);
|
|
20699
21982
|
return {
|
|
@@ -21548,7 +22831,7 @@ var NcpAgentSessionSummaryIndexStore = class {
|
|
|
21548
22831
|
const { sessionId: rawSessionId, event, updatedAt } = params;
|
|
21549
22832
|
const sessionId = normalizeNcpSessionId(rawSessionId);
|
|
21550
22833
|
const currentRow = this.db().prepare("SELECT * FROM sessions WHERE session_id = ? LIMIT 1").get(sessionId);
|
|
21551
|
-
const
|
|
22834
|
+
const { deleted_at: _deletedAt, ...upsertParams } = summaryToRow({
|
|
21552
22835
|
...upsertNcpAgentSessionSummaryEvent({
|
|
21553
22836
|
current: currentRow && currentRow.deleted_at === null ? rowToSummary(currentRow) : void 0,
|
|
21554
22837
|
sessionId,
|
|
@@ -21577,7 +22860,7 @@ var NcpAgentSessionSummaryIndexStore = class {
|
|
|
21577
22860
|
END,
|
|
21578
22861
|
message_count = sessions.message_count + excluded.message_count,
|
|
21579
22862
|
status = excluded.status
|
|
21580
|
-
WHERE sessions.deleted_at IS NULL`).run(
|
|
22863
|
+
WHERE sessions.deleted_at IS NULL`).run(upsertParams);
|
|
21581
22864
|
};
|
|
21582
22865
|
remove = async (sessionId) => {
|
|
21583
22866
|
await this.ensureReady();
|
|
@@ -22663,7 +23946,6 @@ function resolveSessionChannelContext(params) {
|
|
|
22663
23946
|
}
|
|
22664
23947
|
//#endregion
|
|
22665
23948
|
//#region src/features/native-runtime/utils/nextclaw-ncp-run-context.utils.ts
|
|
22666
|
-
const REQUESTED_SKILLS_METADATA_READER = new RequestedSkillsMetadataReader();
|
|
22667
23949
|
function resolveRequestedToolNames(metadata) {
|
|
22668
23950
|
const rawValue = metadata.requested_tools ?? metadata.requestedTools;
|
|
22669
23951
|
if (!Array.isArray(rawValue)) return [];
|
|
@@ -22700,7 +23982,6 @@ function buildNextclawNcpRunContext(params) {
|
|
|
22700
23982
|
requestMetadata
|
|
22701
23983
|
});
|
|
22702
23984
|
const sessionMetadata = channelContext.metadata;
|
|
22703
|
-
const requestedSkills = REQUESTED_SKILLS_METADATA_READER.readSelection(requestMetadata);
|
|
22704
23985
|
const runtimeThinking = resolveThinkingLevel({
|
|
22705
23986
|
config,
|
|
22706
23987
|
agentId: profile.agentId,
|
|
@@ -22715,7 +23996,6 @@ function buildNextclawNcpRunContext(params) {
|
|
|
22715
23996
|
effectiveWorkspace,
|
|
22716
23997
|
profile,
|
|
22717
23998
|
requestMetadata,
|
|
22718
|
-
requestedSkills,
|
|
22719
23999
|
requestedToolNames: resolveRequestedToolNames(requestMetadata),
|
|
22720
24000
|
runtimeThinking,
|
|
22721
24001
|
sessionKey: sessionId,
|
|
@@ -23513,13 +24793,12 @@ var ReplyFormatContextProvider = class {
|
|
|
23513
24793
|
};
|
|
23514
24794
|
//#endregion
|
|
23515
24795
|
//#region src/contributions/context-provider/providers/skills-context.provider.ts
|
|
23516
|
-
function
|
|
24796
|
+
function renderAlwaysOnSkillsSection(skills, skillSelectors) {
|
|
23517
24797
|
const manifest = skills.buildSkillsManifest(skillSelectors);
|
|
23518
24798
|
if (!manifest) return "";
|
|
23519
24799
|
return [
|
|
23520
|
-
"#
|
|
23521
|
-
"These
|
|
23522
|
-
"For NextClaw self-management, use the active built-in self-management skill before unrelated generic skills.",
|
|
24800
|
+
"# Always-on Skills",
|
|
24801
|
+
"These skills are always active. Read each `Root/<name>/SKILL.md` before following it.",
|
|
23523
24802
|
manifest
|
|
23524
24803
|
].join("\n");
|
|
23525
24804
|
}
|
|
@@ -23554,7 +24833,7 @@ var SkillsContextProvider = class {
|
|
|
23554
24833
|
this.context = context;
|
|
23555
24834
|
}
|
|
23556
24835
|
provide = async (request) => {
|
|
23557
|
-
const { projectContext
|
|
24836
|
+
const { projectContext } = await this.context.resolve(request);
|
|
23558
24837
|
const skills = new SkillsLoader({
|
|
23559
24838
|
workspace: projectContext.hostWorkspace,
|
|
23560
24839
|
projectRoot: projectContext.projectRoot,
|
|
@@ -23564,10 +24843,10 @@ var SkillsContextProvider = class {
|
|
|
23564
24843
|
hostWorkspace: projectContext.hostWorkspace,
|
|
23565
24844
|
projectSkillsRoot: projectContext.projectSkillsRoot
|
|
23566
24845
|
})];
|
|
23567
|
-
const
|
|
23568
|
-
if (
|
|
23569
|
-
const
|
|
23570
|
-
if (
|
|
24846
|
+
const alwaysOnSkills = skills.getAlwaysSkills();
|
|
24847
|
+
if (alwaysOnSkills.length) {
|
|
24848
|
+
const alwaysOnSection = renderAlwaysOnSkillsSection(skills, alwaysOnSkills);
|
|
24849
|
+
if (alwaysOnSection) blocks.push(alwaysOnSection);
|
|
23571
24850
|
}
|
|
23572
24851
|
const availableSkillsSection = renderAvailableSkillsSection(skills);
|
|
23573
24852
|
if (availableSkillsSection) blocks.push(availableSkillsSection);
|
|
@@ -24198,7 +25477,6 @@ const LEARNING_LOOP_LAST_TOOL_CALL_COUNT_METADATA_KEY = "learning_loop_last_tool
|
|
|
24198
25477
|
const LEARNING_LOOP_LAST_REQUESTED_AT_METADATA_KEY = "learning_loop_last_requested_at";
|
|
24199
25478
|
const LEARNING_LOOP_LAST_REVIEW_SESSION_ID_METADATA_KEY = "learning_loop_last_review_session_id";
|
|
24200
25479
|
const LEARNING_LOOP_SOURCE_SESSION_ID_METADATA_KEY = "learning_loop_source_session_id";
|
|
24201
|
-
const LEARNING_LOOP_REQUESTED_SKILLS = ["skill-creator"];
|
|
24202
25480
|
function readLearningLoopRuntimeConfig(config) {
|
|
24203
25481
|
return {
|
|
24204
25482
|
enabled: config.agents.learningLoop.enabled,
|
|
@@ -24311,7 +25589,6 @@ var LearningLoopContribution = class extends Contribution$1 {
|
|
|
24311
25589
|
sourceSessionId: sessionId,
|
|
24312
25590
|
sourceSessionMetadata: metadata,
|
|
24313
25591
|
metadataOverrides: {
|
|
24314
|
-
requested_skills: LEARNING_LOOP_REQUESTED_SKILLS,
|
|
24315
25592
|
[LEARNING_LOOP_DISABLED_METADATA_KEY]: true,
|
|
24316
25593
|
[LEARNING_LOOP_SOURCE_SESSION_ID_METADATA_KEY]: sessionId
|
|
24317
25594
|
},
|
|
@@ -26478,11 +27755,17 @@ function createKernelSessionManagers(params) {
|
|
|
26478
27755
|
ingress,
|
|
26479
27756
|
eventBus
|
|
26480
27757
|
});
|
|
27758
|
+
const projectObservation = new ProjectObservationService({
|
|
27759
|
+
projectManager,
|
|
27760
|
+
sessionManager,
|
|
27761
|
+
workspacePath: getWorkspacePathFromConfig(configManager.config)
|
|
27762
|
+
});
|
|
26481
27763
|
observationOwner.current = observations;
|
|
26482
27764
|
return {
|
|
26483
27765
|
journalStore,
|
|
26484
27766
|
observations,
|
|
26485
27767
|
projectManager,
|
|
27768
|
+
projectObservation,
|
|
26486
27769
|
sessionManager,
|
|
26487
27770
|
sessionSearch
|
|
26488
27771
|
};
|
|
@@ -26578,6 +27861,7 @@ var NextclawKernel = class {
|
|
|
26578
27861
|
panelAppManager;
|
|
26579
27862
|
preferenceManager;
|
|
26580
27863
|
projectManager;
|
|
27864
|
+
projectObservation;
|
|
26581
27865
|
serviceAppManager;
|
|
26582
27866
|
extensions;
|
|
26583
27867
|
agentRuntimeManager = new AgentRuntimeManager();
|
|
@@ -26623,7 +27907,7 @@ var NextclawKernel = class {
|
|
|
26623
27907
|
homeDir: options.homeDir
|
|
26624
27908
|
});
|
|
26625
27909
|
this.capabilityGrantLegacyMigration = this.createCapabilityGrantLegacyMigration(options);
|
|
26626
|
-
({journalStore: this.ncpAgentSessionJournalStore, observations: this.observations, projectManager: this.projectManager, sessionManager: this.sessionManager, sessionSearch: this.sessionSearch} = createKernelSessionManagers({
|
|
27910
|
+
({journalStore: this.ncpAgentSessionJournalStore, observations: this.observations, projectManager: this.projectManager, projectObservation: this.projectObservation, sessionManager: this.sessionManager, sessionSearch: this.sessionSearch} = createKernelSessionManagers({
|
|
26627
27911
|
agentContextWindowManager: this.agentContextWindowManager,
|
|
26628
27912
|
agentManager: this.agents,
|
|
26629
27913
|
configManager: this.configManager,
|
|
@@ -26730,6 +28014,7 @@ var NextclawKernel = class {
|
|
|
26730
28014
|
this.sessionSearch.start();
|
|
26731
28015
|
this.mcpManager.start();
|
|
26732
28016
|
this.providerModelCatalog.start();
|
|
28017
|
+
await this.projectManager.migrateLegacyProjects();
|
|
26733
28018
|
await this.projectManager.importSessionProjects((await this.sessionManager.listSessions()).map((session) => readProjectRoot(session.metadata)));
|
|
26734
28019
|
await this.sessionManager.start();
|
|
26735
28020
|
for (const contribution of this.contributions) await contribution.start();
|
|
@@ -27892,6 +29177,6 @@ function resolveLegacyEventType(message) {
|
|
|
27892
29177
|
return `message.${role || "other"}`;
|
|
27893
29178
|
}
|
|
27894
29179
|
//#endregion
|
|
27895
|
-
export { AUTOMATIC_UPDATE_CHECK_INTERVAL_MS, AccessManager, AgentManager, AgentRunClient, AppDataError, AppDataManager, AppPackageError, AppPackageManager, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_CONTINUATION_TEXT, CONTEXT_COMPACTION_PROJECTION_KIND, CONTEXT_COMPACTION_PROJECTION_METADATA_KEY, CONTEXT_COMPACTION_SYSTEM_PREAMBLE, CONTEXT_COMPACTION_TIMELINE_KIND, CapabilityGrantLegacyMigrationService, CapabilityGrantManager, CapabilityGrantStore, ChannelManager, CommandRegistry, ConfigManager, ContextCompactionJournalRecoveryService, ContextCompactionPreflightService, Contribution, DEFAULT_AGENT_RUNTIME_ENTRY_ID, DEFAULT_SERVICE_ACTION_RISK, DESKTOP_HOST_ACCESS, DESKTOP_HOST_PROTOCOL_VERSION, DesktopHostCapabilityManager, DesktopNodeReplService, DesktopSessionStateService, EventBus, ExtensionManager, FeatureControlsService, GatewayInboundProcessor, InboxDeliveryError, InboxDeliveryManager, Ingress, LlmProviderManager, LlmUsageManager, LlmUsageStore, MAX_INBOX_DELIVERY_CONTENT_LENGTH, McpManager, McpServiceAppRuntimeService, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, NEXTCLAW_TIMELINE_KIND_METADATA_KEY, NcpAgentSessionJournalStore, NextclawHarness, NextclawHarnessError, NextclawKernel, ObservationManager, PANEL_APP_AGENT_CAPABILITIES, PORTABLE_RUNTIME_ACCEPTANCE_CONTRACT, PORTABLE_RUNTIME_ACCEPTANCE_CONTRACT_FINGERPRINT, PORTABLE_RUNTIME_ACCEPTANCE_LOCALES, PORTABLE_RUNTIME_ACCEPTANCE_PLATFORMS, PORTABLE_RUNTIME_ACCEPTANCE_PRESENTATION, PORTABLE_RUNTIME_ACCEPTANCE_REFERENCE_APP_ID, PROJECT_TEMPLATE_IDS, PROVIDER_MODEL_CATALOG_REFRESH_INTERVAL_MS, PanelAppAssetTokenService, PanelAppError, PanelAppManager, PortableRuntimeAcceptanceIdentityService, PortableRuntimeAcceptanceManager, PreferenceError, PreferenceManager, ProjectError, ProjectManager, ProviderManagerNcpLLMApi, ProviderModelCatalogManager, SERVICE_APP_MANIFEST_FILE_NAME, ServiceAppAiCapabilityService, ServiceAppError, ServiceAppJobJournalService, ServiceAppManager, ServiceAppResidentEventInboxService, ServiceAppRuntimeService, SessionContextCompactionError, SessionContextCompactionManager, SessionManager, SessionMessageCursorError, SessionRequestManager, SessionSettingsError, SkillManager, SystemObjectReferenceError, SystemObjectReferenceManager, UnavailableDesktopHost, UpdateManifestReader, VerificationRecordService, assertObservationJsonValue, assertObservationPredicate, buildAgentRunSendPayload, buildContextCompactionModelProjection, buildContextCompactionTimelineNcpMessage, buildLlmUsageSummary, buildLocalizedTextMap, buildNextclawNcpRunContext, buildObservationEventModelMessage, buildServiceActionId, buildSessionRequestCompletionMessage, capabilityGrantCovers, createAgentRuntimeSessionRequestDispatcher, createAgentRuntimeSessionRequestSourceNotifier, createAssetTools, createCapabilityDeclarationFingerprint, createContextCompactionMessageId, createContextWindowSignature, createCronJobSystemObjectProvider, createDesktopHostError, createInboxDeliverySystemObjectProvider, createLlmUsageRecord, createPanelAppAgentGrantRequest, createPanelAppClientGrantRequest, createServiceActionGrantRequest, createServiceAppAgentSlotGrantRequest, createServiceAppModelSlotGrantRequest, createTypedKey, describeAgentRuntimeSessionTypes, dispatchAgentRuntimeSessionRequest, dispatchChannelReplyRoute, dispatchPromptOverNcp, dispatchPromptOverNcpResult, evaluateObservationEventAdmission, evaluatePortableRuntimeAcceptance, evaluatePortableRuntimeAcceptanceArtifact, eventKeys, getAutomaticUpdateCheckDelay, getCapabilityGrantKey, getServiceActionName, getServiceAppManifestPath, getUiContentParamsBootstrapScript, getUnsignedUpdateManifest, hasLlmUsageTelemetry, ingressKeys, injectUiContentParamsBootstrap, isAppDataError, isAppPackageError, isContextCompactionProjectionMessage, isContextCompactionTimelineMessage, isContextWindowSnapshot, isInboxDeliveryError, isPanelAppAgentCapability, isPanelAppError, isPreferenceError, isProjectError, isReplyCapableChannel, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError, isSystemObjectReferenceError, listExtensionChannelIds, listServiceAppManifestActions, matchesCapabilityGrantFilter, matchesObservationPredicate, mergeServiceAppRuntimeActions, normalizeAgentRuntimeSessionTypeIcon, normalizeCapabilityGrantRequest, normalizeLlmUsageModel, normalizeOptionalString, normalizePortableRuntimeEnvironment, parseObservationDuration, parsePortableRuntimeAcceptanceEvidenceArtifact, parseServiceAppManifest, parseSkillFrontmatter, presentPortableRuntimeAcceptanceDefinition, readContextCompactionCheckpoint, readContextWindowEventSessionId, readJsonPointer, readLatestContextCompactionCheckpoint, readLearningLoopRuntimeConfig, readMetadataModel, readMetadataThinking, readServiceActionTargetId, readServiceAppManifest, readServiceAppSlotTarget, resolveAgentRuntimeEntries, resolveAutomaticUpdateCheckIntervalMs, resolveChannelReplyRoute, resolveEffectiveModel, resolveLegacyEventType, resolvePortableRuntimeAcceptanceLocale, resolveSessionChannelContext, runGatewayInboundLoop, runNextclawTask, sanitizeLlmUsage, serializeContextTail, serializeUnsignedUpdateManifest, shouldRefreshContextWindowDuringStream, shouldRefreshContextWindowImmediately, startPromptOverNcpExecution, stripSkillFrontmatter, syncSessionThinkingPreference, toBoundedJson, toNcpMessages, waitForAgentRuntimeSessionReply };
|
|
29180
|
+
export { AUTOMATIC_UPDATE_CHECK_INTERVAL_MS, AccessManager, AgentManager, AgentRunClient, AppDataError, AppDataManager, AppPackageError, AppPackageManager, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_CONTINUATION_TEXT, CONTEXT_COMPACTION_PROJECTION_KIND, CONTEXT_COMPACTION_PROJECTION_METADATA_KEY, CONTEXT_COMPACTION_SYSTEM_PREAMBLE, CONTEXT_COMPACTION_TIMELINE_KIND, CapabilityGrantLegacyMigrationService, CapabilityGrantManager, CapabilityGrantStore, ChannelManager, CommandRegistry, ConfigManager, ContextCompactionJournalRecoveryService, ContextCompactionPreflightService, Contribution, DEFAULT_AGENT_RUNTIME_ENTRY_ID, DEFAULT_SERVICE_ACTION_RISK, DESKTOP_HOST_ACCESS, DESKTOP_HOST_PROTOCOL_VERSION, DesktopHostCapabilityManager, DesktopNodeReplService, DesktopSessionStateService, EventBus, ExtensionManager, FeatureControlsService, GatewayInboundProcessor, InboxDeliveryError, InboxDeliveryManager, Ingress, LlmProviderManager, LlmUsageManager, LlmUsageStore, MAX_INBOX_DELIVERY_CONTENT_LENGTH, McpManager, McpServiceAppRuntimeService, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, NEXTCLAW_TIMELINE_KIND_METADATA_KEY, NcpAgentSessionJournalStore, NextclawHarness, NextclawHarnessError, NextclawKernel, ObservationManager, PANEL_APP_AGENT_CAPABILITIES, PORTABLE_RUNTIME_ACCEPTANCE_CONTRACT, PORTABLE_RUNTIME_ACCEPTANCE_CONTRACT_FINGERPRINT, PORTABLE_RUNTIME_ACCEPTANCE_LOCALES, PORTABLE_RUNTIME_ACCEPTANCE_PLATFORMS, PORTABLE_RUNTIME_ACCEPTANCE_PRESENTATION, PORTABLE_RUNTIME_ACCEPTANCE_REFERENCE_APP_ID, PROJECT_OBSERVATION_PROTOCOL, PROJECT_TEMPLATE_IDS, PROVIDER_MODEL_CATALOG_REFRESH_INTERVAL_MS, PanelAppAssetTokenService, PanelAppError, PanelAppManager, PortableRuntimeAcceptanceIdentityService, PortableRuntimeAcceptanceManager, PreferenceError, PreferenceManager, ProjectError, ProjectManager, ProjectObservationError, ProjectObservationService, ProviderManagerNcpLLMApi, ProviderModelCatalogManager, SERVICE_APP_MANIFEST_FILE_NAME, ServiceAppAiCapabilityService, ServiceAppError, ServiceAppJobJournalService, ServiceAppManager, ServiceAppResidentEventInboxService, ServiceAppRuntimeService, SessionContextCompactionError, SessionContextCompactionManager, SessionManager, SessionMessageCursorError, SessionRequestManager, SessionSettingsError, SkillManager, SystemObjectReferenceError, SystemObjectReferenceManager, UnavailableDesktopHost, UpdateManifestReader, VerificationRecordService, assertObservationJsonValue, assertObservationPredicate, buildAgentRunSendPayload, buildContextCompactionModelProjection, buildContextCompactionTimelineNcpMessage, buildLlmUsageSummary, buildLocalizedTextMap, buildNextclawNcpRunContext, buildObservationEventModelMessage, buildServiceActionId, buildSessionRequestCompletionMessage, capabilityGrantCovers, createAgentRuntimeSessionRequestDispatcher, createAgentRuntimeSessionRequestSourceNotifier, createAssetTools, createCapabilityDeclarationFingerprint, createContextCompactionMessageId, createContextWindowSignature, createCronJobSystemObjectProvider, createDesktopHostError, createInboxDeliverySystemObjectProvider, createLlmUsageRecord, createPanelAppAgentGrantRequest, createPanelAppClientGrantRequest, createServiceActionGrantRequest, createServiceAppAgentSlotGrantRequest, createServiceAppModelSlotGrantRequest, createTypedKey, describeAgentRuntimeSessionTypes, dispatchAgentRuntimeSessionRequest, dispatchChannelReplyRoute, dispatchPromptOverNcp, dispatchPromptOverNcpResult, evaluateObservationEventAdmission, evaluatePortableRuntimeAcceptance, evaluatePortableRuntimeAcceptanceArtifact, eventKeys, getAutomaticUpdateCheckDelay, getCapabilityGrantKey, getServiceActionName, getServiceAppManifestPath, getUiContentParamsBootstrapScript, getUnsignedUpdateManifest, hasLlmUsageTelemetry, ingressKeys, injectUiContentParamsBootstrap, isAppDataError, isAppPackageError, isContextCompactionProjectionMessage, isContextCompactionTimelineMessage, isContextWindowSnapshot, isInboxDeliveryError, isPanelAppAgentCapability, isPanelAppError, isPreferenceError, isProjectError, isProjectObservationError, isReplyCapableChannel, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError, isSystemObjectReferenceError, listExtensionChannelIds, listServiceAppManifestActions, matchesCapabilityGrantFilter, matchesObservationPredicate, mergeServiceAppRuntimeActions, normalizeAgentRuntimeSessionTypeIcon, normalizeCapabilityGrantRequest, normalizeLlmUsageModel, normalizeOptionalString, normalizePortableRuntimeEnvironment, parseObservationDuration, parsePortableRuntimeAcceptanceEvidenceArtifact, parseServiceAppManifest, parseSkillFrontmatter, presentPortableRuntimeAcceptanceDefinition, readContextCompactionCheckpoint, readContextWindowEventSessionId, readJsonPointer, readLatestContextCompactionCheckpoint, readLearningLoopRuntimeConfig, readMetadataModel, readMetadataThinking, readServiceActionTargetId, readServiceAppManifest, readServiceAppSlotTarget, resolveAgentRuntimeEntries, resolveAutomaticUpdateCheckIntervalMs, resolveChannelReplyRoute, resolveEffectiveModel, resolveLegacyEventType, resolvePortableRuntimeAcceptanceLocale, resolveSessionChannelContext, runGatewayInboundLoop, runNextclawTask, sanitizeLlmUsage, serializeContextTail, serializeUnsignedUpdateManifest, shouldRefreshContextWindowDuringStream, shouldRefreshContextWindowImmediately, startPromptOverNcpExecution, stripSkillFrontmatter, syncSessionThinkingPreference, toBoundedJson, toNcpMessages, waitForAgentRuntimeSessionReply };
|
|
27896
29181
|
|
|
27897
29182
|
//# sourceMappingURL=index.js.map
|