@nextclaw/server 0.17.2 → 0.18.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 +83 -50
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +265 -43
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -64,13 +64,13 @@ async function readJson(req) {
|
|
|
64
64
|
return { ok: false };
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
function isRecord$
|
|
67
|
+
function isRecord$3(value) {
|
|
68
68
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69
69
|
}
|
|
70
70
|
function readErrorMessage(value, fallback) {
|
|
71
|
-
if (!isRecord$
|
|
71
|
+
if (!isRecord$3(value)) return fallback;
|
|
72
72
|
const maybeError = value.error;
|
|
73
|
-
if (!isRecord$
|
|
73
|
+
if (!isRecord$3(maybeError)) return fallback;
|
|
74
74
|
return typeof maybeError.message === "string" && maybeError.message.trim().length > 0 ? maybeError.message : fallback;
|
|
75
75
|
}
|
|
76
76
|
function readNonEmptyString(value) {
|
|
@@ -477,7 +477,8 @@ const ingressKeys = {
|
|
|
477
477
|
channelCommandList: createTypedKey("extension.channel.command.list"),
|
|
478
478
|
channelCommandExecute: createTypedKey("extension.channel.command.execute"),
|
|
479
479
|
runtimeReady: createTypedKey("extension.runtime.ready"),
|
|
480
|
-
response: createTypedKey("extension.response")
|
|
480
|
+
response: createTypedKey("extension.response"),
|
|
481
|
+
observationEvent: createTypedKey("extension.observation.event")
|
|
481
482
|
},
|
|
482
483
|
agentRun: {
|
|
483
484
|
send: createTypedKey("agent-run.send"),
|
|
@@ -1456,7 +1457,7 @@ var ServerPathRoutesController = class {
|
|
|
1456
1457
|
watch = async (c) => {
|
|
1457
1458
|
if (!this.watchService) return c.json(err("SERVER_PATH_WATCH_UNAVAILABLE", "server path watch is unavailable"), 503);
|
|
1458
1459
|
const body = await readJson(c.req.raw);
|
|
1459
|
-
if (!body.ok || !isRecord$
|
|
1460
|
+
if (!body.ok || !isRecord$3(body.data) || !Array.isArray(body.data.directories) || !body.data.directories.every((path) => typeof path === "string")) return c.json(err("INVALID_SERVER_PATH_WATCH", "directories are required"), 400);
|
|
1460
1461
|
try {
|
|
1461
1462
|
const request = {
|
|
1462
1463
|
directories: body.data.directories,
|
|
@@ -1502,7 +1503,7 @@ var ServerPathRoutesController = class {
|
|
|
1502
1503
|
};
|
|
1503
1504
|
createDirectory = async (c) => {
|
|
1504
1505
|
const body = await readJson(c.req.raw);
|
|
1505
|
-
if (!body.ok || !isRecord$
|
|
1506
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_SERVER_PATH_DIRECTORY", "directory input is required"), 400);
|
|
1506
1507
|
try {
|
|
1507
1508
|
return c.json(ok(await createServerPathDirectory({
|
|
1508
1509
|
basePath: body.data.basePath,
|
|
@@ -1539,7 +1540,7 @@ var ServerPathRoutesController = class {
|
|
|
1539
1540
|
};
|
|
1540
1541
|
createFile = async (c) => {
|
|
1541
1542
|
const body = await readJson(c.req.raw);
|
|
1542
|
-
if (!body.ok || !isRecord$
|
|
1543
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_SERVER_PATH_FILE", "file input is required"), 400);
|
|
1543
1544
|
try {
|
|
1544
1545
|
return c.json(ok(await createServerPathFile({
|
|
1545
1546
|
basePath: body.data.basePath,
|
|
@@ -1553,7 +1554,7 @@ var ServerPathRoutesController = class {
|
|
|
1553
1554
|
};
|
|
1554
1555
|
renameEntry = async (c) => {
|
|
1555
1556
|
const body = await readJson(c.req.raw);
|
|
1556
|
-
if (!body.ok || !isRecord$
|
|
1557
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_SERVER_PATH_RENAME", "rename input is required"), 400);
|
|
1557
1558
|
try {
|
|
1558
1559
|
return c.json(ok(await renameServerPathEntry({
|
|
1559
1560
|
basePath: body.data.basePath,
|
|
@@ -1905,6 +1906,44 @@ function buildFallbackBootstrapStatus() {
|
|
|
1905
1906
|
remote: { state: "pending" }
|
|
1906
1907
|
};
|
|
1907
1908
|
}
|
|
1909
|
+
function buildExtensionsView(options) {
|
|
1910
|
+
const manifests = options.kernel.extensions.getManifests();
|
|
1911
|
+
const statuses = options.kernel.extensions.getRuntimeStatus();
|
|
1912
|
+
const statusById = new Map(statuses.map((status) => [status.extensionId, status]));
|
|
1913
|
+
const extensions = manifests.map((manifest) => {
|
|
1914
|
+
const status = statusById.get(manifest.id);
|
|
1915
|
+
const observations = manifest.contributes?.observations;
|
|
1916
|
+
const channels = (manifest.contributes?.channels ?? []).map((channel) => ({
|
|
1917
|
+
id: channel.id,
|
|
1918
|
+
...channel.name ? { name: channel.name } : {},
|
|
1919
|
+
...typeof channel.meta?.description === "string" ? { description: channel.meta.description } : {}
|
|
1920
|
+
}));
|
|
1921
|
+
return {
|
|
1922
|
+
id: manifest.id,
|
|
1923
|
+
name: manifest.name?.trim() || manifest.id,
|
|
1924
|
+
...manifest.version ? { version: manifest.version } : {},
|
|
1925
|
+
state: status?.state ?? "stopped",
|
|
1926
|
+
...status?.generation ? { generation: status.generation } : {},
|
|
1927
|
+
...status?.pid ? { pid: status.pid } : {},
|
|
1928
|
+
...status?.startedAt ? { startedAt: status.startedAt } : {},
|
|
1929
|
+
leaseCount: status?.leaseReasons.length ?? 0,
|
|
1930
|
+
observations: {
|
|
1931
|
+
context: Boolean(observations?.read),
|
|
1932
|
+
events: Boolean(observations?.events)
|
|
1933
|
+
},
|
|
1934
|
+
channels
|
|
1935
|
+
};
|
|
1936
|
+
});
|
|
1937
|
+
return {
|
|
1938
|
+
extensions,
|
|
1939
|
+
counts: {
|
|
1940
|
+
total: extensions.length,
|
|
1941
|
+
running: extensions.filter((extension) => extension.state === "running").length,
|
|
1942
|
+
withObservations: extensions.filter((extension) => extension.observations.context || extension.observations.events).length,
|
|
1943
|
+
withChannels: extensions.filter((extension) => extension.channels.length > 0).length
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1908
1947
|
var AppRoutesController = class {
|
|
1909
1948
|
constructor(options) {
|
|
1910
1949
|
this.options = options;
|
|
@@ -1918,7 +1957,8 @@ var AppRoutesController = class {
|
|
|
1918
1957
|
}));
|
|
1919
1958
|
appMeta = (c) => c.json(ok(buildAppMetaView(this.options)));
|
|
1920
1959
|
bootstrapStatus = (c) => c.json(ok(this.options.bootstrapStatus?.getStatus() ?? buildFallbackBootstrapStatus()));
|
|
1921
|
-
extensionRuntimeStatus = (c) => c.json(ok(this.options.extensions
|
|
1960
|
+
extensionRuntimeStatus = (c) => c.json(ok(this.options.kernel.extensions.getRuntimeStatus()));
|
|
1961
|
+
extensionCatalog = (c) => c.json(ok(buildExtensionsView(this.options)));
|
|
1922
1962
|
};
|
|
1923
1963
|
//#endregion
|
|
1924
1964
|
//#region src/features/app-packages/controllers/app-packages.controller.ts
|
|
@@ -1930,7 +1970,7 @@ var AppPackagesRoutesController = class {
|
|
|
1930
1970
|
listOperations = async (c) => c.json(ok(await this.manager.listOperations()));
|
|
1931
1971
|
startInstallOperation = async (c) => {
|
|
1932
1972
|
const body = await readJson(c.req.raw);
|
|
1933
|
-
if (!body.ok || !isRecord$
|
|
1973
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.source !== "string") return c.json(err("INVALID_APP_PACKAGE_INSTALL", "source is required"), 400);
|
|
1934
1974
|
try {
|
|
1935
1975
|
return c.json(ok(await this.manager.startOperation({
|
|
1936
1976
|
action: "install",
|
|
@@ -1943,7 +1983,7 @@ var AppPackagesRoutesController = class {
|
|
|
1943
1983
|
};
|
|
1944
1984
|
startUpdateOperation = async (c) => {
|
|
1945
1985
|
const body = await readJson(c.req.raw);
|
|
1946
|
-
if (!body.ok || !isRecord$
|
|
1986
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_APP_PACKAGE_UPDATE", "invalid update request"), 400);
|
|
1947
1987
|
try {
|
|
1948
1988
|
return c.json(ok(await this.manager.startOperation({
|
|
1949
1989
|
action: "update",
|
|
@@ -1957,7 +1997,7 @@ var AppPackagesRoutesController = class {
|
|
|
1957
1997
|
};
|
|
1958
1998
|
startRollbackOperation = async (c) => {
|
|
1959
1999
|
const body = await readJson(c.req.raw);
|
|
1960
|
-
if (!body.ok || !isRecord$
|
|
2000
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.version !== "string") return c.json(err("INVALID_APP_PACKAGE_ROLLBACK", "version is required"), 400);
|
|
1961
2001
|
try {
|
|
1962
2002
|
return c.json(ok(await this.manager.startOperation({
|
|
1963
2003
|
action: "rollback",
|
|
@@ -1970,7 +2010,7 @@ var AppPackagesRoutesController = class {
|
|
|
1970
2010
|
};
|
|
1971
2011
|
startUninstallOperation = async (c) => {
|
|
1972
2012
|
const body = await readJson(c.req.raw);
|
|
1973
|
-
const purgeData = body.ok && isRecord$
|
|
2013
|
+
const purgeData = body.ok && isRecord$3(body.data) && body.data.purgeData === true;
|
|
1974
2014
|
try {
|
|
1975
2015
|
return c.json(ok(await this.manager.startOperation({
|
|
1976
2016
|
action: "uninstall",
|
|
@@ -1990,7 +2030,7 @@ var AppPackagesRoutesController = class {
|
|
|
1990
2030
|
};
|
|
1991
2031
|
install = async (c) => {
|
|
1992
2032
|
const body = await readJson(c.req.raw);
|
|
1993
|
-
if (!body.ok || !isRecord$
|
|
2033
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.source !== "string") return c.json(err("INVALID_APP_PACKAGE_INSTALL", "source is required"), 400);
|
|
1994
2034
|
try {
|
|
1995
2035
|
return c.json(ok(await this.manager.install(body.data.source, typeof body.data.registryUrl === "string" ? body.data.registryUrl : void 0)));
|
|
1996
2036
|
} catch (error) {
|
|
@@ -2013,7 +2053,7 @@ var AppPackagesRoutesController = class {
|
|
|
2013
2053
|
};
|
|
2014
2054
|
update = async (c) => {
|
|
2015
2055
|
const body = await readJson(c.req.raw);
|
|
2016
|
-
if (!body.ok || !isRecord$
|
|
2056
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_APP_PACKAGE_UPDATE", "invalid update request"), 400);
|
|
2017
2057
|
try {
|
|
2018
2058
|
return c.json(ok(await this.manager.update(c.req.param("appId"), {
|
|
2019
2059
|
version: typeof body.data.version === "string" ? body.data.version : void 0,
|
|
@@ -2025,7 +2065,7 @@ var AppPackagesRoutesController = class {
|
|
|
2025
2065
|
};
|
|
2026
2066
|
rollback = async (c) => {
|
|
2027
2067
|
const body = await readJson(c.req.raw);
|
|
2028
|
-
if (!body.ok || !isRecord$
|
|
2068
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.version !== "string") return c.json(err("INVALID_APP_PACKAGE_ROLLBACK", "version is required"), 400);
|
|
2029
2069
|
try {
|
|
2030
2070
|
return c.json(ok(await this.manager.rollback(c.req.param("appId"), body.data.version)));
|
|
2031
2071
|
} catch (error) {
|
|
@@ -2034,7 +2074,7 @@ var AppPackagesRoutesController = class {
|
|
|
2034
2074
|
};
|
|
2035
2075
|
uninstall = async (c) => {
|
|
2036
2076
|
const body = await readJson(c.req.raw);
|
|
2037
|
-
const purgeData = body.ok && isRecord$
|
|
2077
|
+
const purgeData = body.ok && isRecord$3(body.data) && body.data.purgeData === true;
|
|
2038
2078
|
try {
|
|
2039
2079
|
return c.json(ok(await this.manager.uninstall(c.req.param("appId"), purgeData)));
|
|
2040
2080
|
} catch (error) {
|
|
@@ -2060,7 +2100,7 @@ var AppDataRoutesController = class {
|
|
|
2060
2100
|
};
|
|
2061
2101
|
deleteRetained = async (c) => {
|
|
2062
2102
|
const body = await readJson(c.req.raw);
|
|
2063
|
-
if (!body.ok || !isRecord$
|
|
2103
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.confirmAppId !== "string" || !body.data.confirmAppId.trim()) return c.json(err("INVALID_APP_DATA_DELETE_REQUEST", "confirmAppId is required."), 400);
|
|
2064
2104
|
try {
|
|
2065
2105
|
return c.json(ok(await this.manager.deleteRetained(c.req.param("dataId"), body.data.confirmAppId.trim())));
|
|
2066
2106
|
} catch (error) {
|
|
@@ -2097,7 +2137,7 @@ var SystemObjectReferencesRoutesController = class {
|
|
|
2097
2137
|
};
|
|
2098
2138
|
resolve = async (c) => {
|
|
2099
2139
|
const body = await readJson(c.req.raw);
|
|
2100
|
-
if (!body.ok || !isRecord$
|
|
2140
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.uri !== "string" || !body.data.uri.trim()) return c.json(err("INVALID_SYSTEM_OBJECT_REFERENCE", "uri must be a non-empty string"), 400);
|
|
2101
2141
|
try {
|
|
2102
2142
|
return c.json(ok(await this.manager.resolveReference(body.data.uri)));
|
|
2103
2143
|
} catch (error) {
|
|
@@ -4492,7 +4532,7 @@ var InboxDeliveriesRoutesController = class {
|
|
|
4492
4532
|
};
|
|
4493
4533
|
updateState = async (c) => {
|
|
4494
4534
|
const body = await readJson(c.req.raw);
|
|
4495
|
-
if (!body.ok || !isRecord$
|
|
4535
|
+
if (!body.ok || !isRecord$3(body.data) || !isStateAction(body.data.action)) return c.json(err("INVALID_INBOX_DELIVERY_ACTION", "invalid inbox delivery action"), 400);
|
|
4496
4536
|
return await this.handleManagerAction(c, () => this.manager.updateDeliveryState(c.req.param("deliveryId"), body.data.action));
|
|
4497
4537
|
};
|
|
4498
4538
|
delete = async (c) => {
|
|
@@ -5472,21 +5512,19 @@ function isDeferrableMessage(message) {
|
|
|
5472
5512
|
function deferMessageToolPayload(message) {
|
|
5473
5513
|
const tools = message.parts.filter((part) => part.type === "tool-invocation");
|
|
5474
5514
|
const toolNames = [...new Set(tools.map((part) => part.toolName.trim()).filter(Boolean))].slice(0, SUMMARY_TOOL_NAME_LIMIT);
|
|
5475
|
-
const parts = [];
|
|
5476
5515
|
let keptRepresentative = false;
|
|
5477
|
-
|
|
5478
|
-
if (part.type !== "tool-invocation")
|
|
5479
|
-
|
|
5480
|
-
continue;
|
|
5481
|
-
}
|
|
5482
|
-
if (keptRepresentative) continue;
|
|
5516
|
+
const parts = message.parts.map((part) => {
|
|
5517
|
+
if (part.type !== "tool-invocation") return part;
|
|
5518
|
+
const isRepresentative = !keptRepresentative;
|
|
5483
5519
|
keptRepresentative = true;
|
|
5484
|
-
|
|
5520
|
+
return {
|
|
5485
5521
|
...part,
|
|
5522
|
+
...isRepresentative ? {} : { payloadDeferred: true },
|
|
5486
5523
|
args: void 0,
|
|
5487
|
-
result: void 0
|
|
5488
|
-
|
|
5489
|
-
|
|
5524
|
+
result: void 0,
|
|
5525
|
+
resultContentItems: void 0
|
|
5526
|
+
};
|
|
5527
|
+
});
|
|
5490
5528
|
return {
|
|
5491
5529
|
...message,
|
|
5492
5530
|
metadata: {
|
|
@@ -5499,6 +5537,20 @@ function deferMessageToolPayload(message) {
|
|
|
5499
5537
|
parts
|
|
5500
5538
|
};
|
|
5501
5539
|
}
|
|
5540
|
+
function sanitizeContextCompactionHistoryMessage(message) {
|
|
5541
|
+
const metadata = message.metadata;
|
|
5542
|
+
if (metadata?.nextclaw_timeline_kind !== "context_compaction") return message;
|
|
5543
|
+
const checkpoint = metadata.checkpoint;
|
|
5544
|
+
if (!checkpoint || typeof checkpoint !== "object" || Array.isArray(checkpoint)) return message;
|
|
5545
|
+
const { summary: _summary, summaryDiagnostics: _summaryDiagnostics, ...uiCheckpoint } = checkpoint;
|
|
5546
|
+
return {
|
|
5547
|
+
...message,
|
|
5548
|
+
metadata: {
|
|
5549
|
+
...metadata,
|
|
5550
|
+
checkpoint: uiCheckpoint
|
|
5551
|
+
}
|
|
5552
|
+
};
|
|
5553
|
+
}
|
|
5502
5554
|
function buildSessionMessageHistoryPayloadView(params) {
|
|
5503
5555
|
const { messageBudgetBytes: requestedMessageBudgetBytes, messageDetailCursors, messages, messageToolCallBudget: requestedMessageToolCallBudget, pageBudgetBytes: requestedPageBudgetBytes, pageToolCallBudget: requestedPageToolCallBudget } = params;
|
|
5504
5556
|
const messageBudgetBytes = requestedMessageBudgetBytes ?? 262144;
|
|
@@ -5530,7 +5582,10 @@ function buildSessionMessageHistoryPayloadView(params) {
|
|
|
5530
5582
|
}
|
|
5531
5583
|
const deferredToolPayloads = Object.fromEntries([...deferredIds].map((messageId) => [messageId, { cursor: messageDetailCursors[messageId] }]));
|
|
5532
5584
|
return {
|
|
5533
|
-
messages: messages.map((message) =>
|
|
5585
|
+
messages: messages.map((message) => {
|
|
5586
|
+
const sanitized = sanitizeContextCompactionHistoryMessage(message);
|
|
5587
|
+
return deferredIds.has(message.id) ? deferMessageToolPayload(sanitized) : sanitized;
|
|
5588
|
+
}),
|
|
5534
5589
|
deferredToolPayloads
|
|
5535
5590
|
};
|
|
5536
5591
|
}
|
|
@@ -5538,7 +5593,14 @@ function compactSessionMessageHistoryPayloadView(params) {
|
|
|
5538
5593
|
const { view } = params;
|
|
5539
5594
|
const budgetBytes = params.budgetBytes ?? 24576;
|
|
5540
5595
|
const minimumMessages = Math.max(1, Math.trunc(params.minimumMessages ?? 5));
|
|
5541
|
-
let startIndex =
|
|
5596
|
+
let startIndex = view.messages.length;
|
|
5597
|
+
let conversationMessageCount = 0;
|
|
5598
|
+
while (startIndex > 0 && conversationMessageCount < minimumMessages) {
|
|
5599
|
+
startIndex -= 1;
|
|
5600
|
+
const message = view.messages[startIndex];
|
|
5601
|
+
if (message?.role === "user" || message?.role === "assistant") conversationMessageCount += 1;
|
|
5602
|
+
}
|
|
5603
|
+
if (startIndex === view.messages.length) startIndex = Math.max(0, view.messages.length - minimumMessages);
|
|
5542
5604
|
let bytes = view.messages.slice(startIndex).reduce((total, message) => total + serializedBytes(message), 0);
|
|
5543
5605
|
while (startIndex > 0) {
|
|
5544
5606
|
const previousBytes = serializedBytes(view.messages[startIndex - 1]);
|
|
@@ -5555,6 +5617,115 @@ function compactSessionMessageHistoryPayloadView(params) {
|
|
|
5555
5617
|
};
|
|
5556
5618
|
}
|
|
5557
5619
|
//#endregion
|
|
5620
|
+
//#region src/features/sessions/utils/session-observation-view.utils.ts
|
|
5621
|
+
const SENSITIVE_KEY_PATTERN = /(token|secret|password|cookie|api[-_]?key|credential|authorization)/i;
|
|
5622
|
+
const MAX_PREVIEW_ENTRIES = 6;
|
|
5623
|
+
const MAX_PREVIEW_VALUE_LENGTH = 80;
|
|
5624
|
+
function isRecord$2(value) {
|
|
5625
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5626
|
+
}
|
|
5627
|
+
function previewValue(key, value) {
|
|
5628
|
+
if (SENSITIVE_KEY_PATTERN.test(key)) return "••••••";
|
|
5629
|
+
if (value === null) return "null";
|
|
5630
|
+
if (typeof value === "string") {
|
|
5631
|
+
const normalized = value.trim();
|
|
5632
|
+
if (normalized.length <= MAX_PREVIEW_VALUE_LENGTH) return normalized || "空字符串";
|
|
5633
|
+
return `${normalized.slice(0, MAX_PREVIEW_VALUE_LENGTH - 1)}…`;
|
|
5634
|
+
}
|
|
5635
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
5636
|
+
if (Array.isArray(value)) return `[${value.length} 项]`;
|
|
5637
|
+
if (isRecord$2(value)) return "已配置";
|
|
5638
|
+
return "已配置";
|
|
5639
|
+
}
|
|
5640
|
+
function buildSafeConfigPreview(config) {
|
|
5641
|
+
if (!isRecord$2(config)) return config === void 0 ? void 0 : "已配置";
|
|
5642
|
+
const entries = Object.entries(config).slice(0, MAX_PREVIEW_ENTRIES);
|
|
5643
|
+
if (entries.length === 0) return void 0;
|
|
5644
|
+
const preview = entries.map(([key, value]) => `${key}: ${previewValue(key, value)}`);
|
|
5645
|
+
if (Object.keys(config).length > MAX_PREVIEW_ENTRIES) preview.push("…");
|
|
5646
|
+
return preview.join(" · ");
|
|
5647
|
+
}
|
|
5648
|
+
function buildDescriptorMap(descriptors) {
|
|
5649
|
+
return new Map(descriptors.map((descriptor) => [`${descriptor.kind}:${descriptor.extensionId}`, descriptor]));
|
|
5650
|
+
}
|
|
5651
|
+
function buildDeliveryCounts(deliveries) {
|
|
5652
|
+
const counts = /* @__PURE__ */ new Map();
|
|
5653
|
+
for (const delivery of deliveries) {
|
|
5654
|
+
const current = counts.get(delivery.subscriptionId) ?? {
|
|
5655
|
+
pending: 0,
|
|
5656
|
+
failures: 0
|
|
5657
|
+
};
|
|
5658
|
+
if (delivery.status === "pending" || delivery.status === "submitted") current.pending += 1;
|
|
5659
|
+
if (delivery.status === "failed") current.failures += 1;
|
|
5660
|
+
counts.set(delivery.subscriptionId, current);
|
|
5661
|
+
}
|
|
5662
|
+
return counts;
|
|
5663
|
+
}
|
|
5664
|
+
function buildContextView(binding, descriptors) {
|
|
5665
|
+
const descriptor = descriptors.get(`context:${binding.extensionId}`);
|
|
5666
|
+
const safeConfigPreview = buildSafeConfigPreview(binding.config);
|
|
5667
|
+
return {
|
|
5668
|
+
id: binding.bindingId,
|
|
5669
|
+
kind: "context",
|
|
5670
|
+
extensionId: binding.extensionId,
|
|
5671
|
+
title: descriptor?.title ?? binding.extensionId,
|
|
5672
|
+
...descriptor?.description ? { description: descriptor.description } : {},
|
|
5673
|
+
status: binding.status,
|
|
5674
|
+
...binding.statusReason ? { statusReason: binding.statusReason } : {},
|
|
5675
|
+
createdAt: binding.createdAt,
|
|
5676
|
+
...binding.expiresAt ? { expiresAt: binding.expiresAt } : {},
|
|
5677
|
+
...binding.lastReadAt ? { lastReadAt: binding.lastReadAt } : {},
|
|
5678
|
+
...safeConfigPreview ? { safeConfigPreview } : {}
|
|
5679
|
+
};
|
|
5680
|
+
}
|
|
5681
|
+
function buildSubscriptionView(subscription, descriptors, deliveryCounts) {
|
|
5682
|
+
const descriptor = descriptors.get(`events:${subscription.extensionId}`);
|
|
5683
|
+
const counts = deliveryCounts.get(subscription.subscriptionId) ?? {
|
|
5684
|
+
pending: 0,
|
|
5685
|
+
failures: 0
|
|
5686
|
+
};
|
|
5687
|
+
const safeConfigPreview = buildSafeConfigPreview(subscription.config);
|
|
5688
|
+
return {
|
|
5689
|
+
id: subscription.subscriptionId,
|
|
5690
|
+
kind: "events",
|
|
5691
|
+
extensionId: subscription.extensionId,
|
|
5692
|
+
title: descriptor?.title ?? subscription.extensionId,
|
|
5693
|
+
...descriptor?.description ? { description: descriptor.description } : {},
|
|
5694
|
+
status: subscription.status,
|
|
5695
|
+
...subscription.statusReason ? { statusReason: subscription.statusReason } : {},
|
|
5696
|
+
createdAt: subscription.createdAt,
|
|
5697
|
+
...subscription.expiresAt ? { expiresAt: subscription.expiresAt } : {},
|
|
5698
|
+
...safeConfigPreview ? { safeConfigPreview } : {},
|
|
5699
|
+
pendingCount: counts.pending,
|
|
5700
|
+
...subscription.suppressedCount ? { suppressedCount: subscription.suppressedCount } : {},
|
|
5701
|
+
...counts.failures > 0 ? { deliveryFailureCount: counts.failures } : {},
|
|
5702
|
+
...subscription.lastSuppressionReason ? { lastSuppressionReason: subscription.lastSuppressionReason } : {},
|
|
5703
|
+
...subscription.lastGapAt ? { lastGapAt: subscription.lastGapAt } : {},
|
|
5704
|
+
...subscription.gapReason ? { gapReason: subscription.gapReason } : {},
|
|
5705
|
+
delivery: subscription.delivery
|
|
5706
|
+
};
|
|
5707
|
+
}
|
|
5708
|
+
function needsAttention(observation) {
|
|
5709
|
+
return observation.status !== "active" || (observation.deliveryFailureCount ?? 0) > 0 || Boolean(observation.lastGapAt);
|
|
5710
|
+
}
|
|
5711
|
+
function buildSessionObservationsView(input) {
|
|
5712
|
+
const descriptors = buildDescriptorMap(input.descriptors);
|
|
5713
|
+
const deliveryCounts = buildDeliveryCounts(input.deliveries);
|
|
5714
|
+
const bindings = input.bindings.map((binding) => buildContextView(binding, descriptors));
|
|
5715
|
+
const subscriptions = input.subscriptions.map((subscription) => buildSubscriptionView(subscription, descriptors, deliveryCounts));
|
|
5716
|
+
return {
|
|
5717
|
+
sessionId: input.sessionId,
|
|
5718
|
+
bindings,
|
|
5719
|
+
subscriptions,
|
|
5720
|
+
counts: {
|
|
5721
|
+
total: bindings.length + subscriptions.length,
|
|
5722
|
+
context: bindings.length,
|
|
5723
|
+
events: subscriptions.length,
|
|
5724
|
+
needsAttention: [...bindings, ...subscriptions].filter(needsAttention).length
|
|
5725
|
+
}
|
|
5726
|
+
};
|
|
5727
|
+
}
|
|
5728
|
+
//#endregion
|
|
5558
5729
|
//#region src/features/sessions/controllers/sessions.controller.ts
|
|
5559
5730
|
const DEFAULT_SESSION_MESSAGE_PAGE_SIZE = 40;
|
|
5560
5731
|
const MAX_SESSION_MESSAGE_PAGE_SIZE = 200;
|
|
@@ -5689,6 +5860,42 @@ var NcpSessionRoutesController = class {
|
|
|
5689
5860
|
if (!payload) return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
5690
5861
|
return c.json(ok(payload));
|
|
5691
5862
|
};
|
|
5863
|
+
listSessionObservations = async (c) => {
|
|
5864
|
+
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
5865
|
+
if (!await this.options.kernel.sessionManager.getSession(sessionId)) return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
5866
|
+
const payload = buildSessionObservationsView({
|
|
5867
|
+
sessionId,
|
|
5868
|
+
...await this.options.kernel.observations.listObservations(sessionId),
|
|
5869
|
+
descriptors: this.options.kernel.observations.discoverObservations()
|
|
5870
|
+
});
|
|
5871
|
+
return c.json(ok(payload));
|
|
5872
|
+
};
|
|
5873
|
+
updateSessionObservation = async (c) => {
|
|
5874
|
+
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
5875
|
+
const kind = c.req.param("kind");
|
|
5876
|
+
const id = decodeURIComponent(c.req.param("id"));
|
|
5877
|
+
if (!await this.options.kernel.sessionManager.getSession(sessionId)) return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
5878
|
+
const body = await readJson(c.req.raw);
|
|
5879
|
+
const action = body.ok && body.data?.action;
|
|
5880
|
+
if (action !== "pause" && action !== "resume" && action !== "remove") return c.json(err("INVALID_BODY", "action must be pause, resume, or remove"), 400);
|
|
5881
|
+
if (kind !== "context" && kind !== "events") return c.json(err("NOT_FOUND", `observation kind not found: ${kind}`), 404);
|
|
5882
|
+
const ref = kind === "context" ? {
|
|
5883
|
+
kind: "context_binding",
|
|
5884
|
+
id
|
|
5885
|
+
} : {
|
|
5886
|
+
kind: "event_subscription",
|
|
5887
|
+
id
|
|
5888
|
+
};
|
|
5889
|
+
const observation = await this.options.kernel.observations.getObservation(ref);
|
|
5890
|
+
if (!observation || observation.target.sessionId !== sessionId) return c.json(err("NOT_FOUND", `observation not found in session: ${sessionId}`), 404);
|
|
5891
|
+
await this.options.kernel.observations.updateObservation(action, ref);
|
|
5892
|
+
const state = await this.options.kernel.observations.listObservations(sessionId);
|
|
5893
|
+
return c.json(ok(buildSessionObservationsView({
|
|
5894
|
+
sessionId,
|
|
5895
|
+
...state,
|
|
5896
|
+
descriptors: this.options.kernel.observations.discoverObservations()
|
|
5897
|
+
})));
|
|
5898
|
+
};
|
|
5692
5899
|
getSessionSkills = async (c) => {
|
|
5693
5900
|
const sessionManager = this.options.kernel.sessionManager;
|
|
5694
5901
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
@@ -6020,7 +6227,7 @@ var PanelAppsRoutesController = class {
|
|
|
6020
6227
|
};
|
|
6021
6228
|
updatePanelAppPreferences = async (c) => {
|
|
6022
6229
|
const body = await readJson(c.req.raw);
|
|
6023
|
-
if (!body.ok || !isRecord$
|
|
6230
|
+
if (!body.ok || !isRecord$3(body.data)) return c.json(err("INVALID_PANEL_APP_PREFERENCES", "invalid panel app preferences"), 400);
|
|
6024
6231
|
if (body.data.mainSidebar !== void 0 && typeof body.data.mainSidebar !== "boolean") return c.json(err("INVALID_PANEL_APP_PREFERENCES", "mainSidebar must be boolean"), 400);
|
|
6025
6232
|
try {
|
|
6026
6233
|
const preferences = {
|
|
@@ -6100,7 +6307,7 @@ var PanelAppsRoutesController = class {
|
|
|
6100
6307
|
};
|
|
6101
6308
|
createBridgeSession = async (c) => {
|
|
6102
6309
|
const body = await readJson(c.req.raw);
|
|
6103
|
-
if (!body.ok || !isRecord$
|
|
6310
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.panelAppId !== "string" && typeof body.data.appId !== "string") return c.json(err("INVALID_PANEL_APP_BRIDGE_SESSION", "invalid bridge session request"), 400);
|
|
6104
6311
|
const panelAppId = typeof body.data.appId === "string" ? body.data.appId : body.data.panelAppId;
|
|
6105
6312
|
if (typeof panelAppId !== "string") return c.json(err("INVALID_PANEL_APP_BRIDGE_SESSION", "invalid bridge session request"), 400);
|
|
6106
6313
|
try {
|
|
@@ -6137,7 +6344,7 @@ var PanelAppsRoutesController = class {
|
|
|
6137
6344
|
};
|
|
6138
6345
|
sendAgentMessage = async (c) => {
|
|
6139
6346
|
const body = await readJson(c.req.raw);
|
|
6140
|
-
if (!body.ok || !isRecord$
|
|
6347
|
+
if (!body.ok || !isRecord$3(body.data) || !isRecord$3(body.data.payload)) return c.json(err("INVALID_PANEL_APP_AGENT_REQUEST", "invalid agent send request"), 400);
|
|
6141
6348
|
try {
|
|
6142
6349
|
return c.json(ok(await this.panelAppManager.sendAgentMessage(this.requireBridgeSessionToken(c), body.data.payload)));
|
|
6143
6350
|
} catch (error) {
|
|
@@ -6146,7 +6353,7 @@ var PanelAppsRoutesController = class {
|
|
|
6146
6353
|
};
|
|
6147
6354
|
generateAgentObject = async (c) => {
|
|
6148
6355
|
const body = await readJson(c.req.raw);
|
|
6149
|
-
if (!body.ok || !isRecord$
|
|
6356
|
+
if (!body.ok || !isRecord$3(body.data) || !isRecord$3(body.data.input)) return c.json(err("INVALID_PANEL_APP_AGENT_REQUEST", "invalid generateObject request"), 400);
|
|
6150
6357
|
try {
|
|
6151
6358
|
return c.json(ok(await this.panelAppManager.generateAgentObject(this.requireBridgeSessionToken(c), body.data.input)));
|
|
6152
6359
|
} catch (error) {
|
|
@@ -6219,7 +6426,7 @@ var PreferencesRoutesController = class {
|
|
|
6219
6426
|
};
|
|
6220
6427
|
update = async (c) => {
|
|
6221
6428
|
const body = await readJson(c.req.raw);
|
|
6222
|
-
if (!body.ok || !isRecord$
|
|
6429
|
+
if (!body.ok || !isRecord$3(body.data) || !Object.hasOwn(body.data, "value")) return c.json(err("INVALID_PREFERENCE", "preference value is required"), 400);
|
|
6223
6430
|
try {
|
|
6224
6431
|
const entry = await this.preferenceManager.setPreference(c.req.param("key"), body.data.value);
|
|
6225
6432
|
return c.json(ok({
|
|
@@ -6262,7 +6469,7 @@ var ProjectsRoutesController = class {
|
|
|
6262
6469
|
};
|
|
6263
6470
|
create = async (c) => {
|
|
6264
6471
|
const body = await readJson(c.req.raw);
|
|
6265
|
-
if (!body.ok || !isRecord$
|
|
6472
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.name !== "string") return c.json(err("INVALID_PROJECT", "project name is required"), 400);
|
|
6266
6473
|
try {
|
|
6267
6474
|
return c.json(ok(await this.projectManager.createProject(body.data)), 201);
|
|
6268
6475
|
} catch (error) {
|
|
@@ -6272,7 +6479,7 @@ var ProjectsRoutesController = class {
|
|
|
6272
6479
|
};
|
|
6273
6480
|
addExisting = async (c) => {
|
|
6274
6481
|
const body = await readJson(c.req.raw);
|
|
6275
|
-
if (!body.ok || !isRecord$
|
|
6482
|
+
if (!body.ok || !isRecord$3(body.data) || typeof body.data.rootPath !== "string") return c.json(err("INVALID_PROJECT", "project directory is required"), 400);
|
|
6276
6483
|
try {
|
|
6277
6484
|
const project = await this.projectManager.registerExistingProject(body.data.rootPath);
|
|
6278
6485
|
if (!project) return c.json(err("PROJECT_PATH_IS_DEFAULT_WORKSPACE", "the default workspace cannot be registered as a project"), 400);
|
|
@@ -6334,13 +6541,13 @@ var ServiceAppsRoutesController = class {
|
|
|
6334
6541
|
};
|
|
6335
6542
|
invokeServiceAction = async (c) => {
|
|
6336
6543
|
const body = await readJson(c.req.raw);
|
|
6337
|
-
if (!body.ok || body.data !== void 0 && !isRecord$
|
|
6544
|
+
if (!body.ok || body.data !== void 0 && !isRecord$3(body.data)) return c.json(err("INVALID_SERVICE_ACTION_REQUEST", "invalid service action request"), 400);
|
|
6338
6545
|
try {
|
|
6339
6546
|
const bridgeSession = this.requireBridgeSession(c);
|
|
6340
6547
|
const payload = await this.params.serviceAppManager.invokeServiceAction(c.req.param("actionId"), {
|
|
6341
6548
|
caller: bridgeSession.caller,
|
|
6342
6549
|
declaredActions: bridgeSession.declaredActions,
|
|
6343
|
-
input: isRecord$
|
|
6550
|
+
input: isRecord$3(body.data.input) ? body.data.input : {}
|
|
6344
6551
|
});
|
|
6345
6552
|
return c.json(ok(payload));
|
|
6346
6553
|
} catch (error) {
|
|
@@ -6404,7 +6611,7 @@ var ServiceAppsRoutesController = class {
|
|
|
6404
6611
|
};
|
|
6405
6612
|
deleteServiceApp = async (c) => {
|
|
6406
6613
|
const body = await readJson(c.req.raw);
|
|
6407
|
-
const purgeData = body.ok && isRecord$
|
|
6614
|
+
const purgeData = body.ok && isRecord$3(body.data) && body.data.purgeData === true;
|
|
6408
6615
|
try {
|
|
6409
6616
|
return c.json(ok(await this.params.serviceAppManager.deleteServiceApp(c.req.param("appId"), purgeData)));
|
|
6410
6617
|
} catch (error) {
|
|
@@ -6658,6 +6865,16 @@ var UiRouteRegistry = class {
|
|
|
6658
6865
|
"/api/ncp/sessions/:sessionId/context/compact",
|
|
6659
6866
|
ncpSession.compactSessionContext
|
|
6660
6867
|
],
|
|
6868
|
+
[
|
|
6869
|
+
"get",
|
|
6870
|
+
"/api/ncp/sessions/:sessionId/observations",
|
|
6871
|
+
ncpSession.listSessionObservations
|
|
6872
|
+
],
|
|
6873
|
+
[
|
|
6874
|
+
"patch",
|
|
6875
|
+
"/api/ncp/sessions/:sessionId/observations/:kind/:id",
|
|
6876
|
+
ncpSession.updateSessionObservation
|
|
6877
|
+
],
|
|
6661
6878
|
[
|
|
6662
6879
|
"get",
|
|
6663
6880
|
"/api/ncp/sessions/:sessionId/usage",
|
|
@@ -7058,6 +7275,11 @@ var UiRouteRegistry = class {
|
|
|
7058
7275
|
"/api/runtime/extensions",
|
|
7059
7276
|
app.extensionRuntimeStatus
|
|
7060
7277
|
],
|
|
7278
|
+
[
|
|
7279
|
+
"get",
|
|
7280
|
+
"/api/runtime/extensions/catalog",
|
|
7281
|
+
app.extensionCatalog
|
|
7282
|
+
],
|
|
7061
7283
|
[
|
|
7062
7284
|
"get",
|
|
7063
7285
|
"/api/auth/status",
|