negotium 0.3.5 → 0.3.7
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/agent-helpers.js +6 -15
- package/dist/agent-helpers.js.map +4 -4
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +285 -44
- package/dist/main.js.map +11 -10
- package/dist/mcp-factories.js +6 -15
- package/dist/mcp-factories.js.map +4 -4
- package/dist/registry.js +2 -2
- package/dist/registry.js.map +2 -2
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +47 -22
- package/dist/runtime/src/index.ts +2 -0
- package/dist/runtime/src/node-host.ts +3 -1
- package/dist/runtime/src/storage/app-settings.ts +15 -21
- package/dist/runtime/src/topics/update.ts +175 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/storage.js +6 -16
- package/dist/storage.js.map +3 -3
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1869,7 +1869,7 @@ var exports_version = {};
|
|
|
1869
1869
|
__export(exports_version, {
|
|
1870
1870
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1871
1871
|
});
|
|
1872
|
-
var NEGOTIUM_VERSION = "0.3.
|
|
1872
|
+
var NEGOTIUM_VERSION = "0.3.7";
|
|
1873
1873
|
|
|
1874
1874
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1875
1875
|
import { spawn } from "child_process";
|
|
@@ -18122,39 +18122,30 @@ import { dirname as dirname14, join as join27 } from "path";
|
|
|
18122
18122
|
function settingsFile() {
|
|
18123
18123
|
return join27(resolveStorageDataDir(), "otium-settings.json");
|
|
18124
18124
|
}
|
|
18125
|
-
function
|
|
18125
|
+
function getGlobalAiName() {
|
|
18126
18126
|
const path = settingsFile();
|
|
18127
|
-
if (loadedSettingsFile === path)
|
|
18128
|
-
return path;
|
|
18129
|
-
loadedSettingsFile = path;
|
|
18130
|
-
aiName = DEFAULT_AI_NAME;
|
|
18131
18127
|
try {
|
|
18132
18128
|
if (existsSync18(path)) {
|
|
18133
18129
|
const data = JSON.parse(readFileSync16(path, "utf8"));
|
|
18134
18130
|
if (typeof data.aiName === "string" && data.aiName.trim()) {
|
|
18135
|
-
|
|
18131
|
+
return data.aiName.trim();
|
|
18136
18132
|
}
|
|
18137
18133
|
}
|
|
18138
18134
|
} catch {}
|
|
18139
|
-
return
|
|
18140
|
-
}
|
|
18141
|
-
function getGlobalAiName() {
|
|
18142
|
-
ensureSettingsLoaded();
|
|
18143
|
-
return aiName || DEFAULT_AI_NAME;
|
|
18135
|
+
return DEFAULT_AI_NAME;
|
|
18144
18136
|
}
|
|
18145
18137
|
function setGlobalAiName(name) {
|
|
18146
|
-
const path =
|
|
18147
|
-
aiName = name.trim() || DEFAULT_AI_NAME;
|
|
18138
|
+
const path = settingsFile();
|
|
18139
|
+
const aiName = name.trim() || DEFAULT_AI_NAME;
|
|
18148
18140
|
try {
|
|
18149
18141
|
mkdirSync18(dirname14(path), { recursive: true });
|
|
18150
18142
|
writeFileSync16(path, JSON.stringify({ aiName }, null, 2));
|
|
18151
18143
|
} catch {}
|
|
18152
18144
|
return aiName;
|
|
18153
18145
|
}
|
|
18154
|
-
var DEFAULT_AI_NAME = "Otium"
|
|
18146
|
+
var DEFAULT_AI_NAME = "Otium";
|
|
18155
18147
|
var init_app_settings = __esm(async () => {
|
|
18156
18148
|
await init_storage_host();
|
|
18157
|
-
aiName = DEFAULT_AI_NAME;
|
|
18158
18149
|
});
|
|
18159
18150
|
|
|
18160
18151
|
// ../../packages/core/src/runtime/turn-runner.ts
|
|
@@ -20507,12 +20498,14 @@ function gatewayPayloadHash(params, requestId, actorUserId) {
|
|
|
20507
20498
|
params.clientMessageId,
|
|
20508
20499
|
requestId,
|
|
20509
20500
|
params.allowAutoContinue ?? true,
|
|
20501
|
+
params.respond ?? true,
|
|
20510
20502
|
params.threadRootId ?? null
|
|
20511
20503
|
])).digest("hex");
|
|
20512
20504
|
}
|
|
20513
20505
|
function submitRuntimeGatewayTurn(params) {
|
|
20514
20506
|
const requestId = params.requestId ?? params.clientMessageId;
|
|
20515
20507
|
const actorUserId = params.actorUserId ?? params.userId;
|
|
20508
|
+
const respond = params.respond ?? true;
|
|
20516
20509
|
const payloadHash = gatewayPayloadHash(params, requestId, actorUserId);
|
|
20517
20510
|
const existing = findRuntimeGatewaySubmission(params.clientMessageId, requestId);
|
|
20518
20511
|
if (existing) {
|
|
@@ -20544,28 +20537,30 @@ function submitRuntimeGatewayTurn(params) {
|
|
|
20544
20537
|
try {
|
|
20545
20538
|
db.transaction(() => {
|
|
20546
20539
|
appendApiMessage(message, { notify: false });
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
|
|
20554
|
-
|
|
20540
|
+
if (respond) {
|
|
20541
|
+
mergeRuntimeUserTurnRequest({
|
|
20542
|
+
topicId: params.topic.id,
|
|
20543
|
+
userId: params.userId,
|
|
20544
|
+
userMessages: [
|
|
20545
|
+
{
|
|
20546
|
+
prompt: params.text,
|
|
20547
|
+
actorUserId,
|
|
20548
|
+
...params.actorLabel ? { actorLabel: params.actorLabel } : {}
|
|
20549
|
+
}
|
|
20550
|
+
],
|
|
20551
|
+
allowAutoContinue: params.allowAutoContinue ?? true,
|
|
20552
|
+
requestId,
|
|
20553
|
+
topicEpoch: getRuntimeTopicEpoch(params.topic.id),
|
|
20554
|
+
execution: {
|
|
20555
|
+
sessionId: getTopicSessionId(params.topic.id),
|
|
20556
|
+
sessionIdSpecified: true,
|
|
20557
|
+
conversationPrompts: [params.text],
|
|
20558
|
+
loggedUserMessageCount: 0,
|
|
20559
|
+
vaultUserId: params.vaultUserId,
|
|
20560
|
+
...params.threadRootId ? { threadRootId: params.threadRootId } : {}
|
|
20555
20561
|
}
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
requestId,
|
|
20559
|
-
topicEpoch: getRuntimeTopicEpoch(params.topic.id),
|
|
20560
|
-
execution: {
|
|
20561
|
-
sessionId: getTopicSessionId(params.topic.id),
|
|
20562
|
-
sessionIdSpecified: true,
|
|
20563
|
-
conversationPrompts: [params.text],
|
|
20564
|
-
loggedUserMessageCount: 0,
|
|
20565
|
-
vaultUserId: params.vaultUserId,
|
|
20566
|
-
...params.threadRootId ? { threadRootId: params.threadRootId } : {}
|
|
20567
|
-
}
|
|
20568
|
-
});
|
|
20562
|
+
});
|
|
20563
|
+
}
|
|
20569
20564
|
const acceptedEvent = appendRuntimeEvent("runtime-gateway-ingress", {
|
|
20570
20565
|
type: "ai-status",
|
|
20571
20566
|
topicId: params.topic.id,
|
|
@@ -20591,7 +20586,8 @@ function submitRuntimeGatewayTurn(params) {
|
|
|
20591
20586
|
return duplicateResult(raced, params, requestId, actorUserId, payloadHash);
|
|
20592
20587
|
throw new Error("failed to persist gateway turn idempotency record");
|
|
20593
20588
|
}
|
|
20594
|
-
|
|
20589
|
+
if (respond)
|
|
20590
|
+
requestRuntimeTurnAbort(params.topic.id, "internal");
|
|
20595
20591
|
return { ...submission, message, deduplicated: false };
|
|
20596
20592
|
}
|
|
20597
20593
|
var RuntimeGatewayIdempotencyConflictError;
|
|
@@ -22631,6 +22627,102 @@ var init_inbox = __esm(async () => {
|
|
|
22631
22627
|
topicWorkerBusy = new Set;
|
|
22632
22628
|
});
|
|
22633
22629
|
|
|
22630
|
+
// ../../packages/core/src/topics/update.ts
|
|
22631
|
+
function updateTopicSettings(opts) {
|
|
22632
|
+
const current3 = getTopic(opts.topicId);
|
|
22633
|
+
if (!current3)
|
|
22634
|
+
throw new TopicValidationError("Topic not found");
|
|
22635
|
+
if (current3.kind === "manager") {
|
|
22636
|
+
throw new TopicValidationError("Manager rooms are system-managed");
|
|
22637
|
+
}
|
|
22638
|
+
let title = current3.title;
|
|
22639
|
+
if (opts.title !== undefined) {
|
|
22640
|
+
title = opts.title.trim();
|
|
22641
|
+
if (!title)
|
|
22642
|
+
throw new TopicValidationError("title is required");
|
|
22643
|
+
if (RESERVED_TOPIC_NAMES.has(title.toLowerCase())) {
|
|
22644
|
+
throw new TopicValidationError(`"${title}" is a reserved name`);
|
|
22645
|
+
}
|
|
22646
|
+
}
|
|
22647
|
+
if (opts.agent !== undefined && opts.agent !== null && !isAgentKind(opts.agent)) {
|
|
22648
|
+
throw new TopicValidationError(`Unknown agent '${opts.agent}'`);
|
|
22649
|
+
}
|
|
22650
|
+
const requestedAgent = opts.agent === undefined ? current3.agent : opts.agent ?? undefined;
|
|
22651
|
+
const requestedAiMode = opts.aiMode ?? current3.aiMode;
|
|
22652
|
+
const requestedKind = opts.agent === null || requestedAiMode === "off" || requestedAiMode === "mention" ? "channel" : normalizeTopicKind(current3.kind);
|
|
22653
|
+
const { kind, aiMode, agent } = normalizeTopicState({
|
|
22654
|
+
id: current3.id,
|
|
22655
|
+
kind: requestedKind,
|
|
22656
|
+
agent: requestedAgent,
|
|
22657
|
+
aiMode: normalizeAiMode(requestedAiMode)
|
|
22658
|
+
});
|
|
22659
|
+
if (title.toLowerCase() !== current3.title.toLowerCase() || kind !== current3.kind) {
|
|
22660
|
+
const conflict = findTopicTitleConflict(title, kind, {
|
|
22661
|
+
excludeTopicId: current3.id,
|
|
22662
|
+
surface: current3.surface,
|
|
22663
|
+
surfaceScope: current3.surfaceScope ?? null
|
|
22664
|
+
});
|
|
22665
|
+
if (conflict) {
|
|
22666
|
+
throw new TopicUpdateConflictError(`A topic named "${title}" already exists on ${current3.surface ?? "this surface"}`);
|
|
22667
|
+
}
|
|
22668
|
+
}
|
|
22669
|
+
const registry = getRegistry(agent ?? "maestro");
|
|
22670
|
+
if (opts.defaultModel !== undefined) {
|
|
22671
|
+
if (!agent)
|
|
22672
|
+
throw new TopicValidationError("This topic has no AI model");
|
|
22673
|
+
if (!registry.validateModel(opts.defaultModel)) {
|
|
22674
|
+
throw new TopicValidationError(`model '${opts.defaultModel}' is not valid for agent '${agent}'`);
|
|
22675
|
+
}
|
|
22676
|
+
}
|
|
22677
|
+
if (opts.defaultEffort !== undefined) {
|
|
22678
|
+
if (!agent)
|
|
22679
|
+
throw new TopicValidationError("This topic has no AI effort");
|
|
22680
|
+
if (!registry.validateEffort(opts.defaultEffort)) {
|
|
22681
|
+
throw new TopicValidationError(`effort '${opts.defaultEffort}' is not valid for agent '${agent}'`);
|
|
22682
|
+
}
|
|
22683
|
+
}
|
|
22684
|
+
const defaultModel = resolveModelForAgent(agent ?? "maestro", opts.defaultModel ?? (agent === current3.agent ? current3.defaultModel : undefined), registry);
|
|
22685
|
+
const requestedEffort = opts.defaultEffort ?? (agent === current3.agent ? current3.defaultEffort : undefined);
|
|
22686
|
+
const defaultEffort = requestedEffort && registry.validateEffort(requestedEffort) ? requestedEffort : registry.defaultEffort ?? "medium";
|
|
22687
|
+
const next = {
|
|
22688
|
+
...current3,
|
|
22689
|
+
title,
|
|
22690
|
+
kind,
|
|
22691
|
+
aiMode,
|
|
22692
|
+
agent,
|
|
22693
|
+
defaultModel,
|
|
22694
|
+
defaultEffort
|
|
22695
|
+
};
|
|
22696
|
+
upsertTopic(next);
|
|
22697
|
+
const config = getApiTopicConfig(next.id);
|
|
22698
|
+
if (config && (opts.defaultModel !== undefined || opts.defaultEffort !== undefined)) {
|
|
22699
|
+
setApiTopicConfig(next.id, {
|
|
22700
|
+
...config,
|
|
22701
|
+
...opts.defaultModel !== undefined ? { model: undefined, modelLocked: undefined } : {},
|
|
22702
|
+
...opts.defaultEffort !== undefined ? { effort: undefined, effortLocked: undefined } : {}
|
|
22703
|
+
});
|
|
22704
|
+
}
|
|
22705
|
+
WsHub.get().broadcastTopicUpdated(next.id);
|
|
22706
|
+
return getTopic(next.id) ?? next;
|
|
22707
|
+
}
|
|
22708
|
+
var TopicUpdateConflictError;
|
|
22709
|
+
var init_update = __esm(async () => {
|
|
22710
|
+
init_model_catalog();
|
|
22711
|
+
await init_registry();
|
|
22712
|
+
await init_bus();
|
|
22713
|
+
init_constants();
|
|
22714
|
+
await init_api_topic_config();
|
|
22715
|
+
await init_api_topics();
|
|
22716
|
+
await init_create();
|
|
22717
|
+
init_types();
|
|
22718
|
+
TopicUpdateConflictError = class TopicUpdateConflictError extends Error {
|
|
22719
|
+
constructor(message) {
|
|
22720
|
+
super(message);
|
|
22721
|
+
this.name = "TopicUpdateConflictError";
|
|
22722
|
+
}
|
|
22723
|
+
};
|
|
22724
|
+
});
|
|
22725
|
+
|
|
22634
22726
|
// ../../packages/core/src/index.ts
|
|
22635
22727
|
var exports_src = {};
|
|
22636
22728
|
__export(exports_src, {
|
|
@@ -22644,6 +22736,7 @@ __export(exports_src, {
|
|
|
22644
22736
|
vaultDel: () => vaultDel,
|
|
22645
22737
|
validateVaultKey: () => validateVaultKey,
|
|
22646
22738
|
upsertTopic: () => upsertTopic,
|
|
22739
|
+
updateTopicSettings: () => updateTopicSettings,
|
|
22647
22740
|
updateTopic: () => updateTopic,
|
|
22648
22741
|
unregisterNodeRequestHandler: () => unregisterNodeRequestHandler,
|
|
22649
22742
|
triggerTopicAiTurn: () => triggerTopicAiTurn,
|
|
@@ -22834,6 +22927,7 @@ __export(exports_src, {
|
|
|
22834
22927
|
VAULT_DESCRIPTION_MAX_LENGTH: () => VAULT_DESCRIPTION_MAX_LENGTH,
|
|
22835
22928
|
VAULT_COMMAND_HELP: () => VAULT_COMMAND_HELP,
|
|
22836
22929
|
TopicValidationError: () => TopicValidationError,
|
|
22930
|
+
TopicUpdateConflictError: () => TopicUpdateConflictError,
|
|
22837
22931
|
TopicTurnStillActiveError: () => TopicTurnStillActiveError,
|
|
22838
22932
|
TopicTitleConflictError: () => TopicTitleConflictError,
|
|
22839
22933
|
TopicServiceError: () => TopicServiceError,
|
|
@@ -22933,6 +23027,7 @@ var init_src = __esm(async () => {
|
|
|
22933
23027
|
await init_lifecycle();
|
|
22934
23028
|
await init_personal_general();
|
|
22935
23029
|
await init_session();
|
|
23030
|
+
await init_update();
|
|
22936
23031
|
init_types();
|
|
22937
23032
|
init_types();
|
|
22938
23033
|
});
|
|
@@ -23252,6 +23347,7 @@ var exports_node_host = {};
|
|
|
23252
23347
|
__export(exports_node_host, {
|
|
23253
23348
|
writeDecisionGraphSvg: () => writeDecisionGraphSvg,
|
|
23254
23349
|
upsertTopic: () => upsertTopic,
|
|
23350
|
+
updateTopicSettings: () => updateTopicSettings,
|
|
23255
23351
|
topicService: () => topicService,
|
|
23256
23352
|
switchTopicModel: () => switchTopicModel,
|
|
23257
23353
|
switchTopicEffort: () => switchTopicEffort,
|
|
@@ -23306,6 +23402,8 @@ __export(exports_node_host, {
|
|
|
23306
23402
|
abortAllRooms: () => abortAllRooms,
|
|
23307
23403
|
WsHub: () => WsHub,
|
|
23308
23404
|
WORKSPACE_DIR: () => WORKSPACE_DIR,
|
|
23405
|
+
TopicValidationError: () => TopicValidationError,
|
|
23406
|
+
TopicUpdateConflictError: () => TopicUpdateConflictError,
|
|
23309
23407
|
TopicTitleConflictError: () => TopicTitleConflictError,
|
|
23310
23408
|
TopicServiceError: () => TopicServiceError,
|
|
23311
23409
|
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
@@ -23352,9 +23450,11 @@ var init_node_host = __esm(async () => {
|
|
|
23352
23450
|
await init_runtime_events();
|
|
23353
23451
|
await init_runtime_process_leases();
|
|
23354
23452
|
await init_token_stats();
|
|
23453
|
+
await init_create();
|
|
23355
23454
|
await init_derive();
|
|
23356
23455
|
await init_personal_general();
|
|
23357
23456
|
await init_session();
|
|
23457
|
+
await init_update();
|
|
23358
23458
|
});
|
|
23359
23459
|
|
|
23360
23460
|
// ../../packages/core/src/agents/mcp-tools/inline-assets.ts
|
|
@@ -30097,6 +30197,7 @@ function createNodeControlHandler(options) {
|
|
|
30097
30197
|
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
30098
30198
|
nodeVersion: NODE_VERSION,
|
|
30099
30199
|
nodeId: NODE_ID,
|
|
30200
|
+
aiName: getGlobalAiName(),
|
|
30100
30201
|
capabilities: [
|
|
30101
30202
|
"turn-submit-idempotent",
|
|
30102
30203
|
"turn-events-sse-resume",
|
|
@@ -30104,7 +30205,13 @@ function createNodeControlHandler(options) {
|
|
|
30104
30205
|
"canonical-message-read",
|
|
30105
30206
|
"canonical-topic-list",
|
|
30106
30207
|
"canonical-topic-create",
|
|
30107
|
-
"canonical-
|
|
30208
|
+
"canonical-topic-update",
|
|
30209
|
+
"canonical-topic-delete",
|
|
30210
|
+
"turn-submit-silent",
|
|
30211
|
+
"canonical-history-import",
|
|
30212
|
+
"canonical-topic-abort",
|
|
30213
|
+
"canonical-session-reset",
|
|
30214
|
+
"canonical-session-compact"
|
|
30108
30215
|
],
|
|
30109
30216
|
cursor: latestRuntimeEventSeq()
|
|
30110
30217
|
});
|
|
@@ -30148,6 +30255,7 @@ function createNodeControlHandler(options) {
|
|
|
30148
30255
|
clientMessageId,
|
|
30149
30256
|
requestId,
|
|
30150
30257
|
allowAutoContinue: body.allowAutoContinue !== false,
|
|
30258
|
+
respond: body.respond !== false,
|
|
30151
30259
|
...threadRootId ? { threadRootId } : {}
|
|
30152
30260
|
});
|
|
30153
30261
|
return Response.json({
|
|
@@ -30260,6 +30368,71 @@ function createNodeControlHandler(options) {
|
|
|
30260
30368
|
imported
|
|
30261
30369
|
});
|
|
30262
30370
|
}
|
|
30371
|
+
const runtimeAbortMatch = runtimePath.match(/^\/topics\/([^/]+)\/abort$/);
|
|
30372
|
+
if (runtimeAbortMatch && req.method === "POST") {
|
|
30373
|
+
const body = await bodyRecord(req);
|
|
30374
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
30375
|
+
return jsonError(400, "Unsupported v");
|
|
30376
|
+
const topicId = decodeURIComponent(runtimeAbortMatch[1]);
|
|
30377
|
+
const topic = getTopic(topicId);
|
|
30378
|
+
if (!topic || !topicInRequestScope(req, topic))
|
|
30379
|
+
return jsonError(404, "Topic not found");
|
|
30380
|
+
const userId = requiredText(body.userId, "userId");
|
|
30381
|
+
return Response.json({
|
|
30382
|
+
ok: true,
|
|
30383
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
30384
|
+
aborted: topicService.abortTurn(topicId, userId)
|
|
30385
|
+
});
|
|
30386
|
+
}
|
|
30387
|
+
const runtimeResetMatch = runtimePath.match(/^\/topics\/([^/]+)\/session\/reset$/);
|
|
30388
|
+
if (runtimeResetMatch && req.method === "POST") {
|
|
30389
|
+
const body = await bodyRecord(req);
|
|
30390
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
30391
|
+
return jsonError(400, "Unsupported v");
|
|
30392
|
+
const topicId = decodeURIComponent(runtimeResetMatch[1]);
|
|
30393
|
+
const topic = getTopic(topicId);
|
|
30394
|
+
if (!topic || !topicInRequestScope(req, topic))
|
|
30395
|
+
return jsonError(404, "Topic not found");
|
|
30396
|
+
const userId = requiredText(body.userId, "userId");
|
|
30397
|
+
const reason = body.reason === undefined ? undefined : requiredText(body.reason, "reason");
|
|
30398
|
+
const result = await topicService.reset({
|
|
30399
|
+
topicId,
|
|
30400
|
+
userId,
|
|
30401
|
+
reason: reason ?? "runtime-contract-session-reset"
|
|
30402
|
+
});
|
|
30403
|
+
if (result.isError)
|
|
30404
|
+
return jsonError(409, result.text);
|
|
30405
|
+
return Response.json({
|
|
30406
|
+
ok: true,
|
|
30407
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
30408
|
+
result: result.text
|
|
30409
|
+
});
|
|
30410
|
+
}
|
|
30411
|
+
const runtimeCompactMatch = runtimePath.match(/^\/topics\/([^/]+)\/session\/compact$/);
|
|
30412
|
+
if (runtimeCompactMatch && req.method === "POST") {
|
|
30413
|
+
const body = await bodyRecord(req);
|
|
30414
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
30415
|
+
return jsonError(400, "Unsupported v");
|
|
30416
|
+
const topicId = decodeURIComponent(runtimeCompactMatch[1]);
|
|
30417
|
+
const topic = getTopic(topicId);
|
|
30418
|
+
if (!topic || !topicInRequestScope(req, topic))
|
|
30419
|
+
return jsonError(404, "Topic not found");
|
|
30420
|
+
const userId = requiredText(body.userId, "userId");
|
|
30421
|
+
const reason = body.reason === undefined ? undefined : requiredText(body.reason, "reason");
|
|
30422
|
+
const result = await topicService.compact({
|
|
30423
|
+
topicId,
|
|
30424
|
+
userId,
|
|
30425
|
+
reason: reason ?? "runtime-contract-session-compact",
|
|
30426
|
+
compactSession: options.compactSession
|
|
30427
|
+
});
|
|
30428
|
+
if (result.isError)
|
|
30429
|
+
return jsonError(409, result.text);
|
|
30430
|
+
return Response.json({
|
|
30431
|
+
ok: true,
|
|
30432
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
30433
|
+
result: result.text
|
|
30434
|
+
});
|
|
30435
|
+
}
|
|
30263
30436
|
const runtimeTopicMatch = runtimePath.match(/^\/topics\/([^/]+)$/);
|
|
30264
30437
|
if (runtimeTopicMatch && req.method === "GET") {
|
|
30265
30438
|
const topic = getTopic(decodeURIComponent(runtimeTopicMatch[1]));
|
|
@@ -30269,6 +30442,69 @@ function createNodeControlHandler(options) {
|
|
|
30269
30442
|
return jsonError(404, "Topic not found");
|
|
30270
30443
|
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic });
|
|
30271
30444
|
}
|
|
30445
|
+
if (runtimeTopicMatch && req.method === "DELETE") {
|
|
30446
|
+
const topicId = decodeURIComponent(runtimeTopicMatch[1]);
|
|
30447
|
+
const topic = getTopic(topicId);
|
|
30448
|
+
if (!topic || !topicInRequestScope(req, topic))
|
|
30449
|
+
return jsonError(404, "Topic not found");
|
|
30450
|
+
const userId = requiredText(url.searchParams.get("user"), "user");
|
|
30451
|
+
try {
|
|
30452
|
+
await topicService.delete({ topicId, userId });
|
|
30453
|
+
} catch (err2) {
|
|
30454
|
+
if (err2 instanceof TopicServiceError) {
|
|
30455
|
+
const status = err2.code === "TOPIC_NOT_FOUND" ? 404 : err2.code === "TOPIC_FORBIDDEN" ? 403 : 400;
|
|
30456
|
+
return jsonError(status, err2.message);
|
|
30457
|
+
}
|
|
30458
|
+
throw err2;
|
|
30459
|
+
}
|
|
30460
|
+
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION });
|
|
30461
|
+
}
|
|
30462
|
+
if (runtimeTopicMatch && req.method === "PATCH") {
|
|
30463
|
+
const body = await bodyRecord(req);
|
|
30464
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
30465
|
+
return jsonError(400, "Unsupported v");
|
|
30466
|
+
const topicId = decodeURIComponent(runtimeTopicMatch[1]);
|
|
30467
|
+
const existing = getTopic(topicId);
|
|
30468
|
+
if (!existing || !topicInRequestScope(req, existing)) {
|
|
30469
|
+
return jsonError(404, "Topic not found");
|
|
30470
|
+
}
|
|
30471
|
+
const userId = requiredText(body.userId, "userId");
|
|
30472
|
+
if (!existing.participants.some((participant) => participant.userId === userId)) {
|
|
30473
|
+
return jsonError(404, "Topic not found");
|
|
30474
|
+
}
|
|
30475
|
+
if (body.title !== undefined && typeof body.title !== "string") {
|
|
30476
|
+
return jsonError(400, "title must be a string");
|
|
30477
|
+
}
|
|
30478
|
+
if (body.agent !== undefined && body.agent !== null && !["claude", "codex", "maestro"].includes(String(body.agent))) {
|
|
30479
|
+
return jsonError(400, "Invalid agent");
|
|
30480
|
+
}
|
|
30481
|
+
if (body.defaultModel !== undefined && typeof body.defaultModel !== "string") {
|
|
30482
|
+
return jsonError(400, "defaultModel must be a string");
|
|
30483
|
+
}
|
|
30484
|
+
if (body.defaultEffort !== undefined && typeof body.defaultEffort !== "string") {
|
|
30485
|
+
return jsonError(400, "defaultEffort must be a string");
|
|
30486
|
+
}
|
|
30487
|
+
if (body.aiMode !== undefined && !["always", "mention", "off"].includes(String(body.aiMode))) {
|
|
30488
|
+
return jsonError(400, "Invalid aiMode");
|
|
30489
|
+
}
|
|
30490
|
+
try {
|
|
30491
|
+
const topic = updateTopicSettings({
|
|
30492
|
+
topicId,
|
|
30493
|
+
...body.title !== undefined ? { title: body.title } : {},
|
|
30494
|
+
...body.agent !== undefined ? { agent: body.agent ?? null } : {},
|
|
30495
|
+
...body.defaultModel !== undefined ? { defaultModel: body.defaultModel } : {},
|
|
30496
|
+
...body.defaultEffort !== undefined ? { defaultEffort: body.defaultEffort } : {},
|
|
30497
|
+
...body.aiMode !== undefined ? { aiMode: body.aiMode } : {}
|
|
30498
|
+
});
|
|
30499
|
+
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic });
|
|
30500
|
+
} catch (err2) {
|
|
30501
|
+
if (err2 instanceof TopicUpdateConflictError)
|
|
30502
|
+
return jsonError(409, err2.message);
|
|
30503
|
+
if (err2 instanceof TopicValidationError)
|
|
30504
|
+
return jsonError(400, err2.message);
|
|
30505
|
+
throw err2;
|
|
30506
|
+
}
|
|
30507
|
+
}
|
|
30272
30508
|
return jsonError(404, "Runtime contract route not found");
|
|
30273
30509
|
}
|
|
30274
30510
|
if (req.method === "GET" && path === "/status") {
|
|
@@ -30345,8 +30581,8 @@ function createNodeControlHandler(options) {
|
|
|
30345
30581
|
}
|
|
30346
30582
|
if (req.method === "PATCH" && path === "/ai-name") {
|
|
30347
30583
|
const body = await bodyRecord(req);
|
|
30348
|
-
const
|
|
30349
|
-
return Response.json({ ok: true, aiName: setGlobalAiName(
|
|
30584
|
+
const aiName = requiredText(body.aiName, "aiName");
|
|
30585
|
+
return Response.json({ ok: true, aiName: setGlobalAiName(aiName) });
|
|
30350
30586
|
}
|
|
30351
30587
|
if (req.method === "POST" && path === "/topics") {
|
|
30352
30588
|
const body = await bodyRecord(req);
|
|
@@ -44997,8 +45233,13 @@ function allowedRuntimePath(path, method) {
|
|
|
44997
45233
|
return true;
|
|
44998
45234
|
return /^\/topics\/[^/]+(\/messages)?$/.test(path);
|
|
44999
45235
|
}
|
|
45000
|
-
if (method === "POST")
|
|
45001
|
-
|
|
45236
|
+
if (method === "POST") {
|
|
45237
|
+
if (path === "/turns")
|
|
45238
|
+
return true;
|
|
45239
|
+
return /^\/topics\/[^/]+\/(abort|session\/(reset|compact))$/.test(path);
|
|
45240
|
+
}
|
|
45241
|
+
if (method === "DELETE" || method === "PATCH")
|
|
45242
|
+
return /^\/topics\/[^/]+$/.test(path);
|
|
45002
45243
|
return false;
|
|
45003
45244
|
}
|
|
45004
45245
|
async function forwardGatewayRequest(req, options) {
|
|
@@ -46940,4 +47181,4 @@ switch (command) {
|
|
|
46940
47181
|
}
|
|
46941
47182
|
}
|
|
46942
47183
|
|
|
46943
|
-
//# debugId=
|
|
47184
|
+
//# debugId=E9676B6176D9C6D664756E2164756E21
|