@hybridaione/hybridclaw 0.1.5

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 (196) hide show
  1. package/.env.example +14 -0
  2. package/.github/workflows/pages.yml +41 -0
  3. package/AGENTS.md +24 -0
  4. package/CHANGELOG.md +113 -0
  5. package/LICENSE +21 -0
  6. package/README.md +226 -0
  7. package/SECURITY.md +67 -0
  8. package/config.example.json +62 -0
  9. package/container/Dockerfile +23 -0
  10. package/container/package-lock.json +246 -0
  11. package/container/package.json +17 -0
  12. package/container/src/hybridai-client.ts +38 -0
  13. package/container/src/index.ts +198 -0
  14. package/container/src/ipc.ts +37 -0
  15. package/container/src/tools.ts +1008 -0
  16. package/container/src/types.ts +74 -0
  17. package/container/src/web-fetch.ts +389 -0
  18. package/container/tsconfig.json +16 -0
  19. package/dist/agent.d.ts +3 -0
  20. package/dist/agent.d.ts.map +1 -0
  21. package/dist/agent.js +21 -0
  22. package/dist/agent.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +32 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/config.d.ts +38 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +107 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/container-runner.d.ts +11 -0
  32. package/dist/container-runner.d.ts.map +1 -0
  33. package/dist/container-runner.js +246 -0
  34. package/dist/container-runner.js.map +1 -0
  35. package/dist/conversation.d.ts +18 -0
  36. package/dist/conversation.d.ts.map +1 -0
  37. package/dist/conversation.js +29 -0
  38. package/dist/conversation.js.map +1 -0
  39. package/dist/db.d.ts +29 -0
  40. package/dist/db.d.ts.map +1 -0
  41. package/dist/db.js +205 -0
  42. package/dist/db.js.map +1 -0
  43. package/dist/discord.d.ts +17 -0
  44. package/dist/discord.d.ts.map +1 -0
  45. package/dist/discord.js +115 -0
  46. package/dist/discord.js.map +1 -0
  47. package/dist/env.d.ts +6 -0
  48. package/dist/env.d.ts.map +1 -0
  49. package/dist/env.js +36 -0
  50. package/dist/env.js.map +1 -0
  51. package/dist/gateway-client.d.ts +8 -0
  52. package/dist/gateway-client.d.ts.map +1 -0
  53. package/dist/gateway-client.js +57 -0
  54. package/dist/gateway-client.js.map +1 -0
  55. package/dist/gateway-service.d.ts +23 -0
  56. package/dist/gateway-service.d.ts.map +1 -0
  57. package/dist/gateway-service.js +360 -0
  58. package/dist/gateway-service.js.map +1 -0
  59. package/dist/gateway-types.d.ts +40 -0
  60. package/dist/gateway-types.d.ts.map +1 -0
  61. package/dist/gateway-types.js +6 -0
  62. package/dist/gateway-types.js.map +1 -0
  63. package/dist/gateway.d.ts +2 -0
  64. package/dist/gateway.d.ts.map +1 -0
  65. package/dist/gateway.js +138 -0
  66. package/dist/gateway.js.map +1 -0
  67. package/dist/hatch.d.ts +7 -0
  68. package/dist/hatch.d.ts.map +1 -0
  69. package/dist/hatch.js +99 -0
  70. package/dist/hatch.js.map +1 -0
  71. package/dist/health.d.ts +2 -0
  72. package/dist/health.d.ts.map +1 -0
  73. package/dist/health.js +169 -0
  74. package/dist/health.js.map +1 -0
  75. package/dist/heartbeat.d.ts +3 -0
  76. package/dist/heartbeat.d.ts.map +1 -0
  77. package/dist/heartbeat.js +103 -0
  78. package/dist/heartbeat.js.map +1 -0
  79. package/dist/hybridai-bots.d.ts +5 -0
  80. package/dist/hybridai-bots.d.ts.map +1 -0
  81. package/dist/hybridai-bots.js +34 -0
  82. package/dist/hybridai-bots.js.map +1 -0
  83. package/dist/index.d.ts +2 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +60 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/ipc.d.ts +33 -0
  88. package/dist/ipc.d.ts.map +1 -0
  89. package/dist/ipc.js +142 -0
  90. package/dist/ipc.js.map +1 -0
  91. package/dist/logger.d.ts +3 -0
  92. package/dist/logger.d.ts.map +1 -0
  93. package/dist/logger.js +21 -0
  94. package/dist/logger.js.map +1 -0
  95. package/dist/mount-security.d.ts +28 -0
  96. package/dist/mount-security.d.ts.map +1 -0
  97. package/dist/mount-security.js +187 -0
  98. package/dist/mount-security.js.map +1 -0
  99. package/dist/onboarding.d.ts +7 -0
  100. package/dist/onboarding.d.ts.map +1 -0
  101. package/dist/onboarding.js +445 -0
  102. package/dist/onboarding.js.map +1 -0
  103. package/dist/prompt-hooks.d.ts +17 -0
  104. package/dist/prompt-hooks.d.ts.map +1 -0
  105. package/dist/prompt-hooks.js +83 -0
  106. package/dist/prompt-hooks.js.map +1 -0
  107. package/dist/runtime-config.d.ts +78 -0
  108. package/dist/runtime-config.d.ts.map +1 -0
  109. package/dist/runtime-config.js +471 -0
  110. package/dist/runtime-config.js.map +1 -0
  111. package/dist/scheduled-task-runner.d.ts +11 -0
  112. package/dist/scheduled-task-runner.d.ts.map +1 -0
  113. package/dist/scheduled-task-runner.js +16 -0
  114. package/dist/scheduled-task-runner.js.map +1 -0
  115. package/dist/scheduler.d.ts +11 -0
  116. package/dist/scheduler.d.ts.map +1 -0
  117. package/dist/scheduler.js +165 -0
  118. package/dist/scheduler.js.map +1 -0
  119. package/dist/session-maintenance.d.ts +9 -0
  120. package/dist/session-maintenance.d.ts.map +1 -0
  121. package/dist/session-maintenance.js +168 -0
  122. package/dist/session-maintenance.js.map +1 -0
  123. package/dist/session-transcripts.d.ts +11 -0
  124. package/dist/session-transcripts.d.ts.map +1 -0
  125. package/dist/session-transcripts.js +32 -0
  126. package/dist/session-transcripts.js.map +1 -0
  127. package/dist/side-effects.d.ts +3 -0
  128. package/dist/side-effects.d.ts.map +1 -0
  129. package/dist/side-effects.js +30 -0
  130. package/dist/side-effects.js.map +1 -0
  131. package/dist/skills.d.ts +32 -0
  132. package/dist/skills.d.ts.map +1 -0
  133. package/dist/skills.js +376 -0
  134. package/dist/skills.js.map +1 -0
  135. package/dist/tui.d.ts +2 -0
  136. package/dist/tui.d.ts.map +1 -0
  137. package/dist/tui.js +305 -0
  138. package/dist/tui.js.map +1 -0
  139. package/dist/types.d.ts +132 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +3 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/workspace.d.ts +25 -0
  144. package/dist/workspace.d.ts.map +1 -0
  145. package/dist/workspace.js +154 -0
  146. package/dist/workspace.js.map +1 -0
  147. package/docs/chat.html +929 -0
  148. package/docs/hai_logo_free.png +0 -0
  149. package/docs/hero.png +0 -0
  150. package/docs/index.html +1213 -0
  151. package/package.json +34 -0
  152. package/skills/current-time/SKILL.md +26 -0
  153. package/skills/iss-position/SKILL.md +46 -0
  154. package/skills/iss-position/agents/openai.yaml +3 -0
  155. package/skills/iss-position/scripts/get_iss_position.py +107 -0
  156. package/skills/repo-orientation/SKILL.md +74 -0
  157. package/src/agent.ts +35 -0
  158. package/src/cli.ts +35 -0
  159. package/src/config.ts +137 -0
  160. package/src/container-runner.ts +305 -0
  161. package/src/conversation.ts +49 -0
  162. package/src/db.ts +290 -0
  163. package/src/discord.ts +156 -0
  164. package/src/env.ts +36 -0
  165. package/src/gateway-client.ts +73 -0
  166. package/src/gateway-service.ts +456 -0
  167. package/src/gateway-types.ts +47 -0
  168. package/src/gateway.ts +199 -0
  169. package/src/health.ts +189 -0
  170. package/src/heartbeat.ts +121 -0
  171. package/src/hybridai-bots.ts +48 -0
  172. package/src/ipc.ts +163 -0
  173. package/src/logger.ts +26 -0
  174. package/src/mount-security.ts +216 -0
  175. package/src/onboarding.ts +569 -0
  176. package/src/prompt-hooks.ts +113 -0
  177. package/src/runtime-config.ts +588 -0
  178. package/src/scheduled-task-runner.ts +26 -0
  179. package/src/scheduler.ts +196 -0
  180. package/src/session-maintenance.ts +263 -0
  181. package/src/session-transcripts.ts +45 -0
  182. package/src/side-effects.ts +41 -0
  183. package/src/skills.ts +429 -0
  184. package/src/tui.ts +327 -0
  185. package/src/types.ts +135 -0
  186. package/src/workspace.ts +171 -0
  187. package/templates/AGENTS.md +104 -0
  188. package/templates/BOOT.md +3 -0
  189. package/templates/BOOTSTRAP.md +54 -0
  190. package/templates/HEARTBEAT.md +5 -0
  191. package/templates/IDENTITY.md +18 -0
  192. package/templates/MEMORY.md +19 -0
  193. package/templates/SOUL.md +36 -0
  194. package/templates/TOOLS.md +22 -0
  195. package/templates/USER.md +17 -0
  196. package/tsconfig.json +18 -0
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Scheduler — timer-based, arms for exact next-fire time.
3
+ *
4
+ * Instead of polling every 60s, computes when the next task is due and
5
+ * sets a single setTimeout for that moment. Re-arms after every tick
6
+ * and whenever a task is added/removed via rearmScheduler().
7
+ */
8
+ import { CronExpressionParser } from 'cron-parser';
9
+ import { deleteTask, getAllEnabledTasks, updateTaskLastRun } from './db.js';
10
+ import { logger } from './logger.js';
11
+ const MAX_TIMER_DELAY_MS = 300_000; // 5 min safety net for clock drift
12
+ let timer = null;
13
+ let taskRunner = null;
14
+ let ticking = false;
15
+ // --- Prompt framing (OpenClaw style) ---
16
+ function formatFireTime() {
17
+ return new Date().toLocaleString('en-US', {
18
+ weekday: 'short',
19
+ month: 'short',
20
+ day: 'numeric',
21
+ hour: '2-digit',
22
+ minute: '2-digit',
23
+ timeZoneName: 'short',
24
+ });
25
+ }
26
+ export function wrapCronPrompt(taskId, taskName, message) {
27
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
28
+ return `[cron:#${taskId} ${taskName}] ${message}\nCurrent time: ${formatFireTime()} (${tz})\n\nReturn your response as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`;
29
+ }
30
+ // --- Timer logic ---
31
+ function computeNextFireMs() {
32
+ const tasks = getAllEnabledTasks();
33
+ let earliest = null;
34
+ for (const task of tasks) {
35
+ if (task.run_at) {
36
+ if (!task.last_run) {
37
+ const ms = new Date(task.run_at).getTime();
38
+ if (earliest === null || ms < earliest)
39
+ earliest = ms;
40
+ }
41
+ continue;
42
+ }
43
+ if (task.every_ms) {
44
+ const lastRunMs = task.last_run ? new Date(task.last_run).getTime() : 0;
45
+ const nextMs = lastRunMs > 0 ? lastRunMs + task.every_ms : Date.now();
46
+ if (earliest === null || nextMs < earliest)
47
+ earliest = nextMs;
48
+ continue;
49
+ }
50
+ if (!task.cron_expr)
51
+ continue;
52
+ try {
53
+ const ms = CronExpressionParser.parse(task.cron_expr).next().toDate().getTime();
54
+ if (earliest === null || ms < earliest)
55
+ earliest = ms;
56
+ }
57
+ catch { /* skip invalid */ }
58
+ }
59
+ return earliest;
60
+ }
61
+ function arm() {
62
+ if (timer)
63
+ clearTimeout(timer);
64
+ timer = null;
65
+ const nextFireMs = computeNextFireMs();
66
+ if (nextFireMs === null)
67
+ return; // nothing scheduled
68
+ const delay = Math.max(nextFireMs - Date.now(), 0);
69
+ const clamped = Math.min(delay, MAX_TIMER_DELAY_MS);
70
+ logger.debug({ delayMs: clamped, nextFire: new Date(nextFireMs).toISOString() }, 'Scheduler armed');
71
+ timer = setTimeout(() => {
72
+ void tick().catch((err) => {
73
+ logger.error({ err }, 'Scheduler tick failed');
74
+ arm(); // re-arm even on error
75
+ });
76
+ }, clamped);
77
+ }
78
+ async function tick() {
79
+ if (ticking) {
80
+ arm(); // re-check later
81
+ return;
82
+ }
83
+ ticking = true;
84
+ try {
85
+ const tasks = getAllEnabledTasks();
86
+ const now = new Date();
87
+ for (const task of tasks) {
88
+ try {
89
+ // --- One-shot task ---
90
+ if (task.run_at) {
91
+ const runAt = new Date(task.run_at);
92
+ if (runAt.getTime() <= now.getTime() && !task.last_run) {
93
+ logger.info({ taskId: task.id, runAt: task.run_at, prompt: task.prompt }, 'One-shot task firing');
94
+ updateTaskLastRun(task.id); // prevents re-fire
95
+ const prompt = wrapCronPrompt(task.id, task.prompt, task.prompt);
96
+ taskRunner(task.session_id, task.channel_id, prompt, task.id)
97
+ .then(() => deleteTask(task.id)) // cleanup on success
98
+ .catch((err) => {
99
+ logger.error({ taskId: task.id, err }, 'One-shot task failed (task preserved)');
100
+ });
101
+ }
102
+ continue;
103
+ }
104
+ // --- Interval task ---
105
+ if (task.every_ms) {
106
+ const lastRunMs = task.last_run ? new Date(task.last_run).getTime() : 0;
107
+ const dueAt = lastRunMs > 0 ? lastRunMs + task.every_ms : 0; // fire immediately if never run
108
+ if (dueAt <= now.getTime()) {
109
+ logger.info({ taskId: task.id, everyMs: task.every_ms, prompt: task.prompt }, 'Interval task firing');
110
+ updateTaskLastRun(task.id);
111
+ const prompt = wrapCronPrompt(task.id, task.prompt, task.prompt);
112
+ taskRunner(task.session_id, task.channel_id, prompt, task.id).catch((err) => {
113
+ logger.error({ taskId: task.id, err }, 'Interval task failed');
114
+ });
115
+ }
116
+ continue;
117
+ }
118
+ // --- Recurring cron task ---
119
+ if (!task.cron_expr)
120
+ continue;
121
+ const cron = CronExpressionParser.parse(task.cron_expr);
122
+ const prev = cron.prev();
123
+ const lastRun = task.last_run ? new Date(task.last_run) : new Date(0);
124
+ if (prev.toDate() > lastRun) {
125
+ logger.info({ taskId: task.id, cron: task.cron_expr, prompt: task.prompt }, 'Cron task firing');
126
+ updateTaskLastRun(task.id);
127
+ const prompt = wrapCronPrompt(task.id, task.prompt, task.prompt);
128
+ taskRunner(task.session_id, task.channel_id, prompt, task.id).catch((err) => {
129
+ logger.error({ taskId: task.id, err }, 'Cron task failed');
130
+ });
131
+ }
132
+ }
133
+ catch (err) {
134
+ logger.error({ taskId: task.id, cron: task.cron_expr, err }, 'Scheduler error for task');
135
+ }
136
+ }
137
+ }
138
+ finally {
139
+ ticking = false;
140
+ arm(); // re-arm for next task
141
+ }
142
+ }
143
+ // --- Public API ---
144
+ export function startScheduler(runner) {
145
+ logger.info('Scheduler started');
146
+ taskRunner = runner;
147
+ arm();
148
+ }
149
+ /**
150
+ * Re-arm the scheduler timer. Call after creating or deleting tasks
151
+ * so newly scheduled work is picked up immediately.
152
+ */
153
+ export function rearmScheduler() {
154
+ if (taskRunner)
155
+ arm();
156
+ }
157
+ export function stopScheduler() {
158
+ if (timer) {
159
+ clearTimeout(timer);
160
+ timer = null;
161
+ }
162
+ taskRunner = null;
163
+ logger.info('Scheduler stopped');
164
+ }
165
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,mCAAmC;AAIvE,IAAI,KAAK,GAAyC,IAAI,CAAC;AACvD,IAAI,UAAU,GAAsB,IAAI,CAAC;AACzC,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,0CAA0C;AAE1C,SAAS,cAAc;IACrB,OAAO,IAAI,IAAI,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE;QACxC,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,QAAgB,EAAE,OAAe;IAC9E,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC5D,OAAO,UAAU,MAAM,IAAI,QAAQ,KAAK,OAAO,mBAAmB,cAAc,EAAE,KAAK,EAAE,oNAAoN,CAAC;AAChT,CAAC;AAED,sBAAsB;AAEtB,SAAS,iBAAiB;IACxB,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,QAAQ,GAAkB,IAAI,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC3C,IAAI,QAAQ,KAAK,IAAI,IAAI,EAAE,GAAG,QAAQ;oBAAE,QAAQ,GAAG,EAAE,CAAC;YACxD,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACtE,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,GAAG,QAAQ;gBAAE,QAAQ,GAAG,MAAM,CAAC;YAC9D,SAAS;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QAE9B,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;YAChF,IAAI,QAAQ,KAAK,IAAI,IAAI,EAAE,GAAG,QAAQ;gBAAE,QAAQ,GAAG,EAAE,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,GAAG;IACV,IAAI,KAAK;QAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IAC/B,KAAK,GAAG,IAAI,CAAC;IAEb,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,CAAC,oBAAoB;IAErD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAEpD,MAAM,CAAC,KAAK,CACV,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,EAAE,EAClE,iBAAiB,CAClB,CAAC;IAEF,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QACtB,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC;YAC/C,GAAG,EAAE,CAAC,CAAC,uBAAuB;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,OAAO,CAAC,CAAC;AACd,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,EAAE,CAAC,CAAC,iBAAiB;QACxB,OAAO;IACT,CAAC;IACD,OAAO,GAAG,IAAI,CAAC;IAEf,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,wBAAwB;gBACxB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACpC,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACvD,MAAM,CAAC,IAAI,CACT,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAC5D,sBAAsB,CACvB,CAAC;wBACF,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB;wBAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;wBACjE,UAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;6BAC3D,IAAI,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAG,qBAAqB;6BACvD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;4BACb,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,uCAAuC,CAAC,CAAC;wBAClF,CAAC,CAAC,CAAC;oBACP,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,wBAAwB;gBACxB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;oBACxE,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gCAAgC;oBAC7F,IAAI,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;wBAC3B,MAAM,CAAC,IAAI,CACT,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAChE,sBAAsB,CACvB,CAAC;wBACF,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;wBACjE,UAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;4BAC3E,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,sBAAsB,CAAC,CAAC;wBACjE,CAAC,CAAC,CAAC;oBACL,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,8BAA8B;gBAC9B,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,SAAS;gBAE9B,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;gBAEtE,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;oBAC5B,MAAM,CAAC,IAAI,CACT,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAC9D,kBAAkB,CACnB,CAAC;oBACF,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;oBACjE,UAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;wBAC3E,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;oBAC7D,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,0BAA0B,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,OAAO,GAAG,KAAK,CAAC;QAChB,GAAG,EAAE,CAAC,CAAC,uBAAuB;IAChC,CAAC;AACH,CAAC;AAED,qBAAqB;AAErB,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACjC,UAAU,GAAG,MAAM,CAAC;IACpB,GAAG,EAAE,CAAC;AACR,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,UAAU;QAAE,GAAG,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,KAAK,EAAE,CAAC;QACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,KAAK,GAAG,IAAI,CAAC;IACf,CAAC;IACD,UAAU,GAAG,IAAI,CAAC;IAClB,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare function maybeCompactSession(params: {
2
+ sessionId: string;
3
+ agentId: string;
4
+ chatbotId: string;
5
+ enableRag: boolean;
6
+ model: string;
7
+ channelId: string;
8
+ }): Promise<void>;
9
+ //# sourceMappingURL=session-maintenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-maintenance.d.ts","sourceRoot":"","sources":["../src/session-maintenance.ts"],"names":[],"mappings":"AAsNA,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyChB"}
@@ -0,0 +1,168 @@
1
+ import { PRE_COMPACTION_MEMORY_FLUSH_ENABLED, PRE_COMPACTION_MEMORY_FLUSH_MAX_CHARS, PRE_COMPACTION_MEMORY_FLUSH_MAX_MESSAGES, SESSION_COMPACTION_ENABLED, SESSION_COMPACTION_KEEP_RECENT, SESSION_COMPACTION_SUMMARY_MAX_CHARS, SESSION_COMPACTION_THRESHOLD, } from './config.js';
2
+ import { deleteMessagesBeforeId, getCompactionCandidateMessages, getSessionById, markSessionMemoryFlush, updateSessionSummary, } from './db.js';
3
+ import { logger } from './logger.js';
4
+ import { loadSkills } from './skills.js';
5
+ import { runAgent } from './agent.js';
6
+ import { buildSystemPromptFromHooks } from './prompt-hooks.js';
7
+ const COMPACTION_SOURCE_MAX_MESSAGES = 240;
8
+ const COMPACTION_SOURCE_MAX_CHARS = 80_000;
9
+ function formatDateStampInLocalTimezone(now) {
10
+ const parts = new Intl.DateTimeFormat('en-US', {
11
+ year: 'numeric',
12
+ month: '2-digit',
13
+ day: '2-digit',
14
+ }).formatToParts(now);
15
+ const year = parts.find((part) => part.type === 'year')?.value;
16
+ const month = parts.find((part) => part.type === 'month')?.value;
17
+ const day = parts.find((part) => part.type === 'day')?.value;
18
+ if (year && month && day) {
19
+ return `${year}-${month}-${day}`;
20
+ }
21
+ return now.toISOString().slice(0, 10);
22
+ }
23
+ function normalizeSummary(summary) {
24
+ let text = summary.trim();
25
+ if (text.startsWith('```')) {
26
+ text = text.replace(/^```[a-z0-9_-]*\s*/i, '').replace(/```$/i, '').trim();
27
+ }
28
+ if (text.length > SESSION_COMPACTION_SUMMARY_MAX_CHARS) {
29
+ text = `${text.slice(0, SESSION_COMPACTION_SUMMARY_MAX_CHARS)}\n\n...[truncated]`;
30
+ }
31
+ return text;
32
+ }
33
+ function formatMessagesForPrompt(messages, maxMessages, maxChars) {
34
+ const selected = messages.slice(-Math.max(1, maxMessages));
35
+ const lines = [];
36
+ let usedChars = 0;
37
+ for (const msg of selected) {
38
+ const role = (msg.role || 'unknown').toUpperCase();
39
+ const compact = msg.content.replace(/\r/g, '').trim();
40
+ const bounded = compact.length > 1_200 ? `${compact.slice(0, 1_200)}\n...[truncated]` : compact;
41
+ const entry = `[${role}] ${bounded}`;
42
+ const bytes = entry.length + 2;
43
+ if (usedChars + bytes > maxChars)
44
+ break;
45
+ usedChars += bytes;
46
+ lines.push(entry);
47
+ }
48
+ return lines.join('\n\n');
49
+ }
50
+ function buildSystemPrompt(agentId, sessionSummary, extra) {
51
+ return buildSystemPromptFromHooks({
52
+ agentId,
53
+ sessionSummary,
54
+ skills: loadSkills(agentId),
55
+ purpose: 'memory-flush',
56
+ extraSafetyText: extra,
57
+ });
58
+ }
59
+ async function runPreCompactionMemoryFlush(params) {
60
+ if (!PRE_COMPACTION_MEMORY_FLUSH_ENABLED)
61
+ return;
62
+ const transcript = formatMessagesForPrompt(params.olderMessages, PRE_COMPACTION_MEMORY_FLUSH_MAX_MESSAGES, PRE_COMPACTION_MEMORY_FLUSH_MAX_CHARS);
63
+ if (!transcript)
64
+ return;
65
+ const now = new Date();
66
+ const dateStamp = formatDateStampInLocalTimezone(now);
67
+ const flushPrompt = [
68
+ 'Pre-compaction memory flush.',
69
+ `Store durable memories now using MEMORY.md and memory/${dateStamp}.md (create memory/ if needed).`,
70
+ 'IMPORTANT: If a file already exists, append new content only and do not overwrite existing entries.',
71
+ 'Capture only stable, durable facts, preferences, and decisions worth preserving after compaction.',
72
+ 'If there is nothing worth saving, reply MEMORY_FLUSH_SKIPPED.',
73
+ '',
74
+ `Current time: ${now.toISOString()}`,
75
+ '',
76
+ 'Conversation excerpt (about to be compacted):',
77
+ transcript,
78
+ ].join('\n');
79
+ const systemPrompt = buildSystemPrompt(params.agentId, params.sessionSummary, 'Pre-compaction memory flush turn. The session is near auto-compaction; write durable memory to disk.');
80
+ const messages = [];
81
+ if (systemPrompt) {
82
+ messages.push({ role: 'system', content: systemPrompt });
83
+ }
84
+ messages.push({ role: 'user', content: flushPrompt });
85
+ try {
86
+ const output = await runAgent(`memory-flush:${params.sessionId}:${Date.now()}`, messages, params.chatbotId, params.enableRag, params.model, params.agentId, params.channelId, undefined, ['memory']);
87
+ if (output.status === 'error') {
88
+ logger.warn({ sessionId: params.sessionId, error: output.error }, 'Pre-compaction memory flush failed');
89
+ return;
90
+ }
91
+ markSessionMemoryFlush(params.sessionId);
92
+ }
93
+ catch (err) {
94
+ logger.warn({ sessionId: params.sessionId, err }, 'Pre-compaction memory flush crashed');
95
+ }
96
+ }
97
+ async function generateCompactionSummary(params) {
98
+ const transcript = formatMessagesForPrompt(params.olderMessages, COMPACTION_SOURCE_MAX_MESSAGES, COMPACTION_SOURCE_MAX_CHARS);
99
+ if (!transcript)
100
+ return null;
101
+ const previous = params.previousSummary?.trim() || '(none)';
102
+ const systemPrompt = [
103
+ 'You are compressing conversation history for a long-running AI session.',
104
+ 'Return an updated markdown summary that preserves durable context only.',
105
+ 'Focus on goals, decisions, constraints, preferences, and open follow-ups.',
106
+ 'Do not include low-value chatter, greetings, or transient details.',
107
+ 'Return summary text only.',
108
+ ].join(' ');
109
+ const userPrompt = [
110
+ 'Existing summary:',
111
+ previous,
112
+ '',
113
+ 'Messages to compact:',
114
+ transcript,
115
+ '',
116
+ 'Return a single merged summary that should replace the existing summary.',
117
+ ].join('\n');
118
+ const output = await runAgent(`compact:${params.sessionId}:${Date.now()}`, [
119
+ { role: 'system', content: systemPrompt },
120
+ { role: 'user', content: userPrompt },
121
+ ], params.chatbotId, params.enableRag, params.model, params.agentId, params.channelId, undefined, []);
122
+ if (output.status === 'error' || !output.result) {
123
+ logger.warn({ sessionId: params.sessionId, error: output.error }, 'Session compaction summary failed');
124
+ return null;
125
+ }
126
+ const normalized = normalizeSummary(output.result);
127
+ if (!normalized)
128
+ return null;
129
+ return normalized;
130
+ }
131
+ export async function maybeCompactSession(params) {
132
+ if (!SESSION_COMPACTION_ENABLED)
133
+ return;
134
+ const session = getSessionById(params.sessionId);
135
+ if (!session)
136
+ return;
137
+ const threshold = Math.max(SESSION_COMPACTION_THRESHOLD, 20);
138
+ const keepRecent = Math.max(1, Math.min(SESSION_COMPACTION_KEEP_RECENT, threshold - 1));
139
+ if (session.message_count < threshold)
140
+ return;
141
+ const candidate = getCompactionCandidateMessages(params.sessionId, keepRecent);
142
+ if (!candidate || candidate.olderMessages.length === 0)
143
+ return;
144
+ await runPreCompactionMemoryFlush({
145
+ ...params,
146
+ sessionSummary: session.session_summary,
147
+ olderMessages: candidate.olderMessages,
148
+ });
149
+ const summary = await generateCompactionSummary({
150
+ ...params,
151
+ previousSummary: session.session_summary,
152
+ olderMessages: candidate.olderMessages,
153
+ });
154
+ if (!summary)
155
+ return;
156
+ const deleted = deleteMessagesBeforeId(params.sessionId, candidate.cutoffId);
157
+ if (deleted <= 0)
158
+ return;
159
+ updateSessionSummary(params.sessionId, summary);
160
+ logger.info({
161
+ sessionId: params.sessionId,
162
+ deleted,
163
+ cutoffId: candidate.cutoffId,
164
+ threshold,
165
+ keepRecent,
166
+ }, 'Session compacted');
167
+ }
168
+ //# sourceMappingURL=session-maintenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-maintenance.js","sourceRoot":"","sources":["../src/session-maintenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface TranscriptEntry {
2
+ sessionId: string;
3
+ channelId: string;
4
+ role: string;
5
+ userId: string;
6
+ username: string | null;
7
+ content: string;
8
+ createdAt?: string;
9
+ }
10
+ export declare function appendSessionTranscript(agentId: string, entry: TranscriptEntry): void;
11
+ //# sourceMappingURL=session-transcripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-transcripts.d.ts","sourceRoot":"","sources":["../src/session-transcripts.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAqBrF"}
@@ -0,0 +1,32 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { agentWorkspaceDir, ensureAgentDirs } from './ipc.js';
4
+ import { logger } from './logger.js';
5
+ const TRANSCRIPTS_DIR_NAME = '.session-transcripts';
6
+ function safeSessionFilename(sessionId) {
7
+ const normalized = sessionId.trim().replace(/[^a-zA-Z0-9_-]/g, '_');
8
+ return normalized || 'session';
9
+ }
10
+ export function appendSessionTranscript(agentId, entry) {
11
+ try {
12
+ ensureAgentDirs(agentId);
13
+ const workspace = agentWorkspaceDir(agentId);
14
+ const transcriptDir = path.join(workspace, TRANSCRIPTS_DIR_NAME);
15
+ fs.mkdirSync(transcriptDir, { recursive: true });
16
+ const filePath = path.join(transcriptDir, `${safeSessionFilename(entry.sessionId)}.jsonl`);
17
+ const row = {
18
+ sessionId: entry.sessionId,
19
+ channelId: entry.channelId,
20
+ role: entry.role,
21
+ userId: entry.userId,
22
+ username: entry.username,
23
+ content: entry.content,
24
+ createdAt: entry.createdAt || new Date().toISOString(),
25
+ };
26
+ fs.appendFileSync(filePath, JSON.stringify(row) + '\n', 'utf-8');
27
+ }
28
+ catch (err) {
29
+ logger.debug({ agentId, sessionId: entry.sessionId, err }, 'Failed to append session transcript');
30
+ }
31
+ }
32
+ //# sourceMappingURL=session-transcripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-transcripts.js","sourceRoot":"","sources":["../src/session-transcripts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAYpD,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,UAAU,IAAI,SAAS,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,KAAsB;IAC7E,IAAI,CAAC;QACH,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;QACjE,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3F,MAAM,GAAG,GAAG;YACV,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACvD,CAAC;QACF,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,qCAAqC,CAAC,CAAC;IACpG,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ContainerOutput } from './types.js';
2
+ export declare function processSideEffects(output: ContainerOutput, sessionId: string, channelId: string): void;
3
+ //# sourceMappingURL=side-effects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-effects.d.ts","sourceRoot":"","sources":["../src/side-effects.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,IAAI,CA+BN"}
@@ -0,0 +1,30 @@
1
+ import { createTask, deleteTask } from './db.js';
2
+ import { logger } from './logger.js';
3
+ import { rearmScheduler } from './scheduler.js';
4
+ export function processSideEffects(output, sessionId, channelId) {
5
+ const schedules = output.sideEffects?.schedules;
6
+ if (!schedules || schedules.length === 0)
7
+ return;
8
+ let changed = false;
9
+ for (const effect of schedules) {
10
+ try {
11
+ if (effect.action === 'add') {
12
+ const taskId = createTask(sessionId, channelId, effect.cronExpr || '', effect.prompt, effect.runAt, effect.everyMs);
13
+ logger.info({ taskId, sessionId, channelId, cronExpr: effect.cronExpr, runAt: effect.runAt, everyMs: effect.everyMs }, 'Side-effect: created task');
14
+ changed = true;
15
+ }
16
+ else if (effect.action === 'remove') {
17
+ deleteTask(effect.taskId);
18
+ logger.info({ taskId: effect.taskId, sessionId }, 'Side-effect: removed task');
19
+ changed = true;
20
+ }
21
+ }
22
+ catch (err) {
23
+ logger.error({ effect, err }, 'Failed to process side-effect');
24
+ }
25
+ }
26
+ // Re-arm scheduler so new tasks are picked up immediately
27
+ if (changed)
28
+ rearmScheduler();
29
+ }
30
+ //# sourceMappingURL=side-effects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-effects.js","sourceRoot":"","sources":["../src/side-effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,UAAU,kBAAkB,CAChC,MAAuB,EACvB,SAAiB,EACjB,SAAiB;IAEjB,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC;IAChD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjD,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,UAAU,CACvB,SAAS,EACT,SAAS,EACT,MAAM,CAAC,QAAQ,IAAI,EAAE,EACrB,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,OAAO,CACf,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,2BAA2B,CAAC,CAAC;gBACpJ,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;iBAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACtC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,2BAA2B,CAAC,CAAC;gBAC/E,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,+BAA+B,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO;QAAE,cAAc,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,32 @@
1
+ type SkillSource = 'workspace' | 'project' | 'codex' | 'claude';
2
+ export interface Skill {
3
+ name: string;
4
+ description: string;
5
+ userInvocable: boolean;
6
+ disableModelInvocation: boolean;
7
+ filePath: string;
8
+ baseDir: string;
9
+ source: SkillSource;
10
+ location: string;
11
+ }
12
+ /**
13
+ * Expand explicit skill command invocations into a deterministic user payload.
14
+ * Supports:
15
+ * - /skill <name> [input]
16
+ * - /skill:<name> [input]
17
+ * - /<name> [input] (user-invocable skills)
18
+ */
19
+ export declare function expandSkillInvocation(content: string, skills: Skill[]): string;
20
+ /**
21
+ * Load all skills with precedence:
22
+ * codex/claude managed < project skills < agent workspace skills.
23
+ * Any non-workspace skill selected by precedence is mirrored into workspace so
24
+ * the container can read it via /workspace/... paths.
25
+ */
26
+ export declare function loadSkills(agentId: string): Skill[];
27
+ /**
28
+ * Build compact CLAUDE/OpenClaw-style skill prompt metadata.
29
+ */
30
+ export declare function buildSkillsPrompt(skills: Skill[]): string;
31
+ export {};
32
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAaA,KAAK,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAYhE,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoRD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,CAuCnD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAkCzD"}