bajaclaw 0.10.1

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 (248) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +639 -0
  3. package/bin/bajaclaw.js +35 -0
  4. package/bin/create-bajaclaw.js +17 -0
  5. package/dist/agent.d.ts +29 -0
  6. package/dist/agent.js +231 -0
  7. package/dist/agent.js.map +1 -0
  8. package/dist/api/server.d.ts +15 -0
  9. package/dist/api/server.js +215 -0
  10. package/dist/api/server.js.map +1 -0
  11. package/dist/api/translate.d.ts +61 -0
  12. package/dist/api/translate.js +109 -0
  13. package/dist/api/translate.js.map +1 -0
  14. package/dist/banner.d.ts +7 -0
  15. package/dist/banner.js +31 -0
  16. package/dist/banner.js.map +1 -0
  17. package/dist/channels/gateway.d.ts +1 -0
  18. package/dist/channels/gateway.js +76 -0
  19. package/dist/channels/gateway.js.map +1 -0
  20. package/dist/claude.d.ts +9 -0
  21. package/dist/claude.js +170 -0
  22. package/dist/claude.js.map +1 -0
  23. package/dist/cli.d.ts +2 -0
  24. package/dist/cli.js +303 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/commands/channel.d.ts +3 -0
  27. package/dist/commands/channel.js +27 -0
  28. package/dist/commands/channel.js.map +1 -0
  29. package/dist/commands/compact.d.ts +8 -0
  30. package/dist/commands/compact.js +60 -0
  31. package/dist/commands/compact.js.map +1 -0
  32. package/dist/commands/daemon.d.ts +7 -0
  33. package/dist/commands/daemon.js +129 -0
  34. package/dist/commands/daemon.js.map +1 -0
  35. package/dist/commands/dashboard.d.ts +1 -0
  36. package/dist/commands/dashboard.js +78 -0
  37. package/dist/commands/dashboard.js.map +1 -0
  38. package/dist/commands/doctor.d.ts +1 -0
  39. package/dist/commands/doctor.js +25 -0
  40. package/dist/commands/doctor.js.map +1 -0
  41. package/dist/commands/dry-run.d.ts +1 -0
  42. package/dist/commands/dry-run.js +5 -0
  43. package/dist/commands/dry-run.js.map +1 -0
  44. package/dist/commands/effort.d.ts +6 -0
  45. package/dist/commands/effort.js +33 -0
  46. package/dist/commands/effort.js.map +1 -0
  47. package/dist/commands/guide.d.ts +4 -0
  48. package/dist/commands/guide.js +52 -0
  49. package/dist/commands/guide.js.map +1 -0
  50. package/dist/commands/health.d.ts +1 -0
  51. package/dist/commands/health.js +20 -0
  52. package/dist/commands/health.js.map +1 -0
  53. package/dist/commands/init.d.ts +12 -0
  54. package/dist/commands/init.js +114 -0
  55. package/dist/commands/init.js.map +1 -0
  56. package/dist/commands/mcp.d.ts +9 -0
  57. package/dist/commands/mcp.js +63 -0
  58. package/dist/commands/mcp.js.map +1 -0
  59. package/dist/commands/migrate.d.ts +1 -0
  60. package/dist/commands/migrate.js +58 -0
  61. package/dist/commands/migrate.js.map +1 -0
  62. package/dist/commands/model.d.ts +5 -0
  63. package/dist/commands/model.js +31 -0
  64. package/dist/commands/model.js.map +1 -0
  65. package/dist/commands/persona.d.ts +6 -0
  66. package/dist/commands/persona.js +67 -0
  67. package/dist/commands/persona.js.map +1 -0
  68. package/dist/commands/port.d.ts +15 -0
  69. package/dist/commands/port.js +88 -0
  70. package/dist/commands/port.js.map +1 -0
  71. package/dist/commands/profile.d.ts +4 -0
  72. package/dist/commands/profile.js +41 -0
  73. package/dist/commands/profile.js.map +1 -0
  74. package/dist/commands/serve.d.ts +14 -0
  75. package/dist/commands/serve.js +62 -0
  76. package/dist/commands/serve.js.map +1 -0
  77. package/dist/commands/setup.d.ts +17 -0
  78. package/dist/commands/setup.js +228 -0
  79. package/dist/commands/setup.js.map +1 -0
  80. package/dist/commands/skill.d.ts +7 -0
  81. package/dist/commands/skill.js +137 -0
  82. package/dist/commands/skill.js.map +1 -0
  83. package/dist/commands/start.d.ts +6 -0
  84. package/dist/commands/start.js +25 -0
  85. package/dist/commands/start.js.map +1 -0
  86. package/dist/commands/status.d.ts +1 -0
  87. package/dist/commands/status.js +35 -0
  88. package/dist/commands/status.js.map +1 -0
  89. package/dist/commands/subagent.d.ts +14 -0
  90. package/dist/commands/subagent.js +173 -0
  91. package/dist/commands/subagent.js.map +1 -0
  92. package/dist/commands/trigger.d.ts +1 -0
  93. package/dist/commands/trigger.js +13 -0
  94. package/dist/commands/trigger.js.map +1 -0
  95. package/dist/commands/uninstall.d.ts +5 -0
  96. package/dist/commands/uninstall.js +165 -0
  97. package/dist/commands/uninstall.js.map +1 -0
  98. package/dist/commands/update.d.ts +7 -0
  99. package/dist/commands/update.js +49 -0
  100. package/dist/commands/update.js.map +1 -0
  101. package/dist/concurrency.d.ts +1 -0
  102. package/dist/concurrency.js +17 -0
  103. package/dist/concurrency.js.map +1 -0
  104. package/dist/config.d.ts +5 -0
  105. package/dist/config.js +42 -0
  106. package/dist/config.js.map +1 -0
  107. package/dist/db.d.ts +3 -0
  108. package/dist/db.js +124 -0
  109. package/dist/db.js.map +1 -0
  110. package/dist/delegation.d.ts +6 -0
  111. package/dist/delegation.js +21 -0
  112. package/dist/delegation.js.map +1 -0
  113. package/dist/health-check.d.ts +6 -0
  114. package/dist/health-check.js +38 -0
  115. package/dist/health-check.js.map +1 -0
  116. package/dist/logger.d.ts +11 -0
  117. package/dist/logger.js +53 -0
  118. package/dist/logger.js.map +1 -0
  119. package/dist/mcp/consumer.d.ts +15 -0
  120. package/dist/mcp/consumer.js +74 -0
  121. package/dist/mcp/consumer.js.map +1 -0
  122. package/dist/mcp/server.d.ts +6 -0
  123. package/dist/mcp/server.js +260 -0
  124. package/dist/mcp/server.js.map +1 -0
  125. package/dist/memory/claude-compat.d.ts +4 -0
  126. package/dist/memory/claude-compat.js +56 -0
  127. package/dist/memory/claude-compat.js.map +1 -0
  128. package/dist/memory/compact.d.ts +25 -0
  129. package/dist/memory/compact.js +195 -0
  130. package/dist/memory/compact.js.map +1 -0
  131. package/dist/memory/extract.d.ts +3 -0
  132. package/dist/memory/extract.js +56 -0
  133. package/dist/memory/extract.js.map +1 -0
  134. package/dist/memory/recall.d.ts +5 -0
  135. package/dist/memory/recall.js +47 -0
  136. package/dist/memory/recall.js.map +1 -0
  137. package/dist/model-picker.d.ts +33 -0
  138. package/dist/model-picker.js +104 -0
  139. package/dist/model-picker.js.map +1 -0
  140. package/dist/paths.d.ts +12 -0
  141. package/dist/paths.js +49 -0
  142. package/dist/paths.js.map +1 -0
  143. package/dist/persona-io.d.ts +5 -0
  144. package/dist/persona-io.js +29 -0
  145. package/dist/persona-io.js.map +1 -0
  146. package/dist/persona.d.ts +12 -0
  147. package/dist/persona.js +54 -0
  148. package/dist/persona.js.map +1 -0
  149. package/dist/prompt.d.ts +5 -0
  150. package/dist/prompt.js +56 -0
  151. package/dist/prompt.js.map +1 -0
  152. package/dist/safety.d.ts +17 -0
  153. package/dist/safety.js +47 -0
  154. package/dist/safety.js.map +1 -0
  155. package/dist/scheduler/cron.d.ts +4 -0
  156. package/dist/scheduler/cron.js +44 -0
  157. package/dist/scheduler/cron.js.map +1 -0
  158. package/dist/scheduler/index.d.ts +7 -0
  159. package/dist/scheduler/index.js +15 -0
  160. package/dist/scheduler/index.js.map +1 -0
  161. package/dist/scheduler/launchd.d.ts +4 -0
  162. package/dist/scheduler/launchd.js +73 -0
  163. package/dist/scheduler/launchd.js.map +1 -0
  164. package/dist/scheduler/schtasks.d.ts +4 -0
  165. package/dist/scheduler/schtasks.js +45 -0
  166. package/dist/scheduler/schtasks.js.map +1 -0
  167. package/dist/scheduler/systemd.d.ts +5 -0
  168. package/dist/scheduler/systemd.js +86 -0
  169. package/dist/scheduler/systemd.js.map +1 -0
  170. package/dist/self-improve.d.ts +4 -0
  171. package/dist/self-improve.js +48 -0
  172. package/dist/self-improve.js.map +1 -0
  173. package/dist/skills/auto-skiller.d.ts +21 -0
  174. package/dist/skills/auto-skiller.js +156 -0
  175. package/dist/skills/auto-skiller.js.map +1 -0
  176. package/dist/skills/loader.d.ts +3 -0
  177. package/dist/skills/loader.js +127 -0
  178. package/dist/skills/loader.js.map +1 -0
  179. package/dist/skills/matcher.d.ts +2 -0
  180. package/dist/skills/matcher.js +27 -0
  181. package/dist/skills/matcher.js.map +1 -0
  182. package/dist/skills/porter.d.ts +27 -0
  183. package/dist/skills/porter.js +109 -0
  184. package/dist/skills/porter.js.map +1 -0
  185. package/dist/types.d.ts +110 -0
  186. package/dist/types.js +2 -0
  187. package/dist/types.js.map +1 -0
  188. package/dist/updater.d.ts +25 -0
  189. package/dist/updater.js +185 -0
  190. package/dist/updater.js.map +1 -0
  191. package/package.json +53 -0
  192. package/scripts/postinstall.js +33 -0
  193. package/skills/configure-effort/SKILL.md +36 -0
  194. package/skills/configure-model/SKILL.md +41 -0
  195. package/skills/configure-tools/SKILL.md +51 -0
  196. package/skills/daily-briefing/SKILL.md +19 -0
  197. package/skills/delegate-to-subagent/SKILL.md +63 -0
  198. package/skills/email-triage/SKILL.md +21 -0
  199. package/skills/setup-api/SKILL.md +115 -0
  200. package/skills/setup-compaction/SKILL.md +102 -0
  201. package/skills/setup-daemon/SKILL.md +49 -0
  202. package/skills/setup-dashboard/SKILL.md +39 -0
  203. package/skills/setup-discord/SKILL.md +54 -0
  204. package/skills/setup-heartbeat/SKILL.md +51 -0
  205. package/skills/setup-mcp-port/SKILL.md +54 -0
  206. package/skills/setup-memory-sync/SKILL.md +45 -0
  207. package/skills/setup-profile/SKILL.md +44 -0
  208. package/skills/setup-self-update/SKILL.md +45 -0
  209. package/skills/setup-subagent/SKILL.md +102 -0
  210. package/skills/setup-telegram/SKILL.md +54 -0
  211. package/skills/setup-uninstall/SKILL.md +55 -0
  212. package/skills/web-research/SKILL.md +20 -0
  213. package/templates/code/AGENT.md +15 -0
  214. package/templates/code/HEARTBEAT.md +11 -0
  215. package/templates/code/SOUL.md +10 -0
  216. package/templates/code/bajaclaw.config.json +5 -0
  217. package/templates/code/scripts/launch.bat +4 -0
  218. package/templates/code/scripts/launch.sh +4 -0
  219. package/templates/custom/AGENT.md +14 -0
  220. package/templates/custom/HEARTBEAT.md +11 -0
  221. package/templates/custom/SOUL.md +10 -0
  222. package/templates/custom/bajaclaw.config.json +5 -0
  223. package/templates/custom/scripts/launch.bat +4 -0
  224. package/templates/custom/scripts/launch.sh +4 -0
  225. package/templates/outreach/AGENT.md +11 -0
  226. package/templates/outreach/HEARTBEAT.md +11 -0
  227. package/templates/outreach/SOUL.md +10 -0
  228. package/templates/outreach/bajaclaw.config.json +5 -0
  229. package/templates/outreach/scripts/launch.bat +4 -0
  230. package/templates/outreach/scripts/launch.sh +4 -0
  231. package/templates/research/AGENT.md +27 -0
  232. package/templates/research/HEARTBEAT.md +11 -0
  233. package/templates/research/SOUL.md +10 -0
  234. package/templates/research/bajaclaw.config.json +5 -0
  235. package/templates/research/scripts/launch.bat +4 -0
  236. package/templates/research/scripts/launch.sh +4 -0
  237. package/templates/social/AGENT.md +10 -0
  238. package/templates/social/HEARTBEAT.md +11 -0
  239. package/templates/social/SOUL.md +10 -0
  240. package/templates/social/bajaclaw.config.json +5 -0
  241. package/templates/social/scripts/launch.bat +4 -0
  242. package/templates/social/scripts/launch.sh +4 -0
  243. package/templates/support/AGENT.md +10 -0
  244. package/templates/support/HEARTBEAT.md +11 -0
  245. package/templates/support/SOUL.md +10 -0
  246. package/templates/support/bajaclaw.config.json +5 -0
  247. package/templates/support/scripts/launch.bat +4 -0
  248. package/templates/support/scripts/launch.sh +4 -0
@@ -0,0 +1,47 @@
1
+ export function recall(db, query, limit = 5) {
2
+ const terms = query
3
+ .toLowerCase()
4
+ .replace(/[^a-z0-9 ]+/g, " ")
5
+ .split(/\s+/)
6
+ .filter((t) => t.length >= 3)
7
+ .slice(0, 8);
8
+ if (terms.length === 0) {
9
+ return dedupe(db.prepare("SELECT * FROM memories ORDER BY id DESC LIMIT ?").all(limit));
10
+ }
11
+ const match = terms.map((t) => `${t}*`).join(" OR ");
12
+ try {
13
+ const rows = db.prepare(`
14
+ SELECT m.* FROM memories_fts f
15
+ JOIN memories m ON m.id = f.memory_id
16
+ WHERE memories_fts MATCH ?
17
+ ORDER BY rank
18
+ LIMIT ?
19
+ `).all(match, limit * 2);
20
+ if (rows.length > 0)
21
+ return dedupe(rows).slice(0, limit);
22
+ }
23
+ catch { /* FTS may reject — fall through */ }
24
+ return dedupe(db.prepare("SELECT * FROM memories ORDER BY id DESC LIMIT ?").all(limit));
25
+ }
26
+ // Collapse near-duplicate memory content so we don't inject the same fact
27
+ // three ways. Matches on the first 80 chars, case-insensitive.
28
+ function dedupe(rows) {
29
+ const seen = new Set();
30
+ const out = [];
31
+ for (const r of rows) {
32
+ const key = (r.content ?? "").slice(0, 80).toLowerCase().trim();
33
+ if (!key || seen.has(key))
34
+ continue;
35
+ seen.add(key);
36
+ out.push(r);
37
+ }
38
+ return out;
39
+ }
40
+ export function listRecent(db, limit = 50) {
41
+ return db.prepare("SELECT * FROM memories ORDER BY id DESC LIMIT ?").all(limit);
42
+ }
43
+ export function insertMemory(db, m) {
44
+ const info = db.prepare("INSERT INTO memories(kind,content,source,source_cycle_id,created_at) VALUES(?,?,?,?,?)").run(m.kind, m.content, m.source, m.source_cycle_id ?? null, new Date().toISOString());
45
+ return info.lastInsertRowid;
46
+ }
47
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/memory/recall.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,MAAM,CAAC,EAAM,EAAE,KAAa,EAAE,KAAK,GAAG,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK;SAChB,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;SAC5B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEf,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAa,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;KAMvB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAa,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC,CAAC,mCAAmC,CAAC,CAAC;IAE/C,OAAO,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAa,CAAC,CAAC;AACtG,CAAC;AAED,0EAA0E;AAC1E,+DAA+D;AAC/D,SAAS,MAAM,CAAC,IAAc;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAM,EAAE,KAAK,GAAG,EAAE;IAC3C,OAAO,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAa,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAM,EAAE,CAAoC;IACvE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,wFAAwF,CACzF,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,eAAyB,CAAC;AACxC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { Model } from "./types.js";
2
+ export declare const AUTO = "auto";
3
+ export declare const HAIKU = "claude-haiku-4-5";
4
+ export declare const SONNET = "claude-sonnet-4-6";
5
+ export declare const OPUS = "claude-opus-4-7";
6
+ export interface PickContext {
7
+ /** The literal model field from the profile config. */
8
+ configuredModel?: string;
9
+ /** The task text the cycle will run. */
10
+ task: string;
11
+ /** Optional source marker; passing "heartbeat" biases toward Haiku. */
12
+ source?: string;
13
+ }
14
+ export interface PickResult {
15
+ model: string;
16
+ tier: "haiku" | "sonnet" | "opus";
17
+ reason: string;
18
+ }
19
+ export declare function pickModel(ctx: PickContext): PickResult;
20
+ export declare function tierFor(modelId: string): PickResult["tier"];
21
+ export interface ContextBudget {
22
+ memoryCount: number;
23
+ memoryCharsEach: number;
24
+ skillCount: number;
25
+ maxTurns: number;
26
+ }
27
+ export declare function budgetFor(tier: PickResult["tier"]): ContextBudget;
28
+ export declare const KNOWN_MODELS: {
29
+ id: string;
30
+ note: string;
31
+ }[];
32
+ export declare function isValidModel(id: string): boolean;
33
+ export type { Model };
@@ -0,0 +1,104 @@
1
+ // Auto model selection. When a profile's model is set to "auto", pick a
2
+ // concrete model id based on the task's shape. Heuristic only — no
3
+ // extra backend calls.
4
+ //
5
+ // Tiers:
6
+ // claude-haiku-4-5 trivial / triage / heartbeat
7
+ // claude-sonnet-4-6 default — most normal work
8
+ // claude-opus-4-7 planning, coding, deep research, reflection
9
+ export const AUTO = "auto";
10
+ // Default to the most recent model IDs. Users can override per profile
11
+ // via `bajaclaw model <id>`; any string is accepted, the backend CLI
12
+ // validates against subscription entitlement.
13
+ export const HAIKU = "claude-haiku-4-5";
14
+ export const SONNET = "claude-sonnet-4-6";
15
+ export const OPUS = "claude-opus-4-7";
16
+ export function pickModel(ctx) {
17
+ const configured = ctx.configuredModel ?? AUTO;
18
+ if (configured !== AUTO) {
19
+ return { model: configured, tier: tierFor(configured), reason: "configured" };
20
+ }
21
+ const task = (ctx.task ?? "").trim();
22
+ const lower = task.toLowerCase();
23
+ const words = countWords(task);
24
+ // --- Opus tier: planning / coding / deep reasoning --------------------
25
+ if (matchesAny(lower, OPUS_MARKERS)) {
26
+ return { model: OPUS, tier: "opus", reason: "opus-marker" };
27
+ }
28
+ // --- Haiku tier: short + trivial markers ------------------------------
29
+ if (ctx.source === "heartbeat" || lower.startsWith("heartbeat check")) {
30
+ return { model: HAIKU, tier: "haiku", reason: "heartbeat" };
31
+ }
32
+ if (words <= 8 && matchesAny(lower, HAIKU_MARKERS)) {
33
+ return { model: HAIKU, tier: "haiku", reason: "short+trivial" };
34
+ }
35
+ if (words <= 4) {
36
+ return { model: HAIKU, tier: "haiku", reason: "very-short" };
37
+ }
38
+ // --- Sonnet tier: everything else -------------------------------------
39
+ return { model: SONNET, tier: "sonnet", reason: "default" };
40
+ }
41
+ export function tierFor(modelId) {
42
+ if (modelId.includes("opus"))
43
+ return "opus";
44
+ if (modelId.includes("haiku"))
45
+ return "haiku";
46
+ return "sonnet";
47
+ }
48
+ // Context budgets per model tier. Tightened defaults for token economy.
49
+ export function budgetFor(tier) {
50
+ switch (tier) {
51
+ case "haiku":
52
+ return { memoryCount: 3, memoryCharsEach: 180, skillCount: 1, maxTurns: 4 };
53
+ case "opus":
54
+ return { memoryCount: 7, memoryCharsEach: 280, skillCount: 3, maxTurns: 14 };
55
+ case "sonnet":
56
+ default:
57
+ return { memoryCount: 5, memoryCharsEach: 220, skillCount: 2, maxTurns: 8 };
58
+ }
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Heuristic markers. These are intentionally conservative: a false-positive
62
+ // promotes a cycle to Opus (expensive but correct); a false-negative demotes
63
+ // to Sonnet (still capable, cheaper).
64
+ const OPUS_MARKERS = [
65
+ /\b(plan|planning|architect|architecture|roadmap|strategy|strategize)\b/,
66
+ /\b(refactor|scaffold|migrate)\b/,
67
+ /\b(implement|build|author)\s+(a|an|the)?\s*(system|service|feature|module|component|pipeline|function|class|script|test|migration|endpoint|parser|adapter)\b/,
68
+ /\bwrite\s+(a|the)?\s*(program|script|function|class|module|test|spec|component|migration)\b/,
69
+ /\b(debug|troubleshoot|diagnose)\b/,
70
+ /\b(deep|thorough|comprehensive)\s+(research|analysis|review|dive|audit)\b/,
71
+ /\b(review|audit)\s+(the|my|this)?\s*(code|codebase|implementation|architecture|design)\b/,
72
+ /\b(fix|resolve)\s+(the|this|a)?\s*(bug|issue|regression|incident)\b/,
73
+ /\bcode\s+review\b/,
74
+ /\b(reflect|reflection)\b/,
75
+ ];
76
+ const HAIKU_MARKERS = [
77
+ /^(ack|ok|okay|thanks|thank\s*you|hi|hello|hey|ping|test|status)\b/,
78
+ /^(what|when|where|who)\s+is\s+\w+\??$/,
79
+ /^(show|list|check)\s+(my|the)?\s*(status|logs|queue|tasks|pending|count)\b/,
80
+ /^(does|do|is|are|can)\s+\w+/,
81
+ ];
82
+ function matchesAny(text, patterns) {
83
+ for (const p of patterns)
84
+ if (p.test(text))
85
+ return true;
86
+ return false;
87
+ }
88
+ function countWords(text) {
89
+ return text.trim().split(/\s+/).filter(Boolean).length;
90
+ }
91
+ // Known model ids for display in `bajaclaw model`.
92
+ export const KNOWN_MODELS = [
93
+ { id: AUTO, note: "pick automatically per task (haiku/sonnet/opus)" },
94
+ { id: HAIKU, note: "fast, cheap — triage + simple answers" },
95
+ { id: SONNET, note: "balanced default" },
96
+ { id: OPUS, note: "planning, coding, deep research" },
97
+ ];
98
+ export function isValidModel(id) {
99
+ if (id === AUTO)
100
+ return true;
101
+ // Any string is accepted; the backend validates per subscription.
102
+ return id.trim().length > 0;
103
+ }
104
+ //# sourceMappingURL=model-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-picker.js","sourceRoot":"","sources":["../src/model-picker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare function bajaclawHome(): string;
2
+ export declare function claudeHome(): string;
3
+ export declare function profileDir(profile: string): string;
4
+ export declare function profileDb(profile: string): string;
5
+ export declare function profileLogDir(profile: string): string;
6
+ export declare function profileSkillsDir(profile: string): string;
7
+ export declare function userSkillsDir(): string;
8
+ export declare function claudeAgentsDir(profile: string): string;
9
+ export declare function claudeSkillsDir(): string;
10
+ export declare function claudeMemoryDir(): string;
11
+ export declare function claudeDesktopConfigPath(): string;
12
+ export declare function ensureDir(path: string): string;
package/dist/paths.js ADDED
@@ -0,0 +1,49 @@
1
+ import { homedir, platform } from "node:os";
2
+ import { join } from "node:path";
3
+ import { mkdirSync } from "node:fs";
4
+ export function bajaclawHome() {
5
+ return process.env.BAJACLAW_HOME ?? join(homedir(), ".bajaclaw");
6
+ }
7
+ export function claudeHome() {
8
+ return process.env.CLAUDE_HOME ?? join(homedir(), ".claude");
9
+ }
10
+ export function profileDir(profile) {
11
+ return join(bajaclawHome(), "profiles", profile);
12
+ }
13
+ export function profileDb(profile) {
14
+ return join(profileDir(profile), "bajaclaw.db");
15
+ }
16
+ export function profileLogDir(profile) {
17
+ return join(profileDir(profile), "logs");
18
+ }
19
+ export function profileSkillsDir(profile) {
20
+ return join(profileDir(profile), "skills");
21
+ }
22
+ export function userSkillsDir() {
23
+ return join(bajaclawHome(), "skills");
24
+ }
25
+ export function claudeAgentsDir(profile) {
26
+ return join(claudeHome(), "agents", profile);
27
+ }
28
+ export function claudeSkillsDir() {
29
+ return join(claudeHome(), "skills");
30
+ }
31
+ export function claudeMemoryDir() {
32
+ return join(claudeHome(), "memory");
33
+ }
34
+ export function claudeDesktopConfigPath() {
35
+ const plat = platform();
36
+ if (plat === "darwin") {
37
+ return join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
38
+ }
39
+ if (plat === "win32") {
40
+ const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
41
+ return join(appData, "Claude", "claude_desktop_config.json");
42
+ }
43
+ return join(homedir(), ".config", "Claude", "claude_desktop_config.json");
44
+ }
45
+ export function ensureDir(path) {
46
+ mkdirSync(path, { recursive: true });
47
+ return path;
48
+ }
49
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type Persona } from "./persona.js";
2
+ export declare function personaPath(profile: string): string;
3
+ export declare function soulPath(profile: string): string;
4
+ export declare function loadPersona(profile: string): Persona | null;
5
+ export declare function savePersona(profile: string, persona: Persona): void;
@@ -0,0 +1,29 @@
1
+ // File I/O for persona state. Separated from persona.ts so the renderer
2
+ // stays pure.
3
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { profileDir, ensureDir } from "./paths.js";
6
+ import { renderSoul } from "./persona.js";
7
+ export function personaPath(profile) {
8
+ return join(profileDir(profile), "persona.json");
9
+ }
10
+ export function soulPath(profile) {
11
+ return join(profileDir(profile), "SOUL.md");
12
+ }
13
+ export function loadPersona(profile) {
14
+ const p = personaPath(profile);
15
+ if (!existsSync(p))
16
+ return null;
17
+ try {
18
+ return JSON.parse(readFileSync(p, "utf8"));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ export function savePersona(profile, persona) {
25
+ ensureDir(profileDir(profile));
26
+ writeFileSync(personaPath(profile), JSON.stringify(persona, null, 2));
27
+ writeFileSync(soulPath(profile), renderSoul(persona));
28
+ }
29
+ //# sourceMappingURL=persona-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persona-io.js","sourceRoot":"","sources":["../src/persona-io.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,cAAc;AACd,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAExD,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAY,CAAC;IAAC,CAAC;IAC9D,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,OAAgB;IAC3D,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtE,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface Persona {
2
+ agentName: string;
3
+ userName?: string;
4
+ tone?: "casual" | "concise" | "formal" | "friendly" | "playful" | "terse";
5
+ timezone?: string;
6
+ focus?: string;
7
+ interests?: string[];
8
+ doNots?: string[];
9
+ createdAt?: string;
10
+ }
11
+ export declare const TONE_OPTIONS: Persona["tone"][];
12
+ export declare function renderSoul(p: Persona): string;
@@ -0,0 +1,54 @@
1
+ // Persona state: types + pure rendering. File I/O lives in persona-io.ts
2
+ // so this module stays pure and easy to unit-test.
3
+ export const TONE_OPTIONS = ["concise", "casual", "friendly", "formal", "playful", "terse"];
4
+ // Render the persona into SOUL.md. The cycle loop reads SOUL.md verbatim
5
+ // and prepends it to the prompt as the identity block.
6
+ export function renderSoul(p) {
7
+ const lines = [];
8
+ lines.push(`# ${p.agentName}`);
9
+ lines.push("");
10
+ if (p.focus)
11
+ lines.push(p.focus);
12
+ lines.push("");
13
+ lines.push("## Who I'm talking to");
14
+ if (p.userName)
15
+ lines.push(`- Their name is ${p.userName}. Address them by name when appropriate.`);
16
+ else
17
+ lines.push(`- I don't know their name yet. If it matters, ask.`);
18
+ if (p.timezone)
19
+ lines.push(`- Their timezone is ${p.timezone}. Interpret "today", "tomorrow", and times in that zone.`);
20
+ lines.push("");
21
+ lines.push("## Voice");
22
+ lines.push(`- Tone: ${p.tone ?? "concise"}.`);
23
+ lines.push(`- ${toneDescription(p.tone ?? "concise")}`);
24
+ if (p.interests && p.interests.length > 0) {
25
+ lines.push("");
26
+ lines.push("## What I care about");
27
+ for (const i of p.interests)
28
+ lines.push(`- ${i}`);
29
+ }
30
+ if (p.doNots && p.doNots.length > 0) {
31
+ lines.push("");
32
+ lines.push("## Hard rules");
33
+ for (const d of p.doNots)
34
+ lines.push(`- Don't ${d}`);
35
+ }
36
+ lines.push("");
37
+ lines.push("## Identity principles");
38
+ lines.push(`- I am ${p.agentName}. I maintain this identity across cycles.`);
39
+ lines.push(`- I work for the user — I am not a chatbot. Produce artifacts, not filler.`);
40
+ lines.push(`- When I don't know something, I say so and stop. No placeholder data.`);
41
+ return lines.join("\n") + "\n";
42
+ }
43
+ function toneDescription(tone) {
44
+ switch (tone) {
45
+ case "casual": return "Speak informally. Contractions welcome. Plain English, no jargon.";
46
+ case "concise": return "Keep it tight. Short sentences. Ship the answer; skip the preamble.";
47
+ case "formal": return "Speak professionally. Complete sentences. Precise vocabulary.";
48
+ case "friendly": return "Warm and conversational. It's fine to acknowledge feelings.";
49
+ case "playful": return "Light and witty — but useful first, witty second.";
50
+ case "terse": return "Minimum words. One-line answers when possible.";
51
+ default: return "Clear and direct.";
52
+ }
53
+ }
54
+ //# sourceMappingURL=persona.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persona.js","sourceRoot":"","sources":["../src/persona.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function isInteractive(): boolean;
2
+ export declare function ask(question: string, fallback?: string): Promise<string>;
3
+ export declare function askChoice(question: string, options: string[], fallback?: string): Promise<string>;
4
+ export declare function askList(question: string, separator?: string): Promise<string[]>;
5
+ export declare function detectTimezone(): string;
package/dist/prompt.js ADDED
@@ -0,0 +1,56 @@
1
+ // Tiny readline-based prompt helpers for the interactive setup wizard.
2
+ // No new dep — uses node:readline/promises.
3
+ import { createInterface } from "node:readline/promises";
4
+ import { stdin, stdout } from "node:process";
5
+ export function isInteractive() {
6
+ return !!stdin.isTTY && !!stdout.isTTY;
7
+ }
8
+ export async function ask(question, fallback) {
9
+ if (!isInteractive())
10
+ return fallback ?? "";
11
+ const rl = createInterface({ input: stdin, output: stdout });
12
+ try {
13
+ const hint = fallback ? ` \x1b[90m[${fallback}]\x1b[0m` : "";
14
+ const answer = (await rl.question(`${question}${hint} `)).trim();
15
+ return answer || (fallback ?? "");
16
+ }
17
+ finally {
18
+ rl.close();
19
+ }
20
+ }
21
+ export async function askChoice(question, options, fallback = options[0]) {
22
+ if (!isInteractive())
23
+ return fallback;
24
+ const rl = createInterface({ input: stdin, output: stdout });
25
+ try {
26
+ const labels = options.map((o, i) => `${i + 1}. ${o}${o === fallback ? " \x1b[90m(default)\x1b[0m" : ""}`).join("\n ");
27
+ stdout.write(`${question}\n ${labels}\n`);
28
+ const raw = (await rl.question("choice: ")).trim();
29
+ if (!raw)
30
+ return fallback;
31
+ const n = Number(raw);
32
+ if (Number.isInteger(n) && n >= 1 && n <= options.length)
33
+ return options[n - 1];
34
+ // Allow typed-in free-form that matches.
35
+ const match = options.find((o) => o.toLowerCase() === raw.toLowerCase());
36
+ return match ?? fallback;
37
+ }
38
+ finally {
39
+ rl.close();
40
+ }
41
+ }
42
+ export async function askList(question, separator = ",") {
43
+ const raw = await ask(`${question} \x1b[90m(comma-separated, blank to skip)\x1b[0m`);
44
+ if (!raw)
45
+ return [];
46
+ return raw.split(separator).map((s) => s.trim()).filter(Boolean);
47
+ }
48
+ export function detectTimezone() {
49
+ try {
50
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
51
+ }
52
+ catch {
53
+ return "";
54
+ }
55
+ }
56
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { DB } from "./db.js";
2
+ export interface CircuitState {
3
+ open: boolean;
4
+ failures: number;
5
+ opened_at?: string;
6
+ }
7
+ export declare function read(db: DB): CircuitState;
8
+ export declare function shouldAllow(db: DB): {
9
+ allow: boolean;
10
+ reason?: string;
11
+ };
12
+ export declare function recordSuccess(db: DB): void;
13
+ export declare function recordFailure(db: DB): CircuitState;
14
+ export declare function rateLimit(db: DB, maxPerHour?: number): {
15
+ allow: boolean;
16
+ used: number;
17
+ };
package/dist/safety.js ADDED
@@ -0,0 +1,47 @@
1
+ const KEY = "claude.breaker";
2
+ const FAIL_THRESHOLD = 5;
3
+ const COOLDOWN_MS = 15 * 60 * 1000;
4
+ export function read(db) {
5
+ const row = db.prepare("SELECT value FROM circuit_state WHERE key=?").get(KEY);
6
+ if (!row)
7
+ return { open: false, failures: 0 };
8
+ try {
9
+ return JSON.parse(row.value);
10
+ }
11
+ catch {
12
+ return { open: false, failures: 0 };
13
+ }
14
+ }
15
+ function write(db, state) {
16
+ db.prepare("INSERT INTO circuit_state(key,value,updated_at) VALUES(?,?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at").run(KEY, JSON.stringify(state), new Date().toISOString());
17
+ }
18
+ export function shouldAllow(db) {
19
+ const s = read(db);
20
+ if (!s.open)
21
+ return { allow: true };
22
+ if (s.opened_at && Date.now() - Date.parse(s.opened_at) > COOLDOWN_MS) {
23
+ write(db, { open: false, failures: 0 });
24
+ return { allow: true };
25
+ }
26
+ return { allow: false, reason: `circuit-breaker open (failures=${s.failures})` };
27
+ }
28
+ export function recordSuccess(db) {
29
+ write(db, { open: false, failures: 0 });
30
+ }
31
+ export function recordFailure(db) {
32
+ const s = read(db);
33
+ const failures = s.failures + 1;
34
+ const open = failures >= FAIL_THRESHOLD;
35
+ const next = { open, failures, opened_at: open ? new Date().toISOString() : s.opened_at };
36
+ write(db, next);
37
+ return next;
38
+ }
39
+ // Conservative default to stay well under backend fair-use limits.
40
+ // Bump via an override if your subscription/plan genuinely supports more.
41
+ const DEFAULT_MAX_PER_HOUR = 30;
42
+ export function rateLimit(db, maxPerHour = DEFAULT_MAX_PER_HOUR) {
43
+ const cutoff = new Date(Date.now() - 60 * 60 * 1000).toISOString();
44
+ const row = db.prepare("SELECT COUNT(*) as c FROM cycles WHERE started_at > ?").get(cutoff);
45
+ return { allow: row.c < maxPerHour, used: row.c };
46
+ }
47
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ScheduleEntry } from "../types.js";
2
+ export declare function install(profile: string, label: string, cronExpr: string, command: string[]): Promise<void>;
3
+ export declare function uninstall(profile: string, label: string): Promise<void>;
4
+ export declare function list(profile: string): Promise<ScheduleEntry[]>;
@@ -0,0 +1,44 @@
1
+ import { execa } from "execa";
2
+ const MARKER_BEGIN = "# BEGIN BAJACLAW";
3
+ const MARKER_END = "# END BAJACLAW";
4
+ async function readCrontab() {
5
+ const r = await execa("crontab", ["-l"], { reject: false });
6
+ return r.exitCode === 0 ? r.stdout : "";
7
+ }
8
+ async function writeCrontab(body) {
9
+ await execa("crontab", ["-"], { input: body });
10
+ }
11
+ function lineTag(profile, label) {
12
+ return `# bajaclaw:${profile}:${label}`;
13
+ }
14
+ export async function install(profile, label, cronExpr, command) {
15
+ const entry = `${cronExpr} ${command.map((c) => (c.includes(" ") ? `"${c}"` : c)).join(" ")} ${lineTag(profile, label)}`;
16
+ const current = await readCrontab();
17
+ const lines = current.split(/\r?\n/).filter((l) => !l.includes(lineTag(profile, label)));
18
+ ensureBlock(lines);
19
+ const idxEnd = lines.findIndex((l) => l === MARKER_END);
20
+ lines.splice(idxEnd, 0, entry);
21
+ await writeCrontab(lines.join("\n") + "\n");
22
+ }
23
+ export async function uninstall(profile, label) {
24
+ const current = await readCrontab();
25
+ const lines = current.split(/\r?\n/).filter((l) => !l.includes(lineTag(profile, label)));
26
+ await writeCrontab(lines.join("\n"));
27
+ }
28
+ export async function list(profile) {
29
+ const current = await readCrontab();
30
+ const out = [];
31
+ for (const l of current.split(/\r?\n/)) {
32
+ const m = l.match(new RegExp(`^(\\S+\\s+\\S+\\s+\\S+\\s+\\S+\\s+\\S+)\\s+.*#\\s*bajaclaw:${profile}:(\\S+)`));
33
+ if (m)
34
+ out.push({ cron: m[1], task: m[2], enabled: 1 });
35
+ }
36
+ return out;
37
+ }
38
+ function ensureBlock(lines) {
39
+ if (!lines.includes(MARKER_BEGIN))
40
+ lines.push(MARKER_BEGIN);
41
+ if (!lines.includes(MARKER_END))
42
+ lines.push(MARKER_END);
43
+ }
44
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/scheduler/cron.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ScheduleEntry } from "../types.js";
2
+ export interface SchedulerAdapter {
3
+ install(profile: string, label: string, cronExpr: string, command: string[]): Promise<void>;
4
+ uninstall(profile: string, label: string): Promise<void>;
5
+ list(profile: string): Promise<ScheduleEntry[]>;
6
+ }
7
+ export declare function pickAdapter(): SchedulerAdapter;
@@ -0,0 +1,15 @@
1
+ import { platform } from "node:os";
2
+ import * as launchd from "./launchd.js";
3
+ import * as systemd from "./systemd.js";
4
+ import * as cron from "./cron.js";
5
+ import * as schtasks from "./schtasks.js";
6
+ export function pickAdapter() {
7
+ const plat = platform();
8
+ if (plat === "darwin")
9
+ return launchd;
10
+ if (plat === "win32")
11
+ return schtasks;
12
+ // Prefer systemd user units; fall back to crontab.
13
+ return systemd.available() ? systemd : cron;
14
+ }
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAQ1C,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IACtC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC;IACtC,mDAAmD;IACnD,OAAO,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ScheduleEntry } from "../types.js";
2
+ export declare function install(profile: string, label: string, cronExpr: string, command: string[]): Promise<void>;
3
+ export declare function uninstall(profile: string, label: string): Promise<void>;
4
+ export declare function list(profile: string): Promise<ScheduleEntry[]>;