thinkwork-cli 0.12.16 → 0.12.17

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 (149) hide show
  1. package/dist/cli.js +517 -10403
  2. package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
  3. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
  4. package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
  5. package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
  6. package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
  7. package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
  8. package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
  9. package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
  10. package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
  11. package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
  12. package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
  13. package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
  14. package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
  15. package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
  16. package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
  17. package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
  18. package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
  19. package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
  20. package/dist/drizzle/0203_threads_mode_override.sql +61 -0
  21. package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
  22. package/dist/drizzle/0205_routines_git_python.sql +185 -0
  23. package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
  24. package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
  25. package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
  26. package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
  27. package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
  28. package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
  29. package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
  30. package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
  31. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
  32. package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
  33. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
  34. package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
  35. package/dist/drizzle/0218_document_plates.sql +30 -0
  36. package/dist/drizzle/0219_document_section_waivers.sql +29 -0
  37. package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
  38. package/dist/drizzle/0221_artifact_shares.sql +29 -0
  39. package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
  40. package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
  41. package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
  42. package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
  43. package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
  44. package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
  45. package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
  46. package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
  47. package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
  48. package/dist/drizzle/0230_analyst_rls.sql +1613 -0
  49. package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
  50. package/dist/plugins/catalog/package.json +0 -1
  51. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
  52. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
  53. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
  54. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
  55. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
  56. package/dist/plugins/catalog/src/contracts.ts +112 -0
  57. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
  58. package/dist/plugins/n8n/README.md +4 -36
  59. package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
  60. package/dist/plugins/n8n/src/manifest.ts +0 -5
  61. package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
  62. package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
  63. package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
  64. package/dist/plugins/n8n/test/manifest.test.ts +0 -1
  65. package/dist/plugins/twenty/package.json +5 -0
  66. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
  67. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
  69. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
  70. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
  71. package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
  72. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
  73. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
  74. package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
  75. package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
  76. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
  77. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
  78. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
  79. package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
  80. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
  81. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
  82. package/dist/plugins/twenty/src/manifest.ts +99 -0
  83. package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
  84. package/dist/plugins/twenty/test/manifest.test.ts +12 -2
  85. package/dist/terraform/examples/greenfield/main.tf +90 -380
  86. package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
  87. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  88. package/dist/terraform/modules/app/agentcore-pi/main.tf +29 -38
  89. package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
  90. package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
  91. package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
  92. package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
  93. package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
  94. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
  95. package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
  96. package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
  97. package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
  98. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
  99. package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
  100. package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
  101. package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
  102. package/dist/terraform/modules/app/ses-email/main.tf +14 -2
  103. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
  104. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
  105. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
  106. package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
  107. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
  108. package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
  109. package/dist/terraform/modules/thinkwork/README.md +0 -1
  110. package/dist/terraform/modules/thinkwork/main.tf +167 -446
  111. package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
  112. package/dist/terraform/modules/thinkwork/variables.tf +55 -309
  113. package/dist/terraform/schema.graphql +4 -0
  114. package/dist/workspace-defaults/files/AGENTS.md +45 -31
  115. package/dist/workspace-defaults/files/CONTEXT.md +48 -4
  116. package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
  117. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
  118. package/dist/workspace-defaults/files/SPACE.md +34 -19
  119. package/dist/workspace-defaults/files/TOOLS.md +30 -0
  120. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
  121. package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
  122. package/package.json +1 -1
  123. package/dist/plugins/company-brain/README.md +0 -37
  124. package/dist/plugins/company-brain/package.json +0 -33
  125. package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
  126. package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
  127. package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
  128. package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
  129. package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
  130. package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
  131. package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
  132. package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
  133. package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
  134. package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
  135. package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
  136. package/dist/plugins/company-brain/src/api/migration.ts +0 -665
  137. package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
  138. package/dist/plugins/company-brain/src/index.ts +0 -62
  139. package/dist/plugins/company-brain/src/manifest.ts +0 -112
  140. package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
  141. package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
  142. package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
  143. package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
  144. package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
  145. package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
  146. package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
  147. package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
  148. package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
  149. package/dist/plugins/company-brain/tsconfig.json +0 -8
@@ -1,562 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { CogneeClient } from "../../src/api/cognee-client.js";
3
- import { buildCogneeMemoryScope } from "../../src/api/cognee-memory-scope.js";
4
-
5
- const ontology = {
6
- mechanism: "cognee_owl_ontology" as const,
7
- entityTypes: [],
8
- relationshipTypes: [],
9
- customPrompt: "Extract the graph.",
10
- ontologyKey: "thinkwork_tenant_abc123",
11
- ontologyOwlXml: "<rdf:RDF></rdf:RDF>",
12
- };
13
-
14
- function response(status: number, body: unknown) {
15
- return {
16
- ok: status >= 200 && status < 300,
17
- status,
18
- text: async () => JSON.stringify(body),
19
- } as Response;
20
- }
21
-
22
- function textResponse(status: number, body: string) {
23
- return {
24
- ok: status >= 200 && status < 300,
25
- status,
26
- text: async () => body,
27
- } as Response;
28
- }
29
-
30
- describe("CogneeClient", () => {
31
- it("uses remember and fetches a dataset graph", async () => {
32
- const fetchFn = vi
33
- .fn<typeof fetch>()
34
- .mockResolvedValueOnce(response(200, {}))
35
- .mockResolvedValueOnce(
36
- response(200, {
37
- uploaded_ontologies: [{ ontology_key: ontology.ontologyKey }],
38
- }),
39
- )
40
- .mockResolvedValueOnce(
41
- response(200, { dataset_id: "11111111-1111-4111-8111-111111111111" }),
42
- )
43
- .mockResolvedValueOnce(
44
- response(200, {
45
- nodes: [{ id: "n1", label: "Acme", type: "Company" }],
46
- edges: [{ source: "n1", target: "n1", label: "mentions" }],
47
- }),
48
- );
49
- const client = new CogneeClient({
50
- endpoint: "http://cognee.local/",
51
- token: "token",
52
- fetchFn,
53
- });
54
-
55
- const ingest = await client.ingestThread({
56
- tenantId: "tenant-1",
57
- threadId: "thread-1",
58
- datasetName: "thinkwork:t:thread:x",
59
- transcript: "Acme",
60
- ontology,
61
- });
62
- const graph = await client.fetchDatasetGraph(ingest.datasetId!);
63
-
64
- expect(ingest).toEqual(
65
- expect.objectContaining({
66
- datasetId: "11111111-1111-4111-8111-111111111111",
67
- mode: "remember",
68
- }),
69
- );
70
- expect(fetchFn.mock.calls.map((call) => String(call[0]))).toEqual([
71
- "http://cognee.local/api/v1/ontologies",
72
- "http://cognee.local/api/v1/ontologies",
73
- "http://cognee.local/api/v1/remember",
74
- "http://cognee.local/api/v1/datasets/11111111-1111-4111-8111-111111111111/graph",
75
- ]);
76
- const uploadBody = fetchFn.mock.calls[1]?.[1]?.body;
77
- expect(uploadBody).toBeInstanceOf(FormData);
78
- expect(Object.fromEntries(uploadBody as FormData)).toEqual(
79
- expect.objectContaining({
80
- ontology_key: ontology.ontologyKey,
81
- }),
82
- );
83
- const rememberBody = fetchFn.mock.calls[2]?.[1]?.body;
84
- expect(rememberBody).toBeInstanceOf(FormData);
85
- expect(Array.from((rememberBody as FormData).keys()).sort()).toEqual([
86
- "custom_prompt",
87
- "data",
88
- "datasetName",
89
- "node_set",
90
- "node_set",
91
- "node_set",
92
- "ontology_key",
93
- "run_in_background",
94
- ]);
95
- expect((rememberBody as FormData).getAll("node_set")).toEqual([
96
- "thinkwork_thread",
97
- "tenant_tenant_1",
98
- "thread_thread_1",
99
- ]);
100
- expect((rememberBody as FormData).get("ontology_key")).toBe(
101
- ontology.ontologyKey,
102
- );
103
- expect((rememberBody as FormData).get("run_in_background")).toBe("true");
104
- expect(graph.nodes).toEqual([
105
- {
106
- id: "n1",
107
- label: "Acme",
108
- type: "Company",
109
- properties: {},
110
- },
111
- ]);
112
- });
113
-
114
- it("posts user and space memory documents into separate Cognee scopes", async () => {
115
- const fetchFn = vi
116
- .fn<typeof fetch>()
117
- .mockResolvedValueOnce(response(200, { [ontology.ontologyKey]: {} }))
118
- .mockResolvedValueOnce(
119
- response(200, { dataset_id: "11111111-1111-4111-8111-111111111111" }),
120
- )
121
- .mockResolvedValueOnce(response(200, { [ontology.ontologyKey]: {} }))
122
- .mockResolvedValueOnce(
123
- response(200, { dataset_id: "22222222-2222-4222-8222-222222222222" }),
124
- );
125
- const client = new CogneeClient({
126
- endpoint: "http://cognee.local",
127
- fetchFn,
128
- });
129
- const userScope = buildCogneeMemoryScope({
130
- tenantId: "tenant-1",
131
- kind: "user",
132
- userId: "user-1",
133
- });
134
- const spaceScope = buildCogneeMemoryScope({
135
- tenantId: "tenant-1",
136
- kind: "space",
137
- spaceId: "space-1",
138
- });
139
-
140
- await client.ingestDocument({
141
- tenantId: userScope.tenantId,
142
- sourceKind: userScope.sourceKind,
143
- sourceRef: userScope.sourceRef,
144
- datasetName: userScope.datasetName,
145
- document: "User memory",
146
- filename: "thinkwork-user-memory.md",
147
- ontology,
148
- });
149
- await client.ingestDocument({
150
- tenantId: spaceScope.tenantId,
151
- sourceKind: spaceScope.sourceKind,
152
- sourceRef: spaceScope.sourceRef,
153
- datasetName: spaceScope.datasetName,
154
- document: "Space memory",
155
- filename: "thinkwork-space-memory.md",
156
- ontology,
157
- });
158
-
159
- const userBody = fetchFn.mock.calls[1]?.[1]?.body as FormData;
160
- const spaceBody = fetchFn.mock.calls[3]?.[1]?.body as FormData;
161
- expect(userBody.get("datasetName")).toBe(
162
- "thinkwork:memory:v1:tenant:tenant_1:user:user_1",
163
- );
164
- expect(userBody.getAll("node_set")).toEqual([
165
- "thinkwork_memory",
166
- "thinkwork_memory_v1",
167
- "thinkwork_user_memory",
168
- "tenant_tenant_1",
169
- "user_user_1",
170
- ]);
171
- expect(spaceBody.get("datasetName")).toBe(
172
- "thinkwork:memory:v1:tenant:tenant_1:space:space_1",
173
- );
174
- expect(spaceBody.getAll("node_set")).toEqual([
175
- "thinkwork_memory",
176
- "thinkwork_memory_v1",
177
- "thinkwork_space_memory",
178
- "tenant_tenant_1",
179
- "space_space_1",
180
- ]);
181
- });
182
-
183
- it("posts scoped Cognee search requests", async () => {
184
- const fetchFn = vi
185
- .fn<typeof fetch>()
186
- .mockResolvedValueOnce(
187
- response(200, { results: [{ text: "Use concise summaries." }] }),
188
- );
189
- const client = new CogneeClient({
190
- endpoint: "http://cognee.local",
191
- fetchFn,
192
- });
193
-
194
- const result = await client.search({
195
- query: "summary preference",
196
- searchType: "CHUNKS",
197
- datasets: ["thinkwork:memory:v1:tenant:tenant_1:user:user_1"],
198
- nodeNames: ["thinkwork_user_memory", "user_user_1"],
199
- nodeNameFilterOperator: "AND",
200
- topK: 25,
201
- onlyContext: true,
202
- includeReferences: true,
203
- systemPrompt: "Use memory only.",
204
- });
205
-
206
- expect(result).toEqual({
207
- results: [{ text: "Use concise summaries." }],
208
- });
209
- expect(fetchFn).toHaveBeenCalledWith(
210
- "http://cognee.local/api/v1/search",
211
- expect.objectContaining({
212
- method: "POST",
213
- body: JSON.stringify({
214
- query: "summary preference",
215
- search_type: "CHUNKS",
216
- datasets: ["thinkwork:memory:v1:tenant:tenant_1:user:user_1"],
217
- node_name: ["thinkwork_user_memory", "user_user_1"],
218
- node_name_filter_operator: "AND",
219
- top_k: 25,
220
- only_context: true,
221
- include_references: true,
222
- system_prompt: "Use memory only.",
223
- }),
224
- }),
225
- );
226
- });
227
-
228
- it("falls back to add plus cognify when remember is unsupported", async () => {
229
- const fetchFn = vi
230
- .fn<typeof fetch>()
231
- .mockResolvedValueOnce(response(200, { [ontology.ontologyKey]: {} }))
232
- .mockResolvedValueOnce(response(404, { detail: "missing" }))
233
- .mockResolvedValueOnce(response(200, {}))
234
- .mockResolvedValueOnce(
235
- response(200, { datasetId: "22222222-2222-4222-8222-222222222222" }),
236
- );
237
- const client = new CogneeClient({
238
- endpoint: "http://cognee.local",
239
- fetchFn,
240
- });
241
-
242
- const ingest = await client.ingestThread({
243
- tenantId: "tenant-1",
244
- threadId: "thread-1",
245
- datasetName: "thinkwork:t:thread:x",
246
- transcript: "Acme",
247
- ontology,
248
- });
249
-
250
- expect(ingest).toEqual(
251
- expect.objectContaining({
252
- datasetId: "22222222-2222-4222-8222-222222222222",
253
- mode: "add_cognify",
254
- }),
255
- );
256
- expect(fetchFn.mock.calls.map((call) => String(call[0]))).toEqual([
257
- "http://cognee.local/api/v1/ontologies",
258
- "http://cognee.local/api/v1/remember",
259
- "http://cognee.local/api/v1/add",
260
- "http://cognee.local/api/v1/cognify",
261
- ]);
262
- expect(JSON.parse(String(fetchFn.mock.calls[3]?.[1]?.body))).toEqual({
263
- datasets: ["thinkwork:t:thread:x"],
264
- run_in_background: true,
265
- custom_prompt: ontology.customPrompt,
266
- ontology_key: [ontology.ontologyKey],
267
- });
268
- });
269
-
270
- it("polls dataset status until Cognee indexing completes", async () => {
271
- const fetchFn = vi
272
- .fn<typeof fetch>()
273
- .mockResolvedValueOnce(
274
- response(200, {
275
- "11111111-1111-4111-8111-111111111111": "DATASET_PROCESSING_STARTED",
276
- }),
277
- )
278
- .mockResolvedValueOnce(
279
- response(200, {
280
- "11111111-1111-4111-8111-111111111111":
281
- "DATASET_PROCESSING_COMPLETED",
282
- }),
283
- );
284
-
285
- vi.stubEnv("COGNEE_INDEX_POLL_MS", "1");
286
- try {
287
- const client = new CogneeClient({
288
- endpoint: "http://cognee.local",
289
- fetchFn,
290
- retryDelayMs: 0,
291
- });
292
- const status = await client.waitForDatasetIndexing(
293
- "11111111-1111-4111-8111-111111111111",
294
- );
295
-
296
- expect(status).toEqual(
297
- expect.objectContaining({
298
- status: "completed",
299
- rawStatus: "DATASET_PROCESSING_COMPLETED",
300
- attempts: 2,
301
- }),
302
- );
303
- expect(status.samples.map((sample) => sample.status)).toEqual([
304
- "running",
305
- "completed",
306
- ]);
307
- } finally {
308
- vi.unstubAllEnvs();
309
- }
310
- });
311
-
312
- it("preserves Cognee ontology metadata from graph payloads", async () => {
313
- const fetchFn = vi.fn<typeof fetch>().mockResolvedValueOnce(
314
- response(200, {
315
- nodes: [
316
- {
317
- id: "n1",
318
- label: "Acme",
319
- type: "Entity",
320
- is_a: { name: "Company" },
321
- ontology_valid: true,
322
- },
323
- ],
324
- edges: [
325
- {
326
- id: "e1",
327
- source: "n1",
328
- target: "n1",
329
- relationship_type: "Uses",
330
- ontology_valid: true,
331
- },
332
- ],
333
- }),
334
- );
335
- const client = new CogneeClient({
336
- endpoint: "http://cognee.local",
337
- fetchFn,
338
- retryDelayMs: 0,
339
- });
340
-
341
- const graph = await client.fetchDatasetGraph(
342
- "11111111-1111-4111-8111-111111111111",
343
- );
344
-
345
- expect(graph.nodes).toEqual([
346
- expect.objectContaining({
347
- id: "n1",
348
- label: "Acme",
349
- type: "Entity",
350
- properties: {
351
- is_a: { name: "Company" },
352
- ontology_valid: true,
353
- },
354
- }),
355
- ]);
356
- expect(graph.edges).toEqual([
357
- expect.objectContaining({
358
- id: "e1",
359
- label: "Uses",
360
- type: "Uses",
361
- properties: { relationship_type: "Uses", ontology_valid: true },
362
- }),
363
- ]);
364
- });
365
-
366
- it("summarizes Cognee HTML errors without leaking markup", async () => {
367
- const fetchFn = vi
368
- .fn<typeof fetch>()
369
- .mockResolvedValueOnce(
370
- textResponse(
371
- 503,
372
- "<html><head><title>503 Service Temporarily Unavailable</title></head><body></body></html>",
373
- ),
374
- );
375
- const client = new CogneeClient({
376
- endpoint: "http://cognee.local",
377
- fetchFn,
378
- retryAttempts: 1,
379
- retryDelayMs: 0,
380
- });
381
-
382
- await expect(
383
- client.ingestThread({
384
- tenantId: "tenant-1",
385
- threadId: "thread-1",
386
- datasetName: "thinkwork:t:thread:x",
387
- transcript: "Acme",
388
- ontology,
389
- }),
390
- ).rejects.toThrow(
391
- "Cognee /api/v1/ontologies failed with 503: 503 Service Temporarily Unavailable",
392
- );
393
- });
394
-
395
- it("rides through a transient 503 on the status endpoint and completes", async () => {
396
- const fetchFn = vi
397
- .fn<typeof fetch>()
398
- .mockResolvedValueOnce(
399
- response(200, {
400
- "11111111-1111-4111-8111-111111111111": "DATASET_PROCESSING_STARTED",
401
- }),
402
- )
403
- .mockResolvedValueOnce(response(503, { detail: "Service Unavailable" }))
404
- .mockResolvedValueOnce(response(503, { detail: "Service Unavailable" }))
405
- .mockResolvedValueOnce(
406
- response(200, {
407
- "11111111-1111-4111-8111-111111111111":
408
- "DATASET_PROCESSING_COMPLETED",
409
- }),
410
- );
411
-
412
- vi.stubEnv("COGNEE_INDEX_POLL_MS", "1");
413
- try {
414
- const client = new CogneeClient({
415
- endpoint: "http://cognee.local",
416
- fetchFn,
417
- retryDelayMs: 0,
418
- retryAttempts: 1,
419
- });
420
- const status = await client.waitForDatasetIndexing(
421
- "11111111-1111-4111-8111-111111111111",
422
- );
423
- expect(status.status).toBe("completed");
424
- expect(status.rawStatus).toBe("DATASET_PROCESSING_COMPLETED");
425
- } finally {
426
- vi.unstubAllEnvs();
427
- }
428
- });
429
-
430
- it("falls back to a graph probe when status stays unavailable past timeout", async () => {
431
- // status endpoint always 503; the graph probe finds nodes (pipeline done)
432
- const fetchFn = vi.fn<typeof fetch>().mockImplementation(async (url) => {
433
- if (String(url).includes("/datasets/status")) {
434
- return response(503, { detail: "Service Unavailable" });
435
- }
436
- if (String(url).includes("/graph")) {
437
- return response(200, {
438
- nodes: [{ id: "n1", label: "Acme", type: "Company" }],
439
- edges: [],
440
- });
441
- }
442
- return response(200, {});
443
- });
444
-
445
- vi.stubEnv("COGNEE_INDEX_POLL_MS", "1");
446
- vi.stubEnv("COGNEE_INDEX_TIMEOUT_MS", "5");
447
- try {
448
- const client = new CogneeClient({
449
- endpoint: "http://cognee.local",
450
- fetchFn,
451
- retryDelayMs: 0,
452
- retryAttempts: 1,
453
- });
454
- const status = await client.waitForDatasetIndexing(
455
- "11111111-1111-4111-8111-111111111111",
456
- );
457
- expect(status.status).toBe("completed");
458
- expect(status.rawStatus).toBe("completed_via_graph_probe");
459
- } finally {
460
- vi.unstubAllEnvs();
461
- }
462
- });
463
-
464
- it("throws past timeout when status is unavailable AND the graph is empty", async () => {
465
- const fetchFn = vi.fn<typeof fetch>().mockImplementation(async (url) => {
466
- if (String(url).includes("/datasets/status")) {
467
- return response(503, { detail: "Service Unavailable" });
468
- }
469
- if (String(url).includes("/graph")) {
470
- return response(200, { nodes: [], edges: [] });
471
- }
472
- return response(200, {});
473
- });
474
-
475
- vi.stubEnv("COGNEE_INDEX_POLL_MS", "1");
476
- vi.stubEnv("COGNEE_INDEX_TIMEOUT_MS", "5");
477
- try {
478
- const client = new CogneeClient({
479
- endpoint: "http://cognee.local",
480
- fetchFn,
481
- retryDelayMs: 0,
482
- retryAttempts: 1,
483
- });
484
- await expect(
485
- client.waitForDatasetIndexing("11111111-1111-4111-8111-111111111111"),
486
- ).rejects.toThrow(/did not complete|failed with 503/);
487
- } finally {
488
- vi.unstubAllEnvs();
489
- }
490
- });
491
-
492
- it("deleteDatasetByName finds matching datasets and deletes them", async () => {
493
- const fetchFn = vi
494
- .fn<typeof fetch>()
495
- .mockResolvedValueOnce(
496
- response(200, {
497
- datasets: [
498
- { id: "ds-1", name: "thinkwork:t:observations" },
499
- { id: "ds-2", name: "thinkwork:t:thread:x" },
500
- { id: "ds-3", name: "thinkwork:t:observations" },
501
- ],
502
- }),
503
- )
504
- .mockResolvedValueOnce(response(200, {}))
505
- .mockResolvedValueOnce(response(200, {}));
506
- const client = new CogneeClient({
507
- endpoint: "http://cognee.local",
508
- fetchFn,
509
- retryDelayMs: 0,
510
- });
511
- const deleted = await client.deleteDatasetByName(
512
- "thinkwork:t:observations",
513
- );
514
- expect(deleted).toBe(2);
515
- const calls = fetchFn.mock.calls.map((c) => [String(c[0]), c[1]?.method]);
516
- expect(calls[0]).toEqual(["http://cognee.local/api/v1/datasets", "GET"]);
517
- expect(calls).toContainEqual([
518
- "http://cognee.local/api/v1/datasets/ds-1",
519
- "DELETE",
520
- ]);
521
- expect(calls).toContainEqual([
522
- "http://cognee.local/api/v1/datasets/ds-3",
523
- "DELETE",
524
- ]);
525
- // ds-2 (a thread dataset) must NOT be deleted
526
- expect(calls).not.toContainEqual([
527
- "http://cognee.local/api/v1/datasets/ds-2",
528
- "DELETE",
529
- ]);
530
- });
531
-
532
- it("deleteDatasetByName is a no-op when no dataset matches", async () => {
533
- const fetchFn = vi
534
- .fn<typeof fetch>()
535
- .mockResolvedValueOnce(
536
- response(200, { datasets: [{ id: "ds-2", name: "other" }] }),
537
- );
538
- const client = new CogneeClient({
539
- endpoint: "http://cognee.local",
540
- fetchFn,
541
- retryDelayMs: 0,
542
- });
543
- expect(await client.deleteDatasetByName("missing")).toBe(0);
544
- expect(fetchFn).toHaveBeenCalledTimes(1);
545
- });
546
-
547
- it("pruneAll POSTs to the prune endpoint", async () => {
548
- const fetchFn = vi
549
- .fn<typeof fetch>()
550
- .mockResolvedValueOnce(response(200, {}));
551
- const client = new CogneeClient({
552
- endpoint: "http://cognee.local",
553
- fetchFn,
554
- retryDelayMs: 0,
555
- });
556
- expect(await client.pruneAll()).toBe(true);
557
- expect(String(fetchFn.mock.calls[0][0])).toBe(
558
- "http://cognee.local/api/v1/prune",
559
- );
560
- expect(fetchFn.mock.calls[0][1]?.method).toBe("POST");
561
- });
562
- });
@@ -1,74 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import {
4
- buildCogneeMemoryScope,
5
- COGNEE_MEMORY_SCOPE_VERSION,
6
- } from "../../src/api/cognee-memory-scope.js";
7
-
8
- describe("buildCogneeMemoryScope", () => {
9
- it("builds a stable user memory scope", () => {
10
- const scope = buildCogneeMemoryScope({
11
- tenantId: "Tenant 1",
12
- kind: "user",
13
- userId: "User 1",
14
- });
15
-
16
- expect(scope).toEqual({
17
- version: COGNEE_MEMORY_SCOPE_VERSION,
18
- kind: "user",
19
- tenantId: "Tenant 1",
20
- ownerId: "User 1",
21
- sourceKind: "user_memory",
22
- sourceRef: "User 1",
23
- datasetName: "thinkwork:memory:v1:tenant:tenant_1:user:user_1",
24
- nodeSets: [
25
- "thinkwork_memory",
26
- "thinkwork_memory_v1",
27
- "thinkwork_user_memory",
28
- "tenant_tenant_1",
29
- "user_user_1",
30
- ],
31
- metadata: {
32
- memory_scope_version: "v1",
33
- memory_scope_kind: "user",
34
- tenant_id: "Tenant 1",
35
- owner_id: "User 1",
36
- },
37
- });
38
- });
39
-
40
- it("builds a separate stable space memory scope", () => {
41
- const scope = buildCogneeMemoryScope({
42
- tenantId: "Tenant 1",
43
- kind: "space",
44
- spaceId: "Space 1",
45
- });
46
-
47
- expect(scope).toEqual(
48
- expect.objectContaining({
49
- kind: "space",
50
- ownerId: "Space 1",
51
- sourceKind: "space_memory",
52
- sourceRef: "Space 1",
53
- datasetName: "thinkwork:memory:v1:tenant:tenant_1:space:space_1",
54
- nodeSets: [
55
- "thinkwork_memory",
56
- "thinkwork_memory_v1",
57
- "thinkwork_space_memory",
58
- "tenant_tenant_1",
59
- "space_space_1",
60
- ],
61
- }),
62
- );
63
- });
64
-
65
- it("rejects missing owner ids instead of collapsing memory scopes", () => {
66
- expect(() =>
67
- buildCogneeMemoryScope({
68
- tenantId: "tenant-1",
69
- kind: "space",
70
- spaceId: " ",
71
- }),
72
- ).toThrow("Cognee memory scope requires a non-empty spaceId");
73
- });
74
- });