@desplega.ai/agent-swarm 1.145.0 → 1.147.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 (221) hide show
  1. package/README.md +2 -1
  2. package/dist/{acp-adapter-580t41c0.js → acp-adapter-9n319wqc.js} +61 -6
  3. package/dist/{actions-m662tjng.js → actions-2vxqvpr9.js} +9 -8
  4. package/dist/{app-zb3rndm8.js → app-w066xfy0.js} +6 -5
  5. package/dist/assistant-kt31dj2h.js +236 -0
  6. package/dist/{boot-reembed-072x00vn.js → boot-reembed-az5rassp.js} +7 -6
  7. package/dist/{boot-reembed-65zz2smt.js → boot-reembed-j3mm3rfz.js} +8 -7
  8. package/dist/{boot-scrub-logs-yz0ams04.js → boot-scrub-logs-b6h54817.js} +4 -4
  9. package/dist/{claude-adapter-paj270y2.js → claude-adapter-w1z04ann.js} +8 -6
  10. package/dist/{claude-managed-setup-w619jncn.js → claude-managed-setup-f5pmsyrp.js} +24 -3
  11. package/dist/{claude-sdk-session-swt80j9z.js → claude-sdk-session-f0cc1kec.js} +8 -6
  12. package/dist/{cli-dt553ktb.js → cli-0b6y7kxm.js} +1 -1
  13. package/dist/{cli-bxdhw615.js → cli-12fz972k.js} +4 -4
  14. package/dist/{cli-s2f20r5w.js → cli-1th1728g.js} +2 -2
  15. package/dist/{cli-rs6ec3b9.js → cli-3tgwnf43.js} +3 -3
  16. package/dist/{cli-gxnzc6wh.js → cli-4nr988h6.js} +1 -1
  17. package/dist/{cli-axs8e6d4.js → cli-53s590z8.js} +1 -1
  18. package/dist/{cli-ygbjp3z8.js → cli-54wwve05.js} +5 -4
  19. package/dist/{cli-v0asr5yv.js → cli-719k9j2c.js} +2 -2
  20. package/dist/{cli-anktweqr.js → cli-89xfd7f9.js} +21 -47
  21. package/dist/{cli-q34a0e10.js → cli-8v0g1yc8.js} +1 -1
  22. package/dist/cli-9d8ntetj.js +42 -0
  23. package/dist/{cli-z9fprcrf.js → cli-atcve9y8.js} +881 -738
  24. package/dist/{cli-jmb7g47h.js → cli-b5bq9crk.js} +14 -31
  25. package/dist/cli-d8brzxjb.js +190 -0
  26. package/dist/{cli-gzky0gkr.js → cli-de14znh8.js} +2 -2
  27. package/dist/{cli-xytwff7f.js → cli-dttph1bw.js} +2 -2
  28. package/dist/cli-ep19k3mb.js +19 -0
  29. package/dist/{cli-m1xa8be7.js → cli-f146mn5s.js} +7 -50
  30. package/dist/{cli-1fj0chdk.js → cli-f7dsy61y.js} +5 -3
  31. package/dist/{cli-f567d5c1.js → cli-ftht3zzj.js} +2782 -2589
  32. package/dist/{cli-a0g1gbt5.js → cli-hbv0kq6w.js} +2 -2
  33. package/dist/{cli-fhsz3twr.js → cli-jsp14b6c.js} +171 -1
  34. package/dist/{cli-7fnkj1hj.js → cli-kpv03zhj.js} +21 -17
  35. package/dist/{cli-m4j6trn4.js → cli-m8yrsg97.js} +2 -2
  36. package/dist/cli-m9sxbkhm.js +779 -0
  37. package/dist/cli-mmemxxdc.js +823 -0
  38. package/dist/{cli-tqtvj5pt.js → cli-n8508nre.js} +1 -1
  39. package/dist/{cli-z96t0thj.js → cli-p1d5b073.js} +37 -2
  40. package/dist/{cli-gh8y8f36.js → cli-rw51bq3j.js} +13 -10
  41. package/dist/{cli-59ej1c07.js → cli-smby5m17.js} +7 -6
  42. package/dist/{cli-65vqzz3v.js → cli-tzvk9haz.js} +94 -372
  43. package/dist/{cli-dc9k2ba9.js → cli-w9kb3bk1.js} +1 -1
  44. package/dist/{cli-kpev657q.js → cli-y6b6fb76.js} +25 -3
  45. package/dist/{cli-123q2get.js → cli-yz3djrm0.js} +9 -9
  46. package/dist/{cli-wvp6bvy4.js → cli-zhjmqxzh.js} +1 -1
  47. package/dist/cli.js +13 -13
  48. package/dist/{codex-adapter-k98vaw2r.js → codex-adapter-zw4dwsx7.js} +2 -2
  49. package/dist/{codex-hook-9pf19cks.js → codex-hook-bw8p5nh4.js} +2 -2
  50. package/dist/{codex-session-runner-tngtphx7.js → codex-session-runner-k981s65v.js} +2 -2
  51. package/dist/{commands-y8nbr3fv.js → commands-sykrxx7e.js} +4 -4
  52. package/dist/{db-30p4h2t1.js → db-sfbsc8wt.js} +6 -4
  53. package/dist/handlers-0aspcejm.js +603 -0
  54. package/dist/{hook-dcw4jfbj.js → hook-4nvqj2sb.js} +7 -5
  55. package/dist/{hook-21jexvfx.js → hook-hxccs7m5.js} +24 -49
  56. package/dist/{http-r4kq5g8d.js → http-y06z517d.js} +230 -94
  57. package/dist/{index-q3qja6ta.js → index-hssww7kj.js} +15 -14
  58. package/dist/{index-gay66b9w.js → index-k8znfx0z.js} +13 -12
  59. package/dist/{index-53zyht4z.js → index-tce1rss4.js} +371 -110
  60. package/dist/{index-nqvf26za.js → index-x5j894zf.js} +14 -13
  61. package/dist/{keepalive-xs8fa55y.js → keepalive-w733ax66.js} +6 -6
  62. package/dist/{lead-d9m2t4s0.js → lead-75bjqa9d.js} +29 -27
  63. package/dist/{maintenance-3zh82g6z.js → maintenance-w4f1zjck.js} +8 -7
  64. package/dist/{oauth-refresh-sweep-03snsye5.js → oauth-refresh-sweep-wdetky26.js} +5 -5
  65. package/dist/{onboard-0cg1925x.js → onboard-bb5net8s.js} +2 -2
  66. package/dist/{otel-impl-0ab95z27.js → otel-impl-0w7c14ap.js} +1 -1
  67. package/dist/{pi-mono-adapter-dtkz4e7j.js → pi-mono-adapter-2has4gnp.js} +12 -2
  68. package/dist/{pricing-refresh-e5jhzz4j.js → pricing-refresh-9nzsrgcq.js} +6 -6
  69. package/dist/{rbac-roles-p1mf40z3.js → rbac-roles-r3hqjp09.js} +5 -5
  70. package/dist/{rbac-roles-2w3cmrkc.js → rbac-roles-z1jrffbt.js} +4 -4
  71. package/dist/{registry-9kdck5ye.js → registry-v5wytg0s.js} +1 -2
  72. package/dist/{render-v2-xhawry3k.js → render-v2-vbr89fnb.js} +6 -5
  73. package/dist/{seed-pricing-t223sw91.js → seed-pricing-g62hy1pk.js} +7 -5
  74. package/dist/{setup-zcs0rce7.js → setup-gnfqnptp.js} +2 -2
  75. package/dist/{worker-qnp2ka62.js → worker-kznxp4qm.js} +29 -27
  76. package/openapi.json +263 -12
  77. package/package.json +1 -1
  78. package/plugin/commands/start-worker.md +4 -9
  79. package/plugin/pi-skills/start-worker/SKILL.md +4 -9
  80. package/src/be/db/agents.ts +556 -0
  81. package/src/be/db/context-versions.ts +117 -0
  82. package/src/be/db/runtime.ts +406 -0
  83. package/src/be/db/tasks/read.ts +1167 -0
  84. package/src/be/db/tasks/write.ts +953 -0
  85. package/src/be/db.ts +584 -3429
  86. package/src/be/migrations/147_scheduled_tasks_parent_task.sql +7 -0
  87. package/src/be/migrations/148_pages_svg.sql +123 -0
  88. package/src/be/migrations/149_session_tokens.sql +24 -0
  89. package/src/be/scripts/typecheck.ts +1 -0
  90. package/src/be/seed-pricing.ts +13 -8
  91. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  92. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  93. package/src/be/seed-scripts/catalog/star-history-refresh.ts +101 -0
  94. package/src/be/seed-scripts/catalog/star-history-renderer.ts +119 -0
  95. package/src/be/seed-scripts/index.ts +17 -0
  96. package/src/be/seed-skills/index.ts +14 -0
  97. package/src/be/swarm-config-guard.ts +5 -2
  98. package/src/be/task-attachment-store.ts +70 -0
  99. package/src/be/users.ts +77 -0
  100. package/src/commands/attachments-section.ts +37 -0
  101. package/src/commands/claude-managed-setup.ts +45 -3
  102. package/src/commands/claude-md-session.ts +408 -0
  103. package/src/commands/context-preamble.ts +15 -3
  104. package/src/commands/profile-sync.ts +205 -5
  105. package/src/commands/provider-credentials.ts +60 -27
  106. package/src/commands/runner.ts +63 -58
  107. package/src/commands/templates.ts +25 -2
  108. package/src/hooks/hook.ts +26 -67
  109. package/src/http/agents.ts +40 -1
  110. package/src/http/auth.ts +13 -1
  111. package/src/http/fs.ts +21 -51
  112. package/src/http/index.ts +2 -0
  113. package/src/http/mcp.ts +32 -0
  114. package/src/http/pages-public.ts +20 -4
  115. package/src/http/pages.ts +11 -3
  116. package/src/http/poll.ts +4 -0
  117. package/src/http/repos.ts +3 -3
  118. package/src/http/sessions.ts +82 -0
  119. package/src/http/tasks.ts +10 -2
  120. package/src/http/utils.ts +79 -1
  121. package/src/prompts/session-templates.ts +12 -8
  122. package/src/providers/acp-adapter.ts +62 -8
  123. package/src/providers/pi-mono-adapter.ts +23 -6
  124. package/src/providers/pricing-sources.md +11 -0
  125. package/src/scheduler/scheduler.test.ts +49 -2
  126. package/src/scheduler/scheduler.ts +4 -0
  127. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  128. package/src/scripts-runtime/types/stdlib.d.ts +8 -0
  129. package/src/scripts-runtime/types/swarm-sdk.d.ts +8 -0
  130. package/src/server.ts +2 -0
  131. package/src/slack/assistant.ts +87 -46
  132. package/src/slack/handlers.test.ts +1 -3
  133. package/src/slack/handlers.ts +102 -87
  134. package/src/slack/inbound-files.ts +466 -0
  135. package/src/slack/templates.ts +14 -0
  136. package/src/tasks/task-terminal-effects.ts +158 -0
  137. package/src/tests/acp-adapter.test.ts +369 -117
  138. package/src/tests/budget-claim-gate.test.ts +1 -0
  139. package/src/tests/build-pi-skills.test.ts +5 -7
  140. package/src/tests/claude-managed-setup.test.ts +52 -4
  141. package/src/tests/claude-md-session.test.ts +603 -0
  142. package/src/tests/codex-skill-resolver.test.ts +19 -0
  143. package/src/tests/context-versioning.test.ts +107 -0
  144. package/src/tests/cors-allowlist.test.ts +309 -0
  145. package/src/tests/credential-check.test.ts +157 -14
  146. package/src/tests/db-agents.test.ts +91 -0
  147. package/src/tests/db-context-versions.test.ts +37 -0
  148. package/src/tests/db-extraction-contract.test.ts +45 -0
  149. package/src/tests/db-runtime.test.ts +70 -0
  150. package/src/tests/db-task-read-contract.test.ts +624 -0
  151. package/src/tests/db-task-write-contract.test.ts +653 -0
  152. package/src/tests/db-tasks-read.test.ts +183 -0
  153. package/src/tests/db-tasks-write.test.ts +230 -0
  154. package/src/tests/defer-task.test.ts +389 -0
  155. package/src/tests/docs-index-footprint.test.js +2 -2
  156. package/src/tests/e2e-visuals-stage.test.ts +151 -0
  157. package/src/tests/file-lock.test.ts +144 -0
  158. package/src/tests/fixtures/file-lock-holder.ts +13 -0
  159. package/src/tests/fixtures/hold-file-lock.ts +25 -0
  160. package/src/tests/heartbeat-expiry.test.ts +188 -0
  161. package/src/tests/http-api-integration.test.ts +78 -1
  162. package/src/tests/pages-public-html.test.ts +43 -0
  163. package/src/tests/pages-svg-migration.test.ts +42 -0
  164. package/src/tests/preload.ts +4 -1
  165. package/src/tests/profile-sync-warning.test.ts +16 -0
  166. package/src/tests/profile-sync.test.ts +126 -0
  167. package/src/tests/prompt-template-session.test.ts +20 -4
  168. package/src/tests/provider-registration.test.ts +93 -0
  169. package/src/tests/rbac-e2e-helpers.test.ts +53 -0
  170. package/src/tests/rbac-e2e-helpers.ts +19 -2
  171. package/src/tests/reload-config.test.ts +26 -0
  172. package/src/tests/routing-affinity-inventory.test.ts +1 -1
  173. package/src/tests/runner-attachments-section.test.ts +22 -2
  174. package/src/tests/runner-context-preamble.test.ts +30 -0
  175. package/src/tests/runner-deployment-resume.test.ts +107 -0
  176. package/src/tests/runner-repo-autostash.test.ts +12 -0
  177. package/src/tests/script-connections.test.ts +4 -0
  178. package/src/tests/seed-scripts.test.ts +2 -2
  179. package/src/tests/session-tokens.test.ts +279 -0
  180. package/src/tests/slack-file-tools-attachments.test.ts +408 -0
  181. package/src/tests/slack-inbound-files.test.ts +847 -0
  182. package/src/tests/star-history-refresh.test.ts +102 -0
  183. package/src/tests/swarm-config-reserved-keys.test.ts +21 -0
  184. package/src/tests/swarm-repos.test.ts +20 -0
  185. package/src/tests/tool-annotations.test.ts +4 -3
  186. package/src/tests/ui-logs-parser.test.ts +176 -0
  187. package/src/tools/create-page.ts +4 -2
  188. package/src/tools/defer-task.ts +239 -0
  189. package/src/tools/repos/update-repo.ts +2 -2
  190. package/src/tools/schedules/create-schedule.ts +1 -0
  191. package/src/tools/schedules/list-schedules.ts +1 -0
  192. package/src/tools/schedules/patch-schedule.ts +1 -0
  193. package/src/tools/schedules/update-schedule.ts +1 -0
  194. package/src/tools/slack-download-file.ts +60 -29
  195. package/src/tools/slack-read.ts +73 -32
  196. package/src/tools/store-progress.ts +16 -146
  197. package/src/tools/tool-config.ts +1 -0
  198. package/src/tools/utils.ts +21 -0
  199. package/src/types.ts +37 -4
  200. package/src/utils/acp-session-token.ts +56 -0
  201. package/src/utils/file-lock.ts +111 -0
  202. package/src/utils/heartbeat-expiry.ts +78 -0
  203. package/src/utils/request-auth-context.ts +2 -0
  204. package/src/utils/task-attachment-links.ts +22 -0
  205. package/templates/skills/code-quality/content.md +8 -5
  206. package/templates/skills/download-task-attachment/content.md +2 -1
  207. package/{plugin/pi-skills → templates/skills}/review-offered-task/SKILL.md +5 -5
  208. package/templates/skills/review-offered-task/config.json +14 -0
  209. package/{plugin/commands/review-offered-task.md → templates/skills/review-offered-task/content.md} +3 -8
  210. package/templates/skills/scheduling/content.md +4 -0
  211. package/templates/skills/slack-interaction/content.md +2 -2
  212. package/templates/skills/work-on-task/SKILL.md +16 -0
  213. package/templates/skills/work-on-task/config.json +14 -0
  214. package/templates/skills/work-on-task/content.md +11 -0
  215. package/dist/assistant-0qt42nzg.js +0 -212
  216. package/dist/cli-fs1kkqgr.js +0 -317
  217. package/dist/cli-jnf5zghe.js +0 -269
  218. package/dist/cli-n1q8q14d.js +0 -177
  219. package/dist/handlers-yfp1qn81.js +0 -592
  220. package/plugin/commands/work-on-task.md +0 -39
  221. package/plugin/pi-skills/work-on-task/SKILL.md +0 -39
@@ -0,0 +1,91 @@
1
+ import { afterEach, beforeEach, expect, spyOn, test } from "bun:test";
2
+ import * as db from "../be/db";
3
+
4
+ beforeEach(() => db.initDb(":memory:"));
5
+ afterEach(() => db.closeDb());
6
+
7
+ const worker = { name: "Worker", isLead: false, status: "idle" as const };
8
+
9
+ test("facade registration installs defaults and records lifecycle logs", async () => {
10
+ const skill = await db.createSkill({
11
+ name: "test-default",
12
+ description: "Default",
13
+ content: "Instructions",
14
+ type: "personal",
15
+ scope: "swarm",
16
+ systemDefault: true,
17
+ });
18
+ const agent = await db.createAgent(worker);
19
+ expect(
20
+ await db.getDbClient().get("SELECT skillId FROM agent_skills WHERE agentId = ?", [agent.id]),
21
+ ).toEqual({ skillId: skill.id });
22
+ await db.updateAgentStatus(agent.id, "busy");
23
+ expect(
24
+ (await db.getLogsByAgentId(agent.id)).map(({ eventType, oldValue, newValue }) => ({
25
+ eventType,
26
+ oldValue,
27
+ newValue,
28
+ })),
29
+ ).toEqual(
30
+ expect.arrayContaining([
31
+ { eventType: "agent_joined", oldValue: undefined, newValue: "idle" },
32
+ { eventType: "agent_status_change", oldValue: "idle", newValue: "busy" },
33
+ ]),
34
+ );
35
+ // Logging precedes deletion, including when the existing log FK rejects deletion.
36
+ await db.getDbClient().run("CREATE TABLE deletion_probe (eventType TEXT, oldValue TEXT)");
37
+ await db
38
+ .getDbClient()
39
+ .run(
40
+ "CREATE TRIGGER deletion_log AFTER INSERT ON agent_log WHEN NEW.eventType = 'agent_left' BEGIN INSERT INTO deletion_probe VALUES (NEW.eventType, NEW.oldValue); END",
41
+ );
42
+ await expect(db.deleteAgent(agent.id)).rejects.toThrow("FOREIGN KEY constraint failed");
43
+ expect(await db.getDbClient().get("SELECT * FROM deletion_probe")).toEqual({
44
+ eventType: "agent_left",
45
+ oldValue: "busy",
46
+ });
47
+ });
48
+
49
+ test("skill and log failures retain the original catch boundaries", async () => {
50
+ await db.getDbClient().run("DROP TABLE skills");
51
+ await db
52
+ .getDbClient()
53
+ .run(
54
+ "CREATE TRIGGER reject_logs BEFORE INSERT ON agent_log BEGIN SELECT RAISE(FAIL, 'log failure'); END",
55
+ );
56
+ const warning = spyOn(console, "warn").mockImplementation(() => {});
57
+ try {
58
+ const agent = await db.createAgent(worker);
59
+ expect(warning).toHaveBeenCalledWith(
60
+ "[db] Failed to install system-default skills for new agent:",
61
+ expect.any(String),
62
+ );
63
+ expect((await db.updateAgentStatus(agent.id, "busy"))?.status).toBe("busy");
64
+ expect(await db.deleteAgent(agent.id)).toBe(true);
65
+ } finally {
66
+ warning.mockRestore();
67
+ }
68
+ });
69
+
70
+ test("unmoved profile and idle-worker callers share agent mapping defaults", async () => {
71
+ const agent = await db.createAgent(worker);
72
+ expect(agent).toMatchObject({
73
+ maxTasks: 1,
74
+ emptyPollCount: 0,
75
+ capabilities: [],
76
+ credentialMissing: null,
77
+ credStatus: null,
78
+ harnessProvider: null,
79
+ avatar: null,
80
+ });
81
+ const updated = await db.updateAgentProfile(agent.id, {
82
+ role: "coder",
83
+ capabilities: ["typescript"],
84
+ });
85
+ expect(updated).toEqual(await db.getAgentById(agent.id));
86
+ expect(await db.getIdleWorkersWithCapacity()).toEqual([updated!]);
87
+ await db
88
+ .getDbClient()
89
+ .run("UPDATE agents SET avatar = ? WHERE id = ?", ["invalid json", agent.id]);
90
+ expect((await db.getAgentById(agent.id))?.avatar).toBeNull();
91
+ });
@@ -0,0 +1,37 @@
1
+ import { afterEach, beforeEach, expect, test } from "bun:test";
2
+ import * as db from "../be/db";
3
+
4
+ beforeEach(() => db.initDb(":memory:"));
5
+ afterEach(() => db.closeDb());
6
+
7
+ const worker = { name: "Worker", isLead: false, status: "idle" as const };
8
+
9
+ test("context history keeps version ordering, limits, hashes and null defaults", async () => {
10
+ const agent = await db.createAgent(worker);
11
+ const versions = [];
12
+ for (const version of [2, 1, 3]) {
13
+ versions.push(
14
+ await db.createContextVersion({
15
+ agentId: agent.id,
16
+ field: "soulMd",
17
+ content: `v${version}`,
18
+ version,
19
+ changeSource: "system",
20
+ contentHash: db.computeContentHash(`v${version}`),
21
+ }),
22
+ );
23
+ }
24
+ expect(
25
+ (await db.getContextVersionHistory({ agentId: agent.id, field: "soulMd", limit: 2 })).map(
26
+ (v) => v.version,
27
+ ),
28
+ ).toEqual([3, 2]);
29
+ expect(await db.getLatestContextVersion(agent.id, "soulMd")).toEqual(versions[2]);
30
+ expect(await db.getContextVersion(versions[0]!.id)).toEqual(versions[0]!);
31
+ expect(versions[0]).toMatchObject({
32
+ changedByAgentId: null,
33
+ changeReason: null,
34
+ previousVersionId: null,
35
+ });
36
+ expect(await db.getLatestContextVersion(agent.id, "toolsMd")).toBeNull();
37
+ });
@@ -0,0 +1,45 @@
1
+ import { expect, test } from "bun:test";
2
+ import * as db from "../be/db";
3
+ import * as agents from "../be/db/agents";
4
+ import * as context from "../be/db/context-versions";
5
+ import * as taskRead from "../be/db/tasks/read";
6
+ import { CHILD_PROCESS_TEST_BUDGET_MS, expectChildOk, runChild } from "./test-proc";
7
+
8
+ test("facade exposes repository bindings without internal exports", () => {
9
+ for (const [name, value] of Object.entries({ ...agents, ...context, ...taskRead })) {
10
+ if (
11
+ [
12
+ "rowToAgent",
13
+ "configureAgentDependencies",
14
+ "rowToAgentTask",
15
+ "rowToAgentTaskSummary",
16
+ "configureTaskReadDependencies",
17
+ ].includes(name)
18
+ ) {
19
+ expect(name in db).toBe(false);
20
+ } else {
21
+ expect((db as Record<string, unknown>)[name]).toBe(value);
22
+ }
23
+ }
24
+ });
25
+
26
+ test(
27
+ "fresh facade initialization does not access the database",
28
+ async () => {
29
+ const runtimePath = JSON.stringify(new URL("../be/db/runtime.ts", import.meta.url).pathname);
30
+ const facadePath = JSON.stringify(new URL("../be/db.ts", import.meta.url).pathname);
31
+ expectChildOk(
32
+ await runChild([process.execPath, "-"], {
33
+ stdin: `
34
+ import { spyOn } from "bun:test";
35
+ const runtime = await import(${runtimePath});
36
+ const access = spyOn(runtime, "getDbClient");
37
+ await import(${facadePath});
38
+ if (access.mock.calls.length) throw new Error("Facade initialization accessed DB client");
39
+ `,
40
+ }),
41
+ "facade initialization",
42
+ );
43
+ },
44
+ CHILD_PROCESS_TEST_BUDGET_MS,
45
+ );
@@ -0,0 +1,70 @@
1
+ import { afterEach, describe, expect, test } from "bun:test";
2
+ import * as facade from "../be/db";
3
+ import * as runtime from "../be/db/runtime";
4
+
5
+ const runtimeExports = [
6
+ "__resetSqliteVecExtensionPathCacheForTests",
7
+ "closeDb",
8
+ "getDb",
9
+ "getDbClient",
10
+ "initDb",
11
+ "isSqliteVecAvailable",
12
+ "resolveSqliteVecExtensionPath",
13
+ ] as const;
14
+
15
+ afterEach(() => runtime.closeDb());
16
+
17
+ describe("database runtime facade", () => {
18
+ test("re-exports the same seven runtime bindings", () => {
19
+ expect(Object.keys(runtime).sort()).toEqual([...runtimeExports].sort());
20
+ expect(facade.__resetSqliteVecExtensionPathCacheForTests).toBe(
21
+ runtime.__resetSqliteVecExtensionPathCacheForTests,
22
+ );
23
+ expect(facade.closeDb).toBe(runtime.closeDb);
24
+ expect(facade.getDb).toBe(runtime.getDb);
25
+ expect(facade.getDbClient).toBe(runtime.getDbClient);
26
+ expect(facade.initDb).toBe(runtime.initDb);
27
+ expect(facade.isSqliteVecAvailable).toBe(runtime.isSqliteVecAvailable);
28
+ expect(facade.resolveSqliteVecExtensionPath).toBe(runtime.resolveSqliteVecExtensionPath);
29
+ });
30
+
31
+ test("shares one connection and reuses the async client across close/reopen", async () => {
32
+ const first = runtime.initDb(":memory:");
33
+ expect(facade.getDb()).toBe(first);
34
+ expect(facade.initDb(":memory:")).toBe(first);
35
+ const client = facade.getDbClient();
36
+ expect(runtime.getDbClient()).toBe(client);
37
+ await client.run("CREATE TABLE runtime_probe (value TEXT)");
38
+ await client.run("INSERT INTO runtime_probe VALUES (?)", ["first"]);
39
+ expect(await client.get("SELECT value FROM runtime_probe")).toEqual({ value: "first" });
40
+
41
+ facade.closeDb();
42
+ expect(runtime.isSqliteVecAvailable()).toBe(false);
43
+ runtime.closeDb();
44
+ const second = facade.initDb(":memory:");
45
+ expect(second).not.toBe(first);
46
+ expect(runtime.getDb()).toBe(second);
47
+ expect(runtime.getDbClient()).toBe(client);
48
+ expect(
49
+ await client.get("SELECT name FROM sqlite_master WHERE name = 'runtime_probe'"),
50
+ ).toBeNull();
51
+ await client.run("CREATE TABLE runtime_probe (value TEXT)");
52
+ await client.run("INSERT INTO runtime_probe VALUES (?)", ["second"]);
53
+ expect(await client.get("SELECT value FROM runtime_probe")).toEqual({ value: "second" });
54
+ });
55
+
56
+ test("cold initialization still seeds templates", () => {
57
+ const globals = globalThis as typeof globalThis & { __testMigrationTemplate?: Uint8Array };
58
+ const template = globals.__testMigrationTemplate;
59
+ runtime.closeDb();
60
+ globals.__testMigrationTemplate = undefined;
61
+ try {
62
+ runtime.initDb(":memory:");
63
+ const templates = facade.getPromptTemplates({ scope: "global" });
64
+ expect(templates.length).toBeGreaterThan(0);
65
+ } finally {
66
+ runtime.closeDb();
67
+ globals.__testMigrationTemplate = template;
68
+ }
69
+ });
70
+ });