negotium 0.1.6 → 0.1.8

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.
Files changed (256) hide show
  1. package/README.md +2 -2
  2. package/dist/chunk-0ay6cjdy.js +1331 -0
  3. package/dist/chunk-0ay6cjdy.js.map +16 -0
  4. package/dist/chunk-1k7t7bnx.js +97 -0
  5. package/dist/chunk-1k7t7bnx.js.map +10 -0
  6. package/dist/chunk-5ahkew9c.js +806 -0
  7. package/dist/chunk-5ahkew9c.js.map +17 -0
  8. package/dist/chunk-6cpn7ht2.js +287 -0
  9. package/dist/chunk-6cpn7ht2.js.map +13 -0
  10. package/dist/chunk-6kctn20e.js +3529 -0
  11. package/dist/chunk-6kctn20e.js.map +20 -0
  12. package/dist/chunk-7xqj7aex.js +77 -0
  13. package/dist/chunk-7xqj7aex.js.map +11 -0
  14. package/dist/chunk-9p0ww3tk.js +41 -0
  15. package/dist/chunk-9p0ww3tk.js.map +10 -0
  16. package/dist/chunk-a92a7nrk.js +252 -0
  17. package/dist/chunk-a92a7nrk.js.map +10 -0
  18. package/dist/chunk-c500xe9z.js +33 -0
  19. package/dist/chunk-c500xe9z.js.map +10 -0
  20. package/dist/chunk-cds1qxsf.js +1644 -0
  21. package/dist/chunk-cds1qxsf.js.map +17 -0
  22. package/dist/chunk-e4407g8x.js +274 -0
  23. package/dist/chunk-e4407g8x.js.map +10 -0
  24. package/dist/chunk-e5pbggsh.js +363 -0
  25. package/dist/chunk-e5pbggsh.js.map +11 -0
  26. package/dist/chunk-edb07sjp.js +567 -0
  27. package/dist/chunk-edb07sjp.js.map +14 -0
  28. package/dist/chunk-exd0v74a.js +3012 -0
  29. package/dist/chunk-exd0v74a.js.map +32 -0
  30. package/dist/chunk-fgrme9tr.js +4398 -0
  31. package/dist/chunk-fgrme9tr.js.map +47 -0
  32. package/dist/chunk-fka9eqe1.js +581 -0
  33. package/dist/chunk-fka9eqe1.js.map +11 -0
  34. package/dist/chunk-g82jygez.js +108 -0
  35. package/dist/chunk-g82jygez.js.map +10 -0
  36. package/dist/chunk-ghs2j1fr.js +312 -0
  37. package/dist/chunk-ghs2j1fr.js.map +10 -0
  38. package/dist/chunk-gmy11efb.js +125 -0
  39. package/dist/chunk-gmy11efb.js.map +10 -0
  40. package/dist/chunk-gxma4c70.js +110 -0
  41. package/dist/chunk-gxma4c70.js.map +10 -0
  42. package/dist/chunk-hkdqhm34.js +61 -0
  43. package/dist/chunk-hkdqhm34.js.map +10 -0
  44. package/dist/chunk-hpa0cpzh.js +134 -0
  45. package/dist/chunk-hpa0cpzh.js.map +10 -0
  46. package/dist/chunk-hwy3n31w.js +21 -0
  47. package/dist/chunk-hwy3n31w.js.map +9 -0
  48. package/dist/chunk-j2behpy7.js +214 -0
  49. package/dist/chunk-j2behpy7.js.map +10 -0
  50. package/dist/chunk-jc0at0tc.js +102 -0
  51. package/dist/chunk-jc0at0tc.js.map +10 -0
  52. package/dist/chunk-jkqq5ef6.js +243 -0
  53. package/dist/chunk-jkqq5ef6.js.map +11 -0
  54. package/dist/chunk-jzkw2f01.js +51 -0
  55. package/dist/chunk-jzkw2f01.js.map +10 -0
  56. package/dist/chunk-jzz91jwh.js +70 -0
  57. package/dist/chunk-jzz91jwh.js.map +10 -0
  58. package/dist/chunk-k9z47mab.js +247 -0
  59. package/dist/chunk-k9z47mab.js.map +12 -0
  60. package/dist/chunk-n17yxpa8.js +23 -0
  61. package/dist/chunk-n17yxpa8.js.map +10 -0
  62. package/dist/chunk-naa09ags.js +2143 -0
  63. package/dist/chunk-naa09ags.js.map +15 -0
  64. package/dist/chunk-ns3ke88n.js +142 -0
  65. package/dist/chunk-ns3ke88n.js.map +10 -0
  66. package/dist/chunk-p3cr2ejg.js +1626 -0
  67. package/dist/chunk-p3cr2ejg.js.map +15 -0
  68. package/dist/chunk-q5bcpf23.js +2925 -0
  69. package/dist/chunk-q5bcpf23.js.map +20 -0
  70. package/dist/chunk-rafc55bs.js +424 -0
  71. package/dist/chunk-rafc55bs.js.map +11 -0
  72. package/dist/chunk-rbrxjvbj.js +2830 -0
  73. package/dist/chunk-rbrxjvbj.js.map +23 -0
  74. package/dist/chunk-sa874j5c.js +9 -0
  75. package/dist/chunk-sa874j5c.js.map +10 -0
  76. package/dist/chunk-sgsz2fpq.js +289 -0
  77. package/dist/chunk-sgsz2fpq.js.map +10 -0
  78. package/dist/chunk-sm6fh5c5.js +569 -0
  79. package/dist/chunk-sm6fh5c5.js.map +14 -0
  80. package/dist/chunk-t9zcg8f1.js +499 -0
  81. package/dist/chunk-t9zcg8f1.js.map +13 -0
  82. package/dist/chunk-vp2db42d.js +121 -0
  83. package/dist/chunk-vp2db42d.js.map +10 -0
  84. package/dist/chunk-w13jjf4a.js +46 -0
  85. package/dist/chunk-w13jjf4a.js.map +10 -0
  86. package/dist/chunk-x1arr7ze.js +63 -0
  87. package/dist/chunk-x1arr7ze.js.map +10 -0
  88. package/dist/chunk-xfq68rch.js +583 -0
  89. package/dist/chunk-xfq68rch.js.map +11 -0
  90. package/dist/main.js +132 -20
  91. package/dist/main.js.map +4 -4
  92. package/dist/runtime/scripts/faster-whisper-wrapper.py +87 -0
  93. package/dist/runtime/scripts/mcp-patchright-http.mjs +349 -0
  94. package/dist/runtime/src/agents/api-topic-agent-switch.ts +178 -0
  95. package/dist/runtime/src/agents/archiver.ts +396 -0
  96. package/dist/runtime/src/agents/auth-check.ts +64 -0
  97. package/dist/runtime/src/agents/claude-provider.ts +737 -0
  98. package/dist/runtime/src/agents/claude-registry.ts +115 -0
  99. package/dist/runtime/src/agents/codex-native-multi-agent.ts +177 -0
  100. package/dist/runtime/src/agents/codex-provider.ts +785 -0
  101. package/dist/runtime/src/agents/codex-registry.ts +115 -0
  102. package/dist/runtime/src/agents/codex-tree-kill.ts +365 -0
  103. package/dist/runtime/src/agents/contracts.ts +69 -0
  104. package/dist/runtime/src/agents/deep-map.ts +13 -0
  105. package/dist/runtime/src/agents/execution-host.ts +91 -0
  106. package/dist/runtime/src/agents/fixtures/claude-attachments.jsonl +2 -0
  107. package/dist/runtime/src/agents/fixtures/codex-shell.jsonl +5 -0
  108. package/dist/runtime/src/agents/fork.ts +65 -0
  109. package/dist/runtime/src/agents/hosted-agent.ts +48 -0
  110. package/dist/runtime/src/agents/idle-archiver.ts +128 -0
  111. package/dist/runtime/src/agents/index.ts +205 -0
  112. package/dist/runtime/src/agents/maestro-provider.ts +206 -0
  113. package/dist/runtime/src/agents/maestro-registry.ts +31 -0
  114. package/dist/runtime/src/agents/mcp-tools/ask-user.ts +280 -0
  115. package/dist/runtime/src/agents/mcp-tools/common.ts +21 -0
  116. package/dist/runtime/src/agents/mcp-tools/self-config.ts +220 -0
  117. package/dist/runtime/src/agents/mcp-tools/spawn-subagent.ts +525 -0
  118. package/dist/runtime/src/agents/mcp-tools/visuals.ts +88 -0
  119. package/dist/runtime/src/agents/model-catalog.ts +151 -0
  120. package/dist/runtime/src/agents/registry.ts +24 -0
  121. package/dist/runtime/src/agents/rollout/claude.ts +331 -0
  122. package/dist/runtime/src/agents/rollout/codex.ts +569 -0
  123. package/dist/runtime/src/agents/rollout/shared.ts +205 -0
  124. package/dist/runtime/src/agents/self-config-core.ts +415 -0
  125. package/dist/runtime/src/agents/task-events.ts +44 -0
  126. package/dist/runtime/src/agents/tool-format.ts +352 -0
  127. package/dist/runtime/src/agents/topic-agent-switch.ts +193 -0
  128. package/dist/runtime/src/agents/topic-cleanup.ts +231 -0
  129. package/dist/runtime/src/agents/vault-tool-policy.ts +33 -0
  130. package/dist/runtime/src/application/execute-external-user-turn.ts +23 -0
  131. package/dist/runtime/src/application/submit-user-message.ts +47 -0
  132. package/dist/runtime/src/application/switch-topic-effort.ts +48 -0
  133. package/dist/runtime/src/application/switch-topic-model.ts +79 -0
  134. package/dist/runtime/src/application/topic-service.ts +139 -0
  135. package/dist/runtime/src/application/vault-command.ts +170 -0
  136. package/dist/runtime/src/bus.ts +319 -0
  137. package/dist/runtime/src/index.ts +333 -0
  138. package/dist/runtime/src/mcp/agent-health-server.ts +309 -0
  139. package/dist/runtime/src/mcp/background-bash-server.ts +346 -0
  140. package/dist/runtime/src/mcp/canonical-bridge-config.ts +84 -0
  141. package/dist/runtime/src/mcp/canonical-proxy-server.ts +171 -0
  142. package/dist/runtime/src/mcp/dm-ipc.ts +60 -0
  143. package/dist/runtime/src/mcp/mcp-helpers.ts +40 -0
  144. package/dist/runtime/src/mcp/paddleocr-server.ts +105 -0
  145. package/dist/runtime/src/mcp/peer-bridge.ts +114 -0
  146. package/dist/runtime/src/mcp/runtime-spec.ts +134 -0
  147. package/dist/runtime/src/mcp/session-comm/bridge-ipc-config.ts +27 -0
  148. package/dist/runtime/src/mcp/session-comm/peer-forward.ts +165 -0
  149. package/dist/runtime/src/mcp/session-comm/runtime.ts +115 -0
  150. package/dist/runtime/src/mcp/session-comm/server.ts +649 -0
  151. package/dist/runtime/src/mcp/session-comm/topic-config.ts +131 -0
  152. package/dist/runtime/src/mcp/session-comm/topics.ts +229 -0
  153. package/dist/runtime/src/mcp/stdio-protect.ts +84 -0
  154. package/dist/runtime/src/mcp/system-health-server.ts +130 -0
  155. package/dist/runtime/src/mcp/task-server.ts +173 -0
  156. package/dist/runtime/src/mcp/token-stats-server.ts +98 -0
  157. package/dist/runtime/src/mcp/vault-http.ts +219 -0
  158. package/dist/runtime/src/mcp/vault-run.ts +153 -0
  159. package/dist/runtime/src/mcp/vault-server.ts +104 -0
  160. package/dist/runtime/src/mcp/wiki-server.ts +755 -0
  161. package/dist/runtime/src/media/file-events.ts +33 -0
  162. package/dist/runtime/src/media/text-extractor.ts +312 -0
  163. package/dist/runtime/src/media/video.ts +92 -0
  164. package/dist/runtime/src/outbox/file-ops.ts +210 -0
  165. package/dist/runtime/src/outbox/index.ts +8 -0
  166. package/dist/runtime/src/outbox/utils.ts +51 -0
  167. package/dist/runtime/src/platform/background-bash/manager.ts +279 -0
  168. package/dist/runtime/src/platform/config.ts +371 -0
  169. package/dist/runtime/src/platform/constants.ts +18 -0
  170. package/dist/runtime/src/platform/debug-users.ts +14 -0
  171. package/dist/runtime/src/platform/delay.ts +1 -0
  172. package/dist/runtime/src/platform/error.ts +9 -0
  173. package/dist/runtime/src/platform/file-utils.ts +16 -0
  174. package/dist/runtime/src/platform/jsonl.ts +202 -0
  175. package/dist/runtime/src/platform/lifecycle.ts +174 -0
  176. package/dist/runtime/src/platform/logger.ts +31 -0
  177. package/dist/runtime/src/platform/maestro-bootstrap-env.ts +3 -0
  178. package/dist/runtime/src/platform/mcp-config.ts +865 -0
  179. package/dist/runtime/src/platform/modules.ts +145 -0
  180. package/dist/runtime/src/platform/node-plugins.ts +46 -0
  181. package/dist/runtime/src/platform/playwright/manager.ts +1233 -0
  182. package/dist/runtime/src/prompts/agents/wiki-archiver.md +261 -0
  183. package/dist/runtime/src/prompts/builders.ts +357 -0
  184. package/dist/runtime/src/prompts/sessions/channel-system.md +48 -0
  185. package/dist/runtime/src/prompts/sessions/manager-system.md +37 -0
  186. package/dist/runtime/src/prompts/sessions/topic-system.md +47 -0
  187. package/dist/runtime/src/prompts/sessions/visual-design.md +86 -0
  188. package/dist/runtime/src/query/active-rooms.ts +532 -0
  189. package/dist/runtime/src/query/control.ts +313 -0
  190. package/dist/runtime/src/query/index.ts +24 -0
  191. package/dist/runtime/src/query/session-inbox-cleanup.ts +44 -0
  192. package/dist/runtime/src/query/session-inbox-path.ts +42 -0
  193. package/dist/runtime/src/query/state.ts +94 -0
  194. package/dist/runtime/src/query/types.ts +83 -0
  195. package/dist/runtime/src/runtime/ask-callbacks.ts +153 -0
  196. package/dist/runtime/src/runtime/attachments.ts +151 -0
  197. package/dist/runtime/src/runtime/background-sessions.ts +83 -0
  198. package/dist/runtime/src/runtime/channel-context.ts +107 -0
  199. package/dist/runtime/src/runtime/errors.ts +69 -0
  200. package/dist/runtime/src/runtime/event-heartbeat.ts +77 -0
  201. package/dist/runtime/src/runtime/file-hooks.ts +81 -0
  202. package/dist/runtime/src/runtime/footer.ts +23 -0
  203. package/dist/runtime/src/runtime/inbox.ts +946 -0
  204. package/dist/runtime/src/runtime/tasks.ts +56 -0
  205. package/dist/runtime/src/runtime/topic-config.ts +29 -0
  206. package/dist/runtime/src/runtime/turn-runner.ts +2286 -0
  207. package/dist/runtime/src/runtime/usage-alert.ts +84 -0
  208. package/dist/runtime/src/runtime/visual-html.ts +109 -0
  209. package/dist/runtime/src/runtime/visual-store.ts +430 -0
  210. package/dist/runtime/src/runtime/visuals.ts +171 -0
  211. package/dist/runtime/src/security/sanitize.ts +27 -0
  212. package/dist/runtime/src/security/sensitive-path.ts +34 -0
  213. package/dist/runtime/src/storage/activity-log.ts +152 -0
  214. package/dist/runtime/src/storage/api-messages.ts +617 -0
  215. package/dist/runtime/src/storage/api-topic-brief.ts +127 -0
  216. package/dist/runtime/src/storage/api-topic-config.ts +192 -0
  217. package/dist/runtime/src/storage/api-topics.ts +844 -0
  218. package/dist/runtime/src/storage/app-settings.ts +44 -0
  219. package/dist/runtime/src/storage/browser-profiles.ts +133 -0
  220. package/dist/runtime/src/storage/conversations.ts +268 -0
  221. package/dist/runtime/src/storage/forum/agent-settings.ts +20 -0
  222. package/dist/runtime/src/storage/forum/index.ts +4 -0
  223. package/dist/runtime/src/storage/forum/repository.ts +283 -0
  224. package/dist/runtime/src/storage/forum/schema.ts +300 -0
  225. package/dist/runtime/src/storage/forum-db.ts +23 -0
  226. package/dist/runtime/src/storage/runtime-events.ts +130 -0
  227. package/dist/runtime/src/storage/runtime-leases.ts +189 -0
  228. package/dist/runtime/src/storage/runtime-process-leases.ts +216 -0
  229. package/dist/runtime/src/storage/runtime-topic-state.ts +148 -0
  230. package/dist/runtime/src/storage/runtime-turn-requests.ts +300 -0
  231. package/dist/runtime/src/storage/self-schedules.ts +298 -0
  232. package/dist/runtime/src/storage/session-asks.ts +347 -0
  233. package/dist/runtime/src/storage/sqlite.ts +129 -0
  234. package/dist/runtime/src/storage/tasks.ts +179 -0
  235. package/dist/runtime/src/storage/token-stats.ts +144 -0
  236. package/dist/runtime/src/storage/topic-archive-state.ts +59 -0
  237. package/dist/runtime/src/storage/topic-archive.ts +74 -0
  238. package/dist/runtime/src/storage/topic-settings.ts +67 -0
  239. package/dist/runtime/src/storage/topic-transcript.ts +98 -0
  240. package/dist/runtime/src/storage/vault-crypto.ts +65 -0
  241. package/dist/runtime/src/storage/vault.ts +225 -0
  242. package/dist/runtime/src/storage/wiki-summary-names.ts +33 -0
  243. package/dist/runtime/src/storage/wiki.ts +85 -0
  244. package/dist/runtime/src/topics/create.ts +123 -0
  245. package/dist/runtime/src/topics/derive.ts +398 -0
  246. package/dist/runtime/src/topics/lifecycle.ts +311 -0
  247. package/dist/runtime/src/topics/links.ts +7 -0
  248. package/dist/runtime/src/topics/personal-general.ts +65 -0
  249. package/dist/runtime/src/topics/session.ts +381 -0
  250. package/dist/runtime/src/types/api.ts +497 -0
  251. package/dist/runtime/src/types.ts +255 -0
  252. package/dist/runtime/src/version.ts +1 -0
  253. package/dist/runtime/tsconfig.json +13 -0
  254. package/package.json +16 -3
  255. package/dist/main.d.ts +0 -3
  256. package/dist/main.d.ts.map +0 -1
@@ -0,0 +1,569 @@
1
+ // @bun
2
+ import {
3
+ cancelAskCallbacksForTopic
4
+ } from "./chunk-jc0at0tc.js";
5
+ import {
6
+ deletePendingAsksForTopic
7
+ } from "./chunk-sgsz2fpq.js";
8
+ import"./chunk-1k7t7bnx.js";
9
+ import {
10
+ archiveTopicMessages,
11
+ cancelIdleArchiveForTopic,
12
+ cancelRuntimeUserTurnRequests,
13
+ cancelRuntimeUserTurnRequestsBeforeEpoch,
14
+ cancelSubagentWatchForDeletedTopic,
15
+ clearQueryState,
16
+ clearQueryUsageAlert,
17
+ deleteFilesForTopic,
18
+ deleteTopicArchiveState,
19
+ deleteTopicBrief,
20
+ deleteTopicVisuals,
21
+ killBgBash,
22
+ runArchiverTurn
23
+ } from "./chunk-fgrme9tr.js";
24
+ import {
25
+ WsHub,
26
+ closeBrowserOwnerTabs,
27
+ delay,
28
+ deleteMessagesForTopic,
29
+ deleteTopicProfileDir,
30
+ getBrowserProfileOwner,
31
+ getTopicBrowserProfile
32
+ } from "./chunk-0ay6cjdy.js";
33
+ import {
34
+ GENERAL_TOPIC_ID,
35
+ deleteTopic,
36
+ getTopicMemoryOrigin,
37
+ getTopicSessionId,
38
+ listTopics,
39
+ reparentTopicChildren
40
+ } from "./chunk-xfq68rch.js";
41
+ import {
42
+ deleteApiTopicConfig
43
+ } from "./chunk-gmy11efb.js";
44
+ import {
45
+ TOPIC_MAINTENANCE_STALE_MS,
46
+ TURN_LEASE_STALE_MS,
47
+ abortRoom,
48
+ beginRuntimeTopicMaintenance,
49
+ getRoomQuery,
50
+ getRuntimeTurnLease,
51
+ interSessionQueue
52
+ } from "./chunk-t9zcg8f1.js";
53
+ import {
54
+ db
55
+ } from "./chunk-7xqj7aex.js";
56
+ import {
57
+ getRegistry
58
+ } from "./chunk-5ahkew9c.js";
59
+ import {
60
+ getConversationPath,
61
+ readConversation
62
+ } from "./chunk-6cpn7ht2.js";
63
+ import {
64
+ SESSION_INBOX_DIR,
65
+ SUPPORTED_AGENTS,
66
+ logger,
67
+ resolveTopicWorkspaceDir
68
+ } from "./chunk-k9z47mab.js";
69
+ import"./chunk-hwy3n31w.js";
70
+
71
+ // ../../packages/core/src/topics/lifecycle.ts
72
+ import { rmSync } from "fs";
73
+
74
+ // ../../packages/core/src/agents/topic-cleanup.ts
75
+ import { mkdirSync, renameSync, unlinkSync, writeFileSync } from "fs";
76
+ import { dirname } from "path";
77
+ function collectSessionIdsByAgent(entries, extraSessions = []) {
78
+ const out = new Map;
79
+ for (const e of entries) {
80
+ if (e.event.type !== "session")
81
+ continue;
82
+ const set = out.get(e.agent) ?? new Set;
83
+ set.add(e.event.sessionId);
84
+ out.set(e.agent, set);
85
+ }
86
+ for (const { agent, sessionId } of extraSessions) {
87
+ if (!sessionId)
88
+ continue;
89
+ const set = out.get(agent) ?? new Set;
90
+ set.add(sessionId);
91
+ out.set(agent, set);
92
+ }
93
+ return out;
94
+ }
95
+ async function cleanupSessionRollouts(opts, entries) {
96
+ const { userId, topicName, cwd, extraSessions = [] } = opts;
97
+ const idsByAgent = collectSessionIdsByAgent(entries, extraSessions);
98
+ let cleanupFailed = false;
99
+ await Promise.all(SUPPORTED_AGENTS.map(async (agent) => {
100
+ const ids = idsByAgent.get(agent);
101
+ if (!ids || ids.size === 0)
102
+ return;
103
+ try {
104
+ await getRegistry(agent).cleanupRollouts({
105
+ cwd,
106
+ sessionIds: Array.from(ids)
107
+ });
108
+ } catch (e) {
109
+ logger.warn({ err: e, userId, topicName, agent, count: ids.size }, "topic logs: agent cleanup failed");
110
+ cleanupFailed = true;
111
+ }
112
+ }));
113
+ return !cleanupFailed;
114
+ }
115
+ async function cleanupTopicRollouts(opts) {
116
+ return cleanupSessionRollouts(opts, readConversation(opts.userId, opts.topicName));
117
+ }
118
+ async function rotateTopicLogs(opts) {
119
+ const retainTurns = Math.max(0, Math.floor(opts.retainTurns));
120
+ const entries = readConversation(opts.userId, opts.topicName);
121
+ const userEntryIndexes = entries.flatMap((entry, index) => entry.event.type === "user_message" ? [index] : []);
122
+ const totalTurns = userEntryIndexes.length;
123
+ const firstRetainedIndex = retainTurns === 0 ? entries.length : userEntryIndexes[Math.max(0, totalTurns - retainTurns)] ?? 0;
124
+ const retained = entries.slice(firstRetainedIndex).filter((entry) => entry.event.type !== "session");
125
+ if (!await cleanupSessionRollouts(opts, entries)) {
126
+ logger.warn({ userId: opts.userId, topicName: opts.topicName }, "rotateTopicLogs: keeping current context because rollout cleanup failed");
127
+ return {
128
+ rotated: false,
129
+ totalTurns,
130
+ retainedTurns: Math.min(totalTurns, retainTurns),
131
+ retainedEntries: retained.length
132
+ };
133
+ }
134
+ const path = getConversationPath(opts.userId, opts.topicName);
135
+ const tempPath = `${path}.${process.pid}.${Date.now()}.tmp`;
136
+ try {
137
+ mkdirSync(dirname(path), { recursive: true });
138
+ writeFileSync(tempPath, retained.length > 0 ? `${retained.map((entry) => JSON.stringify(entry)).join(`
139
+ `)}
140
+ ` : "", { flag: "wx" });
141
+ renameSync(tempPath, path);
142
+ } catch (e) {
143
+ try {
144
+ unlinkSync(tempPath);
145
+ } catch {}
146
+ logger.warn({ err: e, path }, "rotateTopicLogs: conversation replacement failed");
147
+ return {
148
+ rotated: false,
149
+ totalTurns,
150
+ retainedTurns: Math.min(totalTurns, retainTurns),
151
+ retainedEntries: retained.length
152
+ };
153
+ }
154
+ return {
155
+ rotated: true,
156
+ totalTurns,
157
+ retainedTurns: Math.min(totalTurns, retainTurns),
158
+ retainedEntries: retained.length
159
+ };
160
+ }
161
+ async function purgeTopicLogs(opts) {
162
+ const { userId, topicName } = opts;
163
+ const entries = readConversation(userId, topicName);
164
+ if (!await cleanupSessionRollouts(opts, entries)) {
165
+ logger.warn({ userId, topicName }, "purgeTopicLogs: keeping unified log because one or more rollout cleanups failed");
166
+ return;
167
+ }
168
+ const path = getConversationPath(userId, topicName);
169
+ try {
170
+ unlinkSync(path);
171
+ } catch (e) {
172
+ if (e?.code !== "ENOENT") {
173
+ logger.warn({ err: e, path }, "purgeTopicLogs: unified log unlink failed");
174
+ }
175
+ }
176
+ }
177
+
178
+ // ../../packages/core/src/query/session-inbox-cleanup.ts
179
+ import { unlinkSync as unlinkSync2 } from "fs";
180
+ import { basename, join as join2 } from "path";
181
+
182
+ // ../../packages/core/src/query/session-inbox-path.ts
183
+ import { join } from "path";
184
+ var TOPIC_ID_FILE_PREFIX = "topic-id-";
185
+ var JSONL_SUFFIX = ".jsonl";
186
+ var SCHEDULE_SUFFIX = ".schedule";
187
+ function sessionInboxPath(userId, topicId) {
188
+ const key = Buffer.from(topicId, "utf8").toString("base64url");
189
+ return join(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${JSONL_SUFFIX}`);
190
+ }
191
+ function scheduledSessionInboxPath(userId, topicId) {
192
+ const key = Buffer.from(topicId, "utf8").toString("base64url");
193
+ return join(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${SCHEDULE_SUFFIX}`);
194
+ }
195
+ function decodeTopicIdFileName(fileName, suffix) {
196
+ if (!fileName.startsWith(TOPIC_ID_FILE_PREFIX) || !fileName.endsWith(suffix))
197
+ return null;
198
+ const encoded = fileName.slice(TOPIC_ID_FILE_PREFIX.length, -suffix.length);
199
+ if (!encoded || !/^[A-Za-z0-9_-]+$/.test(encoded))
200
+ return null;
201
+ try {
202
+ return Buffer.from(encoded, "base64url").toString("utf8") || null;
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ function topicIdFromSessionInboxFileName(fileName) {
208
+ return decodeTopicIdFileName(fileName, JSONL_SUFFIX);
209
+ }
210
+ function topicIdFromScheduledSessionInboxFileName(fileName) {
211
+ const base = fileName.endsWith(".processing") ? fileName.slice(0, -".processing".length) : fileName;
212
+ return decodeTopicIdFileName(base, SCHEDULE_SUFFIX);
213
+ }
214
+
215
+ // ../../packages/core/src/query/session-inbox-cleanup.ts
216
+ function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
217
+ const live = sessionInboxPath(userId, topicId);
218
+ const scheduled = scheduledSessionInboxPath(userId, topicId);
219
+ const candidates = new Set([live, `${live}.processing`, scheduled, `${scheduled}.processing`]);
220
+ if (legacyTopicTitle && legacyTopicTitle !== "." && legacyTopicTitle !== ".." && basename(legacyTopicTitle) === legacyTopicTitle) {
221
+ const legacyBase = join2(SESSION_INBOX_DIR, userId, legacyTopicTitle);
222
+ for (const suffix of [".jsonl", ".jsonl.processing", ".schedule", ".schedule.processing"]) {
223
+ candidates.add(`${legacyBase}${suffix}`);
224
+ }
225
+ }
226
+ let deleted = 0;
227
+ for (const path of candidates) {
228
+ try {
229
+ unlinkSync2(path);
230
+ deleted++;
231
+ } catch (err) {
232
+ if (err?.code !== "ENOENT") {
233
+ logger.warn({ err, path, topicId, userId }, "topic cleanup: inbox unlink failed");
234
+ }
235
+ }
236
+ }
237
+ return deleted;
238
+ }
239
+
240
+ // ../../packages/core/src/storage/self-schedules.ts
241
+ import { randomUUID } from "crypto";
242
+ db.exec(`
243
+ CREATE TABLE IF NOT EXISTS runtime_self_schedules (
244
+ id TEXT PRIMARY KEY,
245
+ topic_id TEXT NOT NULL,
246
+ user_id TEXT NOT NULL,
247
+ message TEXT NOT NULL,
248
+ deliver_at INTEGER NOT NULL,
249
+ created_at INTEGER NOT NULL,
250
+ updated_at INTEGER NOT NULL,
251
+ status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running')),
252
+ claimed_by TEXT,
253
+ claimed_at INTEGER,
254
+ running_query_id TEXT
255
+ )
256
+ `);
257
+ db.exec(`
258
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_runtime_self_schedules_one_pending
259
+ ON runtime_self_schedules(topic_id)
260
+ WHERE status = 'pending'
261
+ `);
262
+ db.exec(`
263
+ CREATE INDEX IF NOT EXISTS idx_runtime_self_schedules_due
264
+ ON runtime_self_schedules(status, deliver_at)
265
+ `);
266
+ function rowToSchedule(row) {
267
+ return {
268
+ id: row.id,
269
+ topicId: row.topic_id,
270
+ userId: row.user_id,
271
+ message: row.message,
272
+ deliverAt: Number(row.deliver_at),
273
+ createdAt: Number(row.created_at),
274
+ updatedAt: Number(row.updated_at),
275
+ status: row.status === "running" ? "running" : "pending",
276
+ claimedBy: row.claimed_by ?? undefined,
277
+ claimedAt: row.claimed_at === null ? undefined : Number(row.claimed_at),
278
+ runningQueryId: row.running_query_id ?? undefined
279
+ };
280
+ }
281
+ function createPendingSelfSchedule(input) {
282
+ return db.transaction(() => {
283
+ const existing = getPendingSelfSchedule(input.topicId);
284
+ if (existing)
285
+ return { ok: false, existing };
286
+ const now = input.now ?? Date.now();
287
+ const schedule = {
288
+ id: `scheduled-${randomUUID()}`,
289
+ topicId: input.topicId,
290
+ userId: input.userId,
291
+ message: input.message,
292
+ deliverAt: input.deliverAt,
293
+ createdAt: now,
294
+ updatedAt: now,
295
+ status: "pending"
296
+ };
297
+ db.query(`INSERT INTO runtime_self_schedules
298
+ (id, topic_id, user_id, message, deliver_at, created_at, updated_at, status)
299
+ VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')`).run(schedule.id, schedule.topicId, schedule.userId, schedule.message, schedule.deliverAt, schedule.createdAt, schedule.updatedAt);
300
+ return { ok: true, schedule };
301
+ }).immediate();
302
+ }
303
+ function getPendingSelfSchedule(topicId) {
304
+ const row = db.query("SELECT * FROM runtime_self_schedules WHERE topic_id = ? AND status = 'pending'").get(topicId);
305
+ return row ? rowToSchedule(row) : null;
306
+ }
307
+ function updatePendingSelfSchedule(input) {
308
+ const existing = getPendingSelfSchedule(input.topicId);
309
+ if (!existing || existing.id !== input.scheduleId)
310
+ return null;
311
+ const result = db.query(`UPDATE runtime_self_schedules
312
+ SET message = ?, deliver_at = ?, updated_at = ?
313
+ WHERE id = ? AND topic_id = ? AND status = 'pending'`).run(input.message ?? existing.message, input.deliverAt ?? existing.deliverAt, input.now ?? Date.now(), input.scheduleId, input.topicId);
314
+ return Number(result.changes ?? 0) > 0 ? getPendingSelfSchedule(input.topicId) : null;
315
+ }
316
+ function cancelPendingSelfSchedule(topicId, scheduleId) {
317
+ const result = db.query("DELETE FROM runtime_self_schedules WHERE id = ? AND topic_id = ? AND status = 'pending'").run(scheduleId, topicId);
318
+ return Number(result.changes ?? 0) > 0;
319
+ }
320
+ function claimNextDueSelfSchedule(ownerId, now = Date.now()) {
321
+ const staleBefore = now - TURN_LEASE_STALE_MS;
322
+ return db.transaction(() => {
323
+ const row = db.query(`SELECT s.*
324
+ FROM runtime_self_schedules s
325
+ LEFT JOIN runtime_turn_leases l ON l.topic_id = s.topic_id
326
+ LEFT JOIN runtime_topic_state t ON t.topic_id = s.topic_id
327
+ WHERE (l.topic_id IS NULL OR l.heartbeat_at < ?)
328
+ AND (t.topic_id IS NULL OR t.maintenance = 0 OR t.heartbeat_at < ?)
329
+ AND (
330
+ (s.status = 'pending' AND s.deliver_at <= ?)
331
+ OR (s.status = 'running' AND (s.claimed_at IS NULL OR s.claimed_at < ?))
332
+ )
333
+ ORDER BY CASE s.status WHEN 'running' THEN 0 ELSE 1 END, s.deliver_at ASC
334
+ LIMIT 1`).get(staleBefore, now - TOPIC_MAINTENANCE_STALE_MS, now, staleBefore);
335
+ if (!row)
336
+ return null;
337
+ const result = db.query(`UPDATE runtime_self_schedules
338
+ SET status = 'running', claimed_by = ?, claimed_at = ?, running_query_id = NULL
339
+ WHERE id = ? AND (
340
+ (status = 'pending' AND deliver_at <= ?)
341
+ OR (status = 'running' AND (claimed_at IS NULL OR claimed_at < ?))
342
+ )`).run(ownerId, now, row.id, now, staleBefore);
343
+ if (Number(result.changes ?? 0) === 0)
344
+ return null;
345
+ return rowToSchedule({
346
+ ...row,
347
+ status: "running",
348
+ claimed_by: ownerId,
349
+ claimed_at: now,
350
+ running_query_id: null
351
+ });
352
+ }).immediate();
353
+ }
354
+ function markSelfScheduleRunning(scheduleId, ownerId, queryId) {
355
+ const result = db.query(`UPDATE runtime_self_schedules
356
+ SET running_query_id = ?, claimed_at = ?
357
+ WHERE id = ? AND status = 'running' AND claimed_by = ?`).run(queryId, Date.now(), scheduleId, ownerId);
358
+ return Number(result.changes ?? 0) > 0;
359
+ }
360
+ function heartbeatSelfScheduleClaim(scheduleId, ownerId, now = Date.now()) {
361
+ const result = db.query(`UPDATE runtime_self_schedules
362
+ SET claimed_at = ?
363
+ WHERE id = ? AND status = 'running' AND claimed_by = ?`).run(now, scheduleId, ownerId);
364
+ return Number(result.changes ?? 0) > 0;
365
+ }
366
+ function releaseSelfScheduleClaim(scheduleId, ownerId) {
367
+ return db.transaction(() => {
368
+ const row = db.query("SELECT * FROM runtime_self_schedules WHERE id = ? AND status = 'running' AND claimed_by = ?").get(scheduleId, ownerId);
369
+ if (!row)
370
+ return "dropped";
371
+ const newer = getPendingSelfSchedule(row.topic_id);
372
+ if (newer) {
373
+ db.query("DELETE FROM runtime_self_schedules WHERE id = ?").run(scheduleId);
374
+ return "dropped";
375
+ }
376
+ db.query(`UPDATE runtime_self_schedules
377
+ SET status = 'pending', claimed_by = NULL, claimed_at = NULL,
378
+ running_query_id = NULL, updated_at = ?
379
+ WHERE id = ? AND claimed_by = ?`).run(Date.now(), scheduleId, ownerId);
380
+ return "released";
381
+ }).immediate();
382
+ }
383
+ function completeSelfSchedule(scheduleId, ownerId) {
384
+ const result = ownerId ? db.query("DELETE FROM runtime_self_schedules WHERE id = ? AND claimed_by = ?").run(scheduleId, ownerId) : db.query("DELETE FROM runtime_self_schedules WHERE id = ?").run(scheduleId);
385
+ return Number(result.changes ?? 0) > 0;
386
+ }
387
+ function deleteSelfSchedulesForTopic(topicId) {
388
+ const result = db.query("DELETE FROM runtime_self_schedules WHERE topic_id = ?").run(topicId);
389
+ return Number(result.changes ?? 0);
390
+ }
391
+
392
+ // ../../packages/core/src/topics/lifecycle.ts
393
+ var DELETE_TURN_WAIT_MS = 5000;
394
+ async function abortAndWaitForTopic(topicId) {
395
+ interSessionQueue.drop(topicId);
396
+ cancelIdleArchiveForTopic(topicId);
397
+ const aborted = abortRoom(topicId);
398
+ if (!aborted)
399
+ return true;
400
+ logger.info({ topicId }, "deleteTopicCascade: aborted in-flight turn");
401
+ const deadline = Date.now() + DELETE_TURN_WAIT_MS;
402
+ while ((getRoomQuery(topicId) || getRuntimeTurnLease(topicId)) && Date.now() < deadline) {
403
+ await delay(50);
404
+ }
405
+ if (getRoomQuery(topicId) || getRuntimeTurnLease(topicId)) {
406
+ logger.warn({ topicId, timeoutMs: DELETE_TURN_WAIT_MS }, "deleteTopicCascade: timed out waiting for in-flight turn cleanup");
407
+ return false;
408
+ }
409
+ return true;
410
+ }
411
+ function currentSessionRef(topic, sessionId) {
412
+ return topic.agent && sessionId ? [{ agent: topic.agent, sessionId }] : [];
413
+ }
414
+ async function cleanupParticipantResources(topic, userIds, sessionId, cwd) {
415
+ for (const [index, participantUserId] of userIds.entries()) {
416
+ try {
417
+ await purgeTopicLogs({
418
+ userId: participantUserId,
419
+ topicName: topic.title,
420
+ cwd,
421
+ extraSessions: index === 0 ? currentSessionRef(topic, sessionId) : []
422
+ });
423
+ } catch (err) {
424
+ logger.warn({ err, topicId: topic.id, userId: participantUserId }, "deleteTopicCascade: participant rollout cleanup failed");
425
+ }
426
+ cleanupSessionInboxFiles(participantUserId, topic.id, topic.title);
427
+ clearQueryState(participantUserId, topic.title);
428
+ clearQueryUsageAlert(participantUserId, topic.id);
429
+ deletePendingAsksForTopic({ userId: participantUserId, topicName: topic.title });
430
+ }
431
+ }
432
+
433
+ class TopicArchiveRequiredError extends Error {
434
+ code = "TOPIC_ARCHIVE_FAILED";
435
+ topicId;
436
+ constructor(topicId, cause) {
437
+ super("Topic archive failed; deletion was blocked to avoid losing conversation history.");
438
+ this.name = "TopicArchiveRequiredError";
439
+ this.topicId = topicId;
440
+ this.cause = cause;
441
+ }
442
+ }
443
+
444
+ class TopicTurnStillActiveError extends Error {
445
+ code = "TOPIC_TURN_STILL_ACTIVE";
446
+ topicId;
447
+ constructor(topicId) {
448
+ super("The active turn did not stop in time; deletion was blocked. Use force-delete explicitly.");
449
+ this.name = "TopicTurnStillActiveError";
450
+ this.topicId = topicId;
451
+ }
452
+ }
453
+ async function deleteTopicCascade(topic, userId, options = {}) {
454
+ await deleteTopicCascadeImpl(topic, userId, options, new Set);
455
+ }
456
+ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorIds) {
457
+ const topicId = topic.id;
458
+ if (topicId === GENERAL_TOPIC_ID || topic.kind === "manager" && !options.allowManager) {
459
+ logger.warn({ topicId }, "deleteTopicCascade: refused to delete essential topic");
460
+ return;
461
+ }
462
+ const deletingTopicIds = new Set(deletingAncestorIds);
463
+ deletingTopicIds.add(topicId);
464
+ const force = options.force === true;
465
+ const maintenance = beginRuntimeTopicMaintenance(topicId);
466
+ if (!maintenance)
467
+ throw new Error("Topic maintenance is already in progress.");
468
+ let deleted = false;
469
+ const cancelledQueryIds = cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, maintenance.epoch);
470
+ for (const queryId of cancelledQueryIds) {
471
+ WsHub.get().broadcastAborted(topicId, queryId, "stopped");
472
+ }
473
+ try {
474
+ const turnStopped = await abortAndWaitForTopic(topicId);
475
+ if (!turnStopped && !force)
476
+ throw new TopicTurnStillActiveError(topicId);
477
+ if (!maintenance.isOwned())
478
+ throw new Error("Topic maintenance ownership was lost.");
479
+ let archived = null;
480
+ if (!options.skipArchive) {
481
+ try {
482
+ archived = archiveTopicMessages(topicId, topic.title);
483
+ } catch (err) {
484
+ if (!force) {
485
+ logger.warn({ err, topicId }, "deleteTopicCascade: archive failed - blocking delete unless force=true");
486
+ throw new TopicArchiveRequiredError(topicId, err);
487
+ }
488
+ logger.warn({ err, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
489
+ }
490
+ }
491
+ if (archived) {
492
+ try {
493
+ const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
494
+ runArchiverTurn({
495
+ userId,
496
+ ...memoryTopic.id !== topicId && !deletingTopicIds.has(memoryTopic.id) ? { topicId: memoryTopic.id } : {},
497
+ topicTitle: memoryTopic.title,
498
+ archivePath: archived.path,
499
+ messageCount: archived.messageCount
500
+ });
501
+ } catch (err) {
502
+ logger.warn({ err, topicId, archive: archived.path }, "deleteTopicCascade: background archiver launch failed - raw archive preserved");
503
+ }
504
+ }
505
+ cancelSubagentWatchForDeletedTopic(topicId);
506
+ const spawnedChildren = listTopics().filter((candidate) => candidate.parentTopicId === topicId && candidate.isSubagent && !deletingTopicIds.has(candidate.id));
507
+ for (const child of spawnedChildren) {
508
+ await deleteTopicCascadeImpl(child, userId, options, deletingTopicIds);
509
+ }
510
+ const sessionId = getTopicSessionId(topicId);
511
+ const cwd = resolveTopicWorkspaceDir(topicId);
512
+ const participantUserIds = Array.from(new Set([userId, ...topic.participants.map((participant) => participant.userId)]));
513
+ killBgBash(userId, topicId);
514
+ const browserProfileOwner = getBrowserProfileOwner(topicId, userId);
515
+ const browserProfile = getTopicBrowserProfile(topicId);
516
+ try {
517
+ await closeBrowserOwnerTabs(browserProfileOwner, browserProfile, `topic:${topicId}`);
518
+ } catch (err) {
519
+ logger.warn({ err, topicId }, "deleteTopicCascade: browser owner cleanup failed");
520
+ }
521
+ deleteTopicProfileDir(userId, topicId);
522
+ cancelAskCallbacksForTopic(topicId);
523
+ deleteSelfSchedulesForTopic(topicId);
524
+ await cleanupParticipantResources(topic, participantUserIds, sessionId, cwd);
525
+ try {
526
+ await deleteFilesForTopic(topicId);
527
+ } catch (err) {
528
+ logger.warn({ err, topicId }, "deleteTopicCascade: host file cleanup failed");
529
+ }
530
+ try {
531
+ rmSync(cwd, { recursive: true, force: true });
532
+ } catch (err) {
533
+ logger.warn({ err, topicId, cwd }, "deleteTopicCascade: workspace cleanup failed");
534
+ }
535
+ deleteTopicVisuals(topicId);
536
+ deleteTopicArchiveState(topicId);
537
+ deleteMessagesForTopic(topicId);
538
+ deleteApiTopicConfig(topicId);
539
+ deleteTopicBrief(topicId);
540
+ const reparentedChildIds = reparentTopicChildren(topicId, topic.parentTopicId ?? null);
541
+ const rowDeleted = deleteTopic(topicId, { allowManager: options.allowManager });
542
+ if (!rowDeleted) {
543
+ logger.warn({ topicId }, "deleteTopicCascade: topic row was not deleted");
544
+ return;
545
+ }
546
+ deleted = true;
547
+ WsHub.get().broadcastTopicDeleted(topicId);
548
+ for (const childId of reparentedChildIds)
549
+ WsHub.get().broadcastTopicUpdated(childId);
550
+ } finally {
551
+ if (deleted) {
552
+ for (const queryId of cancelRuntimeUserTurnRequests(topicId)) {
553
+ WsHub.get().broadcastAborted(topicId, queryId, "stopped");
554
+ }
555
+ maintenance.finish({ deleteState: true });
556
+ } else {
557
+ maintenance.finish();
558
+ }
559
+ }
560
+ }
561
+ export {
562
+ deleteTopicCascade,
563
+ TopicTurnStillActiveError,
564
+ TopicArchiveRequiredError
565
+ };
566
+
567
+ export { createPendingSelfSchedule, getPendingSelfSchedule, updatePendingSelfSchedule, cancelPendingSelfSchedule, claimNextDueSelfSchedule, markSelfScheduleRunning, heartbeatSelfScheduleClaim, releaseSelfScheduleClaim, completeSelfSchedule, cleanupTopicRollouts, rotateTopicLogs, purgeTopicLogs, sessionInboxPath, topicIdFromSessionInboxFileName, topicIdFromScheduledSessionInboxFileName, TopicArchiveRequiredError, TopicTurnStillActiveError, deleteTopicCascade };
568
+
569
+ //# debugId=CD7A49E8BD3277ED64756E2164756E21