verybot 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 (277) hide show
  1. package/README.md +167 -0
  2. package/dist/aliases/store.d.ts +21 -0
  3. package/dist/aliases/store.js +148 -0
  4. package/dist/aliases/types.d.ts +6 -0
  5. package/dist/aliases/types.js +1 -0
  6. package/dist/brain/agent-registry.d.ts +96 -0
  7. package/dist/brain/agent-registry.js +141 -0
  8. package/dist/brain/agent.d.ts +167 -0
  9. package/dist/brain/agent.js +932 -0
  10. package/dist/brain/channel-store.d.ts +27 -0
  11. package/dist/brain/channel-store.js +78 -0
  12. package/dist/brain/compaction.d.ts +37 -0
  13. package/dist/brain/compaction.js +214 -0
  14. package/dist/brain/context.d.ts +43 -0
  15. package/dist/brain/context.js +139 -0
  16. package/dist/brain/delegation-store.d.ts +33 -0
  17. package/dist/brain/delegation-store.js +106 -0
  18. package/dist/brain/loop.d.ts +24 -0
  19. package/dist/brain/loop.js +318 -0
  20. package/dist/brain/mcp-adapter.d.ts +43 -0
  21. package/dist/brain/mcp-adapter.js +244 -0
  22. package/dist/brain/memory-extractor.d.ts +26 -0
  23. package/dist/brain/memory-extractor.js +82 -0
  24. package/dist/brain/providers.d.ts +14 -0
  25. package/dist/brain/providers.js +85 -0
  26. package/dist/brain/queue.d.ts +18 -0
  27. package/dist/brain/queue.js +111 -0
  28. package/dist/brain/run-tools.d.ts +50 -0
  29. package/dist/brain/run-tools.js +136 -0
  30. package/dist/brain/session-key.d.ts +23 -0
  31. package/dist/brain/session-key.js +41 -0
  32. package/dist/brain/session-state.d.ts +36 -0
  33. package/dist/brain/session-state.js +51 -0
  34. package/dist/brain/session-store.d.ts +50 -0
  35. package/dist/brain/session-store.js +207 -0
  36. package/dist/brain/session.d.ts +32 -0
  37. package/dist/brain/session.js +75 -0
  38. package/dist/brain/task-subscriber.d.ts +56 -0
  39. package/dist/brain/task-subscriber.js +317 -0
  40. package/dist/brain/user-content.d.ts +16 -0
  41. package/dist/brain/user-content.js +32 -0
  42. package/dist/brain/utils.d.ts +4 -0
  43. package/dist/brain/utils.js +26 -0
  44. package/dist/brain/worker-coordinator.d.ts +25 -0
  45. package/dist/brain/worker-coordinator.js +83 -0
  46. package/dist/channels/commands.d.ts +50 -0
  47. package/dist/channels/commands.js +132 -0
  48. package/dist/channels/discord/channel.d.ts +29 -0
  49. package/dist/channels/discord/channel.js +159 -0
  50. package/dist/channels/discord/markdown.d.ts +19 -0
  51. package/dist/channels/discord/markdown.js +62 -0
  52. package/dist/channels/manager.d.ts +29 -0
  53. package/dist/channels/manager.js +100 -0
  54. package/dist/channels/slack/channel.d.ts +37 -0
  55. package/dist/channels/slack/channel.js +227 -0
  56. package/dist/channels/slack/markdown.d.ts +19 -0
  57. package/dist/channels/slack/markdown.js +62 -0
  58. package/dist/channels/specs.d.ts +32 -0
  59. package/dist/channels/specs.js +99 -0
  60. package/dist/channels/telegram/channel.d.ts +29 -0
  61. package/dist/channels/telegram/channel.js +182 -0
  62. package/dist/channels/telegram/markdown.d.ts +17 -0
  63. package/dist/channels/telegram/markdown.js +66 -0
  64. package/dist/channels/types.d.ts +26 -0
  65. package/dist/channels/types.js +1 -0
  66. package/dist/channels/whatsapp/channel.d.ts +34 -0
  67. package/dist/channels/whatsapp/channel.js +276 -0
  68. package/dist/channels/whatsapp/markdown.d.ts +20 -0
  69. package/dist/channels/whatsapp/markdown.js +51 -0
  70. package/dist/cli/claude-login.d.ts +5 -0
  71. package/dist/cli/claude-login.js +47 -0
  72. package/dist/cli/config.d.ts +5 -0
  73. package/dist/cli/config.js +78 -0
  74. package/dist/cli/index.d.ts +11 -0
  75. package/dist/cli/index.js +96 -0
  76. package/dist/computer/browser/actions.d.ts +31 -0
  77. package/dist/computer/browser/actions.js +148 -0
  78. package/dist/computer/browser/context-manager.d.ts +28 -0
  79. package/dist/computer/browser/context-manager.js +78 -0
  80. package/dist/computer/browser/manager.d.ts +91 -0
  81. package/dist/computer/browser/manager.js +344 -0
  82. package/dist/computer/browser/profile-badge.d.ts +13 -0
  83. package/dist/computer/browser/profile-badge.js +67 -0
  84. package/dist/computer/browser/screenshot.d.ts +5 -0
  85. package/dist/computer/browser/screenshot.js +21 -0
  86. package/dist/computer/browser/snapshot.d.ts +30 -0
  87. package/dist/computer/browser/snapshot.js +242 -0
  88. package/dist/computer/browser/tools.d.ts +5 -0
  89. package/dist/computer/browser/tools.js +167 -0
  90. package/dist/computer/browser/types.d.ts +26 -0
  91. package/dist/computer/browser/types.js +1 -0
  92. package/dist/computer/desktop/adapter.d.ts +25 -0
  93. package/dist/computer/desktop/adapter.js +11 -0
  94. package/dist/computer/desktop/macos.d.ts +24 -0
  95. package/dist/computer/desktop/macos.js +223 -0
  96. package/dist/computer/desktop/tools.d.ts +25 -0
  97. package/dist/computer/desktop/tools.js +114 -0
  98. package/dist/config/agent-config.d.ts +55 -0
  99. package/dist/config/agent-config.js +16 -0
  100. package/dist/config/model-catalog.d.ts +22 -0
  101. package/dist/config/model-catalog.js +112 -0
  102. package/dist/config/model-spec.d.ts +8 -0
  103. package/dist/config/model-spec.js +66 -0
  104. package/dist/config/store.d.ts +25 -0
  105. package/dist/config/store.js +143 -0
  106. package/dist/config.d.ts +110 -0
  107. package/dist/config.js +259 -0
  108. package/dist/control-ui/assets/index-Cbl7G5Sc.css +1 -0
  109. package/dist/control-ui/assets/index-Cu1P4C62.js +266 -0
  110. package/dist/control-ui/assets/noto-sans-cyrillic-ext-wght-normal-DSNfmdVt.woff2 +0 -0
  111. package/dist/control-ui/assets/noto-sans-cyrillic-wght-normal-B2hlT84T.woff2 +0 -0
  112. package/dist/control-ui/assets/noto-sans-devanagari-wght-normal-Cv-Vwajv.woff2 +0 -0
  113. package/dist/control-ui/assets/noto-sans-greek-ext-wght-normal-12T8GTDR.woff2 +0 -0
  114. package/dist/control-ui/assets/noto-sans-greek-wght-normal-Ymb6dZNd.woff2 +0 -0
  115. package/dist/control-ui/assets/noto-sans-latin-ext-wght-normal-W1qJv59z.woff2 +0 -0
  116. package/dist/control-ui/assets/noto-sans-latin-wght-normal-BYSzYMf3.woff2 +0 -0
  117. package/dist/control-ui/assets/noto-sans-vietnamese-wght-normal-DLTJy58D.woff2 +0 -0
  118. package/dist/control-ui/index.html +14 -0
  119. package/dist/control-ui/vite.svg +1 -0
  120. package/dist/events.d.ts +2 -0
  121. package/dist/events.js +11 -0
  122. package/dist/gateway/broadcast.d.ts +5 -0
  123. package/dist/gateway/broadcast.js +33 -0
  124. package/dist/gateway/methods/aliases.d.ts +17 -0
  125. package/dist/gateway/methods/aliases.js +22 -0
  126. package/dist/gateway/methods/chat.d.ts +33 -0
  127. package/dist/gateway/methods/chat.js +37 -0
  128. package/dist/gateway/methods/config.d.ts +14 -0
  129. package/dist/gateway/methods/config.js +24 -0
  130. package/dist/gateway/methods/models.d.ts +10 -0
  131. package/dist/gateway/methods/models.js +14 -0
  132. package/dist/gateway/methods/playbooks.d.ts +45 -0
  133. package/dist/gateway/methods/playbooks.js +488 -0
  134. package/dist/gateway/methods/prompt-templates.d.ts +27 -0
  135. package/dist/gateway/methods/prompt-templates.js +106 -0
  136. package/dist/gateway/methods/scheduler.d.ts +62 -0
  137. package/dist/gateway/methods/scheduler.js +129 -0
  138. package/dist/gateway/methods/sessions.d.ts +44 -0
  139. package/dist/gateway/methods/sessions.js +111 -0
  140. package/dist/gateway/methods/system.d.ts +12 -0
  141. package/dist/gateway/methods/system.js +39 -0
  142. package/dist/gateway/methods/tasks.d.ts +40 -0
  143. package/dist/gateway/methods/tasks.js +151 -0
  144. package/dist/gateway/methods/teams.d.ts +69 -0
  145. package/dist/gateway/methods/teams.js +376 -0
  146. package/dist/gateway/methods/tools.d.ts +6 -0
  147. package/dist/gateway/methods/tools.js +7 -0
  148. package/dist/gateway/methods/whatsapp.d.ts +19 -0
  149. package/dist/gateway/methods/whatsapp.js +35 -0
  150. package/dist/gateway/rpc.d.ts +38 -0
  151. package/dist/gateway/rpc.js +79 -0
  152. package/dist/gateway/server.d.ts +9 -0
  153. package/dist/gateway/server.js +137 -0
  154. package/dist/index.d.ts +1 -0
  155. package/dist/index.js +254 -0
  156. package/dist/integrations/github.d.ts +7 -0
  157. package/dist/integrations/github.js +133 -0
  158. package/dist/integrations/mcp.d.ts +7 -0
  159. package/dist/integrations/mcp.js +106 -0
  160. package/dist/integrations/registry.d.ts +47 -0
  161. package/dist/integrations/registry.js +332 -0
  162. package/dist/integrations/scanner.d.ts +10 -0
  163. package/dist/integrations/scanner.js +122 -0
  164. package/dist/integrations/twitter.d.ts +10 -0
  165. package/dist/integrations/twitter.js +120 -0
  166. package/dist/integrations/types.d.ts +72 -0
  167. package/dist/integrations/types.js +1 -0
  168. package/dist/logger.d.ts +16 -0
  169. package/dist/logger.js +104 -0
  170. package/dist/markdown/chunk.d.ts +9 -0
  171. package/dist/markdown/chunk.js +52 -0
  172. package/dist/markdown/ir.d.ts +37 -0
  173. package/dist/markdown/ir.js +529 -0
  174. package/dist/markdown/render.d.ts +22 -0
  175. package/dist/markdown/render.js +148 -0
  176. package/dist/markdown/table-render.d.ts +43 -0
  177. package/dist/markdown/table-render.js +219 -0
  178. package/dist/markdown/tables.d.ts +17 -0
  179. package/dist/markdown/tables.js +27 -0
  180. package/dist/memory/embedding.d.ts +16 -0
  181. package/dist/memory/embedding.js +66 -0
  182. package/dist/memory/explicit.d.ts +16 -0
  183. package/dist/memory/explicit.js +29 -0
  184. package/dist/memory/extractor.d.ts +13 -0
  185. package/dist/memory/extractor.js +82 -0
  186. package/dist/memory/search.d.ts +15 -0
  187. package/dist/memory/search.js +57 -0
  188. package/dist/memory/session-learning.d.ts +23 -0
  189. package/dist/memory/session-learning.js +55 -0
  190. package/dist/memory/store.d.ts +36 -0
  191. package/dist/memory/store.js +334 -0
  192. package/dist/memory/types.d.ts +9 -0
  193. package/dist/memory/types.js +2 -0
  194. package/dist/paths.d.ts +28 -0
  195. package/dist/paths.js +48 -0
  196. package/dist/prompt-templates/builtins/index.d.ts +4 -0
  197. package/dist/prompt-templates/builtins/index.js +5 -0
  198. package/dist/prompt-templates/builtins/planner.d.ts +4 -0
  199. package/dist/prompt-templates/builtins/planner.js +77 -0
  200. package/dist/prompt-templates/store.d.ts +45 -0
  201. package/dist/prompt-templates/store.js +224 -0
  202. package/dist/prompt-templates/types.d.ts +10 -0
  203. package/dist/prompt-templates/types.js +1 -0
  204. package/dist/scheduler/connected-channels.d.ts +24 -0
  205. package/dist/scheduler/connected-channels.js +57 -0
  206. package/dist/scheduler/scheduler.d.ts +22 -0
  207. package/dist/scheduler/scheduler.js +132 -0
  208. package/dist/scheduler/store.d.ts +27 -0
  209. package/dist/scheduler/store.js +205 -0
  210. package/dist/scheduler/types.d.ts +29 -0
  211. package/dist/scheduler/types.js +1 -0
  212. package/dist/security/command-validator.d.ts +22 -0
  213. package/dist/security/command-validator.js +160 -0
  214. package/dist/security/docker-sandbox.d.ts +48 -0
  215. package/dist/security/docker-sandbox.js +218 -0
  216. package/dist/security/env-filter.d.ts +8 -0
  217. package/dist/security/env-filter.js +41 -0
  218. package/dist/skills/loader.d.ts +33 -0
  219. package/dist/skills/loader.js +132 -0
  220. package/dist/skills/prompt.d.ts +6 -0
  221. package/dist/skills/prompt.js +17 -0
  222. package/dist/skills/read-tool.d.ts +7 -0
  223. package/dist/skills/read-tool.js +24 -0
  224. package/dist/skills/scanner.d.ts +6 -0
  225. package/dist/skills/scanner.js +73 -0
  226. package/dist/skills/types.d.ts +15 -0
  227. package/dist/skills/types.js +1 -0
  228. package/dist/tasks/inline-attachment-content.d.ts +9 -0
  229. package/dist/tasks/inline-attachment-content.js +64 -0
  230. package/dist/tasks/store.d.ts +112 -0
  231. package/dist/tasks/store.js +519 -0
  232. package/dist/tasks/types.d.ts +129 -0
  233. package/dist/tasks/types.js +80 -0
  234. package/dist/teams/status-config.d.ts +8 -0
  235. package/dist/teams/status-config.js +40 -0
  236. package/dist/teams/store.d.ts +111 -0
  237. package/dist/teams/store.js +671 -0
  238. package/dist/teams/types.d.ts +30 -0
  239. package/dist/teams/types.js +1 -0
  240. package/dist/tools/bash.d.ts +18 -0
  241. package/dist/tools/bash.js +64 -0
  242. package/dist/tools/channel-history.d.ts +10 -0
  243. package/dist/tools/channel-history.js +43 -0
  244. package/dist/tools/delegate.d.ts +20 -0
  245. package/dist/tools/delegate.js +299 -0
  246. package/dist/tools/fs.d.ts +4 -0
  247. package/dist/tools/fs.js +335 -0
  248. package/dist/tools/integration-toggle.d.ts +14 -0
  249. package/dist/tools/integration-toggle.js +47 -0
  250. package/dist/tools/memory.d.ts +13 -0
  251. package/dist/tools/memory.js +59 -0
  252. package/dist/tools/prompt-templates.d.ts +7 -0
  253. package/dist/tools/prompt-templates.js +133 -0
  254. package/dist/tools/registry.d.ts +6 -0
  255. package/dist/tools/registry.js +9 -0
  256. package/dist/tools/schedule.d.ts +8 -0
  257. package/dist/tools/schedule.js +219 -0
  258. package/dist/tools/speak.d.ts +10 -0
  259. package/dist/tools/speak.js +56 -0
  260. package/dist/tools/tasks.d.ts +67 -0
  261. package/dist/tools/tasks.js +288 -0
  262. package/dist/tools/teams.d.ts +22 -0
  263. package/dist/tools/teams.js +470 -0
  264. package/dist/tools/web-fetch.d.ts +3 -0
  265. package/dist/tools/web-fetch.js +22 -0
  266. package/dist/tts/edge.d.ts +10 -0
  267. package/dist/tts/edge.js +60 -0
  268. package/dist/tts/speak.d.ts +12 -0
  269. package/dist/tts/speak.js +81 -0
  270. package/dist/tts/transcribe.d.ts +5 -0
  271. package/dist/tts/transcribe.js +40 -0
  272. package/dist/utils.d.ts +5 -0
  273. package/dist/utils.js +22 -0
  274. package/dist/version.d.ts +1 -0
  275. package/dist/version.js +13 -0
  276. package/package.json +102 -0
  277. package/verybot.js +2 -0
@@ -0,0 +1,129 @@
1
+ import { broadcast, onClientClose } from "../broadcast.js";
2
+ const VALID_STATUSES = new Set(["active", "paused", "completed", "failed"]);
3
+ /** Validate that `teamId` belongs to a real team. */
4
+ function validateTeamId(agent, teamId) {
5
+ if (!teamId)
6
+ throw new Error("Missing teamId");
7
+ const teams = agent.getTeams();
8
+ if (!teams.some((t) => t.id === teamId)) {
9
+ throw new Error(`Unknown team: "${teamId}"`);
10
+ }
11
+ }
12
+ export function schedulerMethods(getAgent, getScheduleStore, getConnectedChannels, ctx) {
13
+ return {
14
+ /** Connect a WS client to a team's scheduler. Returns session history + connection key. */
15
+ "scheduler.connect": async (params) => {
16
+ const { teamId } = params;
17
+ validateTeamId(getAgent(), teamId);
18
+ const connectedChannels = getConnectedChannels();
19
+ // Register this WS as a connected channel — send fn broadcasts via WS events
20
+ const connectionKey = connectedChannels.connect(teamId, {
21
+ channelType: "gateway",
22
+ channelId: `ws:${teamId}`,
23
+ send: async (text) => {
24
+ broadcast("schedulerMessage", { teamId, role: "assistant", content: text });
25
+ },
26
+ });
27
+ // Auto-disconnect when the WS closes (prevents stale entries)
28
+ if (ctx?.ws) {
29
+ onClientClose(ctx.ws, () => {
30
+ connectedChannels.disconnect(teamId, connectionKey);
31
+ });
32
+ }
33
+ // Return existing session history
34
+ const session = getAgent().getSchedulerSession(teamId);
35
+ const messages = session?.getMessages() ?? [];
36
+ return { connectionKey, messages };
37
+ },
38
+ /** Disconnect a WS client from a team's scheduler. */
39
+ "scheduler.disconnect": async (params) => {
40
+ const { teamId, connectionKey } = params;
41
+ if (!teamId || !connectionKey)
42
+ throw new Error("Missing teamId or connectionKey");
43
+ getConnectedChannels().disconnect(teamId, connectionKey);
44
+ return { status: "ok" };
45
+ },
46
+ /** Send a message to the team's scheduler session. */
47
+ "scheduler.send": async (params) => {
48
+ const { teamId, message } = params;
49
+ if (!message)
50
+ throw new Error("Missing message");
51
+ validateTeamId(getAgent(), teamId);
52
+ // Broadcast user message to OTHER clients (sender already has it via optimistic UI)
53
+ const excludeWs = ctx?.ws;
54
+ broadcast("schedulerMessage", { teamId, role: "user", content: message, senderInfo: "Web UI" }, excludeWs);
55
+ const reply = await getAgent().handleSchedulerMessage(teamId, message, "Web UI");
56
+ // Broadcast reply to OTHER clients (sender gets it via RPC response)
57
+ broadcast("schedulerMessage", { teamId, role: "assistant", content: reply }, excludeWs);
58
+ return { status: "ok", reply };
59
+ },
60
+ /** Get scheduler session history for a team. */
61
+ "scheduler.history": async (params) => {
62
+ const { teamId } = params;
63
+ validateTeamId(getAgent(), teamId);
64
+ const session = getAgent().getSchedulerSession(teamId);
65
+ return { messages: session?.getMessages() ?? [] };
66
+ },
67
+ /** List schedules for a team. */
68
+ "scheduler.list": async (params) => {
69
+ const { teamId, status } = params;
70
+ validateTeamId(getAgent(), teamId);
71
+ if (status && !VALID_STATUSES.has(status)) {
72
+ throw new Error(`Invalid status: "${status}". Must be one of: active, paused, completed, failed`);
73
+ }
74
+ const store = getScheduleStore();
75
+ const schedules = store.listByTeam(teamId, status);
76
+ return { schedules };
77
+ },
78
+ // --- Direct schedule CRUD (bypasses LLM) ---
79
+ /** Pause an active schedule. */
80
+ "scheduler.pause": async (params) => {
81
+ const { teamId, scheduleId } = params;
82
+ if (!scheduleId)
83
+ throw new Error("Missing scheduleId");
84
+ validateTeamId(getAgent(), teamId);
85
+ const store = getScheduleStore();
86
+ const schedule = store.getById(scheduleId);
87
+ if (!schedule || schedule.teamId !== teamId) {
88
+ throw new Error(`Schedule "${scheduleId}" not found for this team`);
89
+ }
90
+ if (schedule.status !== "active") {
91
+ throw new Error(`Schedule is not active (status: ${schedule.status})`);
92
+ }
93
+ store.update(scheduleId, { status: "paused" });
94
+ return { status: "ok" };
95
+ },
96
+ /** Resume a paused schedule. */
97
+ "scheduler.resume": async (params) => {
98
+ const { teamId, scheduleId } = params;
99
+ if (!scheduleId)
100
+ throw new Error("Missing scheduleId");
101
+ validateTeamId(getAgent(), teamId);
102
+ const store = getScheduleStore();
103
+ const schedule = store.getById(scheduleId);
104
+ if (!schedule || schedule.teamId !== teamId) {
105
+ throw new Error(`Schedule "${scheduleId}" not found for this team`);
106
+ }
107
+ if (schedule.status !== "paused") {
108
+ throw new Error(`Schedule is not paused (status: ${schedule.status})`);
109
+ }
110
+ const nextRun = store.computeNextRun(schedule);
111
+ store.update(scheduleId, { status: "active", nextRun });
112
+ return { status: "ok" };
113
+ },
114
+ /** Delete a schedule. */
115
+ "scheduler.delete": async (params) => {
116
+ const { teamId, scheduleId } = params;
117
+ if (!scheduleId)
118
+ throw new Error("Missing scheduleId");
119
+ validateTeamId(getAgent(), teamId);
120
+ const store = getScheduleStore();
121
+ const schedule = store.getById(scheduleId);
122
+ if (!schedule || schedule.teamId !== teamId) {
123
+ throw new Error(`Schedule "${scheduleId}" not found for this team`);
124
+ }
125
+ store.delete(scheduleId);
126
+ return { status: "ok" };
127
+ },
128
+ };
129
+ }
@@ -0,0 +1,44 @@
1
+ import type { Agent } from "../../brain/agent.js";
2
+ interface ListSessionsParams {
3
+ limit?: number;
4
+ offset?: number;
5
+ teamId?: string;
6
+ }
7
+ interface ClearOldSessionsParams {
8
+ keepLatest?: number;
9
+ teamId?: string;
10
+ }
11
+ export declare function sessionMethods(getAgent: () => Agent): {
12
+ "sessions.list": (params?: ListSessionsParams) => Promise<{
13
+ sessions: import("../../brain/session-store.js").SessionIndexEntry[];
14
+ total: number;
15
+ hasMore: boolean;
16
+ nextOffset: number | null;
17
+ ts: number;
18
+ }>;
19
+ "sessions.get": (params: {
20
+ sessionKey: string;
21
+ }) => Promise<{
22
+ messages: {
23
+ role: "system" | "user" | "assistant" | "tool";
24
+ content: string | (import("ai").TextPart | import("ai").ImagePart | import("ai").FilePart)[] | (import("ai").TextPart | import("ai").FilePart | import("@ai-sdk/provider-utils").ReasoningPart | import("ai").ToolCallPart | import("ai").ToolResultPart | import("ai").ToolApprovalRequest)[] | import("ai").ToolContent;
25
+ }[];
26
+ }>;
27
+ "sessions.rename": (params: {
28
+ sessionKey: string;
29
+ title: string;
30
+ }) => Promise<{
31
+ status: string;
32
+ }>;
33
+ "sessions.clear": (params: {
34
+ sessionKey: string;
35
+ }) => Promise<{
36
+ status: string;
37
+ }>;
38
+ "sessions.clearOld": (params?: ClearOldSessionsParams) => Promise<{
39
+ status: string;
40
+ keepLatest: number;
41
+ cleared: number;
42
+ }>;
43
+ };
44
+ export {};
@@ -0,0 +1,111 @@
1
+ import { parseSessionKey } from "../../brain/session-key.js";
2
+ import { logger } from "../../logger.js";
3
+ const DEFAULT_KEEP_LATEST_SESSIONS = 300;
4
+ function toOptionalPositiveInteger(value, fieldName) {
5
+ if (value === undefined)
6
+ return undefined;
7
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
8
+ throw new Error(`${fieldName} must be a positive integer`);
9
+ }
10
+ return value;
11
+ }
12
+ function toNonNegativeInteger(value, fieldName, defaultValue) {
13
+ if (value === undefined)
14
+ return defaultValue;
15
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
16
+ throw new Error(`${fieldName} must be a non-negative integer`);
17
+ }
18
+ return value;
19
+ }
20
+ function toOptionalString(value, fieldName) {
21
+ if (value === undefined)
22
+ return undefined;
23
+ if (typeof value !== "string")
24
+ throw new Error(`${fieldName} must be a string`);
25
+ const trimmed = value.trim();
26
+ return trimmed.length > 0 ? trimmed : undefined;
27
+ }
28
+ function resolveSessionTeamId(session) {
29
+ if (session.teamId)
30
+ return session.teamId;
31
+ return parseSessionKey(session.key).teamId;
32
+ }
33
+ export function sessionMethods(getAgent) {
34
+ return {
35
+ "sessions.list": async (params) => {
36
+ const agent = getAgent();
37
+ const allSessions = agent.getStore().list();
38
+ const limit = toOptionalPositiveInteger(params?.limit, "limit");
39
+ const offset = toNonNegativeInteger(params?.offset, "offset", 0);
40
+ const teamId = toOptionalString(params?.teamId, "teamId");
41
+ const sessions = teamId
42
+ ? allSessions.filter((session) => resolveSessionTeamId(session) === teamId)
43
+ : allSessions;
44
+ const pagedSessions = limit === undefined
45
+ ? sessions.slice(offset)
46
+ : sessions.slice(offset, offset + limit);
47
+ // Enrich sessions with team name + color from the team store
48
+ const teams = agent.getTeams();
49
+ const teamById = new Map(teams.map((t) => [t.id, t]));
50
+ const enriched = pagedSessions.map((s) => {
51
+ const sessionTeamId = resolveSessionTeamId(s);
52
+ const team = sessionTeamId ? teamById.get(sessionTeamId) : undefined;
53
+ if (!team)
54
+ return s;
55
+ return {
56
+ ...s,
57
+ ...(sessionTeamId && !s.teamId && { teamId: sessionTeamId }),
58
+ ...(team.name && { teamName: team.name }),
59
+ ...(team.color && { teamColor: team.color }),
60
+ };
61
+ });
62
+ const nextOffset = offset + enriched.length;
63
+ const hasMore = nextOffset < sessions.length;
64
+ return {
65
+ sessions: enriched,
66
+ total: sessions.length,
67
+ hasMore,
68
+ nextOffset: hasMore ? nextOffset : null,
69
+ ts: Date.now(),
70
+ };
71
+ },
72
+ "sessions.get": async (params) => {
73
+ if (!params?.sessionKey || typeof params.sessionKey !== "string") {
74
+ throw new Error("sessionKey is required and must be a string");
75
+ }
76
+ const session = await getAgent().getStore().load(params.sessionKey);
77
+ if (!session)
78
+ return { messages: [] };
79
+ const messages = session.getMessages().map((m) => ({
80
+ role: m.role,
81
+ content: m.content,
82
+ }));
83
+ return { messages };
84
+ },
85
+ "sessions.rename": async (params) => {
86
+ if (!params?.sessionKey || typeof params.sessionKey !== "string") {
87
+ throw new Error("sessionKey is required and must be a string");
88
+ }
89
+ if (!params?.title || typeof params.title !== "string") {
90
+ throw new Error("title is required and must be a string");
91
+ }
92
+ const ok = getAgent().getStore().rename(params.sessionKey, params.title);
93
+ if (!ok)
94
+ return { status: "not_found" };
95
+ logger.info(`[${params.sessionKey}] Session renamed to: ${params.title}`);
96
+ return { status: "ok" };
97
+ },
98
+ "sessions.clear": async (params) => {
99
+ logger.info(`[${params.sessionKey}] Session clear requested`);
100
+ await getAgent().clearSession(params.sessionKey);
101
+ return { status: "ok" };
102
+ },
103
+ "sessions.clearOld": async (params) => {
104
+ const keepLatest = toNonNegativeInteger(params?.keepLatest, "keepLatest", DEFAULT_KEEP_LATEST_SESSIONS);
105
+ const teamId = toOptionalString(params?.teamId, "teamId");
106
+ logger.info(`[sessions] Clear old requested (keepLatest=${keepLatest}${teamId ? `, teamId=${teamId}` : ""})`);
107
+ const cleared = await getAgent().clearOldSessions(keepLatest, teamId);
108
+ return { status: "ok", keepLatest, cleared };
109
+ },
110
+ };
111
+ }
@@ -0,0 +1,12 @@
1
+ import { type LogEntry } from "../../logger.js";
2
+ import type { RpcContext } from "../rpc.js";
3
+ export declare function systemMethods(restart: () => Promise<void>, ctx?: RpcContext): {
4
+ /** Hot-restart all backend components. WebSocket connections stay alive. */
5
+ "system.restart": () => Promise<{
6
+ status: string;
7
+ }>;
8
+ /** Return buffered log history and subscribe the caller to real-time log events. */
9
+ "system.logs.subscribe": () => Promise<{
10
+ logs: LogEntry[];
11
+ }>;
12
+ };
@@ -0,0 +1,39 @@
1
+ import { emit } from "../../events.js";
2
+ import { onClientClose } from "../broadcast.js";
3
+ import { logger, getLogBuffer, addLogSubscriber } from "../../logger.js";
4
+ export function systemMethods(restart, ctx) {
5
+ return {
6
+ /** Hot-restart all backend components. WebSocket connections stay alive. */
7
+ "system.restart": async () => {
8
+ logger.info("Hot restart requested via RPC");
9
+ emit("system", { action: "restarting" });
10
+ // Run restart in background so the RPC response is sent first
11
+ setTimeout(async () => {
12
+ try {
13
+ await restart();
14
+ emit("system", { action: "restarted" });
15
+ logger.info("Hot restart complete");
16
+ }
17
+ catch (err) {
18
+ logger.error(`Hot restart failed: ${err}`);
19
+ emit("system", { action: "restart_failed", error: String(err) });
20
+ }
21
+ }, 0);
22
+ return { status: "restarting" };
23
+ },
24
+ /** Return buffered log history and subscribe the caller to real-time log events. */
25
+ "system.logs.subscribe": async () => {
26
+ const ws = ctx?.ws;
27
+ if (ws) {
28
+ const send = (entry) => {
29
+ if (ws.readyState === ws.OPEN) {
30
+ ws.send(JSON.stringify({ type: "event", event: "log", payload: entry }));
31
+ }
32
+ };
33
+ const unsub = addLogSubscriber(send);
34
+ onClientClose(ws, unsub);
35
+ }
36
+ return { logs: getLogBuffer() };
37
+ },
38
+ };
39
+ }
@@ -0,0 +1,40 @@
1
+ import type { TaskStore } from "../../tasks/store.js";
2
+ import type { TeamStore } from "../../teams/store.js";
3
+ import { type TaskAttachment } from "../../tasks/types.js";
4
+ export declare function taskMethods(taskStore: TaskStore, _teamStore?: TeamStore | null): {
5
+ "tasks.list": (params: unknown) => Promise<{
6
+ tasks: import("../../tasks/types.js").Task[];
7
+ }>;
8
+ "tasks.create": (params: unknown) => Promise<{
9
+ task: import("../../tasks/types.js").Task;
10
+ }>;
11
+ "tasks.update": (params: unknown) => Promise<{
12
+ task: import("../../tasks/types.js").Task;
13
+ }>;
14
+ "tasks.delete": (params: unknown) => Promise<{
15
+ status: string;
16
+ }>;
17
+ "tasks.reorder": (params: unknown) => Promise<{
18
+ status: string;
19
+ }>;
20
+ "tasks.archiveDone": (params: unknown) => Promise<{
21
+ archived: number;
22
+ }>;
23
+ "tasks.listComments": (params: unknown) => Promise<{
24
+ comments: import("../../tasks/types.js").TaskComment[];
25
+ }>;
26
+ "tasks.addComment": (params: unknown) => Promise<{
27
+ comment: import("../../tasks/types.js").TaskComment;
28
+ }>;
29
+ "tasks.updateComment": (params: unknown) => Promise<{
30
+ comment: import("../../tasks/types.js").TaskComment;
31
+ }>;
32
+ "tasks.deleteComment": (params: unknown) => Promise<{
33
+ status: string;
34
+ }>;
35
+ "tasks.uploadAttachment": (params: unknown) => Promise<TaskAttachment>;
36
+ "tasks.getAttachment": (params: unknown) => Promise<{
37
+ data: string;
38
+ type: string;
39
+ }>;
40
+ };
@@ -0,0 +1,151 @@
1
+ import { writeFile, readFile } from "node:fs/promises";
2
+ import { join, basename, extname } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { z } from "zod";
5
+ import { emit } from "../../events.js";
6
+ import { logger } from "../../logger.js";
7
+ import { ATTACHMENTS_DIR } from "../../paths.js";
8
+ import { CreateTaskSchema, UpdateTaskSchema, ListTasksSchema, ReorderTasksSchema, ListTaskCommentsSchema, AddTaskCommentSchema, UpdateTaskCommentSchema, DeleteTaskCommentSchema, MAX_FILE_SIZE, ALLOWED_IMAGE_TYPES, EXT_FOR_MIME, } from "../../tasks/types.js";
9
+ /** Reverse lookup: file extension -> MIME type */
10
+ const MIME_FOR_EXT = Object.fromEntries(Object.entries(EXT_FOR_MIME).map(([mime, ext]) => [ext, mime]));
11
+ /** Max base64 string length for MAX_FILE_SIZE bytes */
12
+ const MAX_BASE64_LENGTH = Math.ceil(MAX_FILE_SIZE * 4 / 3) + 4;
13
+ const STATUS_KEY_RE = /^\w+$/;
14
+ const UploadAttachmentSchema = z.object({
15
+ name: z.string().min(1).max(255),
16
+ type: z.string(),
17
+ data: z.string().min(1),
18
+ });
19
+ const GetAttachmentSchema = z.object({
20
+ id: z.string().min(1),
21
+ });
22
+ const ArchiveDoneSchema = z.object({
23
+ teamId: z.string().optional(),
24
+ status: z.string().regex(STATUS_KEY_RE).optional(),
25
+ });
26
+ const DEFAULT_DONE_STATUS = "done";
27
+ function resolveDoneStatus(status) {
28
+ if (status)
29
+ return status;
30
+ return DEFAULT_DONE_STATUS;
31
+ }
32
+ export function taskMethods(taskStore, _teamStore) {
33
+ return {
34
+ "tasks.list": async (params) => {
35
+ const filter = ListTasksSchema.parse(params ?? {});
36
+ return { tasks: taskStore.list(filter) };
37
+ },
38
+ "tasks.create": async (params) => {
39
+ const input = CreateTaskSchema.parse(params);
40
+ const task = taskStore.create(input, { updatedBy: "user" });
41
+ emit("taskChange", { action: "created", task });
42
+ return { task };
43
+ },
44
+ "tasks.update": async (params) => {
45
+ const { id, ...updates } = UpdateTaskSchema.parse(params);
46
+ const task = taskStore.update(id, updates, { updatedBy: "user" });
47
+ if (!task)
48
+ throw new Error(`Task not found: ${id}`);
49
+ emit("taskChange", { action: "updated", task });
50
+ return { task };
51
+ },
52
+ "tasks.delete": async (params) => {
53
+ const { id } = z.object({ id: z.string().min(1) }).parse(params);
54
+ const deleted = taskStore.delete(id);
55
+ if (!deleted)
56
+ throw new Error(`Task not found: ${id}`);
57
+ emit("taskChange", { action: "deleted", id });
58
+ return { status: "ok" };
59
+ },
60
+ "tasks.reorder": async (params) => {
61
+ const { status, orderedIds } = ReorderTasksSchema.parse(params);
62
+ taskStore.reorder(status, orderedIds);
63
+ emit("taskChange", { action: "reordered", status });
64
+ return { status: "ok" };
65
+ },
66
+ "tasks.archiveDone": async (params) => {
67
+ const { teamId, status } = ArchiveDoneSchema.parse(params ?? {});
68
+ const doneStatus = resolveDoneStatus(status);
69
+ const count = taskStore.archiveDone(teamId, doneStatus, "user");
70
+ emit("taskChange", { action: "archived", count });
71
+ return { archived: count };
72
+ },
73
+ "tasks.listComments": async (params) => {
74
+ const { taskId } = ListTaskCommentsSchema.parse(params);
75
+ const task = taskStore.getById(taskId);
76
+ if (!task)
77
+ throw new Error(`Task not found: ${taskId}`);
78
+ return { comments: taskStore.listComments(taskId) };
79
+ },
80
+ "tasks.addComment": async (params) => {
81
+ const { taskId, content } = AddTaskCommentSchema.parse(params);
82
+ const comment = taskStore.addComment(taskId, content, { actor: "user" });
83
+ if (!comment)
84
+ throw new Error(`Task not found: ${taskId}`);
85
+ emit("taskChange", { action: "commentAdded", taskId, comment });
86
+ return { comment };
87
+ },
88
+ "tasks.updateComment": async (params) => {
89
+ const { id, content } = UpdateTaskCommentSchema.parse(params);
90
+ const comment = taskStore.updateComment(id, content, { actor: "user" });
91
+ if (!comment)
92
+ throw new Error(`Comment not found: ${id}`);
93
+ emit("taskChange", { action: "commentUpdated", taskId: comment.taskId, comment });
94
+ return { comment };
95
+ },
96
+ "tasks.deleteComment": async (params) => {
97
+ const { id } = DeleteTaskCommentSchema.parse(params);
98
+ const comment = taskStore.deleteComment(id, { actor: "user" });
99
+ if (!comment)
100
+ throw new Error(`Comment not found: ${id}`);
101
+ emit("taskChange", { action: "commentDeleted", taskId: comment.taskId, id: comment.id });
102
+ return { status: "ok" };
103
+ },
104
+ "tasks.uploadAttachment": async (params) => {
105
+ const { name, type, data } = UploadAttachmentSchema.parse(params);
106
+ if (!ALLOWED_IMAGE_TYPES.has(type)) {
107
+ throw new Error("Unsupported image type. Allowed: png, jpg, gif, webp");
108
+ }
109
+ // Pre-check base64 string length to avoid unnecessary memory allocation
110
+ if (data.length > MAX_BASE64_LENGTH) {
111
+ throw new Error(`File exceeds ${MAX_FILE_SIZE / (1024 * 1024)}MB limit`);
112
+ }
113
+ const buf = Buffer.from(data, "base64");
114
+ if (buf.length > MAX_FILE_SIZE) {
115
+ throw new Error(`File exceeds ${MAX_FILE_SIZE / (1024 * 1024)}MB limit`);
116
+ }
117
+ const id = randomUUID();
118
+ const ext = EXT_FOR_MIME[type] ?? ".bin";
119
+ const diskName = `${id}${ext}`;
120
+ const filePath = join(ATTACHMENTS_DIR, diskName);
121
+ await writeFile(filePath, buf);
122
+ logger.info(`Attachment saved: ${diskName} (${buf.length} bytes)`);
123
+ const attachment = {
124
+ id: diskName,
125
+ name: name.replace(/[<>"'&]/g, "_").slice(0, 255),
126
+ type,
127
+ size: buf.length,
128
+ createdAt: Date.now(),
129
+ };
130
+ return attachment;
131
+ },
132
+ "tasks.getAttachment": async (params) => {
133
+ const { id } = GetAttachmentSchema.parse(params);
134
+ // Guard against path traversal
135
+ const safe = basename(id);
136
+ if (safe !== id || id.startsWith(".")) {
137
+ throw new Error("Invalid attachment id");
138
+ }
139
+ const filePath = join(ATTACHMENTS_DIR, safe);
140
+ let buf;
141
+ try {
142
+ buf = await readFile(filePath);
143
+ }
144
+ catch {
145
+ throw new Error("Attachment not found");
146
+ }
147
+ const ext = extname(filePath);
148
+ return { data: buf.toString("base64"), type: MIME_FOR_EXT[ext] ?? "application/octet-stream" };
149
+ },
150
+ };
151
+ }
@@ -0,0 +1,69 @@
1
+ import type { TeamStore } from "../../teams/store.js";
2
+ import type { TeamConfig, TaskStatusConfig } from "../../config/agent-config.js";
3
+ import type { MemoryStore } from "../../memory/store.js";
4
+ import type { EmbeddingProvider } from "../../memory/embedding.js";
5
+ export declare function teamMethods(teamStore: TeamStore, memoryStore?: MemoryStore | null, embeddingProvider?: EmbeddingProvider | null): {
6
+ /** List all teams with their agents. */
7
+ "teams.list": () => Promise<{
8
+ teams: {
9
+ agents: import("../../teams/types.js").AgentRow[];
10
+ id: string;
11
+ name: string;
12
+ color: string;
13
+ workspace: string;
14
+ statuses?: TaskStatusConfig[];
15
+ createdAt: number;
16
+ updatedAt: number;
17
+ }[];
18
+ }>;
19
+ /** Return teams in the TeamConfig[] format used by the UI. */
20
+ "teams.configs": () => Promise<{
21
+ teams: TeamConfig[];
22
+ }>;
23
+ /**
24
+ * Save a single team (create or update) including its agents.
25
+ * Accepts a full TeamConfig; handles agent diff internally.
26
+ */
27
+ "teams.save": (params: unknown) => Promise<{
28
+ teams: TeamConfig[];
29
+ }>;
30
+ /** Create a new team. */
31
+ "teams.create": (params: unknown) => Promise<{
32
+ team: import("../../teams/types.js").Team;
33
+ }>;
34
+ /** Update a team (rename / recolor / workspace / variables / statuses). */
35
+ "teams.update": (params: unknown) => Promise<{
36
+ team: import("../../teams/types.js").Team;
37
+ }>;
38
+ /** Delete a team and all its agents. */
39
+ "teams.delete": (params: unknown) => Promise<{
40
+ teams: TeamConfig[];
41
+ }>;
42
+ /** Add an agent to a team. */
43
+ "teams.createAgent": (params: unknown) => Promise<{
44
+ agent: import("../../teams/types.js").AgentRow;
45
+ }>;
46
+ /** Update an agent's configuration. */
47
+ "teams.updateAgent": (params: unknown) => Promise<{
48
+ agent: import("../../teams/types.js").AgentRow;
49
+ }>;
50
+ /** Remove an agent from a team. */
51
+ "teams.deleteAgent": (params: unknown) => Promise<{
52
+ status: string;
53
+ }>;
54
+ /** List memories for a team (paginated). */
55
+ "teams.memories.list": (params: unknown) => Promise<{
56
+ entries: import("../../memory/types.js").MemoryEntry[];
57
+ total: number;
58
+ }>;
59
+ /** Search memories scoped to a team (returns global + team). */
60
+ "teams.memories.search": (params: unknown) => Promise<{
61
+ facts: string[];
62
+ }>;
63
+ /** Manually add a memory for a team. */
64
+ "teams.memories.add": (params: unknown) => Promise<import("../../memory/explicit.js").SaveExplicitMemoryResult>;
65
+ /** Delete a single memory by ID (team-scoped for authorization). */
66
+ "teams.memories.delete": (params: unknown) => Promise<{
67
+ status: string;
68
+ }>;
69
+ };