camelagi 0.5.0

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 (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +224 -0
  3. package/camelagi.mjs +2 -0
  4. package/config.example.yaml +107 -0
  5. package/dist/agent/agent-openai.js +206 -0
  6. package/dist/agent/agent-openai.js.map +1 -0
  7. package/dist/agent/agent-sdk.js +209 -0
  8. package/dist/agent/agent-sdk.js.map +1 -0
  9. package/dist/agent/tool-adapter.js +31 -0
  10. package/dist/agent/tool-adapter.js.map +1 -0
  11. package/dist/agent/types.js +3 -0
  12. package/dist/agent/types.js.map +1 -0
  13. package/dist/agent.js +17 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/approval-forward.js +42 -0
  16. package/dist/approval-forward.js.map +1 -0
  17. package/dist/approvals.js +151 -0
  18. package/dist/approvals.js.map +1 -0
  19. package/dist/boot.js +34 -0
  20. package/dist/boot.js.map +1 -0
  21. package/dist/bootstrap.js +451 -0
  22. package/dist/bootstrap.js.map +1 -0
  23. package/dist/camelagi-gateway.mjs +93611 -0
  24. package/dist/camelagi-gateway.mjs.map +7 -0
  25. package/dist/channels/adapter.js +10 -0
  26. package/dist/channels/adapter.js.map +1 -0
  27. package/dist/channels/discord.js +232 -0
  28. package/dist/channels/discord.js.map +1 -0
  29. package/dist/channels/handler.js +349 -0
  30. package/dist/channels/handler.js.map +1 -0
  31. package/dist/channels/index.js +19 -0
  32. package/dist/channels/index.js.map +1 -0
  33. package/dist/channels/registry.js +71 -0
  34. package/dist/channels/registry.js.map +1 -0
  35. package/dist/channels/telegram.js +83 -0
  36. package/dist/channels/telegram.js.map +1 -0
  37. package/dist/channels/types.js +3 -0
  38. package/dist/channels/types.js.map +1 -0
  39. package/dist/chunker.js +102 -0
  40. package/dist/chunker.js.map +1 -0
  41. package/dist/cli/cmd-agents.js +65 -0
  42. package/dist/cli/cmd-agents.js.map +1 -0
  43. package/dist/cli/cmd-bootstrap.js +10 -0
  44. package/dist/cli/cmd-bootstrap.js.map +1 -0
  45. package/dist/cli/cmd-chat.js +32 -0
  46. package/dist/cli/cmd-chat.js.map +1 -0
  47. package/dist/cli/cmd-config.js +88 -0
  48. package/dist/cli/cmd-config.js.map +1 -0
  49. package/dist/cli/cmd-cron.js +120 -0
  50. package/dist/cli/cmd-cron.js.map +1 -0
  51. package/dist/cli/cmd-daemon.js +37 -0
  52. package/dist/cli/cmd-daemon.js.map +1 -0
  53. package/dist/cli/cmd-doctor.js +18 -0
  54. package/dist/cli/cmd-doctor.js.map +1 -0
  55. package/dist/cli/cmd-logs.js +30 -0
  56. package/dist/cli/cmd-logs.js.map +1 -0
  57. package/dist/cli/cmd-pairing.js +41 -0
  58. package/dist/cli/cmd-pairing.js.map +1 -0
  59. package/dist/cli/cmd-reset.js +39 -0
  60. package/dist/cli/cmd-reset.js.map +1 -0
  61. package/dist/cli/cmd-serve.js +30 -0
  62. package/dist/cli/cmd-serve.js.map +1 -0
  63. package/dist/cli/cmd-sessions.js +56 -0
  64. package/dist/cli/cmd-sessions.js.map +1 -0
  65. package/dist/cli/cmd-setup.js +11 -0
  66. package/dist/cli/cmd-setup.js.map +1 -0
  67. package/dist/cli/cmd-soul.js +43 -0
  68. package/dist/cli/cmd-soul.js.map +1 -0
  69. package/dist/cli/parse.js +50 -0
  70. package/dist/cli/parse.js.map +1 -0
  71. package/dist/cli/registry.js +15 -0
  72. package/dist/cli/registry.js.map +1 -0
  73. package/dist/cli.js +103 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/compact.js +92 -0
  76. package/dist/compact.js.map +1 -0
  77. package/dist/config.js +153 -0
  78. package/dist/config.js.map +1 -0
  79. package/dist/constants.js +21 -0
  80. package/dist/constants.js.map +1 -0
  81. package/dist/core/config.js +212 -0
  82. package/dist/core/config.js.map +1 -0
  83. package/dist/core/constants.js +21 -0
  84. package/dist/core/constants.js.map +1 -0
  85. package/dist/core/errors.js +5 -0
  86. package/dist/core/errors.js.map +1 -0
  87. package/dist/core/log.js +41 -0
  88. package/dist/core/log.js.map +1 -0
  89. package/dist/core/models.js +123 -0
  90. package/dist/core/models.js.map +1 -0
  91. package/dist/core/types.js +3 -0
  92. package/dist/core/types.js.map +1 -0
  93. package/dist/core/update-check.js +51 -0
  94. package/dist/core/update-check.js.map +1 -0
  95. package/dist/cron.js +81 -0
  96. package/dist/cron.js.map +1 -0
  97. package/dist/daemon.js +109 -0
  98. package/dist/daemon.js.map +1 -0
  99. package/dist/doctor.js +194 -0
  100. package/dist/doctor.js.map +1 -0
  101. package/dist/errors.js +5 -0
  102. package/dist/errors.js.map +1 -0
  103. package/dist/extensions/approval-forward.js +42 -0
  104. package/dist/extensions/approval-forward.js.map +1 -0
  105. package/dist/extensions/approvals.js +144 -0
  106. package/dist/extensions/approvals.js.map +1 -0
  107. package/dist/extensions/cron.js +306 -0
  108. package/dist/extensions/cron.js.map +1 -0
  109. package/dist/extensions/hooks.js +72 -0
  110. package/dist/extensions/hooks.js.map +1 -0
  111. package/dist/extensions/skills.js +97 -0
  112. package/dist/extensions/skills.js.map +1 -0
  113. package/dist/gateway/csrf.js +44 -0
  114. package/dist/gateway/csrf.js.map +1 -0
  115. package/dist/gateway/logger.js +81 -0
  116. package/dist/gateway/logger.js.map +1 -0
  117. package/dist/gateway/rate-limit.js +33 -0
  118. package/dist/gateway/rate-limit.js.map +1 -0
  119. package/dist/gateway/routes.js +315 -0
  120. package/dist/gateway/routes.js.map +1 -0
  121. package/dist/gateway/state.js +54 -0
  122. package/dist/gateway/state.js.map +1 -0
  123. package/dist/gateway/ws-handler.js +200 -0
  124. package/dist/gateway/ws-handler.js.map +1 -0
  125. package/dist/gateway-entry.js +16 -0
  126. package/dist/gateway-entry.js.map +1 -0
  127. package/dist/hooks.js +72 -0
  128. package/dist/hooks.js.map +1 -0
  129. package/dist/lanes.js +62 -0
  130. package/dist/lanes.js.map +1 -0
  131. package/dist/model.js +30 -0
  132. package/dist/model.js.map +1 -0
  133. package/dist/policy.js +22 -0
  134. package/dist/policy.js.map +1 -0
  135. package/dist/queue.js +45 -0
  136. package/dist/queue.js.map +1 -0
  137. package/dist/retry.js +96 -0
  138. package/dist/retry.js.map +1 -0
  139. package/dist/runs.js +83 -0
  140. package/dist/runs.js.map +1 -0
  141. package/dist/runtime/compact.js +99 -0
  142. package/dist/runtime/compact.js.map +1 -0
  143. package/dist/runtime/lanes.js +66 -0
  144. package/dist/runtime/lanes.js.map +1 -0
  145. package/dist/runtime/orchestrate.js +121 -0
  146. package/dist/runtime/orchestrate.js.map +1 -0
  147. package/dist/runtime/queue.js +50 -0
  148. package/dist/runtime/queue.js.map +1 -0
  149. package/dist/runtime/retry.js +127 -0
  150. package/dist/runtime/retry.js.map +1 -0
  151. package/dist/runtime/runs.js +105 -0
  152. package/dist/runtime/runs.js.map +1 -0
  153. package/dist/serve.js +209 -0
  154. package/dist/serve.js.map +1 -0
  155. package/dist/session.js +75 -0
  156. package/dist/session.js.map +1 -0
  157. package/dist/setup.js +254 -0
  158. package/dist/setup.js.map +1 -0
  159. package/dist/skills.js +89 -0
  160. package/dist/skills.js.map +1 -0
  161. package/dist/subagent.js +71 -0
  162. package/dist/subagent.js.map +1 -0
  163. package/dist/system-prompt.js +157 -0
  164. package/dist/system-prompt.js.map +1 -0
  165. package/dist/telegram/admin-bot.js +705 -0
  166. package/dist/telegram/admin-bot.js.map +1 -0
  167. package/dist/telegram/agent-bot.js +551 -0
  168. package/dist/telegram/agent-bot.js.map +1 -0
  169. package/dist/telegram/bot-approval.js +63 -0
  170. package/dist/telegram/bot-approval.js.map +1 -0
  171. package/dist/telegram/draft-stream.js +86 -0
  172. package/dist/telegram/draft-stream.js.map +1 -0
  173. package/dist/telegram/format.js +106 -0
  174. package/dist/telegram/format.js.map +1 -0
  175. package/dist/telegram/helpers.js +87 -0
  176. package/dist/telegram/helpers.js.map +1 -0
  177. package/dist/telegram/pairing-notify.js +52 -0
  178. package/dist/telegram/pairing-notify.js.map +1 -0
  179. package/dist/telegram/pairing.js +138 -0
  180. package/dist/telegram/pairing.js.map +1 -0
  181. package/dist/telegram/resolve.js +33 -0
  182. package/dist/telegram/resolve.js.map +1 -0
  183. package/dist/telegram/transcribe.js +77 -0
  184. package/dist/telegram/transcribe.js.map +1 -0
  185. package/dist/telegram/types.js +3 -0
  186. package/dist/telegram/types.js.map +1 -0
  187. package/dist/telegram/voice-wizard.js +84 -0
  188. package/dist/telegram/voice-wizard.js.map +1 -0
  189. package/dist/telegram/wizard.js +89 -0
  190. package/dist/telegram/wizard.js.map +1 -0
  191. package/dist/telegram/wizards.js +297 -0
  192. package/dist/telegram/wizards.js.map +1 -0
  193. package/dist/telegram-admin.js +800 -0
  194. package/dist/telegram-admin.js.map +1 -0
  195. package/dist/telegram.js +118 -0
  196. package/dist/telegram.js.map +1 -0
  197. package/dist/tools/cron.js +94 -0
  198. package/dist/tools/cron.js.map +1 -0
  199. package/dist/tools/edit.js +29 -0
  200. package/dist/tools/edit.js.map +1 -0
  201. package/dist/tools/exec.js +38 -0
  202. package/dist/tools/exec.js.map +1 -0
  203. package/dist/tools/fetch.js +28 -0
  204. package/dist/tools/fetch.js.map +1 -0
  205. package/dist/tools/index.js +16 -0
  206. package/dist/tools/index.js.map +1 -0
  207. package/dist/tools/memory.js +164 -0
  208. package/dist/tools/memory.js.map +1 -0
  209. package/dist/tools/patch.js +284 -0
  210. package/dist/tools/patch.js.map +1 -0
  211. package/dist/tools/read.js +26 -0
  212. package/dist/tools/read.js.map +1 -0
  213. package/dist/tools/search.js +62 -0
  214. package/dist/tools/search.js.map +1 -0
  215. package/dist/tools/subagent.js +48 -0
  216. package/dist/tools/subagent.js.map +1 -0
  217. package/dist/tools/write.js +22 -0
  218. package/dist/tools/write.js.map +1 -0
  219. package/dist/tui/commands.js +450 -0
  220. package/dist/tui/commands.js.map +1 -0
  221. package/dist/tui/components/assistant-message.js +26 -0
  222. package/dist/tui/components/assistant-message.js.map +1 -0
  223. package/dist/tui/components/chat-log.js +94 -0
  224. package/dist/tui/components/chat-log.js.map +1 -0
  225. package/dist/tui/components/custom-editor.js +40 -0
  226. package/dist/tui/components/custom-editor.js.map +1 -0
  227. package/dist/tui/components/hint-bar.js +13 -0
  228. package/dist/tui/components/hint-bar.js.map +1 -0
  229. package/dist/tui/components/tool-execution.js +73 -0
  230. package/dist/tui/components/tool-execution.js.map +1 -0
  231. package/dist/tui/components/user-message.js +19 -0
  232. package/dist/tui/components/user-message.js.map +1 -0
  233. package/dist/tui/components/welcome.js +147 -0
  234. package/dist/tui/components/welcome.js.map +1 -0
  235. package/dist/tui/context.js +3 -0
  236. package/dist/tui/context.js.map +1 -0
  237. package/dist/tui/theme.js +91 -0
  238. package/dist/tui/theme.js.map +1 -0
  239. package/dist/tui/tui.js +389 -0
  240. package/dist/tui/tui.js.map +1 -0
  241. package/dist/tui/ws-handler.js +154 -0
  242. package/dist/tui/ws-handler.js.map +1 -0
  243. package/dist/types.js +3 -0
  244. package/dist/types.js.map +1 -0
  245. package/dist/usage.js +88 -0
  246. package/dist/usage.js.map +1 -0
  247. package/dist/workspace.js +245 -0
  248. package/dist/workspace.js.map +1 -0
  249. package/package.json +74 -0
package/dist/runs.js ADDED
@@ -0,0 +1,83 @@
1
+ // Run tracking: prevents concurrent runs on the same session
2
+ import { QUEUE_WAIT_TIMEOUT_MS } from "./core/constants.js";
3
+ // Primary index: runId -> handle
4
+ const runsByRunId = new Map();
5
+ // Secondary index: sessionId -> runId (latest)
6
+ const sessionToRunId = new Map();
7
+ const waiters = new Map();
8
+ let runCounter = 0;
9
+ export function generateRunId() {
10
+ return `run-${Date.now()}-${++runCounter}`;
11
+ }
12
+ export function setActiveRun(sessionId, handle) {
13
+ // Abort any existing run for this session
14
+ const existingRunId = sessionToRunId.get(sessionId);
15
+ if (existingRunId) {
16
+ const existing = runsByRunId.get(existingRunId);
17
+ if (existing)
18
+ existing.abort();
19
+ runsByRunId.delete(existingRunId);
20
+ }
21
+ runsByRunId.set(handle.runId, handle);
22
+ sessionToRunId.set(sessionId, handle.runId);
23
+ }
24
+ export function clearActiveRun(runId) {
25
+ const handle = runsByRunId.get(runId);
26
+ if (!handle)
27
+ return;
28
+ runsByRunId.delete(runId);
29
+ // Only clear session mapping if this is still the latest run
30
+ if (sessionToRunId.get(handle.sessionId) === runId) {
31
+ sessionToRunId.delete(handle.sessionId);
32
+ }
33
+ // Notify waiters for this session
34
+ const sessionWaiters = waiters.get(handle.sessionId);
35
+ if (sessionWaiters) {
36
+ for (const resolve of sessionWaiters)
37
+ resolve(true);
38
+ waiters.delete(handle.sessionId);
39
+ }
40
+ }
41
+ export function isRunActive(sessionId) {
42
+ const runId = sessionToRunId.get(sessionId);
43
+ return runId !== undefined && runsByRunId.has(runId);
44
+ }
45
+ export function getActiveRun(sessionId) {
46
+ const runId = sessionToRunId.get(sessionId);
47
+ return runId ? runsByRunId.get(runId) : undefined;
48
+ }
49
+ export function abortRun(sessionId) {
50
+ const runId = sessionToRunId.get(sessionId);
51
+ if (!runId)
52
+ return false;
53
+ const handle = runsByRunId.get(runId);
54
+ if (handle) {
55
+ handle.abort();
56
+ clearActiveRun(runId);
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+ export function waitForRunEnd(sessionId, timeoutMs = QUEUE_WAIT_TIMEOUT_MS) {
62
+ if (!isRunActive(sessionId))
63
+ return Promise.resolve(true);
64
+ return new Promise((resolve) => {
65
+ const timer = setTimeout(() => {
66
+ const set = waiters.get(sessionId);
67
+ if (set)
68
+ set.delete(wrappedResolve);
69
+ resolve(false);
70
+ }, timeoutMs);
71
+ const wrappedResolve = (ended) => {
72
+ clearTimeout(timer);
73
+ resolve(ended);
74
+ };
75
+ if (!waiters.has(sessionId))
76
+ waiters.set(sessionId, new Set());
77
+ waiters.get(sessionId).add(wrappedResolve);
78
+ });
79
+ }
80
+ export function getActiveRunCount() {
81
+ return runsByRunId.size;
82
+ }
83
+ //# sourceMappingURL=runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../src/runs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ // Context compaction: summarize old messages when context gets too large
2
+ import { chatDirect } from "../model.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { agentMemoryDir } from "../workspace.js";
6
+ import { CHARS_PER_TOKEN, COMPACTION_TRIGGER_RATIO, MEMORY_FLUSH_MAX_CHARS } from "../core/constants.js";
7
+ function estimateTokens(messages) {
8
+ let chars = 0;
9
+ for (const msg of messages) {
10
+ chars += msg.content.length;
11
+ }
12
+ return Math.ceil(chars / CHARS_PER_TOKEN);
13
+ }
14
+ function splitHistory(messages, keepTurns) {
15
+ if (keepTurns <= 0)
16
+ return { old: messages, recent: [] };
17
+ const turnStarts = [];
18
+ for (let i = 0; i < messages.length; i++) {
19
+ if (messages[i].role === "user") {
20
+ turnStarts.push(i);
21
+ }
22
+ }
23
+ if (turnStarts.length <= keepTurns) {
24
+ return { old: [], recent: messages };
25
+ }
26
+ const cutoff = turnStarts[turnStarts.length - keepTurns];
27
+ return {
28
+ old: messages.slice(0, cutoff),
29
+ recent: messages.slice(cutoff),
30
+ };
31
+ }
32
+ const COMPACT_PROMPT = `Summarize the following conversation history concisely. Preserve:
33
+ - Key facts, decisions, and context established
34
+ - Important file paths, names, and technical details mentioned
35
+ - Current state of any ongoing tasks
36
+ - User preferences or instructions given
37
+
38
+ Be concise but don't lose critical context. Output only the summary, no preamble.`;
39
+ export async function compactHistory(client, model, history, opts) {
40
+ if (!opts.enabled)
41
+ return null;
42
+ const tokens = estimateTokens(history);
43
+ if (tokens < opts.maxTokens * COMPACTION_TRIGGER_RATIO)
44
+ return null;
45
+ const { old, recent } = splitHistory(history, opts.keepTurns);
46
+ if (old.length === 0)
47
+ return null;
48
+ await memoryFlush(client, model, old, opts.agentId);
49
+ const oldText = old.map((m) => {
50
+ return `[${m.role}]: ${m.content}`;
51
+ }).join("\n\n");
52
+ const summaryResult = await chatDirect(client, model, COMPACT_PROMPT, oldText);
53
+ const summaryMessage = {
54
+ role: "user",
55
+ content: `[Previous conversation summary]\n${summaryResult.content}\n[End of summary — conversation continues below]`,
56
+ };
57
+ const compacted = [summaryMessage, ...recent];
58
+ // Validate: compaction must actually reduce size
59
+ const compactedTokens = estimateTokens(compacted);
60
+ if (compactedTokens >= tokens) {
61
+ process.stderr.write(`\x1b[33m⚠ Compaction skipped: result (${compactedTokens} tokens) >= original (${tokens} tokens)\x1b[0m\n`);
62
+ return null;
63
+ }
64
+ return compacted;
65
+ }
66
+ // --- Memory flush ---
67
+ const FLUSH_PROMPT = `You are about to lose the following conversation history due to context compaction.
68
+ Extract any durable facts worth remembering: decisions made, user preferences discovered,
69
+ project details, file paths, names, dates, or anything the user would expect you to know later.
70
+
71
+ Format as concise bullet points. If nothing is worth saving, reply with "NOTHING".`;
72
+ async function memoryFlush(client, model, oldMessages, agentId) {
73
+ if (oldMessages.length === 0)
74
+ return;
75
+ try {
76
+ const oldText = oldMessages.map((m) => {
77
+ return `[${m.role}]: ${m.content}`;
78
+ }).join("\n\n");
79
+ if (oldText.length < 200)
80
+ return;
81
+ const response = await chatDirect(client, model, FLUSH_PROMPT, oldText.slice(0, MEMORY_FLUSH_MAX_CHARS));
82
+ const extracted = response.content;
83
+ if (extracted.trim() === "NOTHING" || extracted.trim().length < 10)
84
+ return;
85
+ const rootDir = agentMemoryDir(agentId);
86
+ const memoryDir = path.join(rootDir, "memory");
87
+ fs.mkdirSync(memoryDir, { recursive: true });
88
+ const today = new Date().toISOString().split("T")[0];
89
+ const dailyFile = path.join(memoryDir, `${today}.md`);
90
+ const header = fs.existsSync(dailyFile) ? "" : `# ${today}\n\n`;
91
+ const timestamp = new Date().toTimeString().split(" ")[0];
92
+ const entry = `${header}## ${timestamp} (auto-flush)\n\n${extracted}\n\n`;
93
+ fs.appendFileSync(dailyFile, entry);
94
+ }
95
+ catch {
96
+ // Memory flush is best-effort
97
+ }
98
+ }
99
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/runtime/compact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ // Concurrency lanes: limit parallel agent runs by type
2
+ export var Lane;
3
+ (function (Lane) {
4
+ Lane["Main"] = "main";
5
+ Lane["Cron"] = "cron";
6
+ Lane["Subagent"] = "subagent";
7
+ })(Lane || (Lane = {}));
8
+ export function createLaneManager() {
9
+ const lanes = new Map();
10
+ function configureLane(lane, limit) {
11
+ const existing = lanes.get(lane);
12
+ if (existing) {
13
+ existing.limit = limit;
14
+ }
15
+ else {
16
+ lanes.set(lane, { limit, active: 0, queue: [] });
17
+ }
18
+ }
19
+ function releaseLane(lane) {
20
+ const config = lanes.get(lane);
21
+ if (!config)
22
+ return;
23
+ config.active--;
24
+ // Wake up next waiter
25
+ const next = config.queue.shift();
26
+ if (next)
27
+ next();
28
+ }
29
+ async function acquireLane(lane) {
30
+ let config = lanes.get(lane);
31
+ if (!config) {
32
+ // Default: unlimited
33
+ config = { limit: Infinity, active: 0, queue: [] };
34
+ lanes.set(lane, config);
35
+ }
36
+ if (config.active < config.limit) {
37
+ config.active++;
38
+ return () => releaseLane(lane);
39
+ }
40
+ // Wait for a slot
41
+ await new Promise((resolve) => {
42
+ config.queue.push(resolve);
43
+ });
44
+ config.active++;
45
+ return () => releaseLane(lane);
46
+ }
47
+ function getLaneStats() {
48
+ const stats = {};
49
+ for (const [lane, config] of lanes) {
50
+ stats[lane] = {
51
+ active: config.active,
52
+ limit: config.limit === Infinity ? -1 : config.limit,
53
+ queued: config.queue.length,
54
+ };
55
+ }
56
+ return stats;
57
+ }
58
+ function reset() {
59
+ lanes.clear();
60
+ }
61
+ return { configureLane, acquireLane, getLaneStats, reset };
62
+ }
63
+ // Backward-compat singleton
64
+ const defaultManager = createLaneManager();
65
+ export const { configureLane, acquireLane, getLaneStats } = defaultManager;
66
+ //# sourceMappingURL=lanes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lanes.js","sourceRoot":"","sources":["../../src/runtime/lanes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ // Chat orchestrator: single source of truth for the chat flow
2
+ //
3
+ // Deduplicates the check-active → queue → acquire-lane → prepare-history →
4
+ // run-agent-with-retry → save-messages → release sequence that was previously
5
+ // duplicated in routes.ts, ws-handler.ts, and agent-bot.ts.
6
+ import { runAgent } from "../agent.js";
7
+ import { loadMessages, saveMessage } from "../session.js";
8
+ import { setActiveRun, clearActiveRun, isRunActive, generateRunId } from "./runs.js";
9
+ import { queueOrProcess, drainQueue } from "./queue.js";
10
+ import { compactHistory } from "./compact.js";
11
+ import { withRetry } from "./retry.js";
12
+ import { acquireLane, Lane } from "./lanes.js";
13
+ /**
14
+ * Orchestrate a single chat turn. Handles:
15
+ * - Queue check (if a run is already active on this session)
16
+ * - Lane acquisition
17
+ * - History loading + compaction
18
+ * - Agent execution with retry
19
+ * - Message persistence
20
+ * - Cleanup (clear run, release lane)
21
+ */
22
+ export async function orchestrate(opts) {
23
+ const { sessionId, message, config, systemPrompt, client, signal, onEvent, onRetry, onCompact, agentId, resumeSessionId, label, } = opts;
24
+ const model = opts.model ?? config.model;
25
+ const agentSystemPrompt = opts.agentSystemPrompt ?? systemPrompt;
26
+ const thinking = opts.thinking ?? config.thinking;
27
+ const effort = opts.effort ?? config.effort;
28
+ const maxTurns = opts.maxTurns ?? config.maxTurns;
29
+ // If a run is already active, queue this message
30
+ if (isRunActive(sessionId)) {
31
+ const queueResult = await queueOrProcess(sessionId, message);
32
+ if (queueResult.queued) {
33
+ const response = await queueResult.promise;
34
+ return { response, runId: "", sessionId, usage: null, queued: true };
35
+ }
36
+ }
37
+ const release = await acquireLane(Lane.Main);
38
+ const runId = generateRunId();
39
+ const abortController = signal ? new AbortController() : undefined;
40
+ if (signal && abortController) {
41
+ if (signal.aborted)
42
+ abortController.abort();
43
+ else
44
+ signal.addEventListener("abort", () => abortController.abort(), { once: true });
45
+ }
46
+ let streaming = false;
47
+ setActiveRun(sessionId, {
48
+ sessionId,
49
+ runId,
50
+ startedAt: Date.now(),
51
+ abort: () => abortController?.abort(),
52
+ isStreaming: () => streaming,
53
+ });
54
+ try {
55
+ // Load + compact history
56
+ let history = loadMessages(sessionId);
57
+ const compacted = await compactHistory(client, model, history, { ...config.compaction, agentId });
58
+ if (compacted) {
59
+ onCompact?.(history.length, compacted.length);
60
+ history = compacted;
61
+ }
62
+ streaming = true;
63
+ const result = await withRetry(() => runAgent(config.apiKey, model, agentSystemPrompt, history, message, {
64
+ maxTurns,
65
+ timeoutMs: config.timeoutSeconds * 1000,
66
+ signal: abortController?.signal,
67
+ onEvent,
68
+ toolPolicy: config.tools,
69
+ hooksEnabled: config.hooks.enabled,
70
+ sessionId,
71
+ thinking,
72
+ effort,
73
+ provider: config.provider,
74
+ baseUrl: config.baseUrl,
75
+ approvals: config.approvals,
76
+ ...(Object.keys(config.mcp.servers).length > 0 && { mcpServers: config.mcp.servers }),
77
+ ...(config.maxBudgetUsd && { maxBudgetUsd: config.maxBudgetUsd }),
78
+ ...(resumeSessionId && { resumeSessionId }),
79
+ ...(agentId && { agentId }),
80
+ }), {
81
+ maxRetries: config.retry.maxRetries,
82
+ backoffMs: config.retry.backoffMs,
83
+ onRetry: onRetry
84
+ ? (attempt, kind) => onRetry(attempt, kind)
85
+ : undefined,
86
+ onCompact: async () => {
87
+ const h = loadMessages(sessionId);
88
+ await compactHistory(client, model, h, { ...config.compaction, enabled: true, agentId });
89
+ },
90
+ });
91
+ streaming = false;
92
+ // Persist messages
93
+ saveMessage(sessionId, { role: "user", content: message }, model, label);
94
+ if (result.response) {
95
+ saveMessage(sessionId, { role: "assistant", content: result.response }, model, label);
96
+ }
97
+ return {
98
+ response: result.response,
99
+ runId,
100
+ sessionId,
101
+ usage: result.usage,
102
+ sdkSessionId: result.sessionId,
103
+ };
104
+ }
105
+ finally {
106
+ clearActiveRun(runId);
107
+ release();
108
+ // Drain queued messages: process the next one, reject the rest
109
+ const queued = drainQueue(sessionId);
110
+ if (queued.length > 0) {
111
+ const next = queued[0];
112
+ orchestrate({ ...opts, message: next.text })
113
+ .then((r) => next.resolve(r.response))
114
+ .catch((err) => next.reject(err instanceof Error ? err : new Error(String(err))));
115
+ for (const q of queued.slice(1)) {
116
+ q.reject(new Error("Superseded by newer message"));
117
+ }
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=orchestrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrate.js","sourceRoot":"","sources":["../../src/runtime/orchestrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ // Message queue: per-session queue for inbound messages while agent is running
2
+ import { isRunActive, waitForRunEnd } from "./runs.js";
3
+ export function createMessageQueue() {
4
+ const queues = new Map();
5
+ function enqueueMessage(sessionId, text) {
6
+ return new Promise((resolve, reject) => {
7
+ if (!queues.has(sessionId))
8
+ queues.set(sessionId, []);
9
+ queues.get(sessionId).push({ text, resolve, reject, enqueuedAt: Date.now() });
10
+ });
11
+ }
12
+ function getQueueLength(sessionId) {
13
+ return queues.get(sessionId)?.length ?? 0;
14
+ }
15
+ function drainQueue(sessionId) {
16
+ const queue = queues.get(sessionId);
17
+ if (!queue || queue.length === 0)
18
+ return [];
19
+ queues.delete(sessionId);
20
+ return queue;
21
+ }
22
+ function clearQueue(sessionId) {
23
+ const queue = queues.get(sessionId);
24
+ if (queue) {
25
+ for (const msg of queue) {
26
+ msg.reject(new Error("Queue cleared"));
27
+ }
28
+ queues.delete(sessionId);
29
+ }
30
+ }
31
+ async function queueOrProcess(sessionId, text) {
32
+ if (!isRunActive(sessionId)) {
33
+ return { queued: false };
34
+ }
35
+ // Run is active — enqueue and wait for run to end
36
+ const promise = enqueueMessage(sessionId, text);
37
+ await waitForRunEnd(sessionId);
38
+ return { queued: true, promise };
39
+ }
40
+ function reset() {
41
+ for (const [sid] of queues) {
42
+ clearQueue(sid);
43
+ }
44
+ }
45
+ return { enqueueMessage, getQueueLength, drainQueue, clearQueue, queueOrProcess, reset };
46
+ }
47
+ // Backward-compat singleton
48
+ const defaultQueue = createMessageQueue();
49
+ export const { enqueueMessage, getQueueLength, drainQueue, clearQueue, queueOrProcess } = defaultQueue;
50
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/runtime/queue.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAkBvD,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElD,SAAS,cAAc,CAAC,SAAiB,EAAE,IAAY;QACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,cAAc,CAAC,SAAiB;QACvC,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,SAAS,UAAU,CAAC,SAAiB;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,UAAU,CAAC,SAAiB;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,KAAK,UAAU,cAAc,CAC3B,SAAiB,EACjB,IAAY;QAEZ,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,kDAAkD;QAClD,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QAC/B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACnC,CAAC;IAED,SAAS,KAAK;QACZ,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;YAC3B,UAAU,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAC3F,CAAC;AAED,4BAA4B;AAC5B,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;AAC1C,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,YAAY,CAAC"}
@@ -0,0 +1,127 @@
1
+ // Error classification + retry logic for agent runs
2
+ /** Extract HTTP status code from SDK error objects or message */
3
+ function extractStatusCode(err) {
4
+ // OpenAI SDK and Anthropic SDK both set .status on errors
5
+ const status = err.status ?? err.statusCode;
6
+ if (typeof status === "number")
7
+ return status;
8
+ // Fallback: extract 3-digit HTTP codes from message — but only when
9
+ // they appear as standalone tokens (e.g. "Error 429" not "model-429b")
10
+ const match = err.message.match(/\b([4-5]\d{2})\b/);
11
+ return match ? Number(match[1]) : undefined;
12
+ }
13
+ export function classifyError(err) {
14
+ const msg = err.message.toLowerCase();
15
+ const status = extractStatusCode(err);
16
+ // 1. User abort — exact match only (not substring) to avoid collision with timeout
17
+ if (msg === "aborted" || msg === "the operation was aborted" || msg === "this operation was aborted") {
18
+ return "abort";
19
+ }
20
+ // Also check for AbortError name (DOMException style)
21
+ if (err.name === "AbortError") {
22
+ return "abort";
23
+ }
24
+ // 2. Status-code-first classification (more reliable than string matching)
25
+ if (status) {
26
+ if (status === 401 || status === 403)
27
+ return "auth";
28
+ if (status === 402)
29
+ return "billing";
30
+ if (status === 429)
31
+ return "rate_limit";
32
+ if (status === 400 || status === 422)
33
+ return "format";
34
+ if (status === 408)
35
+ return "timeout";
36
+ if (status >= 500 && status < 600)
37
+ return "server_error";
38
+ }
39
+ // 3. String-based fallbacks for errors without status codes
40
+ // Auth
41
+ if (msg.includes("unauthorized") || msg.includes("invalid api key") || msg.includes("token expired")) {
42
+ return "auth";
43
+ }
44
+ // Billing
45
+ if (msg.includes("insufficient") || msg.includes("payment required") || msg.includes("billing")) {
46
+ return "billing";
47
+ }
48
+ // Rate limit
49
+ if (msg.includes("rate limit") || msg.includes("too many requests")
50
+ || msg.includes("quota") || msg.includes("resource exhausted")) {
51
+ return "rate_limit";
52
+ }
53
+ // Context overflow
54
+ if (msg.includes("context") && (msg.includes("exceeded") || msg.includes("too large"))
55
+ || msg.includes("prompt is too long") || msg.includes("request too large")
56
+ || msg.includes("maximum context length")) {
57
+ return "overflow";
58
+ }
59
+ // Timeout (check after abort to avoid misclassification)
60
+ if (msg.includes("timeout") || msg.includes("deadline exceeded") || msg.includes("etimedout")) {
61
+ return "timeout";
62
+ }
63
+ // Server errors
64
+ if (msg.includes("service unavailable") || msg.includes("internal server error")
65
+ || msg.includes("bad gateway")) {
66
+ return "server_error";
67
+ }
68
+ // Format errors
69
+ if (msg.includes("invalid request") || msg.includes("validation")) {
70
+ return "format";
71
+ }
72
+ return "unknown";
73
+ }
74
+ export function isRetryable(kind) {
75
+ return kind === "rate_limit" || kind === "timeout" || kind === "server_error";
76
+ }
77
+ const DEFAULT_MAX_BACKOFF_MS = 30_000;
78
+ /**
79
+ * Wrap an async function with retry logic.
80
+ * - rate_limit/timeout/server_error: retry with capped exponential backoff
81
+ * - overflow: call onCompact() then retry once
82
+ * - auth/billing/format/abort: fail immediately
83
+ */
84
+ export async function withRetry(fn, opts) {
85
+ let lastError;
86
+ let overflowRetried = false;
87
+ const maxBackoff = opts.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
88
+ for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
89
+ try {
90
+ return await fn();
91
+ }
92
+ catch (err) {
93
+ lastError = err instanceof Error ? err : new Error(String(err));
94
+ const kind = classifyError(lastError);
95
+ // Non-retryable errors
96
+ if (kind === "auth" || kind === "billing" || kind === "format" || kind === "abort") {
97
+ throw lastError;
98
+ }
99
+ // Overflow: compact and retry once
100
+ if (kind === "overflow" && !overflowRetried && opts.onCompact) {
101
+ overflowRetried = true;
102
+ opts.onRetry?.(attempt, kind, lastError);
103
+ await opts.onCompact();
104
+ continue;
105
+ }
106
+ // Last attempt — don't retry
107
+ if (attempt === opts.maxRetries)
108
+ break;
109
+ // Retryable: capped exponential backoff
110
+ if (isRetryable(kind)) {
111
+ opts.onRetry?.(attempt, kind, lastError);
112
+ const delay = Math.min(opts.backoffMs * Math.pow(2, attempt), maxBackoff);
113
+ await new Promise((r) => setTimeout(r, delay));
114
+ continue;
115
+ }
116
+ // Unknown errors: retry once then fail
117
+ if (kind === "unknown" && attempt === 0) {
118
+ opts.onRetry?.(attempt, kind, lastError);
119
+ await new Promise((r) => setTimeout(r, opts.backoffMs));
120
+ continue;
121
+ }
122
+ break;
123
+ }
124
+ }
125
+ throw lastError;
126
+ }
127
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/runtime/retry.ts"],"names":[],"mappings":"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"}