negotium 0.2.26 → 0.2.28
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 +200 -118
- package/dist/agent-helpers.js.map +13 -13
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +1124 -511
- package/dist/main.js.map +43 -41
- package/dist/mcp-factories.js +294 -216
- package/dist/mcp-factories.js.map +13 -13
- package/dist/registry.js +2 -2
- package/dist/registry.js.map +2 -2
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +8 -0
- package/dist/runtime/src/index.ts +6 -0
- package/dist/runtime/src/mcp/session-comm/default-host.ts +25 -6
- package/dist/runtime/src/mcp/session-comm/peer-forward.ts +14 -3
- package/dist/runtime/src/mcp/session-comm/server.ts +1 -1
- package/dist/runtime/src/mcp/session-comm/topics.ts +52 -16
- package/dist/runtime/src/mcp-runtime-host.ts +2 -2
- package/dist/runtime/src/node-host.ts +1 -1
- package/dist/runtime/src/runtime/turn-event-stream.ts +9 -1
- package/dist/runtime/src/runtime/turn-runner.ts +11 -2
- package/dist/runtime/src/storage/api-topics.ts +217 -32
- package/dist/runtime/src/storage/runtime-turn-requests.ts +26 -2
- package/dist/runtime/src/storage/token-stats.ts +27 -2
- package/dist/runtime/src/topics/create.ts +27 -1
- package/dist/runtime/src/topics/derive.ts +20 -6
- package/dist/runtime/src/topics/lifecycle.ts +2 -0
- package/dist/runtime/src/topics/personal-general.ts +28 -4
- package/dist/runtime/src/types/api.ts +7 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/storage.js +141 -31
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/mcp/session-comm/peer-forward.d.ts +7 -2
- package/dist/types/packages/core/src/runtime/turn-event-stream.d.ts +2 -0
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +3 -0
- package/dist/types/packages/core/src/storage/api-topics.d.ts +42 -3
- package/dist/types/packages/core/src/storage/runtime-turn-requests.d.ts +6 -0
- package/dist/types/packages/core/src/storage/token-stats.d.ts +2 -1
- package/dist/types/packages/core/src/topics/derive.d.ts +2 -0
- package/dist/types/packages/core/src/topics/personal-general.d.ts +4 -2
- package/dist/types/packages/core/src/types/api.d.ts +7 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-helpers.js
CHANGED
|
@@ -2062,6 +2062,10 @@ import {
|
|
|
2062
2062
|
writeFileSync as writeFileSync2
|
|
2063
2063
|
} from "fs";
|
|
2064
2064
|
import { dirname as dirname4 } from "path";
|
|
2065
|
+
function readJsonlLines(filePath) {
|
|
2066
|
+
return readFileSync2(filePath, "utf-8").trim().split(`
|
|
2067
|
+
`).filter(Boolean);
|
|
2068
|
+
}
|
|
2065
2069
|
function parseJsonlText(raw) {
|
|
2066
2070
|
return raw.trim().split(`
|
|
2067
2071
|
`).filter(Boolean).map((line) => JSON.parse(line));
|
|
@@ -2395,7 +2399,7 @@ var init_claude_registry = __esm(() => {
|
|
|
2395
2399
|
});
|
|
2396
2400
|
|
|
2397
2401
|
// ../../packages/core/src/version.ts
|
|
2398
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
2402
|
+
var NEGOTIUM_VERSION = "0.2.28";
|
|
2399
2403
|
|
|
2400
2404
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2401
2405
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -7347,6 +7351,15 @@ function defaultTopicSurface() {
|
|
|
7347
7351
|
function normalizeTopicSurface(value) {
|
|
7348
7352
|
return value === "telegram" || value === "otium" || value === "terminal" ? value : "terminal";
|
|
7349
7353
|
}
|
|
7354
|
+
function normalizeSurfaceScope(value) {
|
|
7355
|
+
if (typeof value !== "string")
|
|
7356
|
+
return null;
|
|
7357
|
+
const trimmed = value.trim();
|
|
7358
|
+
return trimmed ? trimmed : null;
|
|
7359
|
+
}
|
|
7360
|
+
function defaultSurfaceScope() {
|
|
7361
|
+
return activeSurfaceScope ?? normalizeSurfaceScope(process.env.NEGOTIUM_SURFACE_SCOPE);
|
|
7362
|
+
}
|
|
7350
7363
|
function tableColumns2(table) {
|
|
7351
7364
|
const rows = db.query(`PRAGMA table_info(${table})`).all();
|
|
7352
7365
|
return new Set(rows.map((row) => row.name));
|
|
@@ -7478,6 +7491,7 @@ function initializeApiTopicsSchema() {
|
|
|
7478
7491
|
is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),
|
|
7479
7492
|
visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),
|
|
7480
7493
|
surface TEXT NOT NULL DEFAULT 'terminal' CHECK (surface IN ('terminal','telegram','otium')),
|
|
7494
|
+
surface_scope TEXT,
|
|
7481
7495
|
browser_profile TEXT NOT NULL DEFAULT 'default',
|
|
7482
7496
|
browser_profile_owner TEXT,
|
|
7483
7497
|
session_id TEXT,
|
|
@@ -7523,8 +7537,8 @@ function initializeApiTopicsSchema() {
|
|
|
7523
7537
|
const legacyBaseEffort = row.base_effort ?? row.default_effort;
|
|
7524
7538
|
db.query(`INSERT INTO api_topics_next
|
|
7525
7539
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
7526
|
-
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,session_id)
|
|
7527
|
-
VALUES (
|
|
7540
|
+
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,surface_scope,session_id)
|
|
7541
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(String(row.id), String(row.title), normalized.kind, typeof row.description === "string" ? row.description : null, normalized.agent ?? null, typeof legacyBaseModel === "string" ? legacyBaseModel : null, typeof legacyBaseEffort === "string" ? legacyBaseEffort : null, normalized.aiMode, String(row.created_at), typeof row.last_message_at === "string" ? row.last_message_at : null, typeof row.parent_topic_id === "string" ? row.parent_topic_id : null, typeof row.memory_topic_id === "string" ? row.memory_topic_id : null, typeof row.memory_key === "string" ? row.memory_key : null, Number(row.is_fork ?? 0) !== 0 ? 1 : 0, Number(row.is_subagent ?? 0) !== 0 ? 1 : 0, row.visibility === "hidden" ? "hidden" : "visible", row.surface === undefined ? defaultTopicSurface() : normalizeTopicSurface(row.surface), normalizeSurfaceScope(row.surface_scope), typeof row.session_id === "string" ? row.session_id : null);
|
|
7528
7542
|
}
|
|
7529
7543
|
db.exec("DROP TABLE IF EXISTS topic_members");
|
|
7530
7544
|
db.exec("DROP TABLE api_topics");
|
|
@@ -7581,6 +7595,9 @@ function initializeApiTopicsSchema() {
|
|
|
7581
7595
|
if (!tableColumns2("api_topics").has("surface")) {
|
|
7582
7596
|
db.exec("ALTER TABLE api_topics ADD COLUMN surface TEXT NOT NULL DEFAULT 'terminal'");
|
|
7583
7597
|
}
|
|
7598
|
+
if (!tableColumns2("api_topics").has("surface_scope")) {
|
|
7599
|
+
db.exec("ALTER TABLE api_topics ADD COLUMN surface_scope TEXT");
|
|
7600
|
+
}
|
|
7584
7601
|
if (tableColumns2("api_topics").has("access_mode")) {
|
|
7585
7602
|
try {
|
|
7586
7603
|
db.exec("ALTER TABLE api_topics DROP COLUMN access_mode");
|
|
@@ -7616,6 +7633,7 @@ function initializeApiTopicsSchema() {
|
|
|
7616
7633
|
backfillTopicSurfaces();
|
|
7617
7634
|
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)");
|
|
7618
7635
|
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_surface ON api_topics(surface)");
|
|
7636
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_surface_scope ON api_topics(surface, surface_scope)");
|
|
7619
7637
|
}
|
|
7620
7638
|
function backfillTopicSurfaces() {
|
|
7621
7639
|
db.exec(`
|
|
@@ -7636,22 +7654,24 @@ function backfillTopicSurfaces() {
|
|
|
7636
7654
|
logger.info({ surface }, "api_topics: surface backfilled");
|
|
7637
7655
|
}
|
|
7638
7656
|
function renameSurfaceTitleCollisions() {
|
|
7639
|
-
const rows = db.query("SELECT id, title, kind, surface FROM api_topics ORDER BY created_at ASC, rowid ASC").all();
|
|
7640
|
-
const
|
|
7657
|
+
const rows = db.query("SELECT id, title, kind, surface FROM api_topics WHERE kind != 'manager' ORDER BY created_at ASC, rowid ASC").all();
|
|
7658
|
+
const keyOf = (surface, kind, title) => [surface, kind, normalizedTitle(title)].join("\x00");
|
|
7659
|
+
const reserved = new Set(rows.map((row) => keyOf(row.surface, row.kind, row.title)));
|
|
7660
|
+
const used = new Set;
|
|
7641
7661
|
const update = db.query("UPDATE api_topics SET title = ? WHERE id = ?");
|
|
7642
7662
|
for (const row of rows) {
|
|
7643
|
-
const key = (title) =>
|
|
7644
|
-
if (!
|
|
7645
|
-
|
|
7663
|
+
const key = (title) => keyOf(row.surface, row.kind, title);
|
|
7664
|
+
if (!used.has(key(row.title))) {
|
|
7665
|
+
used.add(key(row.title));
|
|
7646
7666
|
continue;
|
|
7647
7667
|
}
|
|
7648
7668
|
let suffix = 2;
|
|
7649
7669
|
let candidate = `${row.title} (${suffix})`;
|
|
7650
|
-
while (
|
|
7670
|
+
while (reserved.has(key(candidate)) || used.has(key(candidate))) {
|
|
7651
7671
|
suffix += 1;
|
|
7652
7672
|
candidate = `${row.title} (${suffix})`;
|
|
7653
7673
|
}
|
|
7654
|
-
|
|
7674
|
+
used.add(key(candidate));
|
|
7655
7675
|
update.run(candidate, row.id);
|
|
7656
7676
|
logger.warn({ topicId: row.id, surface: row.surface, from: row.title, to: candidate }, "api_topics: renamed a duplicate title for surface-scoped uniqueness");
|
|
7657
7677
|
}
|
|
@@ -7714,7 +7734,8 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
7714
7734
|
subagentReportMode: r.subagent_report_mode === "tell" || r.subagent_report_mode === "status-only" ? r.subagent_report_mode : "auto"
|
|
7715
7735
|
} : {},
|
|
7716
7736
|
visibility: normalizeTopicVisibility(r.visibility),
|
|
7717
|
-
surface: normalizeTopicSurface(r.surface)
|
|
7737
|
+
surface: normalizeTopicSurface(r.surface),
|
|
7738
|
+
surfaceScope: normalizeSurfaceScope(r.surface_scope)
|
|
7718
7739
|
};
|
|
7719
7740
|
}
|
|
7720
7741
|
function normalizeTopicVisibility(value) {
|
|
@@ -7762,6 +7783,13 @@ function normalizeTopicState(input) {
|
|
|
7762
7783
|
function normalizedTitle(title) {
|
|
7763
7784
|
return title.trim().toLowerCase();
|
|
7764
7785
|
}
|
|
7786
|
+
function surfaceScopeForWrite(t) {
|
|
7787
|
+
if (normalizeTopicSurface(t.surface ?? defaultTopicSurface()) !== "otium")
|
|
7788
|
+
return null;
|
|
7789
|
+
if (t.surfaceScope !== undefined)
|
|
7790
|
+
return normalizeSurfaceScope(t.surfaceScope);
|
|
7791
|
+
return defaultSurfaceScope();
|
|
7792
|
+
}
|
|
7765
7793
|
function upsertTopic(t) {
|
|
7766
7794
|
const normalized = normalizeTopicState({
|
|
7767
7795
|
id: t.id,
|
|
@@ -7774,8 +7802,8 @@ function upsertTopic(t) {
|
|
|
7774
7802
|
db.query(`INSERT INTO api_topics
|
|
7775
7803
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
7776
7804
|
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,
|
|
7777
|
-
subagent_report_mode)
|
|
7778
|
-
VALUES (
|
|
7805
|
+
surface_scope,subagent_report_mode)
|
|
7806
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
7779
7807
|
ON CONFLICT(id) DO UPDATE SET
|
|
7780
7808
|
title = excluded.title,
|
|
7781
7809
|
kind = excluded.kind,
|
|
@@ -7793,7 +7821,11 @@ function upsertTopic(t) {
|
|
|
7793
7821
|
is_subagent = excluded.is_subagent,
|
|
7794
7822
|
visibility = excluded.visibility,
|
|
7795
7823
|
surface = excluded.surface,
|
|
7796
|
-
|
|
7824
|
+
-- A room's workspace is fixed at creation (M-1). COALESCE, not
|
|
7825
|
+
-- assignment: an update may fill in a scope that was unknown when the
|
|
7826
|
+
-- room was created, but may never move a room to another workspace.
|
|
7827
|
+
surface_scope = COALESCE(api_topics.surface_scope, excluded.surface_scope),
|
|
7828
|
+
subagent_report_mode = excluded.subagent_report_mode`).run(t.id, t.title, normalized.kind, t.description ?? null, normalized.agent ?? null, t.defaultModel ?? null, t.defaultEffort ?? null, normalized.aiMode, t.createdAt, t.lastMessageAt ?? null, t.parentTopicId ?? null, t.memoryTopicId ?? null, t.memoryKey ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility), normalizeTopicSurface(t.surface ?? defaultTopicSurface()), surfaceScopeForWrite(t), t.subagentReportMode ?? "auto");
|
|
7797
7829
|
db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
|
|
7798
7830
|
for (const participant of t.participants) {
|
|
7799
7831
|
db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
|
|
@@ -7807,7 +7839,8 @@ function upsertTopic(t) {
|
|
|
7807
7839
|
})();
|
|
7808
7840
|
}
|
|
7809
7841
|
function listTopics(opts = {}) {
|
|
7810
|
-
const
|
|
7842
|
+
const scoped = Object.hasOwn(opts, "surfaceScope");
|
|
7843
|
+
const rows = opts.surface ? db.query(`SELECT * FROM api_topics WHERE surface = ?${scoped ? " AND surface_scope IS ?" : ""} ORDER BY last_message_at DESC`).all(...scoped ? [normalizeTopicSurface(opts.surface), normalizeSurfaceScope(opts.surfaceScope)] : [normalizeTopicSurface(opts.surface)]) : db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
|
|
7811
7844
|
const participants = getAllTopicParticipants();
|
|
7812
7845
|
const tellTargets = rows.some((row) => row.is_subagent !== 0) ? getAllSubagentTellTargets() : undefined;
|
|
7813
7846
|
return rows.map((row) => rowToDto2(row, participants.get(row.id) ?? [], tellTargets));
|
|
@@ -7816,15 +7849,24 @@ function getTopic(id) {
|
|
|
7816
7849
|
const r = db.query("SELECT * FROM api_topics WHERE id = ?").get(id);
|
|
7817
7850
|
return r ? rowToDto2(r) : null;
|
|
7818
7851
|
}
|
|
7819
|
-
function getManagerTopicForUser(userId) {
|
|
7820
|
-
const
|
|
7852
|
+
function getManagerTopicForUser(userId, surface, opts = {}) {
|
|
7853
|
+
const scoped = Object.hasOwn(opts, "surfaceScope");
|
|
7854
|
+
const sql = `SELECT t.* FROM api_topics t
|
|
7821
7855
|
JOIN topic_members m ON m.topic_id = t.id
|
|
7822
7856
|
WHERE t.kind = 'manager'
|
|
7823
7857
|
AND t.id != ?
|
|
7824
7858
|
AND m.user_id = ?
|
|
7825
7859
|
AND m.role = 'owner'
|
|
7860
|
+
${surface ? "AND t.surface = ?" : ""}
|
|
7861
|
+
${scoped ? "AND t.surface_scope IS ?" : ""}
|
|
7826
7862
|
ORDER BY t.created_at ASC
|
|
7827
|
-
LIMIT 1
|
|
7863
|
+
LIMIT 1`;
|
|
7864
|
+
const params = [GENERAL_TOPIC_ID, userId];
|
|
7865
|
+
if (surface)
|
|
7866
|
+
params.push(surface);
|
|
7867
|
+
if (scoped)
|
|
7868
|
+
params.push(normalizeSurfaceScope(opts.surfaceScope));
|
|
7869
|
+
const row = db.query(sql).get(...params);
|
|
7828
7870
|
return row ? rowToDto2(row) : null;
|
|
7829
7871
|
}
|
|
7830
7872
|
function getTopicMemoryOrigin(id) {
|
|
@@ -7851,18 +7893,17 @@ function getTopicMemoryOrigin(id) {
|
|
|
7851
7893
|
function findTopicTitleConflict(title, kind, opts = {}) {
|
|
7852
7894
|
const wanted = normalizedTitle(title);
|
|
7853
7895
|
const surface = normalizeTopicSurface(opts.surface ?? defaultTopicSurface());
|
|
7896
|
+
const surfaceScope = Object.hasOwn(opts, "surfaceScope") ? normalizeSurfaceScope(opts.surfaceScope) : surface === "otium" ? defaultSurfaceScope() : null;
|
|
7854
7897
|
const generalTitleRequested = wanted === normalizedTitle(GENERAL_TOPIC_ID);
|
|
7855
7898
|
if (generalTitleRequested && opts.excludeTopicId !== GENERAL_TOPIC_ID) {
|
|
7856
7899
|
const general = db.query("SELECT * FROM api_topics WHERE id = ?").get(GENERAL_TOPIC_ID);
|
|
7857
7900
|
if (general)
|
|
7858
7901
|
return rowToDto2(general);
|
|
7859
7902
|
}
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
params.push(kind, GENERAL_TOPIC_ID);
|
|
7865
|
-
}
|
|
7903
|
+
if (kind === "manager")
|
|
7904
|
+
return null;
|
|
7905
|
+
const params = [wanted, surface, surfaceScope, kind, GENERAL_TOPIC_ID];
|
|
7906
|
+
let sql = "SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ? AND surface = ? AND surface_scope IS ? AND (kind = ? OR id = ?)";
|
|
7866
7907
|
if (opts.excludeTopicId) {
|
|
7867
7908
|
sql += " AND id != ?";
|
|
7868
7909
|
params.push(opts.excludeTopicId);
|
|
@@ -7943,7 +7984,7 @@ function reparentTopicChildren(deletedTopicId, replacementParentTopicId) {
|
|
|
7943
7984
|
}
|
|
7944
7985
|
return rows.map((row) => row.id);
|
|
7945
7986
|
}
|
|
7946
|
-
var DEFAULT_AGENT_ROOM_AGENT = "maestro", SURFACE_BACKFILL_MIGRATION = "api_topics_surface_backfill_20260808";
|
|
7987
|
+
var DEFAULT_AGENT_ROOM_AGENT = "maestro", activeSurfaceScope = null, SURFACE_BACKFILL_MIGRATION = "api_topics_surface_backfill_20260808";
|
|
7947
7988
|
var init_api_topics = __esm(async () => {
|
|
7948
7989
|
init_constants();
|
|
7949
7990
|
init_logger();
|
|
@@ -7954,8 +7995,10 @@ var init_api_topics = __esm(async () => {
|
|
|
7954
7995
|
|
|
7955
7996
|
// ../../packages/core/src/topics/personal-general.ts
|
|
7956
7997
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7957
|
-
function ensurePersonalGeneral(userId) {
|
|
7958
|
-
const
|
|
7998
|
+
function ensurePersonalGeneral(userId, surface, opts = {}) {
|
|
7999
|
+
const scope = normalizeTopicSurface(surface ?? defaultTopicSurface());
|
|
8000
|
+
const surfaceScope = opts.surfaceScope !== undefined ? normalizeSurfaceScope(opts.surfaceScope) : scope === "otium" ? defaultSurfaceScope() : null;
|
|
8001
|
+
const existing = getManagerTopicForUser(userId, scope, { surfaceScope });
|
|
7959
8002
|
if (existing) {
|
|
7960
8003
|
if (existing.description === LEGACY_PERSONAL_GENERAL_DESCRIPTION) {
|
|
7961
8004
|
existing.description = PERSONAL_GENERAL_DESCRIPTION;
|
|
@@ -7979,6 +8022,8 @@ function ensurePersonalGeneral(userId) {
|
|
|
7979
8022
|
aiMode: "always",
|
|
7980
8023
|
aiMention: false,
|
|
7981
8024
|
participants: [{ userId, role: "owner" }],
|
|
8025
|
+
surface: scope,
|
|
8026
|
+
surfaceScope,
|
|
7982
8027
|
createdAt: now,
|
|
7983
8028
|
lastMessageAt: now
|
|
7984
8029
|
};
|
|
@@ -12079,7 +12124,8 @@ function mergeRuntimeUserTurnRequest(input) {
|
|
|
12079
12124
|
const now = Date.now();
|
|
12080
12125
|
return db.transaction(() => {
|
|
12081
12126
|
const rows = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? ORDER BY created_at ASC, rowid ASC").all(input.topicId);
|
|
12082
|
-
const
|
|
12127
|
+
const thread = input.execution.threadRootId;
|
|
12128
|
+
const previous = rows.map(rowToRequest).filter((request) => request.execution?.threadRootId === thread);
|
|
12083
12129
|
const omittedRequestIds = new Set([
|
|
12084
12130
|
...input.omitRequestIds ?? [],
|
|
12085
12131
|
...previous.filter((request) => Boolean(request.execution?.providerSessionId)).map((request) => request.requestId)
|
|
@@ -12115,7 +12161,11 @@ function mergeRuntimeUserTurnRequest(input) {
|
|
|
12115
12161
|
execution.sessionIdSpecified = true;
|
|
12116
12162
|
}
|
|
12117
12163
|
const attachments = flattenUserTurnAttachments(userMessages);
|
|
12118
|
-
|
|
12164
|
+
const absorbed = previous.map((request) => request.requestId);
|
|
12165
|
+
if (absorbed.length > 0) {
|
|
12166
|
+
db.query(`DELETE FROM runtime_user_turn_requests
|
|
12167
|
+
WHERE topic_id = ? AND request_id IN (${absorbed.map(() => "?").join(",")})`).run(input.topicId, ...absorbed);
|
|
12168
|
+
}
|
|
12119
12169
|
db.query(`INSERT INTO runtime_user_turn_requests
|
|
12120
12170
|
(request_id, topic_id, user_id, prompt, user_messages_json, attachments_json,
|
|
12121
12171
|
allow_auto_continue, execution_json, topic_epoch, created_at,
|
|
@@ -12699,8 +12749,8 @@ function updateTopic(topicId, patch) {
|
|
|
12699
12749
|
function isParticipant(topic, userId) {
|
|
12700
12750
|
return topic.participants.some((p) => p.userId === userId);
|
|
12701
12751
|
}
|
|
12702
|
-
function nextDerivedTopicTitle(sourceTitle, kind, suffix, surface) {
|
|
12703
|
-
const visibleTitles = new Set(listTopics(surface ? { surface } : {}).filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
12752
|
+
function nextDerivedTopicTitle(sourceTitle, kind, suffix, surface, surfaceScope) {
|
|
12753
|
+
const visibleTitles = new Set(listTopics(surface ? { surface, surfaceScope: surfaceScope ?? null } : {}).filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
12704
12754
|
let n = 1;
|
|
12705
12755
|
let title = `${sourceTitle}-${suffix}-${n}`;
|
|
12706
12756
|
while (visibleTitles.has(title.toLowerCase())) {
|
|
@@ -12765,8 +12815,9 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12765
12815
|
] : [{ userId, role: "owner" }];
|
|
12766
12816
|
const kind = topic.kind ?? inferTopicKind(topic);
|
|
12767
12817
|
const surface = topic.surface ?? defaultTopicSurface();
|
|
12768
|
-
const
|
|
12769
|
-
const
|
|
12818
|
+
const surfaceScope = topic.surfaceScope ?? null;
|
|
12819
|
+
const title = opts?.name?.trim() || nextDerivedTopicTitle(topic.title, kind, suffix, surface, surfaceScope);
|
|
12820
|
+
const conflict = findTopicTitleConflict(title, kind, { surface, surfaceScope });
|
|
12770
12821
|
if (conflict) {
|
|
12771
12822
|
logger.info({ sourceTopicId, title, kind, conflictTopicId: conflict.id }, "createDerivedTopic: title conflict");
|
|
12772
12823
|
throw new TopicTitleConflictError(title);
|
|
@@ -12789,7 +12840,8 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12789
12840
|
isFork: copyHistory,
|
|
12790
12841
|
...subagent ? { isSubagent: true } : {},
|
|
12791
12842
|
visibility: topic.visibility,
|
|
12792
|
-
surface
|
|
12843
|
+
surface,
|
|
12844
|
+
surfaceScope
|
|
12793
12845
|
};
|
|
12794
12846
|
let sessionId;
|
|
12795
12847
|
let rollbackHandle;
|
|
@@ -12897,7 +12949,10 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12897
12949
|
if (!currentSource || currentSource.kind === "manager" || !isParticipant(currentSource, userId) || subagent && isRuntimeTopicMaintenance(sourceTopicId)) {
|
|
12898
12950
|
throw new TopicDeriveBusyError("Source topic changed while deriving; try again");
|
|
12899
12951
|
}
|
|
12900
|
-
const transactionalConflict = findTopicTitleConflict(title, kind, {
|
|
12952
|
+
const transactionalConflict = findTopicTitleConflict(title, kind, {
|
|
12953
|
+
surface,
|
|
12954
|
+
surfaceScope
|
|
12955
|
+
});
|
|
12901
12956
|
if (transactionalConflict)
|
|
12902
12957
|
throw new TopicTitleConflictError(title);
|
|
12903
12958
|
upsertTopic(derived);
|
|
@@ -13186,13 +13241,14 @@ async function forwardToPeer(args) {
|
|
|
13186
13241
|
error: forwarded.configured ? "remote session bridge is configured but unavailable" : "remote nodes are not connected on this negotium node (standalone mode)"
|
|
13187
13242
|
};
|
|
13188
13243
|
}
|
|
13189
|
-
async function peerSessionsForUser(userId, sourceQueryId) {
|
|
13244
|
+
async function peerSessionsForUser(userId, sourceQueryId, fromTopicId) {
|
|
13190
13245
|
if (activeBridge)
|
|
13191
|
-
return activeBridge.sessions(userId, sourceQueryId);
|
|
13246
|
+
return activeBridge.sessions(userId, sourceQueryId, fromTopicId);
|
|
13192
13247
|
const sessions = await callLoopbackBridge({
|
|
13193
13248
|
action: "sessions",
|
|
13194
13249
|
userId,
|
|
13195
|
-
sourceQueryId
|
|
13250
|
+
sourceQueryId,
|
|
13251
|
+
fromTopicId
|
|
13196
13252
|
});
|
|
13197
13253
|
if (sessions.result)
|
|
13198
13254
|
return sessions.result;
|
|
@@ -13939,6 +13995,94 @@ body{font-family:system-ui,-apple-system,"Segoe UI",sans-serif;background:var(--
|
|
|
13939
13995
|
</style>`;
|
|
13940
13996
|
});
|
|
13941
13997
|
|
|
13998
|
+
// ../../packages/core/src/storage/token-stats.ts
|
|
13999
|
+
import { createHash as createHash7 } from "crypto";
|
|
14000
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync14 } from "fs";
|
|
14001
|
+
import { join as join25 } from "path";
|
|
14002
|
+
function tokenStatsFileId(userId) {
|
|
14003
|
+
const rawUserId = String(userId);
|
|
14004
|
+
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
|
|
14005
|
+
}
|
|
14006
|
+
function queriesPath(userId) {
|
|
14007
|
+
const fileId = tokenStatsFileId(userId);
|
|
14008
|
+
const logDir = resolveStorageLogDir();
|
|
14009
|
+
mkdirSync16(logDir, { recursive: true });
|
|
14010
|
+
return join25(logDir, `token-queries-${fileId}.jsonl`);
|
|
14011
|
+
}
|
|
14012
|
+
function estimateUsageCost(agent, model, usage) {
|
|
14013
|
+
const prices = TOKEN_PRICES[`${agent}:${model}`];
|
|
14014
|
+
if (!prices)
|
|
14015
|
+
return 0;
|
|
14016
|
+
return (usage.inputTokens * prices.input + usage.outputTokens * prices.output + (agent === "claude" ? usage.cacheCreationInputTokens * (prices.cacheWrite ?? prices.input) : 0) + usage.cacheReadInputTokens * prices.cacheRead) / 1e6;
|
|
14017
|
+
}
|
|
14018
|
+
function recordUsage(userId, session, usage, context) {
|
|
14019
|
+
const cacheReadInputTokens = usage.cacheReadInputTokens ?? 0;
|
|
14020
|
+
const inputTokens = context.agent === "claude" ? usage.inputTokens : Math.max(0, usage.inputTokens - cacheReadInputTokens);
|
|
14021
|
+
const normalized = {
|
|
14022
|
+
inputTokens,
|
|
14023
|
+
outputTokens: usage.outputTokens,
|
|
14024
|
+
cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,
|
|
14025
|
+
cacheReadInputTokens
|
|
14026
|
+
};
|
|
14027
|
+
const record = {
|
|
14028
|
+
schemaVersion: 2,
|
|
14029
|
+
timestamp: new Date().toISOString(),
|
|
14030
|
+
session,
|
|
14031
|
+
topicId: context.topicId,
|
|
14032
|
+
...context.providerSessionId ? { providerSessionId: context.providerSessionId } : {},
|
|
14033
|
+
agent: context.agent,
|
|
14034
|
+
model: context.model,
|
|
14035
|
+
...normalized,
|
|
14036
|
+
...usage.contextTokens !== undefined ? { contextTokens: usage.contextTokens } : {},
|
|
14037
|
+
...usage.contextWindow !== undefined ? { contextWindow: usage.contextWindow } : {},
|
|
14038
|
+
estimatedCostUsd: usage.costUsd ?? estimateUsageCost(context.agent, context.model, normalized)
|
|
14039
|
+
};
|
|
14040
|
+
try {
|
|
14041
|
+
appendJsonlEntry(queriesPath(userId), record);
|
|
14042
|
+
} catch (e) {
|
|
14043
|
+
logger.warn({ err: e, userId }, "token-stats: Failed to record");
|
|
14044
|
+
}
|
|
14045
|
+
}
|
|
14046
|
+
function deleteTopicStats(userId, topicId) {
|
|
14047
|
+
const path = queriesPath(userId);
|
|
14048
|
+
try {
|
|
14049
|
+
const kept = readJsonlLines(path).filter((line) => {
|
|
14050
|
+
try {
|
|
14051
|
+
const record = JSON.parse(line);
|
|
14052
|
+
return record.topicId !== topicId;
|
|
14053
|
+
} catch {
|
|
14054
|
+
return true;
|
|
14055
|
+
}
|
|
14056
|
+
});
|
|
14057
|
+
writeFileSync14(path, kept.length > 0 ? `${kept.join(`
|
|
14058
|
+
`)}
|
|
14059
|
+
` : "", "utf-8");
|
|
14060
|
+
} catch (e) {
|
|
14061
|
+
if (e.code === "ENOENT")
|
|
14062
|
+
return;
|
|
14063
|
+
logger.warn({ err: e, userId, topicId }, "token-stats: Failed to delete topic stats");
|
|
14064
|
+
}
|
|
14065
|
+
}
|
|
14066
|
+
var TOKEN_PRICES;
|
|
14067
|
+
var init_token_stats = __esm(async () => {
|
|
14068
|
+
init_jsonl();
|
|
14069
|
+
init_logger();
|
|
14070
|
+
await init_api_topics();
|
|
14071
|
+
await init_storage_host();
|
|
14072
|
+
TOKEN_PRICES = {
|
|
14073
|
+
"codex:gpt-5.6-sol": { input: 5, cacheRead: 0.5, output: 30 },
|
|
14074
|
+
"codex:gpt-5.6-terra": { input: 2.5, cacheRead: 0.25, output: 15 },
|
|
14075
|
+
"codex:gpt-5.6-luna": { input: 1, cacheRead: 0.1, output: 6 },
|
|
14076
|
+
"claude:fable": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
|
|
14077
|
+
"claude:opus": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
|
|
14078
|
+
"claude:sonnet": { input: 2, cacheWrite: 2.5, cacheRead: 0.2, output: 10 },
|
|
14079
|
+
"maestro:kimi-k3": { input: 3, cacheRead: 0.3, output: 15 },
|
|
14080
|
+
"maestro:kimi-k2.7-code": { input: 0.95, cacheRead: 0.19, output: 4 },
|
|
14081
|
+
"maestro:deepseek-pro": { input: 0.435, cacheRead: 0.003625, output: 0.87 },
|
|
14082
|
+
"maestro:deepseek-flash": { input: 0.14, cacheRead: 0.0028, output: 0.28 }
|
|
14083
|
+
};
|
|
14084
|
+
});
|
|
14085
|
+
|
|
13942
14086
|
// ../../packages/core/src/topics/lifecycle.ts
|
|
13943
14087
|
var exports_lifecycle = {};
|
|
13944
14088
|
__export(exports_lifecycle, {
|
|
@@ -13988,6 +14132,7 @@ async function cleanupParticipantResources(topic, userIds, sessionId, cwd, purge
|
|
|
13988
14132
|
cleanupSessionInboxFiles(participantUserId, topic.id, topic.title);
|
|
13989
14133
|
clearQueryState(participantUserId, topic.id, topic.title);
|
|
13990
14134
|
clearQueryUsageAlert(participantUserId, topic.id);
|
|
14135
|
+
deleteTopicStats(participantUserId, topic.id);
|
|
13991
14136
|
deletePendingAsksForTopic({ userId: participantUserId, topicName: topic.title });
|
|
13992
14137
|
}
|
|
13993
14138
|
return true;
|
|
@@ -14142,6 +14287,7 @@ var init_lifecycle = __esm(async () => {
|
|
|
14142
14287
|
await init_runtime_turn_requests();
|
|
14143
14288
|
await init_self_schedules();
|
|
14144
14289
|
await init_session_asks();
|
|
14290
|
+
await init_token_stats();
|
|
14145
14291
|
await init_topic_archive();
|
|
14146
14292
|
await init_topic_archive_state();
|
|
14147
14293
|
TopicArchiveRequiredError = class TopicArchiveRequiredError extends Error {
|
|
@@ -14176,8 +14322,8 @@ var init_lifecycle = __esm(async () => {
|
|
|
14176
14322
|
|
|
14177
14323
|
// ../../packages/core/src/runtime/attachments.ts
|
|
14178
14324
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
14179
|
-
import { copyFileSync as copyFileSync2, mkdirSync as
|
|
14180
|
-
import { basename as basename5, join as
|
|
14325
|
+
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
14326
|
+
import { basename as basename5, join as join26 } from "path";
|
|
14181
14327
|
function workspaceCwdFor(topicId) {
|
|
14182
14328
|
return resolveTopicWorkspaceDir(topicId);
|
|
14183
14329
|
}
|
|
@@ -14190,7 +14336,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
14190
14336
|
if (!attachmentIds?.length)
|
|
14191
14337
|
return [];
|
|
14192
14338
|
const out = [];
|
|
14193
|
-
const destDir =
|
|
14339
|
+
const destDir = join26(workspaceCwdFor(topicId), "attachments", queryId);
|
|
14194
14340
|
for (const rawId of attachmentIds) {
|
|
14195
14341
|
if (typeof rawId !== "string")
|
|
14196
14342
|
continue;
|
|
@@ -14204,10 +14350,10 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
14204
14350
|
continue;
|
|
14205
14351
|
}
|
|
14206
14352
|
try {
|
|
14207
|
-
|
|
14353
|
+
mkdirSync17(destDir, { recursive: true });
|
|
14208
14354
|
const index = String(out.length + 1).padStart(2, "0");
|
|
14209
14355
|
const safeName = safeAttachmentFilename(attachment.filename, fileId);
|
|
14210
|
-
const destPath =
|
|
14356
|
+
const destPath = join26(destDir, `${index}-${fileId.slice(0, 8)}-${safeName}`);
|
|
14211
14357
|
copyFileSync2(sourcePath, destPath);
|
|
14212
14358
|
out.push({
|
|
14213
14359
|
id: attachment.id,
|
|
@@ -14237,14 +14383,14 @@ function promptWithAttachments(prompt, attachments) {
|
|
|
14237
14383
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
14238
14384
|
}
|
|
14239
14385
|
function ingestAttachment(args) {
|
|
14240
|
-
const destDir =
|
|
14241
|
-
|
|
14386
|
+
const destDir = join26(UPLOADS_DIR, args.topicId);
|
|
14387
|
+
mkdirSync17(destDir, { recursive: true });
|
|
14242
14388
|
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
14243
|
-
const destPath =
|
|
14389
|
+
const destPath = join26(destDir, `${Date.now()}-${randomUUID14().slice(0, 8)}-${safeName}`);
|
|
14244
14390
|
if (args.sourcePath !== undefined) {
|
|
14245
14391
|
copyFileSync2(args.sourcePath, destPath);
|
|
14246
14392
|
} else if (args.bytes !== undefined) {
|
|
14247
|
-
|
|
14393
|
+
writeFileSync15(destPath, args.bytes);
|
|
14248
14394
|
} else {
|
|
14249
14395
|
throw new Error("ingestAttachment: provide sourcePath or bytes");
|
|
14250
14396
|
}
|
|
@@ -14824,73 +14970,6 @@ var init_visuals = __esm(async () => {
|
|
|
14824
14970
|
init_visual_html();
|
|
14825
14971
|
});
|
|
14826
14972
|
|
|
14827
|
-
// ../../packages/core/src/storage/token-stats.ts
|
|
14828
|
-
import { createHash as createHash7 } from "crypto";
|
|
14829
|
-
import { mkdirSync as mkdirSync17 } from "fs";
|
|
14830
|
-
import { join as join26 } from "path";
|
|
14831
|
-
function tokenStatsFileId(userId) {
|
|
14832
|
-
const rawUserId = String(userId);
|
|
14833
|
-
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
|
|
14834
|
-
}
|
|
14835
|
-
function queriesPath(userId) {
|
|
14836
|
-
const fileId = tokenStatsFileId(userId);
|
|
14837
|
-
const logDir = resolveStorageLogDir();
|
|
14838
|
-
mkdirSync17(logDir, { recursive: true });
|
|
14839
|
-
return join26(logDir, `token-queries-${fileId}.jsonl`);
|
|
14840
|
-
}
|
|
14841
|
-
function estimateUsageCost(agent, model, usage) {
|
|
14842
|
-
const prices = TOKEN_PRICES[`${agent}:${model}`];
|
|
14843
|
-
if (!prices)
|
|
14844
|
-
return 0;
|
|
14845
|
-
return (usage.inputTokens * prices.input + usage.outputTokens * prices.output + (agent === "claude" ? usage.cacheCreationInputTokens * (prices.cacheWrite ?? prices.input) : 0) + usage.cacheReadInputTokens * prices.cacheRead) / 1e6;
|
|
14846
|
-
}
|
|
14847
|
-
function recordUsage(userId, session, usage, context) {
|
|
14848
|
-
const cacheReadInputTokens = usage.cacheReadInputTokens ?? 0;
|
|
14849
|
-
const inputTokens = context.agent === "claude" ? usage.inputTokens : Math.max(0, usage.inputTokens - cacheReadInputTokens);
|
|
14850
|
-
const normalized = {
|
|
14851
|
-
inputTokens,
|
|
14852
|
-
outputTokens: usage.outputTokens,
|
|
14853
|
-
cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,
|
|
14854
|
-
cacheReadInputTokens
|
|
14855
|
-
};
|
|
14856
|
-
const record = {
|
|
14857
|
-
schemaVersion: 2,
|
|
14858
|
-
timestamp: new Date().toISOString(),
|
|
14859
|
-
session,
|
|
14860
|
-
topicId: context.topicId,
|
|
14861
|
-
...context.providerSessionId ? { providerSessionId: context.providerSessionId } : {},
|
|
14862
|
-
agent: context.agent,
|
|
14863
|
-
model: context.model,
|
|
14864
|
-
...normalized,
|
|
14865
|
-
...usage.contextTokens !== undefined ? { contextTokens: usage.contextTokens } : {},
|
|
14866
|
-
...usage.contextWindow !== undefined ? { contextWindow: usage.contextWindow } : {},
|
|
14867
|
-
estimatedCostUsd: usage.costUsd ?? estimateUsageCost(context.agent, context.model, normalized)
|
|
14868
|
-
};
|
|
14869
|
-
try {
|
|
14870
|
-
appendJsonlEntry(queriesPath(userId), record);
|
|
14871
|
-
} catch (e) {
|
|
14872
|
-
logger.warn({ err: e, userId }, "token-stats: Failed to record");
|
|
14873
|
-
}
|
|
14874
|
-
}
|
|
14875
|
-
var TOKEN_PRICES;
|
|
14876
|
-
var init_token_stats = __esm(async () => {
|
|
14877
|
-
init_jsonl();
|
|
14878
|
-
init_logger();
|
|
14879
|
-
await init_storage_host();
|
|
14880
|
-
TOKEN_PRICES = {
|
|
14881
|
-
"codex:gpt-5.6-sol": { input: 5, cacheRead: 0.5, output: 30 },
|
|
14882
|
-
"codex:gpt-5.6-terra": { input: 2.5, cacheRead: 0.25, output: 15 },
|
|
14883
|
-
"codex:gpt-5.6-luna": { input: 1, cacheRead: 0.1, output: 6 },
|
|
14884
|
-
"claude:fable": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
|
|
14885
|
-
"claude:opus": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
|
|
14886
|
-
"claude:sonnet": { input: 2, cacheWrite: 2.5, cacheRead: 0.2, output: 10 },
|
|
14887
|
-
"maestro:kimi-k3": { input: 3, cacheRead: 0.3, output: 15 },
|
|
14888
|
-
"maestro:kimi-k2.7-code": { input: 0.95, cacheRead: 0.19, output: 4 },
|
|
14889
|
-
"maestro:deepseek-pro": { input: 0.435, cacheRead: 0.003625, output: 0.87 },
|
|
14890
|
-
"maestro:deepseek-flash": { input: 0.14, cacheRead: 0.0028, output: 0.28 }
|
|
14891
|
-
};
|
|
14892
|
-
});
|
|
14893
|
-
|
|
14894
14973
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
14895
14974
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
14896
14975
|
import { realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
@@ -15006,10 +15085,11 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15006
15085
|
agentType,
|
|
15007
15086
|
model,
|
|
15008
15087
|
sourceNode: execution?.sourceNode,
|
|
15088
|
+
...execution?.threadRootId ? { threadRootId: execution.threadRootId } : {},
|
|
15009
15089
|
usage,
|
|
15010
15090
|
createdAt: new Date().toISOString()
|
|
15011
15091
|
};
|
|
15012
|
-
appendApiMessage(message);
|
|
15092
|
+
appendApiMessage(message, execution?.threadRootId ? { updateTopicLastMessageAt: false } : undefined);
|
|
15013
15093
|
hub.broadcastMessage(topicId, message);
|
|
15014
15094
|
lastVisibleMessageId = message.id;
|
|
15015
15095
|
visibleMessageIds.push(message.id);
|
|
@@ -15525,7 +15605,7 @@ var init_turn_session = __esm(async () => {
|
|
|
15525
15605
|
});
|
|
15526
15606
|
|
|
15527
15607
|
// ../../packages/core/src/storage/app-settings.ts
|
|
15528
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync17, writeFileSync as
|
|
15608
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync16 } from "fs";
|
|
15529
15609
|
import { dirname as dirname14, join as join27 } from "path";
|
|
15530
15610
|
function settingsFile() {
|
|
15531
15611
|
return join27(resolveStorageDataDir(), "otium-settings.json");
|
|
@@ -16043,6 +16123,7 @@ async function drainOneDurableUserTurn() {
|
|
|
16043
16123
|
bridgeSessionFromHistory: execution?.bridgeSessionFromHistory,
|
|
16044
16124
|
peerBridge: execution?.peerBridge,
|
|
16045
16125
|
from: execution?.from,
|
|
16126
|
+
threadRootId: execution?.threadRootId,
|
|
16046
16127
|
_queryId: request.requestId,
|
|
16047
16128
|
_runtimeEpoch: execution?.runtimeEpoch ?? request.topicEpoch,
|
|
16048
16129
|
onSettled: () => {
|
|
@@ -16115,6 +16196,7 @@ function startAiTurn(params) {
|
|
|
16115
16196
|
let sessionId = sessionResolution.sessionId;
|
|
16116
16197
|
const deferredSessionId = params.sessionId === undefined && !sessionResolution.isolated ? undefined : sessionId;
|
|
16117
16198
|
const sourceNode = params.sourceNode;
|
|
16199
|
+
const threadRootId = params.threadRootId;
|
|
16118
16200
|
const topicId = topic.id;
|
|
16119
16201
|
const requestId = params.requestId;
|
|
16120
16202
|
const depth = params.depth;
|
|
@@ -16643,7 +16725,7 @@ function startAiTurn(params) {
|
|
|
16643
16725
|
WsHub.get().broadcastTyping(topicId, "ai");
|
|
16644
16726
|
WsHub.get().broadcastAiActive(topicId, queryId);
|
|
16645
16727
|
}
|
|
16646
|
-
streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, { silent, peerBridge, sourceNode }).then(async (streamOutcome) => {
|
|
16728
|
+
streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, { silent, peerBridge, sourceNode, ...threadRootId ? { threadRootId } : {} }).then(async (streamOutcome) => {
|
|
16647
16729
|
let outcome = streamOutcome;
|
|
16648
16730
|
if (outcome.kind === "session-expired") {
|
|
16649
16731
|
const retry = resolveSessionRetry({
|
|
@@ -18810,4 +18892,4 @@ export {
|
|
|
18810
18892
|
DEFAULT_SELF_CONFIG_PRODUCT
|
|
18811
18893
|
};
|
|
18812
18894
|
|
|
18813
|
-
//# debugId=
|
|
18895
|
+
//# debugId=B47531840AAE99C064756E2164756E21
|