negotium 0.6.4 → 0.6.6
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 +29 -24
- package/dist/agent-helpers.js.map +7 -7
- package/dist/{chunk-tfwbft4r.js → chunk-pxnv3gh2.js} +2 -2
- package/dist/{chunk-tfwbft4r.js.map → chunk-pxnv3gh2.js.map} +2 -2
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +124 -29
- package/dist/main.js.map +14 -14
- package/dist/mcp-factories.js +20 -15
- package/dist/mcp-factories.js.map +6 -6
- package/dist/registry.js +1 -1
- package/dist/runtime/src/agents/archiver.ts +43 -25
- package/dist/runtime/src/index.ts +1 -1
- package/dist/runtime/src/mcp-runtime-host.ts +1 -1
- package/dist/runtime/src/node-host.ts +1 -0
- package/dist/runtime/src/platform/constants.ts +12 -0
- package/dist/runtime/src/runtime-gateway.ts +61 -0
- package/dist/runtime/src/storage/conversations.ts +24 -4
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-gateway.js +24 -1
- package/dist/runtime-gateway.js.map +3 -3
- package/dist/storage.js +12 -4
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/agents/archiver.d.ts +4 -1
- package/dist/types/packages/core/src/platform/constants.d.ts +10 -0
- package/dist/types/packages/core/src/runtime-gateway.d.ts +9 -0
- package/dist/types/packages/core/src/storage/conversations.d.ts +3 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -3674,7 +3674,7 @@ var exports_version = {};
|
|
|
3674
3674
|
__export(exports_version, {
|
|
3675
3675
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
3676
3676
|
});
|
|
3677
|
-
var NEGOTIUM_VERSION = "0.6.
|
|
3677
|
+
var NEGOTIUM_VERSION = "0.6.6";
|
|
3678
3678
|
|
|
3679
3679
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
3680
3680
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -4519,6 +4519,16 @@ var init_task_events = __esm(async () => {
|
|
|
4519
4519
|
defaultTaskEventHost = { readTasks, taskFileMtimeNs, taskScopeKey };
|
|
4520
4520
|
});
|
|
4521
4521
|
|
|
4522
|
+
// ../../packages/core/src/platform/constants.ts
|
|
4523
|
+
var FROM_AUTO_CONTINUE = "auto-continue", FROM_SELF_SCHEDULE = "self-schedule", RESERVED_TOPIC_NAMES, GENERAL_TOPIC_ID = "general", MANAGER_TOPIC_LOG_NAME = "general", NODE_LOCAL_USER_ID = "local";
|
|
4524
|
+
var init_constants = __esm(() => {
|
|
4525
|
+
RESERVED_TOPIC_NAMES = new Set([
|
|
4526
|
+
FROM_AUTO_CONTINUE,
|
|
4527
|
+
FROM_SELF_SCHEDULE,
|
|
4528
|
+
"general"
|
|
4529
|
+
]);
|
|
4530
|
+
});
|
|
4531
|
+
|
|
4522
4532
|
// ../../packages/core/src/storage/conversations.ts
|
|
4523
4533
|
var exports_conversations = {};
|
|
4524
4534
|
__export(exports_conversations, {
|
|
@@ -4548,12 +4558,15 @@ import { dirname as dirname8, join as join13 } from "path";
|
|
|
4548
4558
|
function conversationDir(_userId) {
|
|
4549
4559
|
return join13(resolveStorageDataDir(), "conversations");
|
|
4550
4560
|
}
|
|
4551
|
-
function topicFilename(topicName) {
|
|
4561
|
+
function topicFilename(userId, topicName) {
|
|
4552
4562
|
const t = sanitizeTopicName(topicName, true);
|
|
4553
|
-
|
|
4563
|
+
const owner = String(userId);
|
|
4564
|
+
if (t !== MANAGER_TOPIC_LOG_NAME || owner === NODE_LOCAL_USER_ID)
|
|
4565
|
+
return `${t}.jsonl`;
|
|
4566
|
+
return `${t}.${sanitizeId(owner)}.jsonl`;
|
|
4554
4567
|
}
|
|
4555
4568
|
function getConversationPath(userId, topicName) {
|
|
4556
|
-
return join13(conversationDir(userId), topicFilename(topicName));
|
|
4569
|
+
return join13(conversationDir(userId), topicFilename(userId, topicName));
|
|
4557
4570
|
}
|
|
4558
4571
|
function getActiveConversationPath(userId, topicName) {
|
|
4559
4572
|
const rawPath = getConversationPath(userId, topicName);
|
|
@@ -4687,6 +4700,7 @@ function findLastSessionIdForAgent(entries, agent) {
|
|
|
4687
4700
|
}
|
|
4688
4701
|
var ConversationLogDivergedError;
|
|
4689
4702
|
var init_conversations = __esm(async () => {
|
|
4703
|
+
init_constants();
|
|
4690
4704
|
init_jsonl();
|
|
4691
4705
|
init_logger();
|
|
4692
4706
|
await init_storage_host();
|
|
@@ -7769,16 +7783,6 @@ var init_api_topic_config = __esm(async () => {
|
|
|
7769
7783
|
registerStorageSchemaInitializer(initializeApiTopicConfigSchema, 40);
|
|
7770
7784
|
});
|
|
7771
7785
|
|
|
7772
|
-
// ../../packages/core/src/platform/constants.ts
|
|
7773
|
-
var FROM_AUTO_CONTINUE = "auto-continue", FROM_SELF_SCHEDULE = "self-schedule", RESERVED_TOPIC_NAMES, GENERAL_TOPIC_ID = "general";
|
|
7774
|
-
var init_constants = __esm(() => {
|
|
7775
|
-
RESERVED_TOPIC_NAMES = new Set([
|
|
7776
|
-
FROM_AUTO_CONTINUE,
|
|
7777
|
-
FROM_SELF_SCHEDULE,
|
|
7778
|
-
"general"
|
|
7779
|
-
]);
|
|
7780
|
-
});
|
|
7781
|
-
|
|
7782
7786
|
// ../../packages/core/src/storage/api-topics.ts
|
|
7783
7787
|
var exports_api_topics = {};
|
|
7784
7788
|
__export(exports_api_topics, {
|
|
@@ -12494,12 +12498,15 @@ function createArchiverRuntime(host) {
|
|
|
12494
12498
|
const agent = params.agent ?? "claude";
|
|
12495
12499
|
const model = params.model;
|
|
12496
12500
|
const outputLanguage = resolveMemoryLanguage();
|
|
12501
|
+
const generalReplyInstruction = `Reply with a short completion message in ${outputLanguage} for display in #General. ` + "Do not include tool-call logs or raw transcripts \u2014 just briefly name the summary / brief / articles you saved.";
|
|
12497
12502
|
const prompt = mode === "active-topic" ? [
|
|
12498
12503
|
`Recent idle conversation snapshot of session "${topicTitle}". Extract durable memory from the archive below and save it into this topic's wiki.`,
|
|
12499
12504
|
`archive_path: ${archivePath}`,
|
|
12500
12505
|
...rawArchivePaths.map((path) => `raw_archive_path: ${path}`),
|
|
12501
12506
|
`wiki_dir: ${wikiDir}`,
|
|
12502
|
-
`output_language: ${outputLanguage}
|
|
12507
|
+
`output_language: ${outputLanguage}`,
|
|
12508
|
+
"",
|
|
12509
|
+
generalReplyInstruction
|
|
12503
12510
|
].join(`
|
|
12504
12511
|
`) : [
|
|
12505
12512
|
`Session "${topicTitle}" was deleted. Extract durable memory from the archive below and save it into the wiki.`,
|
|
@@ -12508,7 +12515,7 @@ function createArchiverRuntime(host) {
|
|
|
12508
12515
|
`wiki_dir: ${wikiDir}`,
|
|
12509
12516
|
`output_language: ${outputLanguage}`,
|
|
12510
12517
|
"",
|
|
12511
|
-
|
|
12518
|
+
generalReplyInstruction
|
|
12512
12519
|
].join(`
|
|
12513
12520
|
`);
|
|
12514
12521
|
const activeSessionId = `memory:${host.config.createId()}`;
|
|
@@ -12636,10 +12643,8 @@ function createArchiverRuntime(host) {
|
|
|
12636
12643
|
host.config.warn({ err, userId, topicTitle }, "archiver: settlement callback failed");
|
|
12637
12644
|
}
|
|
12638
12645
|
}
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, topicId, ok && text ? { text, agent, model, usage } : undefined);
|
|
12642
|
-
}
|
|
12646
|
+
const text = finalText.trimEnd();
|
|
12647
|
+
finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, ok && text ? { text, agent, model, usage } : undefined);
|
|
12643
12648
|
});
|
|
12644
12649
|
topicQueues.set(safeTopic, work);
|
|
12645
12650
|
work.finally(() => {
|
|
@@ -12685,7 +12690,7 @@ function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
|
|
|
12685
12690
|
}
|
|
12686
12691
|
return best?.path ?? null;
|
|
12687
12692
|
}
|
|
12688
|
-
function finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, topicId, generalReply) {
|
|
12693
|
+
function finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, generalReply) {
|
|
12689
12694
|
const generalTopicId = host.storage.getGeneralTopicId(userId);
|
|
12690
12695
|
const date = host.config.now().toISOString().slice(0, 10);
|
|
12691
12696
|
try {
|
|
@@ -12702,7 +12707,7 @@ function finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs,
|
|
|
12702
12707
|
].slice(0, MAX_BRIEF_ENTRIES);
|
|
12703
12708
|
const briefMd = `# Workspace Memory Hub
|
|
12704
12709
|
|
|
12705
|
-
Recent memory digest distilled from
|
|
12710
|
+
Recent memory digest distilled from archived topics (deletions and idle/session-reset snapshots). Use \`wiki_query\` for details.
|
|
12706
12711
|
|
|
12707
12712
|
## Recent Archives
|
|
12708
12713
|
${rolled.join(`
|
|
@@ -12717,7 +12722,7 @@ ${rolled.join(`
|
|
|
12717
12722
|
}
|
|
12718
12723
|
try {
|
|
12719
12724
|
const replyText = generalReply?.text.trim();
|
|
12720
|
-
const text = replyText || (ok ? `\uD83D\uDDC2 Topic "${topicTitle}" was deleted and archived into #General memory.` : `\uD83D\uDDC2 Archived topic "${topicTitle}" (summary extraction failed \u2014 raw log preserved in wiki/archive).`);
|
|
12725
|
+
const text = replyText || (mode === "deleted-topic" ? ok ? `\uD83D\uDDC2 Topic "${topicTitle}" was deleted and archived into #General memory.` : `\uD83D\uDDC2 Archived topic "${topicTitle}" (summary extraction failed \u2014 raw log preserved in wiki/archive).` : ok ? `\uD83D\uDDC2 Session "${topicTitle}" was snapshotted and archived into #General memory.` : `\uD83D\uDDC2 Archived a snapshot of "${topicTitle}" (summary extraction failed \u2014 raw log preserved in wiki/archive).`);
|
|
12721
12726
|
const replyMeta = generalReply && replyText ? {
|
|
12722
12727
|
authorId: "ai",
|
|
12723
12728
|
agentType: generalReply.agent,
|
|
@@ -23679,6 +23684,7 @@ __export(exports_src, {
|
|
|
23679
23684
|
PROCESS_LEASE_STALE_MS: () => PROCESS_LEASE_STALE_MS,
|
|
23680
23685
|
PROCESS_LEASE_HEARTBEAT_MS: () => PROCESS_LEASE_HEARTBEAT_MS,
|
|
23681
23686
|
OPTIONAL_FORUM_MCP_SERVERS: () => OPTIONAL_FORUM_MCP_SERVERS,
|
|
23687
|
+
NODE_LOCAL_USER_ID: () => NODE_LOCAL_USER_ID,
|
|
23682
23688
|
NODE_CONTROL_TOKEN: () => NODE_CONTROL_TOKEN,
|
|
23683
23689
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION,
|
|
23684
23690
|
NEGOTIUM_PORT: () => NEGOTIUM_PORT,
|
|
@@ -24094,6 +24100,7 @@ __export(exports_node_host, {
|
|
|
24094
24100
|
startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
|
|
24095
24101
|
startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
|
|
24096
24102
|
startAiTurn: () => startAiTurn,
|
|
24103
|
+
softDeleteApiMessage: () => softDeleteApiMessage,
|
|
24097
24104
|
setRuntimeMcpPort: () => setRuntimeMcpPort,
|
|
24098
24105
|
setNodeMcpServers: () => setNodeMcpServers,
|
|
24099
24106
|
setGlobalAiName: () => setGlobalAiName,
|
|
@@ -24508,6 +24515,7 @@ __export(exports_mcp_runtime_host, {
|
|
|
24508
24515
|
RUNTIME_MCP_BASE_PATH: () => RUNTIME_MCP_BASE_PATH,
|
|
24509
24516
|
REQUIRED_FORUM_MCP_SERVERS: () => REQUIRED_FORUM_MCP_SERVERS,
|
|
24510
24517
|
OPTIONAL_FORUM_MCP_SERVERS: () => OPTIONAL_FORUM_MCP_SERVERS,
|
|
24518
|
+
NODE_LOCAL_USER_ID: () => NODE_LOCAL_USER_ID,
|
|
24511
24519
|
HOSTED_MCP_SURFACES: () => HOSTED_MCP_SURFACES,
|
|
24512
24520
|
FROM_AUTO_CONTINUE: () => FROM_AUTO_CONTINUE,
|
|
24513
24521
|
EFFORT_VALUES: () => EFFORT_VALUES
|
|
@@ -24548,12 +24556,31 @@ import { z as z6 } from "zod";
|
|
|
24548
24556
|
function callerSurface(ctx) {
|
|
24549
24557
|
return getTopic(ctx.topicId)?.surface ?? defaultTopicSurface();
|
|
24550
24558
|
}
|
|
24559
|
+
function callerSurfaceScope(ctx) {
|
|
24560
|
+
return getTopic(ctx.topicId)?.surfaceScope ?? null;
|
|
24561
|
+
}
|
|
24562
|
+
function topicsForCaller(ctx) {
|
|
24563
|
+
const surface = callerSurface(ctx);
|
|
24564
|
+
if (surface !== "otium") {
|
|
24565
|
+
return getTopics({ surface }).filter((topic) => isParticipant(topic, ctx.userId));
|
|
24566
|
+
}
|
|
24567
|
+
return getTopics({ surface, surfaceScope: callerSurfaceScope(ctx) }).filter((topic) => topic.kind !== "manager" || topic.id === ctx.topicId || isParticipant(topic, ctx.userId));
|
|
24568
|
+
}
|
|
24551
24569
|
function resolveTopicForUser(ctx, ref) {
|
|
24552
24570
|
const trimmed = ref.trim();
|
|
24553
24571
|
if (!trimmed)
|
|
24554
24572
|
return { error: "Error: topic is required." };
|
|
24555
24573
|
const notFound = `Error: topic '${trimmed}' not found (or not uniquely named). Use list_topics to see available topics.`;
|
|
24556
24574
|
const surface = callerSurface(ctx);
|
|
24575
|
+
if (surface === "otium") {
|
|
24576
|
+
const visible = topicsForCaller(ctx);
|
|
24577
|
+
const byId2 = visible.find((topic) => topic.id === trimmed);
|
|
24578
|
+
if (byId2)
|
|
24579
|
+
return { topic: byId2 };
|
|
24580
|
+
const wanted = trimmed.toLowerCase();
|
|
24581
|
+
const byTitle2 = visible.filter((topic) => topic.title.toLowerCase() === wanted);
|
|
24582
|
+
return byTitle2.length === 1 ? { topic: byTitle2[0] } : { error: notFound };
|
|
24583
|
+
}
|
|
24557
24584
|
const byId = getTopic(trimmed);
|
|
24558
24585
|
if (byId) {
|
|
24559
24586
|
if (!isParticipant(byId, ctx.userId) || byId.surface !== surface)
|
|
@@ -24565,6 +24592,12 @@ function resolveTopicForUser(ctx, ref) {
|
|
|
24565
24592
|
return { topic: byTitle };
|
|
24566
24593
|
return { error: notFound };
|
|
24567
24594
|
}
|
|
24595
|
+
function actingUserFor(ctx, target) {
|
|
24596
|
+
const owner = target.participants.find((p) => p.role === "owner")?.userId;
|
|
24597
|
+
if (callerSurface(ctx) !== "otium" || owner !== NODE_LOCAL_USER_ID)
|
|
24598
|
+
return ctx.userId;
|
|
24599
|
+
return owner;
|
|
24600
|
+
}
|
|
24568
24601
|
function describeTopic(topic) {
|
|
24569
24602
|
const running = getRoomQuery(topic.id) ? "turn running" : "idle";
|
|
24570
24603
|
const agent = topic.agent ? `agent: ${topic.agent}` : "no agent";
|
|
@@ -24603,8 +24636,8 @@ function registerNodeTools(server, ctx) {
|
|
|
24603
24636
|
return errorResult(`Error: failed to register topic: ${errMsg(err2)}`);
|
|
24604
24637
|
}
|
|
24605
24638
|
});
|
|
24606
|
-
server.tool("list_topics", "List the
|
|
24607
|
-
const topics =
|
|
24639
|
+
server.tool("list_topics", "List the topics this turn can reach on this negotium node: title, id, kind, agent, and whether a turn is currently running.", {}, async () => {
|
|
24640
|
+
const topics = topicsForCaller(ctx);
|
|
24608
24641
|
if (topics.length === 0) {
|
|
24609
24642
|
return textResult("No topics found. Use register_topic to create one.");
|
|
24610
24643
|
}
|
|
@@ -24649,7 +24682,7 @@ function registerNodeTools(server, ctx) {
|
|
|
24649
24682
|
if (target.kind === "manager") {
|
|
24650
24683
|
return errorResult("Error: manager rooms are system-managed and cannot be restarted.");
|
|
24651
24684
|
}
|
|
24652
|
-
const result = await restartTopicSession(target.id, ctx
|
|
24685
|
+
const result = await restartTopicSession(target.id, actingUserFor(ctx, target), "runtime-mcp-session-reset");
|
|
24653
24686
|
return result.isError ? errorResult(`Error: ${result.text}`) : textResult(result.text);
|
|
24654
24687
|
});
|
|
24655
24688
|
server.tool("delete_topic", "Delete a topic owned by the calling user after archiving its conversation history. Deletion is blocked " + "when the archive cannot be written; pass force: true only as an explicit escape hatch that accepts losing history.", {
|
|
@@ -24666,12 +24699,13 @@ function registerNodeTools(server, ctx) {
|
|
|
24666
24699
|
if (target.kind === "manager") {
|
|
24667
24700
|
return errorResult("Error: manager rooms are system-managed and cannot be deleted.");
|
|
24668
24701
|
}
|
|
24669
|
-
const
|
|
24702
|
+
const actingUser = actingUserFor(ctx, target);
|
|
24703
|
+
const isOwner = target.participants.some((participant) => participant.userId === actingUser && participant.role === "owner");
|
|
24670
24704
|
if (!isOwner) {
|
|
24671
24705
|
return errorResult("Error: only the topic owner can delete it.");
|
|
24672
24706
|
}
|
|
24673
24707
|
try {
|
|
24674
|
-
await deleteTopicCascade(target,
|
|
24708
|
+
await deleteTopicCascade(target, actingUser, { force: force === true });
|
|
24675
24709
|
} catch (err2) {
|
|
24676
24710
|
if (err2 instanceof TopicArchiveRequiredError) {
|
|
24677
24711
|
return errorResult([
|
|
@@ -32528,6 +32562,7 @@ function createNodeControlHandler(options) {
|
|
|
32528
32562
|
"turn-events-sse-resume",
|
|
32529
32563
|
"canonical-topic-read",
|
|
32530
32564
|
"canonical-message-read",
|
|
32565
|
+
"canonical-message-delete",
|
|
32531
32566
|
"canonical-topic-usage",
|
|
32532
32567
|
"canonical-file-read",
|
|
32533
32568
|
"canonical-visual-read",
|
|
@@ -32812,6 +32847,36 @@ function createNodeControlHandler(options) {
|
|
|
32812
32847
|
});
|
|
32813
32848
|
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, ...result });
|
|
32814
32849
|
}
|
|
32850
|
+
const runtimeMessageMatch = runtimePath.match(/^\/topics\/([^/]+)\/messages\/([^/]+)$/);
|
|
32851
|
+
if (runtimeMessageMatch && req.method === "DELETE") {
|
|
32852
|
+
const body = await bodyRecord(req);
|
|
32853
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
32854
|
+
return jsonError(400, "Unsupported v");
|
|
32855
|
+
const topicId = decodeURIComponent(runtimeMessageMatch[1]);
|
|
32856
|
+
const messageId = decodeURIComponent(runtimeMessageMatch[2]);
|
|
32857
|
+
const topic = getTopic(topicId);
|
|
32858
|
+
if (!topic || !topicInRequestScope(req, topic))
|
|
32859
|
+
return jsonError(404, "Topic not found");
|
|
32860
|
+
const actorUserId = requiredText(body.actorUserId, "actorUserId");
|
|
32861
|
+
if (body.allowAdmin !== undefined && typeof body.allowAdmin !== "boolean") {
|
|
32862
|
+
return jsonError(400, "allowAdmin must be boolean");
|
|
32863
|
+
}
|
|
32864
|
+
const existing = getApiMessage(topicId, messageId);
|
|
32865
|
+
if (!existing || existing.deleted)
|
|
32866
|
+
return jsonError(404, "Message not found");
|
|
32867
|
+
if (existing.authorId !== actorUserId && body.allowAdmin !== true) {
|
|
32868
|
+
return jsonError(403, "Not allowed");
|
|
32869
|
+
}
|
|
32870
|
+
const message = softDeleteApiMessage(topicId, messageId);
|
|
32871
|
+
if (!message)
|
|
32872
|
+
return jsonError(404, "Message not found");
|
|
32873
|
+
WsHub.get().broadcastMessageUpdated(topicId, messageId, { deleted: true, text: "" });
|
|
32874
|
+
return Response.json({
|
|
32875
|
+
ok: true,
|
|
32876
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
32877
|
+
message
|
|
32878
|
+
});
|
|
32879
|
+
}
|
|
32815
32880
|
if (req.method === "GET" && runtimePath === "/topics") {
|
|
32816
32881
|
const topics = gatewayVisibleTopics(req);
|
|
32817
32882
|
const previews = getLastMessagePreviews(topics.map((topic) => topic.id));
|
|
@@ -32845,6 +32910,34 @@ function createNodeControlHandler(options) {
|
|
|
32845
32910
|
});
|
|
32846
32911
|
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic }, { status: 201 });
|
|
32847
32912
|
}
|
|
32913
|
+
const runtimeDeriveMatch = runtimePath.match(/^\/topics\/([^/]+)\/derive$/);
|
|
32914
|
+
if (runtimeDeriveMatch && req.method === "POST") {
|
|
32915
|
+
const body = await bodyRecord(req);
|
|
32916
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
32917
|
+
return jsonError(400, "Unsupported v");
|
|
32918
|
+
const topicId = decodeURIComponent(runtimeDeriveMatch[1]);
|
|
32919
|
+
const userId = requiredText(body.userId, "userId");
|
|
32920
|
+
if (typeof body.copyHistory !== "boolean") {
|
|
32921
|
+
return jsonError(400, "copyHistory must be a boolean");
|
|
32922
|
+
}
|
|
32923
|
+
if (body.name !== undefined && typeof body.name !== "string") {
|
|
32924
|
+
return jsonError(400, "name must be a string");
|
|
32925
|
+
}
|
|
32926
|
+
const source = topicForUser(topicId, userId);
|
|
32927
|
+
if (!source || source.kind === "manager" || !topicInRequestScope(req, source)) {
|
|
32928
|
+
return jsonError(404, "Topic not found");
|
|
32929
|
+
}
|
|
32930
|
+
const name = typeof body.name === "string" && body.name.trim() ? body.name.trim() : "";
|
|
32931
|
+
const derived = await topicService.derive({
|
|
32932
|
+
sourceTopicId: topicId,
|
|
32933
|
+
userId,
|
|
32934
|
+
copyHistory: body.copyHistory,
|
|
32935
|
+
...name ? { name } : {}
|
|
32936
|
+
});
|
|
32937
|
+
if (!derived)
|
|
32938
|
+
return jsonError(500, "Failed to derive topic");
|
|
32939
|
+
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic: derived }, { status: 201 });
|
|
32940
|
+
}
|
|
32848
32941
|
const importMatch = runtimePath.match(/^\/topics\/([^/]+)\/import$/);
|
|
32849
32942
|
if (importMatch && req.method === "POST") {
|
|
32850
32943
|
const body = await bodyRecord(req);
|
|
@@ -46582,6 +46675,8 @@ function allowedRuntimePath(path, method) {
|
|
|
46582
46675
|
return /^\/topics\/[^/]+\/(abort|session\/(reset|compact))$/.test(path);
|
|
46583
46676
|
}
|
|
46584
46677
|
if (method === "DELETE" || method === "PATCH") {
|
|
46678
|
+
if (method === "DELETE" && /^\/topics\/[^/]+\/messages\/[^/]+$/.test(path))
|
|
46679
|
+
return true;
|
|
46585
46680
|
return /^\/topics\/[^/]+$/.test(path) || /^\/cron\/jobs\/[^/]+$/.test(path);
|
|
46586
46681
|
}
|
|
46587
46682
|
return false;
|
|
@@ -48632,4 +48727,4 @@ switch (command) {
|
|
|
48632
48727
|
}
|
|
48633
48728
|
}
|
|
48634
48729
|
|
|
48635
|
-
//# debugId=
|
|
48730
|
+
//# debugId=679BF40C457A90DE64756E2164756E21
|