negotium 0.2.23 → 0.2.25
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 +84 -30
- package/dist/agent-helpers.js.map +6 -6
- package/dist/background-bash.js +2 -1
- package/dist/background-bash.js.map +3 -3
- package/dist/browser-runtime.js +2 -1
- package/dist/browser-runtime.js.map +3 -3
- package/dist/{chunk-rhp26p2c.js → chunk-1y2xw0xe.js} +2 -1
- package/dist/{chunk-rhp26p2c.js.map → chunk-1y2xw0xe.js.map} +3 -3
- package/dist/hosted-agent.js +3 -2
- package/dist/hosted-agent.js.map +4 -4
- package/dist/main.js +224 -366
- package/dist/main.js.map +27 -28
- package/dist/mcp-factories.js +86 -31
- package/dist/mcp-factories.js.map +7 -7
- package/dist/prompts.js +2 -1
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +2 -1
- package/dist/query-runtime.js.map +3 -3
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/index.ts +3 -7
- package/dist/runtime/src/mcp/session-comm/default-host.ts +6 -1
- package/dist/runtime/src/mcp/session-comm/topic-catalog.ts +17 -1
- package/dist/runtime/src/mcp/session-comm/topics.ts +23 -1
- package/dist/runtime/src/node-host.ts +4 -4
- package/dist/runtime/src/platform/config.ts +12 -0
- package/dist/runtime/src/storage/api-topics.ts +160 -52
- package/dist/runtime/src/storage/storage-public.ts +0 -1
- package/dist/runtime/src/topics/create.ts +12 -6
- package/dist/runtime/src/topics/derive.ts +20 -11
- package/dist/runtime/src/types/api.ts +8 -4
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +2 -1
- package/dist/runtime-helpers.js.map +3 -3
- package/dist/storage.js +92 -38
- package/dist/storage.js.map +3 -3
- package/dist/types/packages/core/src/mcp/session-comm/topic-catalog.d.ts +7 -0
- package/dist/types/packages/core/src/platform/config.d.ts +12 -0
- package/dist/types/packages/core/src/storage/api-topics.d.ts +34 -19
- package/dist/types/packages/core/src/storage/storage-public.d.ts +1 -1
- package/dist/types/packages/core/src/topics/derive.d.ts +13 -4
- package/dist/types/packages/core/src/types/api.d.ts +8 -4
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +2 -1
- package/dist/vault.js.map +3 -3
- package/package.json +1 -1
- package/dist/runtime/src/application/switch-topic-access-mode.ts +0 -110
package/dist/main.js
CHANGED
|
@@ -273,7 +273,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
273
273
|
function codexAuthFilePath() {
|
|
274
274
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
275
275
|
}
|
|
276
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
276
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, NODE_ID, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
277
277
|
var init_config = __esm(() => {
|
|
278
278
|
init_config_helpers();
|
|
279
279
|
init_logger();
|
|
@@ -315,6 +315,7 @@ var init_config = __esm(() => {
|
|
|
315
315
|
BG_BASH_MAX_PORT = parsePortEnv(process.env.BG_BASH_MAX_PORT, 9799);
|
|
316
316
|
RUNTIME_MCP_SECRET = loadOrCreateLocalSecret("RUNTIME_MCP_SECRET", "runtime-mcp-secret");
|
|
317
317
|
NODE_CONTROL_TOKEN = loadOrCreateLocalSecret("NEGOTIUM_CONTROL_TOKEN", "node-control-token");
|
|
318
|
+
NODE_ID = loadOrCreateLocalSecret("NEGOTIUM_NODE_ID", "node-id");
|
|
318
319
|
VAULT_MASTER_KEY = loadOrCreateLocalSecret("NEGOTIUM_VAULT_MASTER_KEY", "vault-master-key", { persistEnvValue: true });
|
|
319
320
|
delete process.env.NEGOTIUM_VAULT_MASTER_KEY;
|
|
320
321
|
NEGOTIUM_PORT = parseInt(process.env.NEGOTIUM_PORT || "7777", 10);
|
|
@@ -1867,7 +1868,7 @@ var exports_version = {};
|
|
|
1867
1868
|
__export(exports_version, {
|
|
1868
1869
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1869
1870
|
});
|
|
1870
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
1871
|
+
var NEGOTIUM_VERSION = "0.2.25";
|
|
1871
1872
|
|
|
1872
1873
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1873
1874
|
import { spawn } from "child_process";
|
|
@@ -7505,21 +7506,20 @@ var init_constants = __esm(() => {
|
|
|
7505
7506
|
var exports_api_topics = {};
|
|
7506
7507
|
__export(exports_api_topics, {
|
|
7507
7508
|
upsertTopic: () => upsertTopic,
|
|
7509
|
+
setTopicSurfaces: () => setTopicSurfaces,
|
|
7508
7510
|
setTopicSessionId: () => setTopicSessionId,
|
|
7509
|
-
setTopicAccessModes: () => setTopicAccessModes,
|
|
7510
7511
|
setApiTopicAgent: () => setApiTopicAgent,
|
|
7511
7512
|
revokeSubagentTellTarget: () => revokeSubagentTellTarget,
|
|
7512
7513
|
reparentTopicChildren: () => reparentTopicChildren,
|
|
7513
7514
|
removeParticipantFromDB: () => removeParticipantFromDB,
|
|
7514
7515
|
normalizeTopicVisibility: () => normalizeTopicVisibility,
|
|
7516
|
+
normalizeTopicSurface: () => normalizeTopicSurface,
|
|
7515
7517
|
normalizeTopicState: () => normalizeTopicState,
|
|
7516
7518
|
normalizeTopicKind: () => normalizeTopicKind,
|
|
7517
|
-
normalizeTopicAccessMode: () => normalizeTopicAccessMode,
|
|
7518
7519
|
normalizeAiMode: () => normalizeAiMode,
|
|
7519
7520
|
listTopics: () => listTopics,
|
|
7520
7521
|
listSubagentTellTargetIds: () => listSubagentTellTargetIds,
|
|
7521
7522
|
isTopicVisible: () => isTopicVisible,
|
|
7522
|
-
isTopicShared: () => isTopicShared,
|
|
7523
7523
|
inferTopicKind: () => inferTopicKind,
|
|
7524
7524
|
inferAiMode: () => inferAiMode,
|
|
7525
7525
|
grantSubagentTellTarget: () => grantSubagentTellTarget,
|
|
@@ -7532,10 +7532,17 @@ __export(exports_api_topics, {
|
|
|
7532
7532
|
getManagerTopicForUser: () => getManagerTopicForUser,
|
|
7533
7533
|
findTopicTitleConflict: () => findTopicTitleConflict,
|
|
7534
7534
|
deleteTopic: () => deleteTopic,
|
|
7535
|
+
defaultTopicSurface: () => defaultTopicSurface,
|
|
7535
7536
|
clearTopicSessionId: () => clearTopicSessionId,
|
|
7536
7537
|
aiMentionFromMode: () => aiMentionFromMode,
|
|
7537
7538
|
addParticipantToDB: () => addParticipantToDB
|
|
7538
7539
|
});
|
|
7540
|
+
function defaultTopicSurface() {
|
|
7541
|
+
return normalizeTopicSurface(process.env.NEGOTIUM_DEFAULT_SURFACE);
|
|
7542
|
+
}
|
|
7543
|
+
function normalizeTopicSurface(value) {
|
|
7544
|
+
return value === "telegram" || value === "otium" || value === "terminal" ? value : "terminal";
|
|
7545
|
+
}
|
|
7539
7546
|
function tableColumns2(table) {
|
|
7540
7547
|
const rows = db.query(`PRAGMA table_info(${table})`).all();
|
|
7541
7548
|
return new Set(rows.map((row) => row.name));
|
|
@@ -7666,7 +7673,7 @@ function initializeApiTopicsSchema() {
|
|
|
7666
7673
|
is_fork INTEGER NOT NULL DEFAULT 0 CHECK (is_fork IN (0,1)),
|
|
7667
7674
|
is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),
|
|
7668
7675
|
visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),
|
|
7669
|
-
|
|
7676
|
+
surface TEXT NOT NULL DEFAULT 'terminal' CHECK (surface IN ('terminal','telegram','otium')),
|
|
7670
7677
|
browser_profile TEXT NOT NULL DEFAULT 'default',
|
|
7671
7678
|
browser_profile_owner TEXT,
|
|
7672
7679
|
session_id TEXT,
|
|
@@ -7712,8 +7719,8 @@ function initializeApiTopicsSchema() {
|
|
|
7712
7719
|
const legacyBaseEffort = row.base_effort ?? row.default_effort;
|
|
7713
7720
|
db.query(`INSERT INTO api_topics_next
|
|
7714
7721
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
7715
|
-
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,
|
|
7716
|
-
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.
|
|
7722
|
+
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,session_id)
|
|
7723
|
+
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), typeof row.session_id === "string" ? row.session_id : null);
|
|
7717
7724
|
}
|
|
7718
7725
|
db.exec("DROP TABLE IF EXISTS topic_members");
|
|
7719
7726
|
db.exec("DROP TABLE api_topics");
|
|
@@ -7767,8 +7774,15 @@ function initializeApiTopicsSchema() {
|
|
|
7767
7774
|
if (!tableColumns2("api_topics").has("visibility")) {
|
|
7768
7775
|
db.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
|
|
7769
7776
|
}
|
|
7770
|
-
if (!tableColumns2("api_topics").has("
|
|
7771
|
-
db.exec("ALTER TABLE api_topics ADD COLUMN
|
|
7777
|
+
if (!tableColumns2("api_topics").has("surface")) {
|
|
7778
|
+
db.exec("ALTER TABLE api_topics ADD COLUMN surface TEXT NOT NULL DEFAULT 'terminal'");
|
|
7779
|
+
}
|
|
7780
|
+
if (tableColumns2("api_topics").has("access_mode")) {
|
|
7781
|
+
try {
|
|
7782
|
+
db.exec("ALTER TABLE api_topics DROP COLUMN access_mode");
|
|
7783
|
+
} catch (err) {
|
|
7784
|
+
logger.warn({ err }, "api_topics: could not drop the retired access_mode column");
|
|
7785
|
+
}
|
|
7772
7786
|
}
|
|
7773
7787
|
if (!tableColumns2("api_topics").has("browser_profile")) {
|
|
7774
7788
|
db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
|
|
@@ -7795,7 +7809,48 @@ function initializeApiTopicsSchema() {
|
|
|
7795
7809
|
)
|
|
7796
7810
|
WHERE browser_profile_owner IS NULL
|
|
7797
7811
|
`);
|
|
7812
|
+
backfillTopicSurfaces();
|
|
7798
7813
|
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)");
|
|
7814
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_surface ON api_topics(surface)");
|
|
7815
|
+
}
|
|
7816
|
+
function backfillTopicSurfaces() {
|
|
7817
|
+
db.exec(`
|
|
7818
|
+
CREATE TABLE IF NOT EXISTS api_schema_migrations (
|
|
7819
|
+
key TEXT PRIMARY KEY,
|
|
7820
|
+
applied_at TEXT NOT NULL
|
|
7821
|
+
)
|
|
7822
|
+
`);
|
|
7823
|
+
const applied = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(SURFACE_BACKFILL_MIGRATION);
|
|
7824
|
+
if (applied)
|
|
7825
|
+
return;
|
|
7826
|
+
const surface = defaultTopicSurface();
|
|
7827
|
+
db.transaction(() => {
|
|
7828
|
+
db.query("UPDATE api_topics SET surface = ?").run(surface);
|
|
7829
|
+
renameSurfaceTitleCollisions();
|
|
7830
|
+
db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(SURFACE_BACKFILL_MIGRATION, new Date().toISOString());
|
|
7831
|
+
})();
|
|
7832
|
+
logger.info({ surface }, "api_topics: surface backfilled");
|
|
7833
|
+
}
|
|
7834
|
+
function renameSurfaceTitleCollisions() {
|
|
7835
|
+
const rows = db.query("SELECT id, title, kind, surface FROM api_topics ORDER BY created_at ASC, rowid ASC").all();
|
|
7836
|
+
const taken = new Set;
|
|
7837
|
+
const update = db.query("UPDATE api_topics SET title = ? WHERE id = ?");
|
|
7838
|
+
for (const row of rows) {
|
|
7839
|
+
const key = (title) => `${row.surface}\x00${row.kind}\x00${normalizedTitle(title)}`;
|
|
7840
|
+
if (!taken.has(key(row.title))) {
|
|
7841
|
+
taken.add(key(row.title));
|
|
7842
|
+
continue;
|
|
7843
|
+
}
|
|
7844
|
+
let suffix = 2;
|
|
7845
|
+
let candidate = `${row.title} (${suffix})`;
|
|
7846
|
+
while (taken.has(key(candidate))) {
|
|
7847
|
+
suffix += 1;
|
|
7848
|
+
candidate = `${row.title} (${suffix})`;
|
|
7849
|
+
}
|
|
7850
|
+
taken.add(key(candidate));
|
|
7851
|
+
update.run(candidate, row.id);
|
|
7852
|
+
logger.warn({ topicId: row.id, surface: row.surface, from: row.title, to: candidate }, "api_topics: renamed a duplicate title for surface-scoped uniqueness");
|
|
7853
|
+
}
|
|
7799
7854
|
}
|
|
7800
7855
|
function shortSessionId(sessionId) {
|
|
7801
7856
|
return sessionId ? sessionId.slice(0, 8) : null;
|
|
@@ -7855,15 +7910,9 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
7855
7910
|
subagentReportMode: r.subagent_report_mode === "tell" || r.subagent_report_mode === "status-only" ? r.subagent_report_mode : "auto"
|
|
7856
7911
|
} : {},
|
|
7857
7912
|
visibility: normalizeTopicVisibility(r.visibility),
|
|
7858
|
-
|
|
7913
|
+
surface: normalizeTopicSurface(r.surface)
|
|
7859
7914
|
};
|
|
7860
7915
|
}
|
|
7861
|
-
function normalizeTopicAccessMode(value) {
|
|
7862
|
-
return value === "shared" ? "shared" : "private";
|
|
7863
|
-
}
|
|
7864
|
-
function isTopicShared(topic) {
|
|
7865
|
-
return topic.accessMode === "shared";
|
|
7866
|
-
}
|
|
7867
7916
|
function normalizeTopicVisibility(value) {
|
|
7868
7917
|
return value === "hidden" ? "hidden" : "visible";
|
|
7869
7918
|
}
|
|
@@ -7940,7 +7989,7 @@ function upsertTopic(t) {
|
|
|
7940
7989
|
db.transaction(() => {
|
|
7941
7990
|
db.query(`INSERT INTO api_topics
|
|
7942
7991
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
7943
|
-
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,
|
|
7992
|
+
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,
|
|
7944
7993
|
subagent_report_mode)
|
|
7945
7994
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
7946
7995
|
ON CONFLICT(id) DO UPDATE SET
|
|
@@ -7959,8 +8008,8 @@ function upsertTopic(t) {
|
|
|
7959
8008
|
is_fork = excluded.is_fork,
|
|
7960
8009
|
is_subagent = excluded.is_subagent,
|
|
7961
8010
|
visibility = excluded.visibility,
|
|
7962
|
-
|
|
7963
|
-
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),
|
|
8011
|
+
surface = excluded.surface,
|
|
8012
|
+
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), t.subagentReportMode ?? "auto");
|
|
7964
8013
|
db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
|
|
7965
8014
|
for (const participant of t.participants) {
|
|
7966
8015
|
db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
|
|
@@ -7973,18 +8022,8 @@ function upsertTopic(t) {
|
|
|
7973
8022
|
}
|
|
7974
8023
|
})();
|
|
7975
8024
|
}
|
|
7976
|
-
function
|
|
7977
|
-
|
|
7978
|
-
return;
|
|
7979
|
-
const normalized = normalizeTopicAccessMode(accessMode);
|
|
7980
|
-
db.transaction(() => {
|
|
7981
|
-
const update = db.query("UPDATE api_topics SET access_mode = ? WHERE id = ?");
|
|
7982
|
-
for (const topicId of topicIds)
|
|
7983
|
-
update.run(normalized, topicId);
|
|
7984
|
-
})();
|
|
7985
|
-
}
|
|
7986
|
-
function listTopics() {
|
|
7987
|
-
const rows = db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
|
|
8025
|
+
function listTopics(opts = {}) {
|
|
8026
|
+
const rows = opts.surface ? db.query("SELECT * FROM api_topics WHERE surface = ? ORDER BY last_message_at DESC").all(normalizeTopicSurface(opts.surface)) : db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
|
|
7988
8027
|
const participants = getAllTopicParticipants();
|
|
7989
8028
|
const tellTargets = rows.some((row) => row.is_subagent !== 0) ? getAllSubagentTellTargets() : undefined;
|
|
7990
8029
|
return rows.map((row) => rowToDto2(row, participants.get(row.id) ?? [], tellTargets));
|
|
@@ -8035,14 +8074,15 @@ function getTopicByNameAndKind(title, kind) {
|
|
|
8035
8074
|
}
|
|
8036
8075
|
function findTopicTitleConflict(title, kind, opts = {}) {
|
|
8037
8076
|
const wanted = normalizedTitle(title);
|
|
8077
|
+
const surface = normalizeTopicSurface(opts.surface ?? defaultTopicSurface());
|
|
8038
8078
|
const generalTitleRequested = wanted === normalizedTitle(GENERAL_TOPIC_ID);
|
|
8039
8079
|
if (generalTitleRequested && opts.excludeTopicId !== GENERAL_TOPIC_ID) {
|
|
8040
8080
|
const general = db.query("SELECT * FROM api_topics WHERE id = ?").get(GENERAL_TOPIC_ID);
|
|
8041
8081
|
if (general)
|
|
8042
8082
|
return rowToDto2(general);
|
|
8043
8083
|
}
|
|
8044
|
-
const params = [wanted];
|
|
8045
|
-
let sql = "SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ?";
|
|
8084
|
+
const params = [wanted, surface];
|
|
8085
|
+
let sql = "SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ? AND surface = ?";
|
|
8046
8086
|
if (kind !== "manager") {
|
|
8047
8087
|
sql += " AND (kind = ? OR id = ?)";
|
|
8048
8088
|
params.push(kind, GENERAL_TOPIC_ID);
|
|
@@ -8055,7 +8095,20 @@ function findTopicTitleConflict(title, kind, opts = {}) {
|
|
|
8055
8095
|
const row = db.query(sql).get(...params);
|
|
8056
8096
|
return row ? rowToDto2(row) : null;
|
|
8057
8097
|
}
|
|
8058
|
-
function
|
|
8098
|
+
function setTopicSurfaces(topicIds, surface) {
|
|
8099
|
+
if (topicIds.length === 0)
|
|
8100
|
+
return 0;
|
|
8101
|
+
const normalized = normalizeTopicSurface(surface);
|
|
8102
|
+
let changed = 0;
|
|
8103
|
+
db.transaction(() => {
|
|
8104
|
+
const update = db.query("UPDATE api_topics SET surface = ? WHERE id = ? AND surface != ?");
|
|
8105
|
+
for (const topicId of topicIds) {
|
|
8106
|
+
changed += Number(update.run(normalized, topicId, normalized).changes ?? 0);
|
|
8107
|
+
}
|
|
8108
|
+
})();
|
|
8109
|
+
return changed;
|
|
8110
|
+
}
|
|
8111
|
+
function getTopicByNameForUser(title, userId, opts = {}) {
|
|
8059
8112
|
const trimmed = title.trim();
|
|
8060
8113
|
const qualified = /^(agent|channel|manager):(.+)$/i.exec(trimmed);
|
|
8061
8114
|
const requestedKind = qualified ? normalizeTopicKind(qualified[1]?.toLowerCase()) : null;
|
|
@@ -8064,9 +8117,10 @@ function getTopicByNameForUser(title, userId) {
|
|
|
8064
8117
|
WHERE LOWER(t.title) = LOWER(?)
|
|
8065
8118
|
AND t.id != ?
|
|
8066
8119
|
AND t.visibility != 'hidden'
|
|
8120
|
+
AND (? IS NULL OR t.surface = ?)
|
|
8067
8121
|
AND EXISTS (
|
|
8068
8122
|
SELECT 1 FROM topic_members m WHERE m.topic_id = t.id AND m.user_id = ?
|
|
8069
|
-
)`).all(requestedTitle, GENERAL_TOPIC_ID, userId);
|
|
8123
|
+
)`).all(requestedTitle, GENERAL_TOPIC_ID, opts.surface ?? null, opts.surface ?? null, userId);
|
|
8070
8124
|
const matches = requestedKind ? rows.filter((row) => row.kind === requestedKind) : rows;
|
|
8071
8125
|
return matches.length === 1 ? rowToDto2(matches[0]) : null;
|
|
8072
8126
|
}
|
|
@@ -8154,7 +8208,7 @@ function removeParticipantFromDB(topicId, userId) {
|
|
|
8154
8208
|
db.query("DELETE FROM topic_members WHERE topic_id = ? AND user_id = ?").run(topicId, userId);
|
|
8155
8209
|
return true;
|
|
8156
8210
|
}
|
|
8157
|
-
var DEFAULT_AGENT_ROOM_AGENT = "maestro";
|
|
8211
|
+
var DEFAULT_AGENT_ROOM_AGENT = "maestro", SURFACE_BACKFILL_MIGRATION = "api_topics_surface_backfill_20260808";
|
|
8158
8212
|
var init_api_topics = __esm(async () => {
|
|
8159
8213
|
init_constants();
|
|
8160
8214
|
init_logger();
|
|
@@ -14240,11 +14294,11 @@ __export(exports_derive, {
|
|
|
14240
14294
|
});
|
|
14241
14295
|
import { createHash as createHash5, randomUUID as randomUUID12 } from "crypto";
|
|
14242
14296
|
import { mkdirSync as mkdirSync13, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
14243
|
-
function getTopics() {
|
|
14244
|
-
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
14297
|
+
function getTopics(opts = {}) {
|
|
14298
|
+
return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
14245
14299
|
}
|
|
14246
|
-
function getVisibleTopics() {
|
|
14247
|
-
return getTopics().filter(isTopicVisible).map((topic) => {
|
|
14300
|
+
function getVisibleTopics(opts = {}) {
|
|
14301
|
+
return getTopics(opts).filter(isTopicVisible).map((topic) => {
|
|
14248
14302
|
if (!topic.agent)
|
|
14249
14303
|
return topic;
|
|
14250
14304
|
const registry = getRegistry(topic.agent);
|
|
@@ -14269,8 +14323,8 @@ function updateTopic(topicId, patch) {
|
|
|
14269
14323
|
function isParticipant(topic, userId) {
|
|
14270
14324
|
return topic.participants.some((p) => p.userId === userId);
|
|
14271
14325
|
}
|
|
14272
|
-
function nextDerivedTopicTitle(sourceTitle, kind, suffix) {
|
|
14273
|
-
const visibleTitles = new Set(listTopics().filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
14326
|
+
function nextDerivedTopicTitle(sourceTitle, kind, suffix, surface) {
|
|
14327
|
+
const visibleTitles = new Set(listTopics(surface ? { surface } : {}).filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
14274
14328
|
let n = 1;
|
|
14275
14329
|
let title = `${sourceTitle}-${suffix}-${n}`;
|
|
14276
14330
|
while (visibleTitles.has(title.toLowerCase())) {
|
|
@@ -14334,8 +14388,9 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
14334
14388
|
{ userId, role: "owner" }
|
|
14335
14389
|
] : [{ userId, role: "owner" }];
|
|
14336
14390
|
const kind = topic.kind ?? inferTopicKind(topic);
|
|
14337
|
-
const
|
|
14338
|
-
const
|
|
14391
|
+
const surface = topic.surface ?? defaultTopicSurface();
|
|
14392
|
+
const title = opts?.name?.trim() || nextDerivedTopicTitle(topic.title, kind, suffix, surface);
|
|
14393
|
+
const conflict = findTopicTitleConflict(title, kind, { surface });
|
|
14339
14394
|
if (conflict) {
|
|
14340
14395
|
logger.info({ sourceTopicId, title, kind, conflictTopicId: conflict.id }, "createDerivedTopic: title conflict");
|
|
14341
14396
|
throw new TopicTitleConflictError(title);
|
|
@@ -14358,7 +14413,7 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
14358
14413
|
isFork: copyHistory,
|
|
14359
14414
|
...subagent ? { isSubagent: true } : {},
|
|
14360
14415
|
visibility: topic.visibility,
|
|
14361
|
-
|
|
14416
|
+
surface
|
|
14362
14417
|
};
|
|
14363
14418
|
let sessionId;
|
|
14364
14419
|
let rollbackHandle;
|
|
@@ -14466,7 +14521,7 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
14466
14521
|
if (!currentSource || currentSource.kind === "manager" || !isParticipant(currentSource, userId) || subagent && isRuntimeTopicMaintenance(sourceTopicId)) {
|
|
14467
14522
|
throw new TopicDeriveBusyError("Source topic changed while deriving; try again");
|
|
14468
14523
|
}
|
|
14469
|
-
const transactionalConflict = findTopicTitleConflict(title, kind);
|
|
14524
|
+
const transactionalConflict = findTopicTitleConflict(title, kind, { surface });
|
|
14470
14525
|
if (transactionalConflict)
|
|
14471
14526
|
throw new TopicTitleConflictError(title);
|
|
14472
14527
|
upsertTopic(derived);
|
|
@@ -20357,74 +20412,6 @@ var init_submit_user_message = __esm(async () => {
|
|
|
20357
20412
|
await init_api_messages();
|
|
20358
20413
|
});
|
|
20359
20414
|
|
|
20360
|
-
// ../../packages/core/src/application/switch-topic-access-mode.ts
|
|
20361
|
-
function collectSubagentDescendants(rootTopicId) {
|
|
20362
|
-
const all = listTopics();
|
|
20363
|
-
const childrenByParent = new Map;
|
|
20364
|
-
for (const topic of all) {
|
|
20365
|
-
if (!topic.isSubagent || !topic.parentTopicId)
|
|
20366
|
-
continue;
|
|
20367
|
-
const siblings = childrenByParent.get(topic.parentTopicId);
|
|
20368
|
-
if (siblings)
|
|
20369
|
-
siblings.push(topic);
|
|
20370
|
-
else
|
|
20371
|
-
childrenByParent.set(topic.parentTopicId, [topic]);
|
|
20372
|
-
}
|
|
20373
|
-
const descendants = [];
|
|
20374
|
-
const seen = new Set([rootTopicId]);
|
|
20375
|
-
const queue = [rootTopicId];
|
|
20376
|
-
while (queue.length > 0) {
|
|
20377
|
-
const parentId = queue.shift();
|
|
20378
|
-
for (const child of childrenByParent.get(parentId) ?? []) {
|
|
20379
|
-
if (seen.has(child.id))
|
|
20380
|
-
continue;
|
|
20381
|
-
seen.add(child.id);
|
|
20382
|
-
descendants.push(child);
|
|
20383
|
-
queue.push(child.id);
|
|
20384
|
-
}
|
|
20385
|
-
}
|
|
20386
|
-
return descendants;
|
|
20387
|
-
}
|
|
20388
|
-
function switchTopicAccessMode(params) {
|
|
20389
|
-
const topic = getTopic(params.topicId);
|
|
20390
|
-
if (!topic)
|
|
20391
|
-
return { ok: false, error: "Topic not found" };
|
|
20392
|
-
const owner = topic.participants.some((participant) => participant.userId === params.userId && participant.role === "owner");
|
|
20393
|
-
if (!owner)
|
|
20394
|
-
return { ok: false, error: "Only topic owners can change privacy" };
|
|
20395
|
-
if (topic.isSubagent) {
|
|
20396
|
-
return {
|
|
20397
|
-
ok: false,
|
|
20398
|
-
error: "Subagent rooms inherit privacy from their parent topic"
|
|
20399
|
-
};
|
|
20400
|
-
}
|
|
20401
|
-
const descendants = collectSubagentDescendants(topic.id);
|
|
20402
|
-
const changed = [topic, ...descendants].filter((candidate) => (candidate.accessMode ?? "private") !== params.accessMode);
|
|
20403
|
-
if (changed.length === 0) {
|
|
20404
|
-
return {
|
|
20405
|
-
ok: true,
|
|
20406
|
-
accessMode: params.accessMode,
|
|
20407
|
-
text: params.accessMode === "shared" ? `"${topic.title}" is already public to the connected Otium Hub.` : `"${topic.title}" is already private to this worker.`,
|
|
20408
|
-
topicIds: []
|
|
20409
|
-
};
|
|
20410
|
-
}
|
|
20411
|
-
setTopicAccessModes(changed.map((candidate) => candidate.id), params.accessMode);
|
|
20412
|
-
for (const candidate of changed)
|
|
20413
|
-
WsHub.get().broadcastTopicUpdated(candidate.id);
|
|
20414
|
-
const subagentCount = changed.filter((candidate) => candidate.id !== topic.id).length;
|
|
20415
|
-
const suffix = subagentCount > 0 ? ` (${subagentCount} subagent room${subagentCount === 1 ? "" : "s"} updated)` : "";
|
|
20416
|
-
return {
|
|
20417
|
-
ok: true,
|
|
20418
|
-
accessMode: params.accessMode,
|
|
20419
|
-
topicIds: changed.map((candidate) => candidate.id),
|
|
20420
|
-
text: (params.accessMode === "shared" ? `"${topic.title}" is public to the connected Otium Hub.` : `"${topic.title}" is private to this worker.`) + suffix
|
|
20421
|
-
};
|
|
20422
|
-
}
|
|
20423
|
-
var init_switch_topic_access_mode = __esm(async () => {
|
|
20424
|
-
await init_bus();
|
|
20425
|
-
await init_api_topics();
|
|
20426
|
-
});
|
|
20427
|
-
|
|
20428
20415
|
// ../../packages/core/src/application/switch-topic-effort.ts
|
|
20429
20416
|
function switchTopicEffort(params) {
|
|
20430
20417
|
const topic = getTopic(params.topicId);
|
|
@@ -20538,9 +20525,10 @@ function registerTopic(opts) {
|
|
|
20538
20525
|
if (requestedKind === "manager") {
|
|
20539
20526
|
throw new TopicValidationError("Manager rooms are system-managed");
|
|
20540
20527
|
}
|
|
20541
|
-
const
|
|
20528
|
+
const surface = normalizeTopicSurface(opts.surface ?? defaultTopicSurface());
|
|
20529
|
+
const conflict = findTopicTitleConflict(title, requestedKind, { surface });
|
|
20542
20530
|
if (conflict) {
|
|
20543
|
-
throw new TopicValidationError(`A topic named "${title}" already exists`);
|
|
20531
|
+
throw new TopicValidationError(`A topic named "${title}" already exists on ${surface}`);
|
|
20544
20532
|
}
|
|
20545
20533
|
const rawAgent = opts.agent;
|
|
20546
20534
|
if (requestedKind === "agent" && rawAgent === "none") {
|
|
@@ -20574,7 +20562,7 @@ function registerTopic(opts) {
|
|
|
20574
20562
|
defaultEffort: defaultEffort ?? "medium",
|
|
20575
20563
|
aiMode,
|
|
20576
20564
|
participants: [{ userId: opts.userId, role: "owner" }],
|
|
20577
|
-
|
|
20565
|
+
surface,
|
|
20578
20566
|
createdAt: now,
|
|
20579
20567
|
lastMessageAt: now
|
|
20580
20568
|
};
|
|
@@ -22413,7 +22401,6 @@ __export(exports_src, {
|
|
|
22413
22401
|
textResult: () => textResult,
|
|
22414
22402
|
switchTopicModel: () => switchTopicModel,
|
|
22415
22403
|
switchTopicEffort: () => switchTopicEffort,
|
|
22416
|
-
switchTopicAccessMode: () => switchTopicAccessMode,
|
|
22417
22404
|
sweepStaleSubagentCards: () => sweepStaleSubagentCards,
|
|
22418
22405
|
submitUserMessage: () => submitUserMessage,
|
|
22419
22406
|
submitRuntimeGatewayTurn: () => submitRuntimeGatewayTurn,
|
|
@@ -22426,6 +22413,7 @@ __export(exports_src, {
|
|
|
22426
22413
|
startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
|
|
22427
22414
|
startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
|
|
22428
22415
|
startAiTurn: () => startAiTurn,
|
|
22416
|
+
setTopicSurfaces: () => setTopicSurfaces,
|
|
22429
22417
|
setTopicSessionId: () => setTopicSessionId,
|
|
22430
22418
|
setRuntimeMcpPort: () => setRuntimeMcpPort,
|
|
22431
22419
|
setRuntimeBus: () => setRuntimeBus,
|
|
@@ -22472,6 +22460,7 @@ __export(exports_src, {
|
|
|
22472
22460
|
prepareDeliveryAck: () => prepareDeliveryAck,
|
|
22473
22461
|
onShutdown: () => onShutdown,
|
|
22474
22462
|
normalizeVaultKey: () => normalizeVaultKey,
|
|
22463
|
+
normalizeTopicSurface: () => normalizeTopicSurface,
|
|
22475
22464
|
nodeRequestHandlerNames: () => nodeRequestHandlerNames,
|
|
22476
22465
|
modelOwner: () => modelOwner,
|
|
22477
22466
|
markPlaywrightUnavailable: () => markPlaywrightUnavailable,
|
|
@@ -22498,7 +22487,6 @@ __export(exports_src, {
|
|
|
22498
22487
|
isVaultCommandLine: () => isVaultCommandLine,
|
|
22499
22488
|
isTranscriptionConfigured: () => isTranscriptionConfigured,
|
|
22500
22489
|
isTopicVisible: () => isTopicVisible,
|
|
22501
|
-
isTopicShared: () => isTopicShared,
|
|
22502
22490
|
isTopicRunning: () => isTopicRunning,
|
|
22503
22491
|
isSensitivePath: () => isSensitivePath,
|
|
22504
22492
|
isParticipant: () => isParticipant,
|
|
@@ -22548,6 +22536,7 @@ __export(exports_src, {
|
|
|
22548
22536
|
deliverAskCallbackToCaller: () => deliverAskCallbackToCaller,
|
|
22549
22537
|
deleteVaultEntry: () => deleteVaultEntry,
|
|
22550
22538
|
deleteTopicCascade: () => deleteTopicCascade,
|
|
22539
|
+
defaultTopicSurface: () => defaultTopicSurface,
|
|
22551
22540
|
db: () => db,
|
|
22552
22541
|
createSubagentManagementToolDefinitions: () => createSubagentManagementToolDefinitions,
|
|
22553
22542
|
createSpawnSubagentToolDefinition: () => createSpawnSubagentToolDefinition,
|
|
@@ -22639,7 +22628,6 @@ var init_src = __esm(async () => {
|
|
|
22639
22628
|
await init_execute_external_user_turn();
|
|
22640
22629
|
await init_submit_runtime_gateway_turn();
|
|
22641
22630
|
await init_submit_user_message();
|
|
22642
|
-
await init_switch_topic_access_mode();
|
|
22643
22631
|
await init_switch_topic_effort();
|
|
22644
22632
|
await init_switch_topic_model();
|
|
22645
22633
|
await init_topic_service();
|
|
@@ -22805,10 +22793,10 @@ var init_conversation_migration = __esm(async () => {
|
|
|
22805
22793
|
// ../../packages/core/src/node-host.ts
|
|
22806
22794
|
var exports_node_host = {};
|
|
22807
22795
|
__export(exports_node_host, {
|
|
22796
|
+
upsertTopic: () => upsertTopic,
|
|
22808
22797
|
topicService: () => topicService,
|
|
22809
22798
|
switchTopicModel: () => switchTopicModel,
|
|
22810
22799
|
switchTopicEffort: () => switchTopicEffort,
|
|
22811
|
-
switchTopicAccessMode: () => switchTopicAccessMode,
|
|
22812
22800
|
sweepStaleSubagentCards: () => sweepStaleSubagentCards,
|
|
22813
22801
|
submitUserMessage: () => submitUserMessage,
|
|
22814
22802
|
submitRuntimeGatewayTurn: () => submitRuntimeGatewayTurn,
|
|
@@ -22842,7 +22830,6 @@ __export(exports_node_host, {
|
|
|
22842
22830
|
killOwnedCodexTreesForShutdown: () => killOwnedCodexTreesForShutdown,
|
|
22843
22831
|
killAllPlaywright: () => killAllPlaywright,
|
|
22844
22832
|
killAllBgBash: () => killAllBgBash,
|
|
22845
|
-
isTopicShared: () => isTopicShared,
|
|
22846
22833
|
isParticipant: () => isParticipant,
|
|
22847
22834
|
getVisibleTopics: () => getVisibleTopics,
|
|
22848
22835
|
getTopicStats: () => getTopicStats,
|
|
@@ -22852,6 +22839,7 @@ __export(exports_node_host, {
|
|
|
22852
22839
|
ensurePersonalGeneral: () => ensurePersonalGeneral,
|
|
22853
22840
|
deleteVaultEntry: () => deleteVaultEntry,
|
|
22854
22841
|
compactTopicSession: () => compactTopicSession,
|
|
22842
|
+
appendApiMessage: () => appendApiMessage,
|
|
22855
22843
|
acquireRuntimeProcessLease: () => acquireRuntimeProcessLease,
|
|
22856
22844
|
abortAllRooms: () => abortAllRooms,
|
|
22857
22845
|
WsHub: () => WsHub,
|
|
@@ -22863,6 +22851,7 @@ __export(exports_node_host, {
|
|
|
22863
22851
|
STATE_DIR: () => STATE_DIR,
|
|
22864
22852
|
RuntimeGatewayIdempotencyConflictError: () => RuntimeGatewayIdempotencyConflictError,
|
|
22865
22853
|
RUN_DIR: () => RUN_DIR,
|
|
22854
|
+
NODE_ID: () => NODE_ID,
|
|
22866
22855
|
NODE_CONTROL_TOKEN: () => NODE_CONTROL_TOKEN,
|
|
22867
22856
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION,
|
|
22868
22857
|
NEGOTIUM_PORT: () => NEGOTIUM_PORT,
|
|
@@ -22874,7 +22863,6 @@ var init_node_host = __esm(async () => {
|
|
|
22874
22863
|
await init_spawn_subagent();
|
|
22875
22864
|
await init_submit_runtime_gateway_turn();
|
|
22876
22865
|
await init_submit_user_message();
|
|
22877
|
-
await init_switch_topic_access_mode();
|
|
22878
22866
|
await init_switch_topic_effort();
|
|
22879
22867
|
await init_switch_topic_model();
|
|
22880
22868
|
await init_topic_service();
|
|
@@ -24150,7 +24138,8 @@ var init_session_comm = __esm(async () => {
|
|
|
24150
24138
|
function createSessionTargetCatalog(host2) {
|
|
24151
24139
|
const { currentTopicId, currentTopicName, isAgent, listRows } = host2;
|
|
24152
24140
|
function listTargets() {
|
|
24153
|
-
const
|
|
24141
|
+
const currentSurface = host2.currentSurface;
|
|
24142
|
+
const eligibleRows = listRows().filter((row) => row.kind !== "manager" && (!currentSurface || (row.surface ?? currentSurface) === currentSurface));
|
|
24154
24143
|
const titleCounts = new Map;
|
|
24155
24144
|
const qualifiedCounts = new Map;
|
|
24156
24145
|
for (const row of eligibleRows) {
|
|
@@ -24266,9 +24255,11 @@ function currentTopic(context) {
|
|
|
24266
24255
|
return topic;
|
|
24267
24256
|
}
|
|
24268
24257
|
function targetCatalog(context) {
|
|
24258
|
+
const surface = (context.currentTopicId ? getTopic(context.currentTopicId)?.surface : undefined) ?? defaultTopicSurface();
|
|
24269
24259
|
return createSessionTargetCatalog({
|
|
24270
24260
|
currentTopicId: context.currentTopicId,
|
|
24271
24261
|
currentTopicName: context.currentTopic,
|
|
24262
|
+
currentSurface: surface,
|
|
24272
24263
|
isAgent: isAgentKind,
|
|
24273
24264
|
listRows: () => listTopics().filter((topic) => topic.participants.some((p) => p.userId === context.userId)).map((topic) => ({
|
|
24274
24265
|
id: topic.id,
|
|
@@ -24276,7 +24267,8 @@ function targetCatalog(context) {
|
|
|
24276
24267
|
kind: topic.kind ?? null,
|
|
24277
24268
|
agent: topic.agent ?? null,
|
|
24278
24269
|
sessionId: null,
|
|
24279
|
-
description: topic.description ?? null
|
|
24270
|
+
description: topic.description ?? null,
|
|
24271
|
+
surface: topic.surface ?? null
|
|
24280
24272
|
}))
|
|
24281
24273
|
});
|
|
24282
24274
|
}
|
|
@@ -27512,6 +27504,7 @@ __export(exports_storage_public, {
|
|
|
27512
27504
|
softDeleteApiMessagesByIdPrefix: () => softDeleteApiMessagesByIdPrefix,
|
|
27513
27505
|
softDeleteApiMessage: () => softDeleteApiMessage,
|
|
27514
27506
|
settleTopicArchiveJob: () => settleTopicArchiveJob,
|
|
27507
|
+
setTopicSurfaces: () => setTopicSurfaces,
|
|
27515
27508
|
setTopicSessionId: () => setTopicSessionId,
|
|
27516
27509
|
setTopicMcpExtra: () => setTopicMcpExtra,
|
|
27517
27510
|
setTopicMcpEnabled: () => setTopicMcpEnabled,
|
|
@@ -27522,7 +27515,6 @@ __export(exports_storage_public, {
|
|
|
27522
27515
|
setTopicAgentAndSession: () => setTopicAgentAndSession,
|
|
27523
27516
|
setTopicAgentAndClearSession: () => setTopicAgentAndClearSession,
|
|
27524
27517
|
setTopicAgent: () => setTopicAgent,
|
|
27525
|
-
setTopicAccessModes: () => setTopicAccessModes,
|
|
27526
27518
|
setSessionForTopic: () => setSessionForTopic,
|
|
27527
27519
|
setLastShownConfig: () => setLastShownConfig,
|
|
27528
27520
|
setGlobalAiName: () => setGlobalAiName,
|
|
@@ -27556,9 +27548,9 @@ __export(exports_storage_public, {
|
|
|
27556
27548
|
quarantineAskUserGate: () => quarantineAskUserGate,
|
|
27557
27549
|
prepareAskUserGate: () => prepareAskUserGate,
|
|
27558
27550
|
normalizeTopicVisibility: () => normalizeTopicVisibility,
|
|
27551
|
+
normalizeTopicSurface: () => normalizeTopicSurface,
|
|
27559
27552
|
normalizeTopicState: () => normalizeTopicState,
|
|
27560
27553
|
normalizeTopicKind: () => normalizeTopicKind,
|
|
27561
|
-
normalizeTopicAccessMode: () => normalizeTopicAccessMode,
|
|
27562
27554
|
normalizeAiMode: () => normalizeAiMode,
|
|
27563
27555
|
markPendingAskState: () => markPendingAskState,
|
|
27564
27556
|
markPendingAskSources: () => markPendingAskSources,
|
|
@@ -27573,7 +27565,6 @@ __export(exports_storage_public, {
|
|
|
27573
27565
|
listApiMessages: () => listApiMessages,
|
|
27574
27566
|
isTopicVisible: () => isTopicVisible,
|
|
27575
27567
|
isTopicSummaryFile: () => isTopicSummaryFile,
|
|
27576
|
-
isTopicShared: () => isTopicShared,
|
|
27577
27568
|
isTopicBriefFile: () => isTopicBriefFile,
|
|
27578
27569
|
isRuntimeProcessLeaseAlive: () => isRuntimeProcessLeaseAlive,
|
|
27579
27570
|
inferTopicKind: () => inferTopicKind,
|
|
@@ -27634,6 +27625,7 @@ __export(exports_storage_public, {
|
|
|
27634
27625
|
deletePendingAsksForTopic: () => deletePendingAsksForTopic,
|
|
27635
27626
|
deleteMessagesForTopic: () => deleteMessagesForTopic,
|
|
27636
27627
|
deleteApiTopicConfig: () => deleteApiTopicConfig,
|
|
27628
|
+
defaultTopicSurface: () => defaultTopicSurface,
|
|
27637
27629
|
db: () => db2,
|
|
27638
27630
|
createTasks: () => createTasks,
|
|
27639
27631
|
createPendingAsk: () => createPendingAsk,
|
|
@@ -29347,13 +29339,19 @@ function requiredText(value, name) {
|
|
|
29347
29339
|
}
|
|
29348
29340
|
return value.trim();
|
|
29349
29341
|
}
|
|
29350
|
-
function topicsForUser(userId) {
|
|
29342
|
+
function topicsForUser(userId, surface) {
|
|
29351
29343
|
const runningTopics = listRunningTopicQueries();
|
|
29352
|
-
return getVisibleTopics().filter((topic) => isParticipant(topic, userId)).map((topic) => {
|
|
29344
|
+
return getVisibleTopics(surface ? { surface } : {}).filter((topic) => isParticipant(topic, userId)).map((topic) => {
|
|
29353
29345
|
const runningQueryId = runningTopics.get(topic.id);
|
|
29354
29346
|
return { ...topic, running: Boolean(runningQueryId), runningQueryId };
|
|
29355
29347
|
});
|
|
29356
29348
|
}
|
|
29349
|
+
function requestedSurface(url) {
|
|
29350
|
+
const raw = url.searchParams.get("surface")?.trim();
|
|
29351
|
+
if (!raw)
|
|
29352
|
+
return;
|
|
29353
|
+
return raw === "terminal" || raw === "telegram" || raw === "otium" ? raw : undefined;
|
|
29354
|
+
}
|
|
29357
29355
|
function topicForUser(topicId, userId) {
|
|
29358
29356
|
const topic = getTopic(topicId);
|
|
29359
29357
|
return topic && isParticipant(topic, userId) ? topic : null;
|
|
@@ -29437,13 +29435,15 @@ function createNodeControlHandler(options) {
|
|
|
29437
29435
|
ok: true,
|
|
29438
29436
|
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
29439
29437
|
nodeVersion: NODE_VERSION,
|
|
29438
|
+
nodeId: NODE_ID,
|
|
29440
29439
|
capabilities: [
|
|
29441
29440
|
"turn-submit-idempotent",
|
|
29442
29441
|
"turn-events-sse-resume",
|
|
29443
29442
|
"canonical-topic-read",
|
|
29444
29443
|
"canonical-message-read",
|
|
29445
29444
|
"canonical-topic-list",
|
|
29446
|
-
"canonical-topic-create"
|
|
29445
|
+
"canonical-topic-create",
|
|
29446
|
+
"canonical-history-import"
|
|
29447
29447
|
],
|
|
29448
29448
|
cursor: latestRuntimeEventSeq()
|
|
29449
29449
|
});
|
|
@@ -29508,11 +29508,7 @@ function createNodeControlHandler(options) {
|
|
|
29508
29508
|
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, ...result });
|
|
29509
29509
|
}
|
|
29510
29510
|
if (req.method === "GET" && runtimePath === "/topics") {
|
|
29511
|
-
const
|
|
29512
|
-
if (accessMode && accessMode !== "shared" && accessMode !== "private") {
|
|
29513
|
-
return jsonError(400, "accessMode must be 'shared' or 'private'");
|
|
29514
|
-
}
|
|
29515
|
-
const topics = getVisibleTopics().filter((topic) => accessMode === "shared" ? isTopicShared(topic) : accessMode === "private" ? !isTopicShared(topic) : true);
|
|
29511
|
+
const topics = getVisibleTopics({ surface: "otium" });
|
|
29516
29512
|
return Response.json({
|
|
29517
29513
|
ok: true,
|
|
29518
29514
|
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
@@ -29534,11 +29530,60 @@ function createNodeControlHandler(options) {
|
|
|
29534
29530
|
title,
|
|
29535
29531
|
userId,
|
|
29536
29532
|
kind: "agent",
|
|
29537
|
-
|
|
29533
|
+
surface: "otium",
|
|
29538
29534
|
...agent ? { agent } : {}
|
|
29539
29535
|
});
|
|
29540
29536
|
return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic }, { status: 201 });
|
|
29541
29537
|
}
|
|
29538
|
+
const importMatch = runtimePath.match(/^\/topics\/([^/]+)\/import$/);
|
|
29539
|
+
if (importMatch && req.method === "POST") {
|
|
29540
|
+
const body = await bodyRecord(req);
|
|
29541
|
+
if (body.v !== NODE_RUNTIME_CONTRACT_VERSION)
|
|
29542
|
+
return jsonError(400, "Unsupported v");
|
|
29543
|
+
const topicId = decodeURIComponent(importMatch[1]);
|
|
29544
|
+
const topic = getTopic(topicId);
|
|
29545
|
+
if (!topic)
|
|
29546
|
+
return jsonError(404, "Topic not found");
|
|
29547
|
+
if (!Array.isArray(body.messages)) {
|
|
29548
|
+
return jsonError(400, "messages must be an array");
|
|
29549
|
+
}
|
|
29550
|
+
if (listApiMessages(topicId, { limit: 1 }).page.length > 0) {
|
|
29551
|
+
return jsonError(409, "topic already has messages");
|
|
29552
|
+
}
|
|
29553
|
+
const messages = body.messages;
|
|
29554
|
+
for (const [index, message] of messages.entries()) {
|
|
29555
|
+
if (typeof message?.id !== "string" || typeof message?.authorId !== "string" || typeof message?.text !== "string" || typeof message?.createdAt !== "string") {
|
|
29556
|
+
return jsonError(400, `messages[${index}] needs id, authorId, text and createdAt`);
|
|
29557
|
+
}
|
|
29558
|
+
}
|
|
29559
|
+
let imported = 0;
|
|
29560
|
+
for (const message of messages) {
|
|
29561
|
+
appendApiMessage({
|
|
29562
|
+
id: message.id,
|
|
29563
|
+
topicId,
|
|
29564
|
+
authorId: message.authorId,
|
|
29565
|
+
text: message.text,
|
|
29566
|
+
createdAt: message.createdAt,
|
|
29567
|
+
deleted: false,
|
|
29568
|
+
...typeof message.agentType === "string" ? { agentType: message.agentType } : {},
|
|
29569
|
+
...typeof message.model === "string" ? { model: message.model } : {}
|
|
29570
|
+
}, { notify: false, updateTopicLastMessageAt: false });
|
|
29571
|
+
imported += 1;
|
|
29572
|
+
}
|
|
29573
|
+
if (imported > 0) {
|
|
29574
|
+
const stamps = messages.map((message) => message.createdAt).sort();
|
|
29575
|
+
upsertTopic({
|
|
29576
|
+
...topic,
|
|
29577
|
+
createdAt: stamps[0] < topic.createdAt ? stamps[0] : topic.createdAt,
|
|
29578
|
+
lastMessageAt: stamps[stamps.length - 1]
|
|
29579
|
+
});
|
|
29580
|
+
}
|
|
29581
|
+
return Response.json({
|
|
29582
|
+
ok: true,
|
|
29583
|
+
v: NODE_RUNTIME_CONTRACT_VERSION,
|
|
29584
|
+
imported
|
|
29585
|
+
});
|
|
29586
|
+
}
|
|
29542
29587
|
const runtimeTopicMatch = runtimePath.match(/^\/topics\/([^/]+)$/);
|
|
29543
29588
|
if (runtimeTopicMatch && req.method === "GET") {
|
|
29544
29589
|
const topic = getTopic(decodeURIComponent(runtimeTopicMatch[1]));
|
|
@@ -29570,13 +29615,13 @@ function createNodeControlHandler(options) {
|
|
|
29570
29615
|
ok: true,
|
|
29571
29616
|
protocolVersion: NODE_CONTROL_PROTOCOL_VERSION,
|
|
29572
29617
|
nodeVersion: NODE_VERSION,
|
|
29573
|
-
topics: topicsForUser(userId),
|
|
29618
|
+
topics: topicsForUser(userId, requestedSurface(url)),
|
|
29574
29619
|
cursor: latestRuntimeEventSeq()
|
|
29575
29620
|
});
|
|
29576
29621
|
}
|
|
29577
29622
|
if (req.method === "GET" && path === "/topics") {
|
|
29578
29623
|
const userId = requiredText(url.searchParams.get("user"), "user");
|
|
29579
|
-
return Response.json({ ok: true, topics: topicsForUser(userId) });
|
|
29624
|
+
return Response.json({ ok: true, topics: topicsForUser(userId, requestedSurface(url)) });
|
|
29580
29625
|
}
|
|
29581
29626
|
if (req.method === "GET" && path === "/background-sessions") {
|
|
29582
29627
|
const userId = requiredText(url.searchParams.get("user"), "user");
|
|
@@ -29707,24 +29752,6 @@ function createNodeControlHandler(options) {
|
|
|
29707
29752
|
return jsonError(400, result.error);
|
|
29708
29753
|
return Response.json({ ok: true, model: result.model, result: result.text });
|
|
29709
29754
|
}
|
|
29710
|
-
const accessModeMatch = path.match(/^\/topics\/([^/]+)\/access-mode$/);
|
|
29711
|
-
if (accessModeMatch && req.method === "POST") {
|
|
29712
|
-
const topicId = decodeURIComponent(accessModeMatch[1]);
|
|
29713
|
-
const body = await bodyRecord(req);
|
|
29714
|
-
const userId = requiredText(body.userId, "userId");
|
|
29715
|
-
const accessMode = requiredText(body.accessMode, "accessMode");
|
|
29716
|
-
if (accessMode !== "private" && accessMode !== "shared") {
|
|
29717
|
-
return jsonError(400, `Unknown access mode: ${accessMode}`);
|
|
29718
|
-
}
|
|
29719
|
-
const result = switchTopicAccessMode({ topicId, userId, accessMode });
|
|
29720
|
-
if (!result.ok)
|
|
29721
|
-
return jsonError(400, result.error);
|
|
29722
|
-
return Response.json({
|
|
29723
|
-
ok: true,
|
|
29724
|
-
accessMode: result.accessMode,
|
|
29725
|
-
result: result.text
|
|
29726
|
-
});
|
|
29727
|
-
}
|
|
29728
29755
|
const effortMatch = path.match(/^\/topics\/([^/]+)\/effort$/);
|
|
29729
29756
|
if (effortMatch && req.method === "POST") {
|
|
29730
29757
|
const topicId = decodeURIComponent(effortMatch[1]);
|
|
@@ -32069,8 +32096,6 @@ var init_commands = __esm(() => {
|
|
|
32069
32096
|
{ name: "model", usage: "/model", description: "choose the model" },
|
|
32070
32097
|
{ name: "effort", usage: "/effort", description: "choose reasoning effort" },
|
|
32071
32098
|
{ name: "topics", usage: "/topics", description: "open topic picker" },
|
|
32072
|
-
{ name: "public", usage: "/public", description: "share this topic with Otium Hub" },
|
|
32073
|
-
{ name: "private", usage: "/private", description: "make this topic local-only" },
|
|
32074
32099
|
{
|
|
32075
32100
|
name: "fork",
|
|
32076
32101
|
usage: "/fork [name]",
|
|
@@ -32416,8 +32441,7 @@ function topicPickerItems(state) {
|
|
|
32416
32441
|
const indexedTopics = state.topics.map((topic, index) => ({ topic, index })).filter(({ topic }) => visible.has(topic.id));
|
|
32417
32442
|
return [
|
|
32418
32443
|
...indexedTopics.filter(({ topic }) => topic.kind === "manager").map(({ topic, index }) => ({ kind: "topic", id: topic.id, index })),
|
|
32419
|
-
...indexedTopics.filter(({ topic }) => topic.kind !== "manager"
|
|
32420
|
-
...indexedTopics.filter(({ topic }) => topic.kind !== "manager" && topic.accessMode === "shared").map(({ topic, index }) => ({ kind: "topic", id: topic.id, index })),
|
|
32444
|
+
...indexedTopics.filter(({ topic }) => topic.kind !== "manager").map(({ topic, index }) => ({ kind: "topic", id: topic.id, index })),
|
|
32421
32445
|
...visibleBackgroundSessions(state).map((session) => ({
|
|
32422
32446
|
kind: "background",
|
|
32423
32447
|
id: session.id
|
|
@@ -32496,7 +32520,7 @@ function setTopics(state, topics, preferredTitle) {
|
|
|
32496
32520
|
activeTopicId: nextActive,
|
|
32497
32521
|
scrollOffset: nextActive === state.activeTopicId ? state.scrollOffset : 0,
|
|
32498
32522
|
askChoiceIndex: nextActive === state.activeTopicId ? state.askChoiceIndex : 0,
|
|
32499
|
-
topicPickerIndex: state.overlay === "topics"
|
|
32523
|
+
topicPickerIndex: state.overlay === "topics" ? pickedTopicIndex : Math.max(0, orderedTopics.findIndex((topic) => topic.id === nextActive)),
|
|
32500
32524
|
topicPickerBackgroundId: state.topicPickerBackgroundId
|
|
32501
32525
|
});
|
|
32502
32526
|
}
|
|
@@ -34034,7 +34058,7 @@ function helpLines() {
|
|
|
34034
34058
|
line(""),
|
|
34035
34059
|
line(" Commands", { fg: theme.cyan, bold: true }),
|
|
34036
34060
|
line(" /new /model /effort /status /context"),
|
|
34037
|
-
line(" /topics /
|
|
34061
|
+
line(" /topics /fork /spawn"),
|
|
34038
34062
|
line(" /del /copy /abort /help /quit", { fg: theme.muted })
|
|
34039
34063
|
];
|
|
34040
34064
|
}
|
|
@@ -34157,8 +34181,8 @@ function topicPickerHints(topicPickerRoot) {
|
|
|
34157
34181
|
const exit = topicPickerRoot ? "Esc/Ctrl-C exit" : "Esc close \xB7 Ctrl-C exit; work continues";
|
|
34158
34182
|
const shortExit = topicPickerRoot ? "Esc/Ctrl-C exit" : "Esc close";
|
|
34159
34183
|
const candidates = [
|
|
34160
|
-
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete \xB7
|
|
34161
|
-
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete \xB7
|
|
34184
|
+
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete \xB7 ${exit}`,
|
|
34185
|
+
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete \xB7 ${shortExit}`,
|
|
34162
34186
|
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete \xB7 ${exit}`,
|
|
34163
34187
|
`\u2191\u2193 select \xB7 Enter open \xB7 type to filter \xB7 Ctrl-N/D/P \xB7 ${shortExit}`,
|
|
34164
34188
|
"\u2191\u2193 \xB7 Enter \xB7 type to filter \xB7 Ctrl-N/D/P",
|
|
@@ -34180,13 +34204,11 @@ function topicOverlayLines(state, width, height, animationFrame = 0) {
|
|
|
34180
34204
|
const visibleIds = visibleTopicPickerIds(state);
|
|
34181
34205
|
const indexedTopics = state.topics.map((topic, topicIndex) => ({ topic, topicIndex })).filter(({ topic }) => visibleIds.has(topic.id));
|
|
34182
34206
|
const managerTopics = indexedTopics.filter(({ topic }) => topic.kind === "manager");
|
|
34183
|
-
const
|
|
34184
|
-
const publicTopics = indexedTopics.filter(({ topic }) => topic.kind !== "manager" && topic.accessMode === "shared");
|
|
34207
|
+
const regularTopics = indexedTopics.filter(({ topic }) => topic.kind !== "manager");
|
|
34185
34208
|
const entries = [];
|
|
34186
34209
|
for (const [label, topics] of [
|
|
34187
34210
|
["Manager", managerTopics],
|
|
34188
|
-
["
|
|
34189
|
-
["Public", publicTopics]
|
|
34211
|
+
["Topics", regularTopics]
|
|
34190
34212
|
]) {
|
|
34191
34213
|
if (topics.length === 0)
|
|
34192
34214
|
continue;
|
|
@@ -34521,34 +34543,6 @@ function conversationLines(state, width, height, animationFrame = 0, nowMs = ter
|
|
|
34521
34543
|
line(" Press y to delete or n to cancel.", { fg: theme.amber })
|
|
34522
34544
|
].slice(0, height);
|
|
34523
34545
|
}
|
|
34524
|
-
if (state.overlay === "confirm-share") {
|
|
34525
|
-
const topic = state.topics.find((candidate) => candidate.id === state.pendingShareTopicId);
|
|
34526
|
-
const subagents = (() => {
|
|
34527
|
-
if (!topic)
|
|
34528
|
-
return 0;
|
|
34529
|
-
const reached = new Set([topic.id]);
|
|
34530
|
-
for (;; ) {
|
|
34531
|
-
const next = state.topics.filter((candidate) => candidate.isSubagent && !reached.has(candidate.id) && candidate.parentTopicId !== undefined && reached.has(candidate.parentTopicId));
|
|
34532
|
-
if (next.length === 0)
|
|
34533
|
-
break;
|
|
34534
|
-
for (const candidate of next)
|
|
34535
|
-
reached.add(candidate.id);
|
|
34536
|
-
}
|
|
34537
|
-
return reached.size - 1;
|
|
34538
|
-
})();
|
|
34539
|
-
const scope = subagents > 0 ? ` Its ${subagents} subagent room${subagents === 1 ? "" : "s"} become public too.` : " Subagent rooms spawned from it will be public too.";
|
|
34540
|
-
return [
|
|
34541
|
-
line(""),
|
|
34542
|
-
line(` Make \u201C${topic?.title ?? "this topic"}\u201D public?`, {
|
|
34543
|
-
fg: theme.amber,
|
|
34544
|
-
bold: true
|
|
34545
|
-
}),
|
|
34546
|
-
line(""),
|
|
34547
|
-
line(" The transcript becomes visible to the connected Otium Hub."),
|
|
34548
|
-
line(scope),
|
|
34549
|
-
line(" Press y to publish or n to cancel.", { fg: theme.amber })
|
|
34550
|
-
].slice(0, height);
|
|
34551
|
-
}
|
|
34552
34546
|
const all = conversationContentLines(state, width, animationFrame, nowMs, includeTasks);
|
|
34553
34547
|
const { contentHeight, maxOffset, offset } = conversationViewport(all.length, height, state.scrollOffset);
|
|
34554
34548
|
const end = all.length - offset;
|
|
@@ -34816,9 +34810,6 @@ function footerHintText(state) {
|
|
|
34816
34810
|
}
|
|
34817
34811
|
return state.topicPickerRoot ? ["Esc/Ctrl-C exit ", "Esc exit "] : ["Esc close \xB7 Ctrl-C exit; work continues ", "Esc close \xB7 Ctrl-C exit ", "Esc "];
|
|
34818
34812
|
}
|
|
34819
|
-
if (state.overlay === "confirm-share") {
|
|
34820
|
-
return ["Y make public \xB7 N cancel ", "Y/N "];
|
|
34821
|
-
}
|
|
34822
34813
|
if (state.overlay === "background-session") {
|
|
34823
34814
|
return [
|
|
34824
34815
|
"wheel/PgUp/PgDn scroll \xB7 Esc back \xB7 read-only ",
|
|
@@ -35422,7 +35413,7 @@ class EmbeddedNegotiumClient {
|
|
|
35422
35413
|
}
|
|
35423
35414
|
listTopics() {
|
|
35424
35415
|
const runningTopics = listRunningTopicQueries();
|
|
35425
|
-
return getVisibleTopics().filter((topic) => topic.participants.some((participant) => participant.userId === this.#userId)).map((topic) => {
|
|
35416
|
+
return getVisibleTopics({ surface: "terminal" }).filter((topic) => topic.participants.some((participant) => participant.userId === this.#userId)).map((topic) => {
|
|
35426
35417
|
const runningQueryId = runningTopics.get(topic.id);
|
|
35427
35418
|
return { ...topic, running: Boolean(runningQueryId), runningQueryId };
|
|
35428
35419
|
});
|
|
@@ -35501,16 +35492,6 @@ class EmbeddedNegotiumClient {
|
|
|
35501
35492
|
throw new Error(result.error);
|
|
35502
35493
|
return result.text;
|
|
35503
35494
|
}
|
|
35504
|
-
setAccessMode(topic, accessMode) {
|
|
35505
|
-
const result = switchTopicAccessMode({
|
|
35506
|
-
topicId: topic.id,
|
|
35507
|
-
userId: this.#userId,
|
|
35508
|
-
accessMode
|
|
35509
|
-
});
|
|
35510
|
-
if (!result.ok)
|
|
35511
|
-
throw new Error(result.error);
|
|
35512
|
-
return result.text;
|
|
35513
|
-
}
|
|
35514
35495
|
async deleteTopic(topic) {
|
|
35515
35496
|
await topicService.delete({ topicId: topic.id, userId: this.#userId });
|
|
35516
35497
|
}
|
|
@@ -35595,7 +35576,7 @@ class RemoteNegotiumClient {
|
|
|
35595
35576
|
async start(onEvent) {
|
|
35596
35577
|
if (this.#started)
|
|
35597
35578
|
return;
|
|
35598
|
-
const session = await this.#request(`/session?user=${encodeURIComponent(this.#userId)}`);
|
|
35579
|
+
const session = await this.#request(`/session?user=${encodeURIComponent(this.#userId)}&surface=terminal`);
|
|
35599
35580
|
if (session.protocolVersion !== NODE_CONTROL_PROTOCOL_VERSION) {
|
|
35600
35581
|
throw new Error(`Node protocol ${String(session.protocolVersion)} is incompatible with terminal protocol ${NODE_CONTROL_PROTOCOL_VERSION}`);
|
|
35601
35582
|
}
|
|
@@ -35621,7 +35602,7 @@ class RemoteNegotiumClient {
|
|
|
35621
35602
|
this.#onEvent = null;
|
|
35622
35603
|
}
|
|
35623
35604
|
async listTopics() {
|
|
35624
|
-
const result = await this.#request(`/topics?user=${encodeURIComponent(this.#userId)}`);
|
|
35605
|
+
const result = await this.#request(`/topics?user=${encodeURIComponent(this.#userId)}&surface=terminal`);
|
|
35625
35606
|
return result.topics ?? [];
|
|
35626
35607
|
}
|
|
35627
35608
|
async listBackgroundSessions() {
|
|
@@ -35693,13 +35674,6 @@ class RemoteNegotiumClient {
|
|
|
35693
35674
|
});
|
|
35694
35675
|
return String(result.result ?? `Effort set to '${effort}'.`);
|
|
35695
35676
|
}
|
|
35696
|
-
async setAccessMode(topic, accessMode) {
|
|
35697
|
-
const result = await this.#request(`/topics/${encodeURIComponent(topic.id)}/access-mode`, {
|
|
35698
|
-
method: "POST",
|
|
35699
|
-
body: JSON.stringify({ userId: this.#userId, accessMode })
|
|
35700
|
-
});
|
|
35701
|
-
return String(result.result ?? `Access mode set to '${accessMode}'.`);
|
|
35702
|
-
}
|
|
35703
35677
|
async deleteTopic(topic) {
|
|
35704
35678
|
await this.#request(`/topics/${encodeURIComponent(topic.id)}?user=${encodeURIComponent(this.#userId)}`, { method: "DELETE" });
|
|
35705
35679
|
}
|
|
@@ -36177,32 +36151,6 @@ async function runTerminalCommand(commandLine, context) {
|
|
|
36177
36151
|
context.queueRender();
|
|
36178
36152
|
return;
|
|
36179
36153
|
}
|
|
36180
|
-
if (command === "public" || command === "private") {
|
|
36181
|
-
if (args.length > 0) {
|
|
36182
|
-
context.state = { ...context.state, notice: `Usage: /${command}`, noticeLevel: "warn" };
|
|
36183
|
-
context.queueRender();
|
|
36184
|
-
return;
|
|
36185
|
-
}
|
|
36186
|
-
const topic = activeTopic(context.state);
|
|
36187
|
-
if (!topic) {
|
|
36188
|
-
context.state = { ...context.state, notice: "No topic selected", noticeLevel: "warn" };
|
|
36189
|
-
context.queueRender();
|
|
36190
|
-
return;
|
|
36191
|
-
}
|
|
36192
|
-
try {
|
|
36193
|
-
const notice = await context.client.setAccessMode(topic, command === "public" ? "shared" : "private");
|
|
36194
|
-
await context.refreshTopics(topic.title);
|
|
36195
|
-
context.state = { ...context.state, notice, noticeLevel: "success" };
|
|
36196
|
-
} catch (error2) {
|
|
36197
|
-
context.state = {
|
|
36198
|
-
...context.state,
|
|
36199
|
-
notice: error2 instanceof Error ? error2.message : String(error2),
|
|
36200
|
-
noticeLevel: "error"
|
|
36201
|
-
};
|
|
36202
|
-
}
|
|
36203
|
-
context.queueRender();
|
|
36204
|
-
return;
|
|
36205
|
-
}
|
|
36206
36154
|
if (command === "compact") {
|
|
36207
36155
|
const topic = activeTopic(context.state);
|
|
36208
36156
|
if (!topic) {
|
|
@@ -37767,16 +37715,6 @@ class TerminalApp {
|
|
|
37767
37715
|
}
|
|
37768
37716
|
return;
|
|
37769
37717
|
}
|
|
37770
|
-
if (this.#state.overlay === "confirm-share") {
|
|
37771
|
-
const key = chunk.toLowerCase();
|
|
37772
|
-
if (CONFIRM_KEYS.has(key))
|
|
37773
|
-
this.#confirmTopicShare();
|
|
37774
|
-
else if (CANCEL_KEYS.has(key) || chunk === "\x1B") {
|
|
37775
|
-
this.#state = { ...this.#state, overlay: "topics", pendingShareTopicId: undefined };
|
|
37776
|
-
this.#queueRender();
|
|
37777
|
-
}
|
|
37778
|
-
return;
|
|
37779
|
-
}
|
|
37780
37718
|
if (this.#state.overlay === "background-session") {
|
|
37781
37719
|
if (chunk === "\x1B") {
|
|
37782
37720
|
this.#state = { ...this.#state, overlay: "topics" };
|
|
@@ -38085,22 +38023,6 @@ class TerminalApp {
|
|
|
38085
38023
|
this.#queueRender();
|
|
38086
38024
|
return;
|
|
38087
38025
|
}
|
|
38088
|
-
if (chunk === TOGGLE_ACCESS_MODE_KEY) {
|
|
38089
|
-
const topic = pickedTopic(this.#state);
|
|
38090
|
-
if (topic) {
|
|
38091
|
-
this.#requestAccessModeToggle(topic);
|
|
38092
|
-
return;
|
|
38093
|
-
}
|
|
38094
|
-
if (!this.#state.topicPickerBackgroundId)
|
|
38095
|
-
return;
|
|
38096
|
-
this.#state = {
|
|
38097
|
-
...this.#state,
|
|
38098
|
-
notice: "Background sessions are read-only",
|
|
38099
|
-
noticeLevel: "warn"
|
|
38100
|
-
};
|
|
38101
|
-
this.#queueRender();
|
|
38102
|
-
return;
|
|
38103
|
-
}
|
|
38104
38026
|
if (FILTER_BACKSPACE_KEYS.has(chunk)) {
|
|
38105
38027
|
if (this.#state.topicFilter.length === 0)
|
|
38106
38028
|
return;
|
|
@@ -38543,65 +38465,6 @@ class TerminalApp {
|
|
|
38543
38465
|
};
|
|
38544
38466
|
this.#queueRender();
|
|
38545
38467
|
}
|
|
38546
|
-
async#requestAccessModeToggle(topic) {
|
|
38547
|
-
if (topic.kind !== "agent") {
|
|
38548
|
-
this.#state = {
|
|
38549
|
-
...this.#state,
|
|
38550
|
-
notice: `${topic.kind === "manager" ? "Manager" : "Channel"} topics cannot be published`,
|
|
38551
|
-
noticeLevel: "warn"
|
|
38552
|
-
};
|
|
38553
|
-
this.#queueRender();
|
|
38554
|
-
return;
|
|
38555
|
-
}
|
|
38556
|
-
if (topic.isSubagent) {
|
|
38557
|
-
this.#state = {
|
|
38558
|
-
...this.#state,
|
|
38559
|
-
notice: "Subagent rooms inherit privacy from their parent topic",
|
|
38560
|
-
noticeLevel: "warn"
|
|
38561
|
-
};
|
|
38562
|
-
this.#queueRender();
|
|
38563
|
-
return;
|
|
38564
|
-
}
|
|
38565
|
-
if (topic.accessMode === "shared") {
|
|
38566
|
-
await this.#applyAccessMode(topic, "private");
|
|
38567
|
-
return;
|
|
38568
|
-
}
|
|
38569
|
-
this.#state = {
|
|
38570
|
-
...this.#state,
|
|
38571
|
-
overlay: "confirm-share",
|
|
38572
|
-
pendingShareTopicId: topic.id
|
|
38573
|
-
};
|
|
38574
|
-
this.#queueRender();
|
|
38575
|
-
}
|
|
38576
|
-
async#confirmTopicShare() {
|
|
38577
|
-
const topic = this.#state.topics.find((candidate) => candidate.id === this.#state.pendingShareTopicId);
|
|
38578
|
-
this.#state = { ...this.#state, overlay: "topics", pendingShareTopicId: undefined };
|
|
38579
|
-
if (!topic) {
|
|
38580
|
-
this.#state = {
|
|
38581
|
-
...this.#state,
|
|
38582
|
-
notice: "That topic no longer exists",
|
|
38583
|
-
noticeLevel: "warn"
|
|
38584
|
-
};
|
|
38585
|
-
this.#queueRender();
|
|
38586
|
-
return;
|
|
38587
|
-
}
|
|
38588
|
-
await this.#applyAccessMode(topic, "shared");
|
|
38589
|
-
}
|
|
38590
|
-
async#applyAccessMode(topic, accessMode) {
|
|
38591
|
-
this.#state = { ...this.#state, overlay: "topics" };
|
|
38592
|
-
try {
|
|
38593
|
-
const notice = await this.#client.setAccessMode(topic, accessMode);
|
|
38594
|
-
await this.#refreshTopics();
|
|
38595
|
-
this.#state = { ...this.#state, notice, noticeLevel: "success" };
|
|
38596
|
-
} catch (error2) {
|
|
38597
|
-
this.#state = {
|
|
38598
|
-
...this.#state,
|
|
38599
|
-
notice: error2 instanceof Error ? error2.message : String(error2),
|
|
38600
|
-
noticeLevel: "error"
|
|
38601
|
-
};
|
|
38602
|
-
}
|
|
38603
|
-
this.#queueRender();
|
|
38604
|
-
}
|
|
38605
38468
|
#requestTopicDelete(topic) {
|
|
38606
38469
|
if (!topic)
|
|
38607
38470
|
return;
|
|
@@ -38880,7 +38743,6 @@ class TerminalApp {
|
|
|
38880
38743
|
...this.#state,
|
|
38881
38744
|
overlay: null,
|
|
38882
38745
|
pendingDeleteTopicId: undefined,
|
|
38883
|
-
pendingShareTopicId: undefined,
|
|
38884
38746
|
creatingTopic: false,
|
|
38885
38747
|
notice: "Input cleared",
|
|
38886
38748
|
noticeLevel: "info"
|
|
@@ -38943,7 +38805,7 @@ class TerminalApp {
|
|
|
38943
38805
|
await this.#client.stop();
|
|
38944
38806
|
}
|
|
38945
38807
|
}
|
|
38946
|
-
var KITTY_KEYBOARD_PUSH = "\x1B[>1u", KITTY_KEYBOARD_POP = "\x1B[<u", CANVAS_RGB, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN, ABORT_ENTER_ALT_SCREEN, NEW_TOPIC_KEY = "\x0E", DELETE_TOPIC_KEY = "\x04",
|
|
38808
|
+
var KITTY_KEYBOARD_PUSH = "\x1B[>1u", KITTY_KEYBOARD_POP = "\x1B[<u", CANVAS_RGB, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN, ABORT_ENTER_ALT_SCREEN, NEW_TOPIC_KEY = "\x0E", DELETE_TOPIC_KEY = "\x04", FILTER_BACKSPACE_KEYS, CONFIRM_KEYS, CANCEL_KEYS, INPUT_CARRY_FLUSH_MS = 15;
|
|
38947
38809
|
var init_app = __esm(async () => {
|
|
38948
38810
|
await init_src();
|
|
38949
38811
|
await init_app_helpers();
|
|
@@ -39421,7 +39283,7 @@ function createTelegramCommandRouter(context) {
|
|
|
39421
39283
|
return;
|
|
39422
39284
|
}
|
|
39423
39285
|
case "/topics": {
|
|
39424
|
-
const topics = listTopics().filter((topic) => isTopicVisible(topic) && topic.participants.some((person) => person.userId === userId));
|
|
39286
|
+
const topics = listTopics({ surface: "telegram" }).filter((topic) => isTopicVisible(topic) && topic.participants.some((person) => person.userId === userId));
|
|
39425
39287
|
reply(chatId, threadId, topics.length ? topics.map((topic) => `- ${topic.title}${topic.agent ? ` (${topic.agent})` : ""}`).join(`
|
|
39426
39288
|
`) : "no topics");
|
|
39427
39289
|
return;
|
|
@@ -39451,6 +39313,7 @@ function createTelegramCommandRouter(context) {
|
|
|
39451
39313
|
title: argument,
|
|
39452
39314
|
userId,
|
|
39453
39315
|
kind: "agent",
|
|
39316
|
+
surface: "telegram",
|
|
39454
39317
|
...context.defaultAgent ? { agent: context.defaultAgent } : {}
|
|
39455
39318
|
};
|
|
39456
39319
|
const fromForumGeneral = context.forum?.enabled === true && chatId === context.forum.chatId && threadId === undefined;
|
|
@@ -39669,6 +39532,15 @@ function openMappingStore(path) {
|
|
|
39669
39532
|
clearForumChatId() {
|
|
39670
39533
|
db4.run("DELETE FROM settings WHERE key = 'forum_chat_id'");
|
|
39671
39534
|
},
|
|
39535
|
+
isFlagSet(key) {
|
|
39536
|
+
return db4.query("SELECT 1 FROM settings WHERE key = ?").get(key) !== null;
|
|
39537
|
+
},
|
|
39538
|
+
setFlag(key) {
|
|
39539
|
+
db4.run("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", [
|
|
39540
|
+
key,
|
|
39541
|
+
new Date().toISOString()
|
|
39542
|
+
]);
|
|
39543
|
+
},
|
|
39672
39544
|
outboxEnqueue(entry) {
|
|
39673
39545
|
db4.run(`INSERT INTO outbox
|
|
39674
39546
|
(chat_id, thread_id, runtime_message_id, footer, html, plain, attempts, next_try_at, last_error)
|
|
@@ -40238,6 +40110,14 @@ function startTelegramAdapter(opts) {
|
|
|
40238
40110
|
bindMapping(chatId, threadId, topic.id);
|
|
40239
40111
|
return true;
|
|
40240
40112
|
}
|
|
40113
|
+
if (!store.isFlagSet(SURFACE_BACKFILL_FLAG)) {
|
|
40114
|
+
const mappedIds = [...new Set(store.load().map((mapping) => mapping.topicId))];
|
|
40115
|
+
const moved = setTopicSurfaces(mappedIds, "telegram");
|
|
40116
|
+
store.setFlag(SURFACE_BACKFILL_FLAG);
|
|
40117
|
+
if (moved > 0) {
|
|
40118
|
+
logger.info({ moved, mapped: mappedIds.length }, "telegram adapter: moved mapped topics onto the telegram surface");
|
|
40119
|
+
}
|
|
40120
|
+
}
|
|
40241
40121
|
for (const persisted of store.load()) {
|
|
40242
40122
|
const topic = getTopic(persisted.topicId);
|
|
40243
40123
|
if (topic?.participants.some((participant) => participant.userId === userId)) {
|
|
@@ -40258,13 +40138,13 @@ function startTelegramAdapter(opts) {
|
|
|
40258
40138
|
function registerTopicLocal(options) {
|
|
40259
40139
|
suppressMaterialize++;
|
|
40260
40140
|
try {
|
|
40261
|
-
return topicService.create(options);
|
|
40141
|
+
return topicService.create({ ...options, surface: "telegram" });
|
|
40262
40142
|
} finally {
|
|
40263
40143
|
suppressMaterialize--;
|
|
40264
40144
|
}
|
|
40265
40145
|
}
|
|
40266
40146
|
function getOrCreateTopic(title, agent) {
|
|
40267
|
-
return getTopicByNameForUser(title, userId) ?? registerTopicLocal({ title, userId, kind: "agent", ...agent ? { agent } : {} });
|
|
40147
|
+
return getTopicByNameForUser(title, userId, { surface: "telegram" }) ?? registerTopicLocal({ title, userId, kind: "agent", ...agent ? { agent } : {} });
|
|
40268
40148
|
}
|
|
40269
40149
|
function resolveMapping(chatId, threadId) {
|
|
40270
40150
|
const cached = byKey.get(mappingKey(chatId, threadId));
|
|
@@ -40855,7 +40735,7 @@ ${suffix}`;
|
|
|
40855
40735
|
function materializeVisibleTopics() {
|
|
40856
40736
|
if (!forumMode || !forumManageTopicsAvailable)
|
|
40857
40737
|
return;
|
|
40858
|
-
for (const topic of listTopics()) {
|
|
40738
|
+
for (const topic of listTopics({ surface: "telegram" })) {
|
|
40859
40739
|
if (isTopicVisible(topic) && topic.participants.some((participant) => participant.userId === userId)) {
|
|
40860
40740
|
materializeTopic(topic);
|
|
40861
40741
|
}
|
|
@@ -41276,7 +41156,7 @@ Warning: enable the bot administrator permission "Manage Topics" before creating
|
|
|
41276
41156
|
}
|
|
41277
41157
|
};
|
|
41278
41158
|
}
|
|
41279
|
-
var FORUM_TOPIC_NAME_MAX = 128, MAX_PARENT_HOPS = 5, DEFAULT_SEND_TIMEOUT_MS = 60000, PHOTO_EXTS;
|
|
41159
|
+
var SURFACE_BACKFILL_FLAG = "surface_backfill_20260808", FORUM_TOPIC_NAME_MAX = 128, MAX_PARENT_HOPS = 5, DEFAULT_SEND_TIMEOUT_MS = 60000, PHOTO_EXTS;
|
|
41280
41160
|
var init_adapter = __esm(async () => {
|
|
41281
41161
|
await init_src();
|
|
41282
41162
|
await init_commands2();
|
|
@@ -43934,7 +43814,7 @@ function requirePrimaryOrigin(peer) {
|
|
|
43934
43814
|
return peer.verified.fromIsPrimary ? null : jsonError2("only the workspace hub may call this endpoint", 403);
|
|
43935
43815
|
}
|
|
43936
43816
|
function peerAddressable(topic) {
|
|
43937
|
-
return
|
|
43817
|
+
return topic.surface === "otium";
|
|
43938
43818
|
}
|
|
43939
43819
|
function localCapabilities() {
|
|
43940
43820
|
const agents = SUPPORTED_AGENTS.map((kind) => {
|
|
@@ -44104,7 +43984,7 @@ async function handleSessions(req) {
|
|
|
44104
43984
|
const userId = str(body, "userId");
|
|
44105
43985
|
if (!userId)
|
|
44106
43986
|
return jsonError2("userId is required", 400);
|
|
44107
|
-
const topics = listTopics().filter((topic) => topic.kind !== "manager" && !topic.isSubagent && peerAddressable(topic) && topic.participants.some((p) => p.userId === userId));
|
|
43987
|
+
const topics = listTopics({ surface: "otium" }).filter((topic) => topic.kind !== "manager" && !topic.isSubagent && peerAddressable(topic) && topic.participants.some((p) => p.userId === userId));
|
|
44108
43988
|
const titleCounts = new Map;
|
|
44109
43989
|
for (const topic of topics) {
|
|
44110
43990
|
const normalized = topic.title.toLowerCase();
|
|
@@ -44820,26 +44700,8 @@ async function runOtiumCli(args = process.argv.slice(2)) {
|
|
|
44820
44700
|
const { loadJoin: loadJoin2, removeJoin: removeJoin2 } = await init_join().then(() => exports_join);
|
|
44821
44701
|
if (!loadJoin2())
|
|
44822
44702
|
throw new Error("not joined to an Otium workspace");
|
|
44823
|
-
const { getVisibleTopics: getVisibleTopics2, isTopicShared: isTopicShared2, switchTopicAccessMode: switchTopicAccessMode2 } = await init_src().then(() => exports_src);
|
|
44824
|
-
let downgraded = 0;
|
|
44825
|
-
for (const topic of getVisibleTopics2()) {
|
|
44826
|
-
if (!isTopicShared2(topic))
|
|
44827
|
-
continue;
|
|
44828
|
-
const owner = topic.participants.find((participant) => participant.role === "owner");
|
|
44829
|
-
if (!owner)
|
|
44830
|
-
continue;
|
|
44831
|
-
if (topic.isSubagent)
|
|
44832
|
-
continue;
|
|
44833
|
-
const switched = switchTopicAccessMode2({
|
|
44834
|
-
topicId: topic.id,
|
|
44835
|
-
userId: owner.userId,
|
|
44836
|
-
accessMode: "private"
|
|
44837
|
-
});
|
|
44838
|
-
if (switched.ok)
|
|
44839
|
-
downgraded += switched.topicIds.length;
|
|
44840
|
-
}
|
|
44841
44703
|
removeJoin2();
|
|
44842
|
-
console.log(
|
|
44704
|
+
console.log("disconnected from Otium; workspace credentials removed");
|
|
44843
44705
|
break;
|
|
44844
44706
|
}
|
|
44845
44707
|
case "serve": {
|
|
@@ -44913,11 +44775,7 @@ function topicsCommand() {
|
|
|
44913
44775
|
}
|
|
44914
44776
|
for (const t of topics) {
|
|
44915
44777
|
const model = t.effectiveModel ?? t.defaultModel;
|
|
44916
|
-
const flags = [
|
|
44917
|
-
t.accessMode ?? "private",
|
|
44918
|
-
t.isSubagent ? "subagent" : null,
|
|
44919
|
-
t.isFork ? "fork" : null
|
|
44920
|
-
].filter(Boolean).join(",");
|
|
44778
|
+
const flags = [t.isSubagent ? "subagent" : null, t.isFork ? "fork" : null].filter(Boolean).join(",");
|
|
44921
44779
|
console.log(`${t.title} ${t.agent ?? "no-ai"}${model ? `/${model}` : ""}` + `${flags ? ` [${flags}]` : ""} ${t.id}`);
|
|
44922
44780
|
}
|
|
44923
44781
|
}
|
|
@@ -45565,4 +45423,4 @@ switch (command) {
|
|
|
45565
45423
|
}
|
|
45566
45424
|
}
|
|
45567
45425
|
|
|
45568
|
-
//# debugId=
|
|
45426
|
+
//# debugId=488B733FDB6D1AD164756E2164756E21
|