@supen-ai/cli 1.4.0 → 1.4.2

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 (205) hide show
  1. package/README.md +1 -1
  2. package/daemon/dist/agent-sdk/app-server-stream.js +5 -5
  3. package/daemon/dist/agent-sdk/app-server-stream.js.map +1 -1
  4. package/daemon/dist/agent-sdk/drivers/codex-app-server-driver.d.ts +3 -2
  5. package/daemon/dist/agent-sdk/drivers/codex-app-server-driver.d.ts.map +1 -1
  6. package/daemon/dist/agent-sdk/drivers/codex-app-server-driver.js +72 -49
  7. package/daemon/dist/agent-sdk/drivers/codex-app-server-driver.js.map +1 -1
  8. package/daemon/dist/agent-sdk/drivers/driver.d.ts +8 -8
  9. package/daemon/dist/agent-sdk/drivers/driver.d.ts.map +1 -1
  10. package/daemon/dist/agent-sdk/index.d.ts +4 -4
  11. package/daemon/dist/agent-sdk/index.d.ts.map +1 -1
  12. package/daemon/dist/agent-sdk/index.js +2 -2
  13. package/daemon/dist/agent-sdk/index.js.map +1 -1
  14. package/daemon/dist/agent-sdk/intelligence/contracts.d.ts +2 -2
  15. package/daemon/dist/agent-sdk/intelligence/contracts.d.ts.map +1 -1
  16. package/daemon/dist/agent-sdk/memory/subsystem.d.ts +1 -1
  17. package/daemon/dist/agent-sdk/memory/subsystem.d.ts.map +1 -1
  18. package/daemon/dist/agent-sdk/{session-events.d.ts → thread-events.d.ts} +18 -18
  19. package/daemon/dist/agent-sdk/thread-events.d.ts.map +1 -0
  20. package/daemon/dist/agent-sdk/{session-events.js → thread-events.js} +15 -15
  21. package/daemon/dist/agent-sdk/thread-events.js.map +1 -0
  22. package/daemon/dist/agent-sdk/{session-manager.d.ts → thread-manager.d.ts} +9 -9
  23. package/daemon/dist/agent-sdk/thread-manager.d.ts.map +1 -0
  24. package/daemon/dist/agent-sdk/{session-manager.js → thread-manager.js} +7 -7
  25. package/daemon/dist/agent-sdk/thread-manager.js.map +1 -0
  26. package/daemon/dist/agent-sdk/types.d.ts +18 -18
  27. package/daemon/dist/agent-sdk/types.d.ts.map +1 -1
  28. package/daemon/dist/automation-event-listener.js +6 -6
  29. package/daemon/dist/automation-event-listener.js.map +1 -1
  30. package/daemon/dist/automation-runner.d.ts +1 -1
  31. package/daemon/dist/automation-runner.d.ts.map +1 -1
  32. package/daemon/dist/automation-runner.js +24 -24
  33. package/daemon/dist/automation-runner.js.map +1 -1
  34. package/daemon/dist/autonomy/memory-rules.d.ts +2 -2
  35. package/daemon/dist/autonomy/memory-rules.d.ts.map +1 -1
  36. package/daemon/dist/autonomy/memory-rules.js +1 -1
  37. package/daemon/dist/autonomy/memory-rules.js.map +1 -1
  38. package/daemon/dist/autonomy/session-autonomy.d.ts +4 -4
  39. package/daemon/dist/autonomy/session-autonomy.d.ts.map +1 -1
  40. package/daemon/dist/autonomy/session-autonomy.js +5 -5
  41. package/daemon/dist/autonomy/session-autonomy.js.map +1 -1
  42. package/daemon/dist/bin/mcp-os.js +1 -1
  43. package/daemon/dist/bin/mcp-os.js.map +1 -1
  44. package/daemon/dist/bin/mcp-scheduler.js +1 -1
  45. package/daemon/dist/bin/mcp-scheduler.js.map +1 -1
  46. package/daemon/dist/bin/supen-sys.js +1 -1
  47. package/daemon/dist/bin/supen-sys.js.map +1 -1
  48. package/daemon/dist/bootstrap/hub-bootstrap.js +1 -1
  49. package/daemon/dist/bootstrap/hub-bootstrap.js.map +1 -1
  50. package/daemon/dist/channels/http-routes.d.ts.map +1 -1
  51. package/daemon/dist/channels/http-routes.js +54 -60
  52. package/daemon/dist/channels/http-routes.js.map +1 -1
  53. package/daemon/dist/channels/http.js +2 -2
  54. package/daemon/dist/channels/http.js.map +1 -1
  55. package/daemon/dist/channels/index.d.ts +0 -1
  56. package/daemon/dist/channels/index.d.ts.map +1 -1
  57. package/daemon/dist/channels/index.js +0 -2
  58. package/daemon/dist/channels/index.js.map +1 -1
  59. package/daemon/dist/channels/registry.d.ts +1 -1
  60. package/daemon/dist/channels/registry.d.ts.map +1 -1
  61. package/daemon/dist/commands/builtin.d.ts +1 -1
  62. package/daemon/dist/commands/builtin.d.ts.map +1 -1
  63. package/daemon/dist/commands/builtin.js +2 -2
  64. package/daemon/dist/commands/builtin.js.map +1 -1
  65. package/daemon/dist/commands/catalog.js +3 -3
  66. package/daemon/dist/commands/catalog.js.map +1 -1
  67. package/daemon/dist/core/config.d.ts +0 -2
  68. package/daemon/dist/core/config.d.ts.map +1 -1
  69. package/daemon/dist/core/config.js +0 -5
  70. package/daemon/dist/core/config.js.map +1 -1
  71. package/daemon/dist/core/control-commands.d.ts +3 -3
  72. package/daemon/dist/core/control-commands.d.ts.map +1 -1
  73. package/daemon/dist/core/control-commands.js +6 -6
  74. package/daemon/dist/core/control-commands.js.map +1 -1
  75. package/daemon/dist/core/control-log.d.ts +4 -4
  76. package/daemon/dist/core/control-log.d.ts.map +1 -1
  77. package/daemon/dist/core/control-log.js +12 -12
  78. package/daemon/dist/core/control-log.js.map +1 -1
  79. package/daemon/dist/core/cortex.d.ts +4 -4
  80. package/daemon/dist/core/cortex.d.ts.map +1 -1
  81. package/daemon/dist/core/cortex.js +98 -117
  82. package/daemon/dist/core/cortex.js.map +1 -1
  83. package/daemon/dist/core/dispatcher.d.ts +3 -3
  84. package/daemon/dist/core/dispatcher.js +18 -18
  85. package/daemon/dist/core/dispatcher.js.map +1 -1
  86. package/daemon/dist/core/gateway-protocol.d.ts +0 -1
  87. package/daemon/dist/core/gateway-protocol.d.ts.map +1 -1
  88. package/daemon/dist/core/gateway.d.ts +3 -3
  89. package/daemon/dist/core/gateway.d.ts.map +1 -1
  90. package/daemon/dist/core/gateway.js +26 -26
  91. package/daemon/dist/core/gateway.js.map +1 -1
  92. package/daemon/dist/core/hub-snapshot.d.ts +1 -1
  93. package/daemon/dist/core/hub-snapshot.d.ts.map +1 -1
  94. package/daemon/dist/core/hub-snapshot.js +1 -1
  95. package/daemon/dist/core/hub-snapshot.js.map +1 -1
  96. package/daemon/dist/core/pairing.d.ts +2 -2
  97. package/daemon/dist/core/pairing.js +3 -3
  98. package/daemon/dist/core/pairing.js.map +1 -1
  99. package/daemon/dist/core/store.d.ts +38 -38
  100. package/daemon/dist/core/store.d.ts.map +1 -1
  101. package/daemon/dist/core/store.js +285 -289
  102. package/daemon/dist/core/store.js.map +1 -1
  103. package/daemon/dist/core/task-artifacts.d.ts +4 -4
  104. package/daemon/dist/core/task-artifacts.d.ts.map +1 -1
  105. package/daemon/dist/core/task-artifacts.js +10 -10
  106. package/daemon/dist/core/task-artifacts.js.map +1 -1
  107. package/daemon/dist/core/thread-context.d.ts +76 -0
  108. package/daemon/dist/core/thread-context.d.ts.map +1 -0
  109. package/daemon/dist/core/thread-context.js +308 -0
  110. package/daemon/dist/core/thread-context.js.map +1 -0
  111. package/daemon/dist/core/types.d.ts +28 -28
  112. package/daemon/dist/core/types.d.ts.map +1 -1
  113. package/daemon/dist/core/utils.js +1 -1
  114. package/daemon/dist/core/utils.js.map +1 -1
  115. package/daemon/dist/http/router.d.ts +2 -2
  116. package/daemon/dist/http/router.d.ts.map +1 -1
  117. package/daemon/dist/http/router.js +5 -5
  118. package/daemon/dist/http/router.js.map +1 -1
  119. package/daemon/dist/http/routes/agents.js +3 -3
  120. package/daemon/dist/http/routes/agents.js.map +1 -1
  121. package/daemon/dist/http/routes/automations.d.ts +2 -2
  122. package/daemon/dist/http/routes/automations.d.ts.map +1 -1
  123. package/daemon/dist/http/routes/automations.js +23 -23
  124. package/daemon/dist/http/routes/automations.js.map +1 -1
  125. package/daemon/dist/http/routes/chat-input.d.ts +1 -1
  126. package/daemon/dist/http/routes/chat-input.d.ts.map +1 -1
  127. package/daemon/dist/http/routes/chat-input.js +2 -2
  128. package/daemon/dist/http/routes/chat-input.js.map +1 -1
  129. package/daemon/dist/http/routes/plugins.d.ts.map +1 -1
  130. package/daemon/dist/http/routes/plugins.js +6 -74
  131. package/daemon/dist/http/routes/plugins.js.map +1 -1
  132. package/daemon/dist/http/routes/rpc.d.ts +3 -3
  133. package/daemon/dist/http/routes/rpc.d.ts.map +1 -1
  134. package/daemon/dist/http/routes/rpc.js +93 -92
  135. package/daemon/dist/http/routes/rpc.js.map +1 -1
  136. package/daemon/dist/http/routes/system.d.ts +8 -7
  137. package/daemon/dist/http/routes/system.d.ts.map +1 -1
  138. package/daemon/dist/http/routes/system.js +225 -111
  139. package/daemon/dist/http/routes/system.js.map +1 -1
  140. package/daemon/dist/http/routes/threads.d.ts +11 -0
  141. package/daemon/dist/http/routes/threads.d.ts.map +1 -0
  142. package/daemon/dist/http/routes/{sessions.js → threads.js} +158 -158
  143. package/daemon/dist/http/routes/threads.js.map +1 -0
  144. package/daemon/dist/http/stream.d.ts +2 -2
  145. package/daemon/dist/http/stream.d.ts.map +1 -1
  146. package/daemon/dist/http/stream.js +3 -3
  147. package/daemon/dist/http/stream.js.map +1 -1
  148. package/daemon/dist/http/thread-title.d.ts +1 -1
  149. package/daemon/dist/http/thread-title.d.ts.map +1 -1
  150. package/daemon/dist/http/thread-title.js +6 -6
  151. package/daemon/dist/http/thread-title.js.map +1 -1
  152. package/daemon/dist/http/websocket.d.ts +2 -2
  153. package/daemon/dist/http/websocket.d.ts.map +1 -1
  154. package/daemon/dist/http/websocket.js +11 -11
  155. package/daemon/dist/http/websocket.js.map +1 -1
  156. package/daemon/dist/index.d.ts +3 -3
  157. package/daemon/dist/index.d.ts.map +1 -1
  158. package/daemon/dist/index.js +65 -81
  159. package/daemon/dist/index.js.map +1 -1
  160. package/daemon/dist/mcp/aggregate-config.d.ts +1 -1
  161. package/daemon/dist/mcp/index.js +1 -1
  162. package/daemon/dist/mcp/index.js.map +1 -1
  163. package/daemon/dist/mcp/tools.d.ts +1 -1
  164. package/daemon/dist/mcp/tools.js +1 -1
  165. package/daemon/dist/plugins/hub.d.ts +2 -8
  166. package/daemon/dist/plugins/hub.d.ts.map +1 -1
  167. package/daemon/dist/plugins/hub.js +63 -214
  168. package/daemon/dist/plugins/hub.js.map +1 -1
  169. package/daemon/dist/plugins/types.d.ts +10 -0
  170. package/daemon/dist/plugins/types.d.ts.map +1 -1
  171. package/daemon/dist/sub-agent.d.ts +3 -3
  172. package/daemon/dist/sub-agent.d.ts.map +1 -1
  173. package/daemon/dist/sub-agent.js +8 -8
  174. package/daemon/dist/sub-agent.js.map +1 -1
  175. package/daemon/dist/sync/supabase-sync.js +18 -18
  176. package/daemon/dist/sync/supabase-sync.js.map +1 -1
  177. package/daemon/dist/task-executor.js +1 -1
  178. package/daemon/dist/task-executor.js.map +1 -1
  179. package/daemon/dist/tools/shell.js +1 -1
  180. package/daemon/dist/tools/shell.js.map +1 -1
  181. package/daemon/dist/tools/types.d.ts +1 -1
  182. package/daemon/dist/tools/types.d.ts.map +1 -1
  183. package/daemon/package.json +1 -1
  184. package/dist/computer.js +1 -1
  185. package/dist/index.js +1 -1
  186. package/package.json +1 -1
  187. package/daemon/dist/acp-client.d.ts +0 -42
  188. package/daemon/dist/acp-client.d.ts.map +0 -1
  189. package/daemon/dist/acp-client.js +0 -149
  190. package/daemon/dist/acp-client.js.map +0 -1
  191. package/daemon/dist/acp-types.d.ts +0 -98
  192. package/daemon/dist/acp-types.d.ts.map +0 -1
  193. package/daemon/dist/acp-types.js +0 -2
  194. package/daemon/dist/acp-types.js.map +0 -1
  195. package/daemon/dist/agent-sdk/session-events.d.ts.map +0 -1
  196. package/daemon/dist/agent-sdk/session-events.js.map +0 -1
  197. package/daemon/dist/agent-sdk/session-manager.d.ts.map +0 -1
  198. package/daemon/dist/agent-sdk/session-manager.js.map +0 -1
  199. package/daemon/dist/channels/acp.d.ts +0 -23
  200. package/daemon/dist/channels/acp.d.ts.map +0 -1
  201. package/daemon/dist/channels/acp.js +0 -915
  202. package/daemon/dist/channels/acp.js.map +0 -1
  203. package/daemon/dist/http/routes/sessions.d.ts +0 -11
  204. package/daemon/dist/http/routes/sessions.d.ts.map +0 -1
  205. package/daemon/dist/http/routes/sessions.js.map +0 -1
@@ -4,7 +4,7 @@ import { CODEX_TRUSTED_DATA_HOSTS, ASSISTANT_NAME, SUPEN_HOME, POLL_INTERVAL, TR
4
4
  import './channels/index.js';
5
5
  import { SkillHub } from './skills/hub.js';
6
6
  import { getChannelFactory, getRegisteredChannelNames, } from './channels/registry.js';
7
- import { ensureSession, getAllChats, getAllRegisteredProjects, getAllSessions, getMessagesSince, getNewMessages, getRouterState, getSessionForAgent, initStore, cleanupStaleSessions, cleanupStaleAutomationExecutions, touchAutomationRun, updateSessionStatus, setRegisteredProject, setRouterState, storeChatMetadata, storeMessage, storeSessionUiEvent, resolveFromChatJid, } from './core/store.js';
7
+ import { ensureThread, getAllChats, getAllRegisteredProjects, getAllThreads, getMessagesSince, getNewMessages, getRouterState, getThreadForAgent, initStore, cleanupStaleThreads, cleanupStaleAutomationExecutions, touchAutomationRun, updateThreadStatus, setRegisteredProject, setRouterState, storeChatMetadata, storeMessage, storeThreadUiEvent, resolveFromChatJid, } from './core/store.js';
8
8
  import { logger } from './core/logger.js';
9
9
  import { readEnrollmentState, verifyEnrollmentToken, } from './core/enrollment.js';
10
10
  import { routeOutbound, routeOutboundFile, routeSetTyping, routeEditMessage, } from './router.js';
@@ -23,6 +23,7 @@ import { listCommands, resolveCommandInput } from './commands/catalog.js';
23
23
  import { findLatestInterruptIndex, trimMessagesAfterInterrupt, } from './core/interrupts.js';
24
24
  import { isSupabaseConfigured, pullFromSupabase, scheduleSupabasePush, startPeriodicSupabasePush, } from './sync/supabase-sync.js';
25
25
  import { appendStreamChunk, createStreamState, } from './core/streaming.js';
26
+ import { attachThreadContextToChunk, readThreadContext, } from './core/thread-context.js';
26
27
  const DEFAULT_AUTOMATION_TASK_TIMEOUT_MS = 12 * 60 * 1000;
27
28
  function automationTaskTimeoutMs() {
28
29
  const raw = process.env.SUPEN_AUTOMATION_TASK_TIMEOUT_MS;
@@ -33,40 +34,23 @@ function automationTaskTimeoutMs() {
33
34
  return DEFAULT_AUTOMATION_TASK_TIMEOUT_MS;
34
35
  return parsed;
35
36
  }
36
- import { appendThreadEvent } from './core/thread-event-log.js';
37
37
  import { parseProgressEvent, formatProgressText, progressKeyFromEvent } from './core/progress.js';
38
38
  import { buildAssistantOutputExcerpt, buildObservableToolDetail, buildProgressDetail, buildTaskContextExcerpt, canonicalAutomationLogFields, classifyObservableLogEvent, excerptText, } from './core/observable-logging.js';
39
39
  // Global state
40
40
  let registeredProjects = {};
41
- const sessions = {}; // folder -> sessionId
41
+ const threads = {}; // folder -> threadId
42
42
  const lastAgentTimestamp = {}; // chatJid -> iso
43
43
  const channels = [];
44
44
  const activeDaemons = new Map();
45
45
  export function captureCodexStreamPayload(input) {
46
- let sequence;
46
+ let payload = input.payload;
47
47
  try {
48
- const event = appendThreadEvent({
49
- threadId: input.threadId,
50
- runtimeThreadId: input.runtimeThreadId || input.threadId,
51
- source: 'codex-app-server',
52
- eventType: typeof input.payload.type === 'string'
53
- ? input.payload.type
54
- : typeof input.payload.method === 'string'
55
- ? input.payload.method
56
- : 'codex-event',
57
- rawPayload: input.payload,
58
- });
59
- sequence = event.sequence;
48
+ payload = attachThreadContextToChunk(input.payload, readThreadContext({ threadId: input.threadId }));
60
49
  }
61
50
  catch (error) {
62
- logger.warn({
63
- err: error,
64
- agentId: input.agentId,
65
- threadId: input.threadId,
66
- runtimeThreadId: input.runtimeThreadId || input.threadId,
67
- }, 'Failed to capture Codex stream payload');
51
+ logger.debug({ err: error, agentId: input.agentId, threadId: input.threadId }, 'Skipped Codex stream context attachment');
68
52
  }
69
- broadcastToThread(input.threadId, input.payload, sequence === undefined ? {} : { id: sequence });
53
+ broadcastToThread(input.threadId, payload);
70
54
  }
71
55
  function appServerChunk(method, params = {}) {
72
56
  return {
@@ -124,24 +108,24 @@ const activeAgentLocks = new Map();
124
108
  // Pending-run flags: if a second message arrives while the lock is held,
125
109
  // set the flag so the run drains immediately after the current one finishes.
126
110
  const pendingRuns = new Set();
127
- function requestSessionStop(agentId, sessionId, actor = 'unknown') {
128
- const session = getSessionForAgent(agentId, sessionId);
129
- const chatJid = session?.source_ref?.trim() || `web:${agentId}:${sessionId}`;
111
+ function requestThreadStop(agentId, threadId, actor = 'unknown') {
112
+ const thread = getThreadForAgent(agentId, threadId);
113
+ const chatJid = thread?.source_ref?.trim() || `web:${agentId}:${threadId}`;
130
114
  const daemon = activeDaemons.get(chatJid);
131
115
  if (!daemon) {
132
116
  return {
133
117
  ok: false,
134
- code: 'session_not_running',
135
- message: `Task "${sessionId}" is not currently running.`,
118
+ code: 'thread_not_running',
119
+ message: `Task "${threadId}" is not currently running.`,
136
120
  chatJid,
137
121
  };
138
122
  }
139
- logger.info({ agentId, sessionId, chatJid, actor }, 'Stop requested for active session');
123
+ logger.info({ agentId, threadId, chatJid, actor }, 'Stop requested for active thread');
140
124
  daemon.interrupt();
141
125
  return {
142
126
  ok: true,
143
127
  code: 'stop_requested',
144
- message: `Stop requested for session "${sessionId}".`,
128
+ message: `Stop requested for thread "${threadId}".`,
145
129
  chatJid,
146
130
  };
147
131
  }
@@ -195,7 +179,7 @@ async function runAndDrain(chatJid) {
195
179
  }
196
180
  }
197
181
  }
198
- export function resolveSessionChannel(chatJid, existingChannel) {
182
+ export function resolveThreadChannel(chatJid, existingChannel) {
199
183
  if (chatJid.startsWith('dc:'))
200
184
  return 'discord';
201
185
  if (chatJid.startsWith('web:'))
@@ -211,14 +195,14 @@ export function resolveSessionChannel(chatJid, existingChannel) {
211
195
  }
212
196
  return existingChannel || chatJid.split(':')[0] || 'unknown';
213
197
  }
214
- export function resolveStoredSessionChannel(chatJid) {
198
+ export function resolveStoredThreadChannel(chatJid) {
215
199
  const resolved = resolveFromChatJid(chatJid);
216
200
  if (!resolved)
217
201
  return undefined;
218
- return getSessionForAgent(resolved.agentId, resolved.sessionId)?.channel;
202
+ return getThreadForAgent(resolved.agentId, resolved.threadId)?.channel;
219
203
  }
220
204
  export function resolveRoutingChannel(chatJid) {
221
- return resolveSessionChannel(chatJid, resolveStoredSessionChannel(chatJid));
205
+ return resolveThreadChannel(chatJid, resolveStoredThreadChannel(chatJid));
222
206
  }
223
207
  async function processMessages(chatJid) {
224
208
  let group = registeredProjects[chatJid];
@@ -233,32 +217,32 @@ async function processMessages(chatJid) {
233
217
  isMain: false,
234
218
  };
235
219
  }
236
- // Resolve or create a session for this chat so directories exist.
237
- // IMPORTANT: always resolve agentId + sessionId from the JID — never use
238
- // chatJid itself as session_id, or the full JID gets stored and re-prefixed
220
+ // Resolve or create a thread for this chat so directories exist.
221
+ // IMPORTANT: always resolve agentId + threadId from the JID — never use
222
+ // chatJid itself as thread_id, or the full JID gets stored and re-prefixed
239
223
  // on every subsequent call, making the key grow indefinitely.
240
224
  let agentId = group.agent_id || group.folder;
241
- let sessionId;
225
+ let threadId;
242
226
  const resolved = resolveFromChatJid(chatJid);
243
227
  if (resolved) {
244
228
  agentId = resolved.agentId;
245
- sessionId = resolved.sessionId;
229
+ threadId = resolved.threadId;
246
230
  }
247
231
  else {
248
232
  // Fallback for unrecognised JID formats: split on ':' and use last segment
249
233
  const parts = chatJid.split(':');
250
- sessionId = parts.length >= 2 ? parts.slice(1).join(':') : chatJid;
234
+ threadId = parts.length >= 2 ? parts.slice(1).join(':') : chatJid;
251
235
  if (agentId === 'unknown' && parts.length >= 2) {
252
236
  agentId = parts[1];
253
237
  }
254
238
  }
255
- const existingSession = getSessionForAgent(agentId, sessionId);
256
- const channel = existingSession
257
- ? resolveSessionChannel(chatJid, existingSession.channel)
239
+ const existingThread = getThreadForAgent(agentId, threadId);
240
+ const channel = existingThread
241
+ ? resolveThreadChannel(chatJid, existingThread.channel)
258
242
  : resolveRoutingChannel(chatJid);
259
- const session = ensureSession({
243
+ const thread = ensureThread({
260
244
  agent_id: agentId,
261
- session_id: sessionId,
245
+ thread_id: threadId,
262
246
  channel,
263
247
  agent_name: group.name,
264
248
  source_ref: chatJid,
@@ -354,7 +338,7 @@ async function processMessages(chatJid) {
354
338
  const portableBuiltinReply = await executePortableBuiltinCommand(resolvedSlashCommand.text, {
355
339
  channel: routingChannel,
356
340
  agentId,
357
- sessionId,
341
+ threadId,
358
342
  actor: latestMsg?.sender || chatJid,
359
343
  isAdmin: isAdminActor(latestMsg?.sender || chatJid),
360
344
  });
@@ -375,7 +359,7 @@ async function processMessages(chatJid) {
375
359
  }
376
360
  // Check if we have a valid workspace for this group
377
361
  // (group is guaranteed to be set now because of our fallback logic at the top)
378
- const workspace = session.task_workspace_folder || getFactoryPath(group);
362
+ const workspace = thread.task_workspace_folder || getFactoryPath(group);
379
363
  const hasWorkspace = fs.existsSync(workspace);
380
364
  logger.info({ chatJid, workspace, hasWorkspace }, 'processMessages: workspace check');
381
365
  const automationMessage = [...runnableMessages]
@@ -571,16 +555,16 @@ async function processMessages(chatJid) {
571
555
  latestMsg?.id ||
572
556
  taskId;
573
557
  const streamState = createStreamState(`${chatJid}:${turnId}`);
574
- const isAdoptedCodexAppServerSession = chatJid.startsWith('web:') && session.backend_driver_id === 'codex-app-server';
575
- const mirroredThreadId = isAdoptedCodexAppServerSession ? session.session_id : taskId;
576
- const shouldMirrorTaskThread = Boolean(mirroredThreadId) && (chatJid.startsWith('task:') || isAdoptedCodexAppServerSession);
558
+ const isAdoptedCodexAppServerThread = chatJid.startsWith('web:') && thread.backend_driver_id === 'codex-app-server';
559
+ const mirroredThreadId = isAdoptedCodexAppServerThread ? thread.thread_id : taskId;
560
+ const shouldMirrorTaskThread = Boolean(mirroredThreadId) && (chatJid.startsWith('task:') || isAdoptedCodexAppServerThread);
577
561
  const mirrorTaskThreadChunk = (payload) => {
578
562
  if (!shouldMirrorTaskThread)
579
563
  return;
580
564
  captureCodexStreamPayload({
581
565
  agentId,
582
566
  threadId: mirroredThreadId,
583
- runtimeThreadId: session.session_id,
567
+ runtimeThreadId: thread.thread_id,
584
568
  payload,
585
569
  });
586
570
  };
@@ -683,7 +667,7 @@ async function processMessages(chatJid) {
683
667
  try {
684
668
  await completeAutomationRun({
685
669
  sendMessage: (jid, notification) => sendFn(jid, notification),
686
- ensureNotificationSessionExists,
670
+ ensureNotificationThreadExists,
687
671
  }, automationMessage, chatJid, outcome, detail);
688
672
  }
689
673
  catch (completeError) {
@@ -697,7 +681,7 @@ async function processMessages(chatJid) {
697
681
  if (useGatewayChannelReplyLifecycle) {
698
682
  await ensureChannelReplyHandle('Thinking...');
699
683
  }
700
- // Get MCP manager for this session
684
+ // Get MCP manager for this thread
701
685
  let mcpManager;
702
686
  try {
703
687
  mcpManager = await getMcpManager();
@@ -705,7 +689,7 @@ async function processMessages(chatJid) {
705
689
  catch (err) {
706
690
  logger.warn({ err }, 'Failed to get MCP manager, continuing without MCP');
707
691
  }
708
- const daemon = new AgentCortex(agentId, { ...session, task_id: taskId }.session_id, {
692
+ const daemon = new AgentCortex(agentId, { ...thread, task_id: taskId }.thread_id, {
709
693
  mcpManager,
710
694
  onStateChange: async (state) => {
711
695
  const eventData = {
@@ -726,7 +710,7 @@ async function processMessages(chatJid) {
726
710
  ? 'idle'
727
711
  : 'active';
728
712
  mirrorTaskThreadChunk(appServerChunk('thread/status/changed', {
729
- threadId: session.session_id,
713
+ threadId: thread.thread_id,
730
714
  status: { type: statusType },
731
715
  }));
732
716
  }
@@ -826,11 +810,11 @@ async function processMessages(chatJid) {
826
810
  id: streamState.streamId,
827
811
  });
828
812
  mirrorTaskThreadChunk(appServerChunk('turn/completed', {
829
- threadId: session.session_id,
813
+ threadId: thread.thread_id,
830
814
  turnId,
831
815
  turn: { id: turnId, status: 'completed' },
832
816
  }));
833
- updateSessionStatus(agentId, sessionId, 'idle');
817
+ updateThreadStatus(agentId, threadId, 'idle');
834
818
  }
835
819
  // Finalize streaming: emit stream_end so consumers
836
820
  // know the streaming phase is complete.
@@ -972,12 +956,12 @@ async function processMessages(chatJid) {
972
956
  id: streamState.streamId,
973
957
  });
974
958
  mirrorTaskThreadChunk(appServerChunk('turn/failed', {
975
- threadId: session.session_id,
959
+ threadId: thread.thread_id,
976
960
  turnId,
977
961
  turn: { id: turnId, status: 'failed' },
978
962
  error: { message: error?.message || text },
979
963
  }));
980
- updateSessionStatus(agentId, sessionId, 'error');
964
+ updateThreadStatus(agentId, threadId, 'error');
981
965
  }
982
966
  if (!isAutomationMessage && chatJid.startsWith('web:') && streamState.nextSeq > 1) {
983
967
  broadcastToChat(chatJid, {
@@ -1026,13 +1010,13 @@ async function processMessages(chatJid) {
1026
1010
  activeDaemons.set(chatJid, daemon);
1027
1011
  try {
1028
1012
  if (shouldMirrorTaskThread) {
1029
- updateSessionStatus(agentId, sessionId, 'running');
1013
+ updateThreadStatus(agentId, threadId, 'running');
1030
1014
  mirrorTaskThreadChunk({
1031
1015
  type: 'start',
1032
1016
  messageId: streamState.streamId,
1033
1017
  });
1034
1018
  mirrorTaskThreadChunk(appServerChunk('turn/started', {
1035
- threadId: session.session_id,
1019
+ threadId: thread.thread_id,
1036
1020
  turnId,
1037
1021
  turn: { id: turnId, status: 'running' },
1038
1022
  }));
@@ -1112,8 +1096,8 @@ async function processMessages(chatJid) {
1112
1096
  const parsedPayload = JSON.parse(payload);
1113
1097
  captureCodexStreamPayload({
1114
1098
  agentId,
1115
- threadId: sessionId,
1116
- runtimeThreadId: session.session_id,
1099
+ threadId: threadId,
1100
+ runtimeThreadId: thread.thread_id,
1117
1101
  payload: parsedPayload,
1118
1102
  });
1119
1103
  broadcastToChat(chatJid, parsedPayload);
@@ -1131,8 +1115,8 @@ async function processMessages(chatJid) {
1131
1115
  const parsedPayload = JSON.parse(payload);
1132
1116
  captureCodexStreamPayload({
1133
1117
  agentId,
1134
- threadId: sessionId,
1135
- runtimeThreadId: session.session_id,
1118
+ threadId: threadId,
1119
+ runtimeThreadId: thread.thread_id,
1136
1120
  payload: parsedPayload,
1137
1121
  });
1138
1122
  broadcastToChat(chatJid, parsedPayload);
@@ -1145,7 +1129,7 @@ async function processMessages(chatJid) {
1145
1129
  // Mark stream dispatch completion after all chunks are broadcast to
1146
1130
  // active web clients. `/chat` waits on this marker before closing
1147
1131
  // the SSE response to avoid cutting off trailing streamed chunks.
1148
- storeSessionUiEvent(agentId, sessionId, {
1132
+ storeThreadUiEvent(agentId, threadId, {
1149
1133
  id: `${taskId}:stream-dispatched:${Date.now()}`,
1150
1134
  timestamp: new Date().toISOString(),
1151
1135
  task_id: taskId,
@@ -1300,11 +1284,11 @@ function loadState() {
1300
1284
  registeredProjects[jid] = group;
1301
1285
  }
1302
1286
  logger.info({ count: Object.keys(registeredProjects).length }, 'Groups loaded');
1303
- const dbSessions = getAllSessions();
1304
- for (const sess of dbSessions) {
1305
- sessions[sess.agent_id] = sess.session_id;
1287
+ const dbThreads = getAllThreads();
1288
+ for (const sess of dbThreads) {
1289
+ threads[sess.agent_id] = sess.thread_id;
1306
1290
  }
1307
- logger.info({ count: Object.keys(sessions).length }, 'Sessions loaded');
1291
+ logger.info({ count: Object.keys(threads).length }, 'Threads loaded');
1308
1292
  for (const jid of Object.keys(registeredProjects)) {
1309
1293
  const timestamp = getRouterState(jid);
1310
1294
  if (timestamp) {
@@ -1327,13 +1311,13 @@ function recoverPendingMessages() {
1327
1311
  }
1328
1312
  let sendFn;
1329
1313
  let createChannelFn;
1330
- function ensureNotificationSessionExists(targetJid, fallbackAgentId) {
1314
+ function ensureNotificationThreadExists(targetJid, fallbackAgentId) {
1331
1315
  const resolved = resolveFromChatJid(targetJid);
1332
1316
  if (!resolved)
1333
1317
  return;
1334
- ensureSession({
1318
+ ensureThread({
1335
1319
  agent_id: resolved.agentId || fallbackAgentId || 'unknown',
1336
- session_id: resolved.sessionId,
1320
+ thread_id: resolved.threadId,
1337
1321
  channel: targetJid.startsWith('web:') ? 'http' : targetJid.split(':')[0] || 'unknown',
1338
1322
  source_ref: targetJid,
1339
1323
  });
@@ -1348,18 +1332,18 @@ async function main() {
1348
1332
  const productName = process.env.SUPEN_PRODUCT_NAME || 'Supen';
1349
1333
  logger.info(`${productName} Daemon starting`);
1350
1334
  initStore();
1351
- cleanupStaleSessions();
1335
+ cleanupStaleThreads();
1352
1336
  cleanupStaleAutomationExecutions();
1353
1337
  logger.info('Database initialized');
1354
- // Ensure default agent and session exist
1355
- ensureSession({
1338
+ // Ensure default agent and thread exist
1339
+ ensureThread({
1356
1340
  agent_id: 'supen-agent',
1357
- session_id: 'supen-session',
1341
+ thread_id: 'supen-thread',
1358
1342
  channel: 'web',
1359
1343
  agent_name: 'Supen Agent',
1360
1344
  space_id: process.env.SUPEN_SPACE_ID || 'local',
1361
1345
  });
1362
- logger.info('Default agent and session ensured');
1346
+ logger.info('Default agent and thread ensured');
1363
1347
  if (isSupabaseConfigured()) {
1364
1348
  await pullFromSupabase();
1365
1349
  startPeriodicSupabasePush();
@@ -1400,7 +1384,7 @@ async function main() {
1400
1384
  });
1401
1385
  }
1402
1386
  },
1403
- onSessionStop: (agentId, sessionId, actor) => requestSessionStop(agentId, sessionId, actor),
1387
+ onThreadStop: (agentId, threadId, actor) => requestThreadStop(agentId, threadId, actor),
1404
1388
  onChatMetadata: (chatJid, timestamp, name, channel, isGroup) => handleChatMetadata(chatJid, timestamp, name, channel, isGroup),
1405
1389
  registeredProjects: () => registeredProjects,
1406
1390
  onGroupRegistered: (jid, group) => registerProject(jid, group),
@@ -1463,8 +1447,8 @@ async function main() {
1463
1447
  sendFn = async (jid, text, options) => {
1464
1448
  const messageId = options?.message_id || `bot-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
1465
1449
  if (!jid.startsWith('task:')) {
1466
- // Check if this is a gateway session - use gateway's routing which handles both
1467
- // regular gateway sessions and channel-based sessions (via sendReplyForChat)
1450
+ // Check if this is a gateway thread - use gateway's routing which handles both
1451
+ // regular gateway threads and channel-based threads (via sendReplyForChat)
1468
1452
  const gw = getGatewayInstance();
1469
1453
  if (jid.startsWith('gateway:') && gw) {
1470
1454
  await gw.sendReplyForChat(jid, text, options?.message_id, options?.trace_id);