comisai 1.0.11 → 1.0.12

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 (247) hide show
  1. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +1 -4
  2. package/node_modules/@comis/agent/package.json +1 -1
  3. package/node_modules/@comis/channels/package.json +1 -1
  4. package/node_modules/@comis/cli/package.json +1 -1
  5. package/node_modules/@comis/core/package.json +1 -1
  6. package/node_modules/@comis/daemon/package.json +1 -1
  7. package/node_modules/@comis/gateway/package.json +1 -1
  8. package/node_modules/@comis/infra/package.json +1 -1
  9. package/node_modules/@comis/memory/package.json +1 -1
  10. package/node_modules/@comis/scheduler/package.json +1 -1
  11. package/node_modules/@comis/shared/package.json +1 -1
  12. package/node_modules/@comis/skills/package.json +1 -1
  13. package/package.json +18 -18
  14. package/node_modules/@comis/core/dist/approval/approval-gate.test.d.ts +0 -1
  15. package/node_modules/@comis/core/dist/approval/approval-gate.test.js +0 -1003
  16. package/node_modules/@comis/core/dist/bootstrap.test.d.ts +0 -1
  17. package/node_modules/@comis/core/dist/bootstrap.test.js +0 -150
  18. package/node_modules/@comis/core/dist/config/backup.test.d.ts +0 -1
  19. package/node_modules/@comis/core/dist/config/backup.test.js +0 -160
  20. package/node_modules/@comis/core/dist/config/env-substitution.test.d.ts +0 -1
  21. package/node_modules/@comis/core/dist/config/env-substitution.test.js +0 -259
  22. package/node_modules/@comis/core/dist/config/field-metadata.test.d.ts +0 -1
  23. package/node_modules/@comis/core/dist/config/field-metadata.test.js +0 -72
  24. package/node_modules/@comis/core/dist/config/git-manager.test.d.ts +0 -1
  25. package/node_modules/@comis/core/dist/config/git-manager.test.js +0 -1042
  26. package/node_modules/@comis/core/dist/config/immutable-keys.test.d.ts +0 -1
  27. package/node_modules/@comis/core/dist/config/immutable-keys.test.js +0 -283
  28. package/node_modules/@comis/core/dist/config/include-resolver.test.d.ts +0 -1
  29. package/node_modules/@comis/core/dist/config/include-resolver.test.js +0 -292
  30. package/node_modules/@comis/core/dist/config/layered.test.d.ts +0 -1
  31. package/node_modules/@comis/core/dist/config/layered.test.js +0 -211
  32. package/node_modules/@comis/core/dist/config/loader.test.d.ts +0 -1
  33. package/node_modules/@comis/core/dist/config/loader.test.js +0 -300
  34. package/node_modules/@comis/core/dist/config/migrate.test.d.ts +0 -1
  35. package/node_modules/@comis/core/dist/config/migrate.test.js +0 -244
  36. package/node_modules/@comis/core/dist/config/partial-validator.test.d.ts +0 -1
  37. package/node_modules/@comis/core/dist/config/partial-validator.test.js +0 -98
  38. package/node_modules/@comis/core/dist/config/schema-agent-model.test.d.ts +0 -1
  39. package/node_modules/@comis/core/dist/config/schema-agent-model.test.js +0 -279
  40. package/node_modules/@comis/core/dist/config/schema-agent-session.test.d.ts +0 -1
  41. package/node_modules/@comis/core/dist/config/schema-agent-session.test.js +0 -242
  42. package/node_modules/@comis/core/dist/config/schema-agent.test.d.ts +0 -1
  43. package/node_modules/@comis/core/dist/config/schema-agent.test.js +0 -645
  44. package/node_modules/@comis/core/dist/config/schema-channel.test.d.ts +0 -1
  45. package/node_modules/@comis/core/dist/config/schema-channel.test.js +0 -341
  46. package/node_modules/@comis/core/dist/config/schema-coalescer.test.d.ts +0 -1
  47. package/node_modules/@comis/core/dist/config/schema-coalescer.test.js +0 -51
  48. package/node_modules/@comis/core/dist/config/schema-context-engine.test.d.ts +0 -1
  49. package/node_modules/@comis/core/dist/config/schema-context-engine.test.js +0 -797
  50. package/node_modules/@comis/core/dist/config/schema-context-guard.test.d.ts +0 -1
  51. package/node_modules/@comis/core/dist/config/schema-context-guard.test.js +0 -111
  52. package/node_modules/@comis/core/dist/config/schema-daemon.test.d.ts +0 -1
  53. package/node_modules/@comis/core/dist/config/schema-daemon.test.js +0 -107
  54. package/node_modules/@comis/core/dist/config/schema-delivery-timing.test.d.ts +0 -1
  55. package/node_modules/@comis/core/dist/config/schema-delivery-timing.test.js +0 -51
  56. package/node_modules/@comis/core/dist/config/schema-documentation.test.d.ts +0 -1
  57. package/node_modules/@comis/core/dist/config/schema-documentation.test.js +0 -63
  58. package/node_modules/@comis/core/dist/config/schema-gateway.test.d.ts +0 -1
  59. package/node_modules/@comis/core/dist/config/schema-gateway.test.js +0 -219
  60. package/node_modules/@comis/core/dist/config/schema-gemini-cache.test.d.ts +0 -1
  61. package/node_modules/@comis/core/dist/config/schema-gemini-cache.test.js +0 -41
  62. package/node_modules/@comis/core/dist/config/schema-integrations.test.d.ts +0 -1
  63. package/node_modules/@comis/core/dist/config/schema-integrations.test.js +0 -92
  64. package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.test.d.ts +0 -1
  65. package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.test.js +0 -61
  66. package/node_modules/@comis/core/dist/config/schema-misc.test.d.ts +0 -1
  67. package/node_modules/@comis/core/dist/config/schema-misc.test.js +0 -394
  68. package/node_modules/@comis/core/dist/config/schema-observability.test.d.ts +0 -1
  69. package/node_modules/@comis/core/dist/config/schema-observability.test.js +0 -76
  70. package/node_modules/@comis/core/dist/config/schema-providers.test.d.ts +0 -1
  71. package/node_modules/@comis/core/dist/config/schema-providers.test.js +0 -294
  72. package/node_modules/@comis/core/dist/config/schema-queue.test.d.ts +0 -1
  73. package/node_modules/@comis/core/dist/config/schema-queue.test.js +0 -234
  74. package/node_modules/@comis/core/dist/config/schema-response-prefix.test.d.ts +0 -1
  75. package/node_modules/@comis/core/dist/config/schema-response-prefix.test.js +0 -36
  76. package/node_modules/@comis/core/dist/config/schema-security.test.d.ts +0 -1
  77. package/node_modules/@comis/core/dist/config/schema-security.test.js +0 -54
  78. package/node_modules/@comis/core/dist/config/schema-sender-trust-display.test.d.ts +0 -1
  79. package/node_modules/@comis/core/dist/config/schema-sender-trust-display.test.js +0 -60
  80. package/node_modules/@comis/core/dist/config/schema-serializer.test.d.ts +0 -1
  81. package/node_modules/@comis/core/dist/config/schema-serializer.test.js +0 -73
  82. package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.test.d.ts +0 -1
  83. package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.test.js +0 -39
  84. package/node_modules/@comis/core/dist/context/context.test.d.ts +0 -1
  85. package/node_modules/@comis/core/dist/context/context.test.js +0 -276
  86. package/node_modules/@comis/core/dist/domain/agent-response.test.d.ts +0 -1
  87. package/node_modules/@comis/core/dist/domain/agent-response.test.js +0 -159
  88. package/node_modules/@comis/core/dist/domain/credential-mapping.test.d.ts +0 -1
  89. package/node_modules/@comis/core/dist/domain/credential-mapping.test.js +0 -135
  90. package/node_modules/@comis/core/dist/domain/delivery-origin.test.d.ts +0 -1
  91. package/node_modules/@comis/core/dist/domain/delivery-origin.test.js +0 -68
  92. package/node_modules/@comis/core/dist/domain/execution-graph.test.d.ts +0 -1
  93. package/node_modules/@comis/core/dist/domain/execution-graph.test.js +0 -441
  94. package/node_modules/@comis/core/dist/domain/memory-entry.test.d.ts +0 -1
  95. package/node_modules/@comis/core/dist/domain/memory-entry.test.js +0 -193
  96. package/node_modules/@comis/core/dist/domain/normalized-message.test.d.ts +0 -1
  97. package/node_modules/@comis/core/dist/domain/normalized-message.test.js +0 -255
  98. package/node_modules/@comis/core/dist/domain/session-key.test.d.ts +0 -1
  99. package/node_modules/@comis/core/dist/domain/session-key.test.js +0 -291
  100. package/node_modules/@comis/core/dist/domain/subagent-context-config.test.d.ts +0 -1
  101. package/node_modules/@comis/core/dist/domain/subagent-context-config.test.js +0 -131
  102. package/node_modules/@comis/core/dist/domain/subagent-context-types.test.d.ts +0 -1
  103. package/node_modules/@comis/core/dist/domain/subagent-context-types.test.js +0 -182
  104. package/node_modules/@comis/core/dist/event-bus/bus.test.d.ts +0 -1
  105. package/node_modules/@comis/core/dist/event-bus/bus.test.js +0 -152
  106. package/node_modules/@comis/core/dist/event-bus/events-agent.test.d.ts +0 -1
  107. package/node_modules/@comis/core/dist/event-bus/events-agent.test.js +0 -409
  108. package/node_modules/@comis/core/dist/event-bus/events-channel.test.d.ts +0 -1
  109. package/node_modules/@comis/core/dist/event-bus/events-channel.test.js +0 -240
  110. package/node_modules/@comis/core/dist/event-bus/events-infra.test.d.ts +0 -1
  111. package/node_modules/@comis/core/dist/event-bus/events-infra.test.js +0 -416
  112. package/node_modules/@comis/core/dist/event-bus/events-messaging.test.d.ts +0 -1
  113. package/node_modules/@comis/core/dist/event-bus/events-messaging.test.js +0 -433
  114. package/node_modules/@comis/core/dist/event-bus/events.test.d.ts +0 -1
  115. package/node_modules/@comis/core/dist/event-bus/events.test.js +0 -93
  116. package/node_modules/@comis/core/dist/hooks/hook-runner-global.test.d.ts +0 -1
  117. package/node_modules/@comis/core/dist/hooks/hook-runner-global.test.js +0 -29
  118. package/node_modules/@comis/core/dist/hooks/hook-runner.test.d.ts +0 -1
  119. package/node_modules/@comis/core/dist/hooks/hook-runner.test.js +0 -490
  120. package/node_modules/@comis/core/dist/hooks/hook-strategies.test.d.ts +0 -1
  121. package/node_modules/@comis/core/dist/hooks/hook-strategies.test.js +0 -209
  122. package/node_modules/@comis/core/dist/hooks/integration.test.d.ts +0 -1
  123. package/node_modules/@comis/core/dist/hooks/integration.test.js +0 -235
  124. package/node_modules/@comis/core/dist/hooks/plugin-registry.test.d.ts +0 -1
  125. package/node_modules/@comis/core/dist/hooks/plugin-registry.test.js +0 -470
  126. package/node_modules/@comis/core/dist/load-env.test.d.ts +0 -1
  127. package/node_modules/@comis/core/dist/load-env.test.js +0 -21
  128. package/node_modules/@comis/core/dist/security/action-classifier.test.d.ts +0 -1
  129. package/node_modules/@comis/core/dist/security/action-classifier.test.js +0 -298
  130. package/node_modules/@comis/core/dist/security/audit-aggregator.test.d.ts +0 -1
  131. package/node_modules/@comis/core/dist/security/audit-aggregator.test.js +0 -128
  132. package/node_modules/@comis/core/dist/security/audit.test.d.ts +0 -1
  133. package/node_modules/@comis/core/dist/security/audit.test.js +0 -154
  134. package/node_modules/@comis/core/dist/security/canary-token.test.d.ts +0 -1
  135. package/node_modules/@comis/core/dist/security/canary-token.test.js +0 -45
  136. package/node_modules/@comis/core/dist/security/config-redaction.test.d.ts +0 -1
  137. package/node_modules/@comis/core/dist/security/config-redaction.test.js +0 -107
  138. package/node_modules/@comis/core/dist/security/external-content.test.d.ts +0 -1
  139. package/node_modules/@comis/core/dist/security/external-content.test.js +0 -210
  140. package/node_modules/@comis/core/dist/security/injection-patterns.test.d.ts +0 -1
  141. package/node_modules/@comis/core/dist/security/injection-patterns.test.js +0 -213
  142. package/node_modules/@comis/core/dist/security/injection-rate-limiter.test.d.ts +0 -1
  143. package/node_modules/@comis/core/dist/security/injection-rate-limiter.test.js +0 -194
  144. package/node_modules/@comis/core/dist/security/input-guard.test.d.ts +0 -1
  145. package/node_modules/@comis/core/dist/security/input-guard.test.js +0 -215
  146. package/node_modules/@comis/core/dist/security/input-security-guard.test.d.ts +0 -1
  147. package/node_modules/@comis/core/dist/security/input-security-guard.test.js +0 -215
  148. package/node_modules/@comis/core/dist/security/input-validator.test.d.ts +0 -1
  149. package/node_modules/@comis/core/dist/security/input-validator.test.js +0 -133
  150. package/node_modules/@comis/core/dist/security/log-sanitizer.test.d.ts +0 -1
  151. package/node_modules/@comis/core/dist/security/log-sanitizer.test.js +0 -260
  152. package/node_modules/@comis/core/dist/security/memory-write-validator.test.d.ts +0 -1
  153. package/node_modules/@comis/core/dist/security/memory-write-validator.test.js +0 -62
  154. package/node_modules/@comis/core/dist/security/output-guard.test.d.ts +0 -1
  155. package/node_modules/@comis/core/dist/security/output-guard.test.js +0 -397
  156. package/node_modules/@comis/core/dist/security/safe-path.test.d.ts +0 -1
  157. package/node_modules/@comis/core/dist/security/safe-path.test.js +0 -95
  158. package/node_modules/@comis/core/dist/security/scoped-secret-manager.test.d.ts +0 -1
  159. package/node_modules/@comis/core/dist/security/scoped-secret-manager.test.js +0 -231
  160. package/node_modules/@comis/core/dist/security/secret-access.test.d.ts +0 -1
  161. package/node_modules/@comis/core/dist/security/secret-access.test.js +0 -41
  162. package/node_modules/@comis/core/dist/security/secret-crypto.test.d.ts +0 -1
  163. package/node_modules/@comis/core/dist/security/secret-crypto.test.js +0 -113
  164. package/node_modules/@comis/core/dist/security/secret-manager.test.d.ts +0 -1
  165. package/node_modules/@comis/core/dist/security/secret-manager.test.js +0 -394
  166. package/node_modules/@comis/core/dist/security/secret-ref-resolver.test.d.ts +0 -1
  167. package/node_modules/@comis/core/dist/security/secret-ref-resolver.test.js +0 -268
  168. package/node_modules/@comis/core/dist/security/secrets-audit.test.d.ts +0 -10
  169. package/node_modules/@comis/core/dist/security/secrets-audit.test.js +0 -295
  170. package/node_modules/@comis/core/dist/security/ssrf-guard.test.d.ts +0 -1
  171. package/node_modules/@comis/core/dist/security/ssrf-guard.test.js +0 -127
  172. package/node_modules/@comis/core/dist/security/token-generator.test.d.ts +0 -1
  173. package/node_modules/@comis/core/dist/security/token-generator.test.js +0 -35
  174. package/node_modules/@comis/core/dist/tool-metadata.test.d.ts +0 -1
  175. package/node_modules/@comis/core/dist/tool-metadata.test.js +0 -112
  176. package/node_modules/@comis/memory/dist/compaction.test.d.ts +0 -1
  177. package/node_modules/@comis/memory/dist/compaction.test.js +0 -298
  178. package/node_modules/@comis/memory/dist/context-schema.test.d.ts +0 -1
  179. package/node_modules/@comis/memory/dist/context-schema.test.js +0 -246
  180. package/node_modules/@comis/memory/dist/context-store.test.d.ts +0 -1
  181. package/node_modules/@comis/memory/dist/context-store.test.js +0 -708
  182. package/node_modules/@comis/memory/dist/credential-mapping-schema.test.d.ts +0 -7
  183. package/node_modules/@comis/memory/dist/credential-mapping-schema.test.js +0 -73
  184. package/node_modules/@comis/memory/dist/credential-mapping-store.test.d.ts +0 -8
  185. package/node_modules/@comis/memory/dist/credential-mapping-store.test.js +0 -340
  186. package/node_modules/@comis/memory/dist/delivery-mirror-adapter.test.d.ts +0 -1
  187. package/node_modules/@comis/memory/dist/delivery-mirror-adapter.test.js +0 -165
  188. package/node_modules/@comis/memory/dist/delivery-queue-adapter.test.d.ts +0 -1
  189. package/node_modules/@comis/memory/dist/delivery-queue-adapter.test.js +0 -263
  190. package/node_modules/@comis/memory/dist/embedding-batch-indexer.test.d.ts +0 -1
  191. package/node_modules/@comis/memory/dist/embedding-batch-indexer.test.js +0 -202
  192. package/node_modules/@comis/memory/dist/embedding-cache-lru.test.d.ts +0 -1
  193. package/node_modules/@comis/memory/dist/embedding-cache-lru.test.js +0 -241
  194. package/node_modules/@comis/memory/dist/embedding-cache-sqlite.test.d.ts +0 -8
  195. package/node_modules/@comis/memory/dist/embedding-cache-sqlite.test.js +0 -678
  196. package/node_modules/@comis/memory/dist/embedding-cache.test.d.ts +0 -1
  197. package/node_modules/@comis/memory/dist/embedding-cache.test.js +0 -213
  198. package/node_modules/@comis/memory/dist/embedding-fingerprint.test.d.ts +0 -1
  199. package/node_modules/@comis/memory/dist/embedding-fingerprint.test.js +0 -87
  200. package/node_modules/@comis/memory/dist/embedding-hash.test.d.ts +0 -1
  201. package/node_modules/@comis/memory/dist/embedding-hash.test.js +0 -31
  202. package/node_modules/@comis/memory/dist/embedding-integration.test.d.ts +0 -8
  203. package/node_modules/@comis/memory/dist/embedding-integration.test.js +0 -232
  204. package/node_modules/@comis/memory/dist/embedding-provider-factory.test.d.ts +0 -1
  205. package/node_modules/@comis/memory/dist/embedding-provider-factory.test.js +0 -176
  206. package/node_modules/@comis/memory/dist/embedding-provider-local.test.d.ts +0 -8
  207. package/node_modules/@comis/memory/dist/embedding-provider-local.test.js +0 -76
  208. package/node_modules/@comis/memory/dist/embedding-provider-openai.test.d.ts +0 -8
  209. package/node_modules/@comis/memory/dist/embedding-provider-openai.test.js +0 -100
  210. package/node_modules/@comis/memory/dist/embedding-queue.test.d.ts +0 -1
  211. package/node_modules/@comis/memory/dist/embedding-queue.test.js +0 -236
  212. package/node_modules/@comis/memory/dist/hybrid-search.test.d.ts +0 -1
  213. package/node_modules/@comis/memory/dist/hybrid-search.test.js +0 -476
  214. package/node_modules/@comis/memory/dist/identity-link-store.test.d.ts +0 -1
  215. package/node_modules/@comis/memory/dist/identity-link-store.test.js +0 -88
  216. package/node_modules/@comis/memory/dist/memory-api.test.d.ts +0 -1
  217. package/node_modules/@comis/memory/dist/memory-api.test.js +0 -495
  218. package/node_modules/@comis/memory/dist/memory-concurrency.test.d.ts +0 -20
  219. package/node_modules/@comis/memory/dist/memory-concurrency.test.js +0 -222
  220. package/node_modules/@comis/memory/dist/named-graph-store.test.d.ts +0 -1
  221. package/node_modules/@comis/memory/dist/named-graph-store.test.js +0 -227
  222. package/node_modules/@comis/memory/dist/observability-store.test.d.ts +0 -1
  223. package/node_modules/@comis/memory/dist/observability-store.test.js +0 -704
  224. package/node_modules/@comis/memory/dist/row-mapper.test.d.ts +0 -1
  225. package/node_modules/@comis/memory/dist/row-mapper.test.js +0 -409
  226. package/node_modules/@comis/memory/dist/schema.test.d.ts +0 -1
  227. package/node_modules/@comis/memory/dist/schema.test.js +0 -240
  228. package/node_modules/@comis/memory/dist/secret-store-schema.test.d.ts +0 -7
  229. package/node_modules/@comis/memory/dist/secret-store-schema.test.js +0 -90
  230. package/node_modules/@comis/memory/dist/session-store.test.d.ts +0 -1
  231. package/node_modules/@comis/memory/dist/session-store.test.js +0 -262
  232. package/node_modules/@comis/memory/dist/setup-secrets.test.d.ts +0 -1
  233. package/node_modules/@comis/memory/dist/setup-secrets.test.js +0 -140
  234. package/node_modules/@comis/memory/dist/sqlite-memory-adapter.test.d.ts +0 -1
  235. package/node_modules/@comis/memory/dist/sqlite-memory-adapter.test.js +0 -888
  236. package/node_modules/@comis/memory/dist/sqlite-secret-store.test.d.ts +0 -8
  237. package/node_modules/@comis/memory/dist/sqlite-secret-store.test.js +0 -245
  238. package/node_modules/@comis/shared/dist/abort.test.d.ts +0 -1
  239. package/node_modules/@comis/shared/dist/abort.test.js +0 -71
  240. package/node_modules/@comis/shared/dist/result.test.d.ts +0 -1
  241. package/node_modules/@comis/shared/dist/result.test.js +0 -178
  242. package/node_modules/@comis/shared/dist/suppress-error.test.d.ts +0 -1
  243. package/node_modules/@comis/shared/dist/suppress-error.test.js +0 -50
  244. package/node_modules/@comis/shared/dist/timeout.test.d.ts +0 -1
  245. package/node_modules/@comis/shared/dist/timeout.test.js +0 -75
  246. package/node_modules/@comis/shared/dist/ttl-cache.test.d.ts +0 -1
  247. package/node_modules/@comis/shared/dist/ttl-cache.test.js +0 -81
@@ -1,176 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { ok, err } from "@comis/shared";
3
- // Mock the local and openai provider modules
4
- vi.mock("./embedding-provider-local.js", () => ({
5
- createLocalEmbeddingProvider: vi.fn(),
6
- }));
7
- vi.mock("./embedding-provider-openai.js", () => ({
8
- createOpenAIEmbeddingProvider: vi.fn(),
9
- }));
10
- import { createEmbeddingProvider } from "./embedding-provider-factory.js";
11
- import { createLocalEmbeddingProvider } from "./embedding-provider-local.js";
12
- import { createOpenAIEmbeddingProvider } from "./embedding-provider-openai.js";
13
- const mockLocal = vi.mocked(createLocalEmbeddingProvider);
14
- const mockOpenAI = vi.mocked(createOpenAIEmbeddingProvider);
15
- function stubPort(overrides) {
16
- return {
17
- provider: "test",
18
- dimensions: 768,
19
- modelId: "test-model",
20
- embed: vi.fn().mockResolvedValue(ok([0.1, 0.2])),
21
- embedBatch: vi.fn().mockResolvedValue(ok([[0.1], [0.2]])),
22
- ...overrides,
23
- };
24
- }
25
- describe("createEmbeddingProvider", () => {
26
- beforeEach(() => {
27
- vi.clearAllMocks();
28
- });
29
- describe("auto mode", () => {
30
- it("selects local when local succeeds", async () => {
31
- const localPort = stubPort({ modelId: "local-model" });
32
- mockLocal.mockResolvedValue(ok(localPort));
33
- const result = await createEmbeddingProvider({
34
- provider: "auto",
35
- local: { modelUri: "hf:test", modelsDir: "models" },
36
- remote: { apiKey: "sk-test", model: "text-embedding-3-small", dimensions: 1536 },
37
- });
38
- expect(result.ok).toBe(true);
39
- if (result.ok) {
40
- expect(result.value.modelId).toBe("local-model");
41
- }
42
- expect(mockLocal).toHaveBeenCalledOnce();
43
- // Remote should NOT have been called since local succeeded
44
- expect(mockOpenAI).not.toHaveBeenCalled();
45
- });
46
- it("falls back to remote when local fails", async () => {
47
- mockLocal.mockResolvedValue(err(new Error("node-llama-cpp not available")));
48
- const remotePort = stubPort({ modelId: "openai-model", dimensions: 1536 });
49
- mockOpenAI.mockReturnValue(ok(remotePort));
50
- const result = await createEmbeddingProvider({
51
- provider: "auto",
52
- local: { modelUri: "hf:test", modelsDir: "models" },
53
- remote: { apiKey: "sk-test", model: "text-embedding-3-small", dimensions: 1536 },
54
- });
55
- expect(result.ok).toBe(true);
56
- if (result.ok) {
57
- expect(result.value.modelId).toBe("openai-model");
58
- }
59
- expect(mockLocal).toHaveBeenCalledOnce();
60
- expect(mockOpenAI).toHaveBeenCalledOnce();
61
- });
62
- it("returns error when both fail", async () => {
63
- mockLocal.mockResolvedValue(err(new Error("native bindings unavailable")));
64
- mockOpenAI.mockReturnValue(err(new Error("OpenAI embedding provider requires an apiKey")));
65
- const result = await createEmbeddingProvider({
66
- provider: "auto",
67
- local: { modelUri: "hf:test", modelsDir: "models" },
68
- remote: { apiKey: "", model: "text-embedding-3-small", dimensions: 1536 },
69
- });
70
- expect(result.ok).toBe(false);
71
- if (!result.ok) {
72
- expect(result.error.message).toContain("No embedding provider available");
73
- expect(result.error.message).toContain("native bindings unavailable");
74
- }
75
- });
76
- it("skips local when no local config provided", async () => {
77
- const remotePort = stubPort({ modelId: "openai-fallback" });
78
- mockOpenAI.mockReturnValue(ok(remotePort));
79
- const result = await createEmbeddingProvider({
80
- provider: "auto",
81
- remote: { apiKey: "sk-test", model: "text-embedding-3-small", dimensions: 1536 },
82
- });
83
- expect(result.ok).toBe(true);
84
- if (result.ok) {
85
- expect(result.value.modelId).toBe("openai-fallback");
86
- }
87
- expect(mockLocal).not.toHaveBeenCalled();
88
- });
89
- });
90
- describe("local mode", () => {
91
- it("returns error when local fails (no fallback)", async () => {
92
- mockLocal.mockResolvedValue(err(new Error("model file not found")));
93
- const result = await createEmbeddingProvider({
94
- provider: "local",
95
- local: { modelUri: "hf:test", modelsDir: "models" },
96
- remote: { apiKey: "sk-test", model: "text-embedding-3-small", dimensions: 1536 },
97
- });
98
- expect(result.ok).toBe(false);
99
- if (!result.ok) {
100
- expect(result.error.message).toBe("model file not found");
101
- }
102
- // Remote should NOT be attempted for explicit local mode
103
- expect(mockOpenAI).not.toHaveBeenCalled();
104
- });
105
- it("returns error when no local config provided", async () => {
106
- const result = await createEmbeddingProvider({
107
- provider: "local",
108
- });
109
- expect(result.ok).toBe(false);
110
- if (!result.ok) {
111
- expect(result.error.message).toContain("no local config provided");
112
- }
113
- });
114
- it("succeeds when local provider works", async () => {
115
- const localPort = stubPort({ modelId: "local-gguf" });
116
- mockLocal.mockResolvedValue(ok(localPort));
117
- const result = await createEmbeddingProvider({
118
- provider: "local",
119
- local: { modelUri: "/path/to/model.gguf", modelsDir: "models" },
120
- });
121
- expect(result.ok).toBe(true);
122
- if (result.ok) {
123
- expect(result.value.modelId).toBe("local-gguf");
124
- }
125
- });
126
- });
127
- describe("openai mode", () => {
128
- it("returns error when no apiKey provided", async () => {
129
- const result = await createEmbeddingProvider({
130
- provider: "openai",
131
- });
132
- expect(result.ok).toBe(false);
133
- if (!result.ok) {
134
- expect(result.error.message).toContain("apiKey");
135
- }
136
- });
137
- it("returns error when apiKey is empty string", async () => {
138
- const result = await createEmbeddingProvider({
139
- provider: "openai",
140
- remote: { apiKey: "", model: "text-embedding-3-small", dimensions: 1536 },
141
- });
142
- expect(result.ok).toBe(false);
143
- if (!result.ok) {
144
- expect(result.error.message).toContain("apiKey");
145
- }
146
- });
147
- it("succeeds with valid config", async () => {
148
- const remotePort = stubPort({ modelId: "text-embedding-3-small", dimensions: 1536 });
149
- mockOpenAI.mockReturnValue(ok(remotePort));
150
- const result = await createEmbeddingProvider({
151
- provider: "openai",
152
- remote: { apiKey: "sk-valid-key", model: "text-embedding-3-small", dimensions: 1536 },
153
- });
154
- expect(result.ok).toBe(true);
155
- if (result.ok) {
156
- expect(result.value.modelId).toBe("text-embedding-3-small");
157
- expect(result.value.dimensions).toBe(1536);
158
- }
159
- expect(mockOpenAI).toHaveBeenCalledWith({
160
- apiKey: "sk-valid-key",
161
- model: "text-embedding-3-small",
162
- dimensions: 1536,
163
- });
164
- });
165
- it("does not attempt local provider", async () => {
166
- const remotePort = stubPort();
167
- mockOpenAI.mockReturnValue(ok(remotePort));
168
- await createEmbeddingProvider({
169
- provider: "openai",
170
- local: { modelUri: "hf:test", modelsDir: "models" },
171
- remote: { apiKey: "sk-test", model: "text-embedding-3-small", dimensions: 1536 },
172
- });
173
- expect(mockLocal).not.toHaveBeenCalled();
174
- });
175
- });
176
- });
@@ -1,8 +0,0 @@
1
- /**
2
- * Contract tests for the local (node-llama-cpp) embedding provider.
3
- *
4
- * Tests gated behind LLAMA_MODEL_PATH are silently skipped in normal
5
- * CI runs and only execute when the env var points to a valid GGUF model.
6
- * The invalid-model-path error handling test runs unconditionally.
7
- */
8
- export {};
@@ -1,76 +0,0 @@
1
- /**
2
- * Contract tests for the local (node-llama-cpp) embedding provider.
3
- *
4
- * Tests gated behind LLAMA_MODEL_PATH are silently skipped in normal
5
- * CI runs and only execute when the env var points to a valid GGUF model.
6
- * The invalid-model-path error handling test runs unconditionally.
7
- */
8
- import { describe, it, expect } from "vitest";
9
- import { createLocalEmbeddingProvider } from "./embedding-provider-local.js";
10
- const LLAMA_MODEL_PATH = process.env.LLAMA_MODEL_PATH;
11
- describe.skipIf(!LLAMA_MODEL_PATH)("Local embedding provider (contract test)", () => {
12
- it("creates provider successfully with valid model path", async () => {
13
- const result = await createLocalEmbeddingProvider({
14
- modelUri: LLAMA_MODEL_PATH,
15
- modelsDir: "/tmp/comis-test-models",
16
- });
17
- expect(result.ok).toBe(true);
18
- if (result.ok) {
19
- expect(result.value.dimensions).toBeGreaterThan(0);
20
- expect(result.value.modelId).toBe(LLAMA_MODEL_PATH);
21
- }
22
- });
23
- it("generates embedding with correct dimensions", async () => {
24
- const createResult = await createLocalEmbeddingProvider({
25
- modelUri: LLAMA_MODEL_PATH,
26
- modelsDir: "/tmp/comis-test-models",
27
- });
28
- expect(createResult.ok).toBe(true);
29
- if (!createResult.ok)
30
- return;
31
- const provider = createResult.value;
32
- const result = await provider.embed("Test text for local embedding");
33
- expect(result.ok).toBe(true);
34
- if (result.ok) {
35
- expect(result.value).toBeInstanceOf(Array);
36
- expect(result.value.length).toBe(provider.dimensions);
37
- // All values should be finite numbers
38
- for (const val of result.value) {
39
- expect(Number.isFinite(val)).toBe(true);
40
- }
41
- }
42
- });
43
- it("generates batch embeddings", async () => {
44
- const createResult = await createLocalEmbeddingProvider({
45
- modelUri: LLAMA_MODEL_PATH,
46
- modelsDir: "/tmp/comis-test-models",
47
- });
48
- expect(createResult.ok).toBe(true);
49
- if (!createResult.ok)
50
- return;
51
- const provider = createResult.value;
52
- const result = await provider.embedBatch(["Hello", "World"]);
53
- expect(result.ok).toBe(true);
54
- if (result.ok) {
55
- expect(result.value).toHaveLength(2);
56
- for (const embedding of result.value) {
57
- expect(embedding.length).toBe(provider.dimensions);
58
- }
59
- }
60
- });
61
- });
62
- // Ungated test: verify error handling with invalid model path
63
- describe("Local embedding provider (error handling)", () => {
64
- it("handles invalid model path gracefully", async () => {
65
- const result = await createLocalEmbeddingProvider({
66
- modelUri: "/nonexistent/model.gguf",
67
- modelsDir: "/tmp/comis-test-models",
68
- });
69
- // Should return err() with a meaningful error, not crash
70
- expect(result.ok).toBe(false);
71
- if (!result.ok) {
72
- expect(result.error).toBeInstanceOf(Error);
73
- expect(result.error.message.length).toBeGreaterThan(0);
74
- }
75
- });
76
- });
@@ -1,8 +0,0 @@
1
- /**
2
- * Contract tests for the OpenAI embedding provider.
3
- *
4
- * These tests call the real OpenAI API and are gated behind the
5
- * OPENAI_API_KEY environment variable. They are silently skipped
6
- * in normal CI runs and only execute when the env var is set.
7
- */
8
- export {};
@@ -1,100 +0,0 @@
1
- /**
2
- * Contract tests for the OpenAI embedding provider.
3
- *
4
- * These tests call the real OpenAI API and are gated behind the
5
- * OPENAI_API_KEY environment variable. They are silently skipped
6
- * in normal CI runs and only execute when the env var is set.
7
- */
8
- import { describe, it, expect } from "vitest";
9
- import { createOpenAIEmbeddingProvider } from "./embedding-provider-openai.js";
10
- const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
11
- describe.skipIf(!OPENAI_API_KEY)("OpenAI embedding provider (contract test)", () => {
12
- it("creates provider successfully", () => {
13
- const result = createOpenAIEmbeddingProvider({
14
- apiKey: OPENAI_API_KEY,
15
- model: "text-embedding-3-small",
16
- dimensions: 1536,
17
- });
18
- expect(result.ok).toBe(true);
19
- if (result.ok) {
20
- expect(result.value.dimensions).toBe(1536);
21
- expect(result.value.modelId).toBe("text-embedding-3-small");
22
- }
23
- });
24
- it("generates embedding for single text", async () => {
25
- const createResult = createOpenAIEmbeddingProvider({
26
- apiKey: OPENAI_API_KEY,
27
- model: "text-embedding-3-small",
28
- dimensions: 1536,
29
- });
30
- expect(createResult.ok).toBe(true);
31
- if (!createResult.ok)
32
- return;
33
- const provider = createResult.value;
34
- const result = await provider.embed("Hello world");
35
- expect(result.ok).toBe(true);
36
- if (result.ok) {
37
- expect(result.value).toBeInstanceOf(Array);
38
- expect(result.value.length).toBe(1536);
39
- // All values should be finite numbers
40
- for (const val of result.value) {
41
- expect(Number.isFinite(val)).toBe(true);
42
- }
43
- }
44
- });
45
- it("generates embeddings for batch", async () => {
46
- const createResult = createOpenAIEmbeddingProvider({
47
- apiKey: OPENAI_API_KEY,
48
- model: "text-embedding-3-small",
49
- dimensions: 1536,
50
- });
51
- expect(createResult.ok).toBe(true);
52
- if (!createResult.ok)
53
- return;
54
- const provider = createResult.value;
55
- const result = await provider.embedBatch(["Hello", "World"]);
56
- expect(result.ok).toBe(true);
57
- if (result.ok) {
58
- expect(result.value).toHaveLength(2);
59
- for (const embedding of result.value) {
60
- expect(embedding.length).toBe(1536);
61
- for (const val of embedding) {
62
- expect(Number.isFinite(val)).toBe(true);
63
- }
64
- }
65
- }
66
- });
67
- it("returns error for empty text", async () => {
68
- const createResult = createOpenAIEmbeddingProvider({
69
- apiKey: OPENAI_API_KEY,
70
- model: "text-embedding-3-small",
71
- dimensions: 1536,
72
- });
73
- expect(createResult.ok).toBe(true);
74
- if (!createResult.ok)
75
- return;
76
- const provider = createResult.value;
77
- const result = await provider.embed("");
78
- // OpenAI may reject empty strings with an error, or return a zero vector.
79
- // Either behavior is acceptable -- we verify it does not crash.
80
- if (!result.ok) {
81
- expect(result.error).toBeInstanceOf(Error);
82
- }
83
- else {
84
- expect(result.value.length).toBe(1536);
85
- }
86
- });
87
- });
88
- // Ungated test: verify provider creation fails with bad API key format
89
- describe("OpenAI embedding provider (error handling)", () => {
90
- it("creates provider with any apiKey format (validation is lazy)", () => {
91
- // The OpenAI SDK accepts any string as apiKey at construction time.
92
- // Actual validation happens at call time. Verify creation succeeds.
93
- const result = createOpenAIEmbeddingProvider({
94
- apiKey: "sk-invalid-key-for-testing",
95
- model: "text-embedding-3-small",
96
- dimensions: 1536,
97
- });
98
- expect(result.ok).toBe(true);
99
- });
100
- });
@@ -1,236 +0,0 @@
1
- import { ok, err } from "@comis/shared";
2
- import Database from "better-sqlite3";
3
- import { describe, it, expect, beforeEach, vi } from "vitest";
4
- import { createEmbeddingQueue } from "./embedding-queue.js";
5
- import { initSchema, isVecAvailable } from "./schema.js";
6
- const DIMS = 4;
7
- /**
8
- * Create a mock EmbeddingPort that returns deterministic embeddings.
9
- * Tracks call order via the `calls` array for FIFO verification.
10
- */
11
- function createMockEmbeddingPort(opts) {
12
- const calls = [];
13
- const delay = opts?.delay ?? 0;
14
- const fail = opts?.fail ?? false;
15
- return {
16
- provider: "test",
17
- dimensions: DIMS,
18
- modelId: "test-embed-model",
19
- calls,
20
- async embed(text) {
21
- calls.push(text);
22
- if (delay > 0) {
23
- await new Promise((r) => setTimeout(r, delay));
24
- }
25
- if (fail) {
26
- return err(new Error("mock embedding failure"));
27
- }
28
- // Deterministic vector based on text chars
29
- const vec = new Array(DIMS).fill(0);
30
- for (let i = 0; i < text.length && i < DIMS; i++) {
31
- vec[i] = text.charCodeAt(i) / 256;
32
- }
33
- return ok(vec);
34
- },
35
- async embedBatch(texts) {
36
- const results = [];
37
- for (const t of texts) {
38
- const r = await this.embed(t);
39
- if (r.ok)
40
- results.push(r.value);
41
- }
42
- return ok(results);
43
- },
44
- };
45
- }
46
- /** Insert a minimal memory row into the database. */
47
- function insertMemory(db, id, content) {
48
- db.prepare(`INSERT INTO memories (id, tenant_id, user_id, content, trust_level, memory_type, source_who, tags, created_at)
49
- VALUES (?, 'default', 'u1', ?, 'learned', 'semantic', 'agent', '[]', ?)`).run(id, content, Date.now());
50
- }
51
- describe("createEmbeddingQueue", () => {
52
- let db;
53
- beforeEach(() => {
54
- db = new Database(":memory:");
55
- initSchema(db, DIMS);
56
- });
57
- it("enqueue does not block (returns immediately before embedding completes)", async () => {
58
- const port = createMockEmbeddingPort({ delay: 50 });
59
- const queue = createEmbeddingQueue(db, port);
60
- insertMemory(db, "m1", "hello world");
61
- queue.enqueue("m1", "hello world");
62
- // The call should have returned immediately -- check that the embedding
63
- // is NOT yet stored (still processing in background)
64
- const row = db.prepare("SELECT has_embedding FROM memories WHERE id = 'm1'").get();
65
- expect(row.has_embedding).toBe(0);
66
- // Now wait for completion
67
- await queue.onIdle();
68
- const after = db.prepare("SELECT has_embedding FROM memories WHERE id = 'm1'").get();
69
- expect(after.has_embedding).toBe(1);
70
- });
71
- it("after onIdle(), entry has embedding in vec_memories", async () => {
72
- if (!isVecAvailable())
73
- return;
74
- const port = createMockEmbeddingPort();
75
- const queue = createEmbeddingQueue(db, port);
76
- insertMemory(db, "m1", "test content");
77
- queue.enqueue("m1", "test content");
78
- await queue.onIdle();
79
- const vecRow = db.prepare("SELECT memory_id FROM vec_memories WHERE memory_id = 'm1'").get();
80
- expect(vecRow).toBeDefined();
81
- expect(vecRow.memory_id).toBe("m1");
82
- });
83
- it("after onIdle(), memories.has_embedding = 1", async () => {
84
- const port = createMockEmbeddingPort();
85
- const queue = createEmbeddingQueue(db, port);
86
- insertMemory(db, "m1", "test content");
87
- queue.enqueue("m1", "test content");
88
- await queue.onIdle();
89
- const row = db.prepare("SELECT has_embedding FROM memories WHERE id = 'm1'").get();
90
- expect(row.has_embedding).toBe(1);
91
- });
92
- it("multiple enqueues process FIFO (call order matches enqueue order)", async () => {
93
- const port = createMockEmbeddingPort();
94
- const queue = createEmbeddingQueue(db, port);
95
- insertMemory(db, "m1", "first");
96
- insertMemory(db, "m2", "second");
97
- insertMemory(db, "m3", "third");
98
- queue.enqueue("m1", "first");
99
- queue.enqueue("m2", "second");
100
- queue.enqueue("m3", "third");
101
- await queue.onIdle();
102
- expect(port.calls).toEqual(["first", "second", "third"]);
103
- });
104
- it("concurrency=1: second embed does not start until first finishes", async () => {
105
- const timeline = [];
106
- const port = {
107
- provider: "test",
108
- dimensions: DIMS,
109
- modelId: "test-embed-model",
110
- calls: [],
111
- async embed(text) {
112
- this.calls.push(text);
113
- timeline.push({ text, event: "start" });
114
- await new Promise((r) => setTimeout(r, 30));
115
- timeline.push({ text, event: "end" });
116
- return ok(new Array(DIMS).fill(0.5));
117
- },
118
- async embedBatch(texts) {
119
- return ok(texts.map(() => new Array(DIMS).fill(0.5)));
120
- },
121
- };
122
- const queue = createEmbeddingQueue(db, port);
123
- insertMemory(db, "m1", "alpha");
124
- insertMemory(db, "m2", "beta");
125
- queue.enqueue("m1", "alpha");
126
- queue.enqueue("m2", "beta");
127
- await queue.onIdle();
128
- // With concurrency=1, "alpha" must end before "beta" starts
129
- const alphaEnd = timeline.findIndex((e) => e.text === "alpha" && e.event === "end");
130
- const betaStart = timeline.findIndex((e) => e.text === "beta" && e.event === "start");
131
- expect(alphaEnd).toBeLessThan(betaStart);
132
- });
133
- it("failed embedding does not crash queue (entry stays without embedding)", async () => {
134
- const port = createMockEmbeddingPort({ fail: true });
135
- const queue = createEmbeddingQueue(db, port);
136
- insertMemory(db, "m1", "will fail");
137
- queue.enqueue("m1", "will fail");
138
- // Should not throw
139
- await queue.onIdle();
140
- // Entry should still exist but without embedding
141
- const row = db.prepare("SELECT has_embedding FROM memories WHERE id = 'm1'").get();
142
- expect(row.has_embedding).toBe(0);
143
- // Memory itself is intact
144
- const mem = db.prepare("SELECT content FROM memories WHERE id = 'm1'").get();
145
- expect(mem.content).toBe("will fail");
146
- });
147
- it("failed embedding logs warning via structured logger", async () => {
148
- const mockLogger = { warn: vi.fn() };
149
- const port = createMockEmbeddingPort({ fail: true });
150
- const queue = createEmbeddingQueue(db, port, mockLogger);
151
- insertMemory(db, "m1", "will fail");
152
- queue.enqueue("m1", "will fail");
153
- await queue.onIdle();
154
- expect(mockLogger.warn).toHaveBeenCalledWith(expect.objectContaining({
155
- entryId: "m1",
156
- err: expect.stringContaining("mock embedding failure"),
157
- hint: expect.stringContaining("FTS5"),
158
- errorKind: "dependency",
159
- }), "Embedding generation failed");
160
- });
161
- it("pending() returns correct count before and after processing", async () => {
162
- const port = createMockEmbeddingPort({ delay: 30 });
163
- const queue = createEmbeddingQueue(db, port);
164
- // Before any enqueue
165
- expect(queue.pending()).toBe(0);
166
- insertMemory(db, "m1", "a");
167
- insertMemory(db, "m2", "b");
168
- insertMemory(db, "m3", "c");
169
- queue.enqueue("m1", "a");
170
- queue.enqueue("m2", "b");
171
- queue.enqueue("m3", "c");
172
- // At least some should be pending (1 running + others queued)
173
- expect(queue.pending()).toBeGreaterThan(0);
174
- await queue.onIdle();
175
- expect(queue.pending()).toBe(0);
176
- });
177
- it("pause() stops processing, resume() continues", async () => {
178
- const port = createMockEmbeddingPort({ delay: 10 });
179
- const queue = createEmbeddingQueue(db, port);
180
- insertMemory(db, "m1", "a");
181
- insertMemory(db, "m2", "b");
182
- queue.pause();
183
- queue.enqueue("m1", "a");
184
- queue.enqueue("m2", "b");
185
- // Give a tick for anything that might process
186
- await new Promise((r) => setTimeout(r, 50));
187
- // Nothing should have been processed while paused
188
- expect(port.calls).toHaveLength(0);
189
- queue.resume();
190
- await queue.onIdle();
191
- expect(port.calls).toHaveLength(2);
192
- });
193
- it("clear() removes pending items", async () => {
194
- const port = createMockEmbeddingPort({ delay: 50 });
195
- const queue = createEmbeddingQueue(db, port);
196
- insertMemory(db, "m1", "a");
197
- insertMemory(db, "m2", "b");
198
- insertMemory(db, "m3", "c");
199
- queue.enqueue("m1", "a");
200
- queue.enqueue("m2", "b");
201
- queue.enqueue("m3", "c");
202
- // Clear pending (in-progress item may still complete)
203
- queue.clear();
204
- await queue.onIdle();
205
- // Only the first item (already in-progress when clear was called) should have been processed
206
- // or possibly none if clear was very fast. At most 1 should complete.
207
- expect(port.calls.length).toBeLessThanOrEqual(1);
208
- });
209
- it("onIdle() resolves immediately when queue is empty", async () => {
210
- const port = createMockEmbeddingPort();
211
- const queue = createEmbeddingQueue(db, port);
212
- const start = Date.now();
213
- await queue.onIdle();
214
- const elapsed = Date.now() - start;
215
- // Should resolve nearly instantly (under 50ms)
216
- expect(elapsed).toBeLessThan(50);
217
- });
218
- it("embedding is stored as Float32Array in vec_memories", async () => {
219
- if (!isVecAvailable())
220
- return;
221
- const port = createMockEmbeddingPort();
222
- const queue = createEmbeddingQueue(db, port);
223
- insertMemory(db, "m1", "AB");
224
- queue.enqueue("m1", "AB");
225
- await queue.onIdle();
226
- // Query the raw embedding from vec_memories
227
- const vecRow = db.prepare("SELECT embedding FROM vec_memories WHERE memory_id = 'm1'").get();
228
- expect(vecRow).toBeDefined();
229
- // Convert Buffer back to Float32Array and verify values
230
- const float32 = new Float32Array(vecRow.embedding.buffer, vecRow.embedding.byteOffset, vecRow.embedding.byteLength / Float32Array.BYTES_PER_ELEMENT);
231
- expect(float32.length).toBe(DIMS);
232
- // "A" = 65, "B" = 66; charCode / 256
233
- expect(float32[0]).toBeCloseTo(65 / 256, 5);
234
- expect(float32[1]).toBeCloseTo(66 / 256, 5);
235
- });
236
- });