thinkwork-cli 0.12.15 → 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 (152) hide show
  1. package/dist/{api-client-4VT3FWOH.js → api-client-JUBCQQDF.js} +1 -1
  2. package/dist/{chunk-H7AB42ES.js → chunk-STY44FQO.js} +13 -0
  3. package/dist/cli.js +1107 -10225
  4. package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
  5. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
  6. package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
  7. package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
  8. package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
  9. package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
  10. package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
  11. package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
  12. package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
  13. package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
  14. package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
  15. package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
  16. package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
  17. package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
  18. package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
  19. package/dist/drizzle/0197_rcm_context_columns.sql +28 -0
  20. package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
  21. package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
  22. package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
  23. package/dist/drizzle/0203_threads_mode_override.sql +61 -0
  24. package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
  25. package/dist/drizzle/0205_routines_git_python.sql +185 -0
  26. package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
  27. package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
  28. package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
  29. package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
  30. package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
  31. package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
  32. package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
  33. package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
  34. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
  35. package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
  36. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
  37. package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
  38. package/dist/drizzle/0218_document_plates.sql +30 -0
  39. package/dist/drizzle/0219_document_section_waivers.sql +29 -0
  40. package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
  41. package/dist/drizzle/0221_artifact_shares.sql +29 -0
  42. package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
  43. package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
  44. package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
  45. package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
  46. package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
  47. package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
  48. package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
  49. package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
  50. package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
  51. package/dist/drizzle/0230_analyst_rls.sql +1613 -0
  52. package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
  53. package/dist/plugins/catalog/package.json +0 -1
  54. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
  55. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
  56. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
  57. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
  58. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
  59. package/dist/plugins/catalog/src/contracts.ts +112 -0
  60. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
  61. package/dist/plugins/n8n/README.md +4 -36
  62. package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
  63. package/dist/plugins/n8n/src/manifest.ts +0 -5
  64. package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
  65. package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
  66. package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
  67. package/dist/plugins/n8n/test/manifest.test.ts +0 -1
  68. package/dist/plugins/twenty/package.json +5 -0
  69. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
  70. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
  71. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
  72. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
  73. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
  74. package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
  75. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
  76. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
  77. package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
  78. package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
  79. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
  80. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
  81. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
  82. package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
  83. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
  84. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
  85. package/dist/plugins/twenty/src/manifest.ts +99 -0
  86. package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
  87. package/dist/plugins/twenty/test/manifest.test.ts +12 -2
  88. package/dist/terraform/examples/greenfield/main.tf +90 -380
  89. package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
  90. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  91. package/dist/terraform/modules/app/agentcore-pi/main.tf +36 -32
  92. package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
  93. package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
  94. package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
  95. package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
  96. package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
  97. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
  98. package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
  99. package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
  100. package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
  101. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
  102. package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
  103. package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
  104. package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
  105. package/dist/terraform/modules/app/ses-email/main.tf +14 -2
  106. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
  107. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
  108. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
  109. package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
  110. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
  111. package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
  112. package/dist/terraform/modules/thinkwork/README.md +0 -1
  113. package/dist/terraform/modules/thinkwork/main.tf +167 -446
  114. package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
  115. package/dist/terraform/modules/thinkwork/variables.tf +55 -309
  116. package/dist/terraform/schema.graphql +4 -0
  117. package/dist/workspace-defaults/files/AGENTS.md +45 -31
  118. package/dist/workspace-defaults/files/CONTEXT.md +48 -4
  119. package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
  120. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
  121. package/dist/workspace-defaults/files/SPACE.md +34 -19
  122. package/dist/workspace-defaults/files/TOOLS.md +30 -0
  123. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
  124. package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
  125. package/package.json +2 -1
  126. package/dist/plugins/company-brain/README.md +0 -37
  127. package/dist/plugins/company-brain/package.json +0 -33
  128. package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
  129. package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
  130. package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
  131. package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
  132. package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
  133. package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
  134. package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
  135. package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
  136. package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
  137. package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
  138. package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
  139. package/dist/plugins/company-brain/src/api/migration.ts +0 -665
  140. package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
  141. package/dist/plugins/company-brain/src/index.ts +0 -62
  142. package/dist/plugins/company-brain/src/manifest.ts +0 -112
  143. package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
  144. package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
  145. package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
  146. package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
  147. package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
  148. package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
  149. package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
  150. package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
  151. package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
  152. package/dist/plugins/company-brain/tsconfig.json +0 -8
@@ -1,37 +0,0 @@
1
- # Company Brain Plugin
2
-
3
- Company Brain is a first-party premium application plugin package for the
4
- THNK-31 `plugins/<plugin-key>/` source boundary. Company Brain is the
5
- customer-facing product; Cognee is the internal Brain substrate adapter and
6
- should appear only in deployment evidence, logs, Terraform/runtime paths, or
7
- implementation notes.
8
-
9
- ## Package Contract
10
-
11
- - `package.json` exposes `@thinkwork/plugin-company-brain`.
12
- - `src/index.ts` exports `companyBrainPluginPackage` with owned source
13
- descriptors and compatibility links.
14
- - `src/manifest.ts` owns the Company Brain catalog manifest.
15
- - `src/deployment/cognee-managed-app.ts` owns the internal substrate
16
- managed-app deployment adapter.
17
- - `terraform/cognee/` owns the internal substrate Terraform module.
18
- - `runtime/cognee/Dockerfile` owns the internal substrate runtime image source.
19
- - `src/api/` owns Company Brain migration helpers, context-engine provider,
20
- internal substrate client, and cluster identity utilities.
21
- - `smoke/` owns Company Brain entitlement, operations, context engine, and
22
- internal substrate smoke scripts.
23
- - `test/manifest.test.ts` keeps Company Brain premium entitlement,
24
- infrastructure, and customer-facing copy contracts aligned.
25
-
26
- ## Temporary Compatibility Links
27
-
28
- No active plugin-specific compatibility source remains outside
29
- `plugins/company-brain/`. The legacy `/settings/applications/cognee` URL is a
30
- shared web redirect to the Company Brain plugin detail page.
31
-
32
- ## Verification
33
-
34
- ```bash
35
- pnpm --filter @thinkwork/plugin-company-brain test
36
- pnpm --filter @thinkwork/plugin-company-brain typecheck
37
- ```
@@ -1,33 +0,0 @@
1
- {
2
- "name": "@thinkwork/plugin-company-brain",
3
- "version": "0.0.0",
4
- "private": true,
5
- "type": "module",
6
- "main": "./src/index.ts",
7
- "exports": {
8
- ".": "./src/index.ts",
9
- "./manifest": "./src/manifest.ts",
10
- "./api/cognee-client": "./src/api/cognee-client.ts",
11
- "./api/cognee-memory-scope": "./src/api/cognee-memory-scope.ts",
12
- "./api/cognee-cluster-identity": "./src/api/cognee-cluster-identity.ts",
13
- "./api/context-engine-provider": "./src/api/context-engine-provider.ts",
14
- "./api/migration": "./src/api/migration.ts",
15
- "./deployment/cognee-managed-app": "./src/deployment/cognee-managed-app.ts"
16
- },
17
- "scripts": {
18
- "build": "tsc --build",
19
- "typecheck": "tsc --noEmit",
20
- "test": "vitest run"
21
- },
22
- "dependencies": {
23
- "@thinkwork/database-pg": "workspace:*",
24
- "drizzle-orm": "^0.39.0",
25
- "graphql": "^16.10.0"
26
- },
27
- "devDependencies": {
28
- "@thinkwork/deployment-runner": "workspace:*",
29
- "@thinkwork/plugin-catalog": "workspace:*",
30
- "typescript": "^5.5.0",
31
- "vitest": "^2.0.0"
32
- }
33
- }
@@ -1,11 +0,0 @@
1
- ARG COGNEE_BASE_IMAGE=cognee/cognee@sha256:5ce7e4052b1d16738d1e24476d64847fcb5b1666631b642651e8ccce414046f8
2
- FROM ${COGNEE_BASE_IMAGE}
3
-
4
- # LiteLLM's Bedrock Converse adapter imports boto3 at extraction time. Cognee's
5
- # PATH points at the uv-built runtime venv, which intentionally omits pip, so
6
- # install the dependency into the venv import path with the system Python that
7
- # remains in the final image.
8
- RUN /usr/local/bin/python -m pip install \
9
- --no-cache-dir \
10
- --target /app/.venv/lib/python3.12/site-packages \
11
- "boto3>=1.34.0"
@@ -1,458 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Smoke test the Cognee managed application deployment.
4
- *
5
- * Dry-run is the default. Set SMOKE_ENABLE_COGNEE_MANAGED_APP=1 after deploy
6
- * to read Terraform/API deployment status and prove Cognee health through the
7
- * ThinkWork GraphQL health check. Direct private ALB probing is opt-in because
8
- * Cognee is normally internal-only.
9
- *
10
- * Optional live env:
11
- * SMOKE_TERRAFORM_DIR=terraform/examples/greenfield
12
- * SMOKE_COGNEE_ENDPOINT=http://internal-alb
13
- * SMOKE_ALLOW_PRIVATE_COGNEE_HTTP=1
14
- * SMOKE_TENANT_ID=<tenant-id>
15
- * VITE_GRAPHQL_HTTP_URL, GRAPHQL_HTTP_URL, or API_GRAPHQL_URL
16
- * API_AUTH_SECRET, THINKWORK_API_SECRET, VITE_GRAPHQL_API_KEY, or GRAPHQL_API_KEY
17
- */
18
-
19
- import { execFileSync } from "node:child_process";
20
- import fs from "node:fs";
21
- import path from "node:path";
22
- import process from "node:process";
23
- import { attachSmokeEvidence } from "../../../scripts/smoke/deployment-evidence.mjs";
24
-
25
- const LIVE_ENABLED = process.env.SMOKE_ENABLE_COGNEE_MANAGED_APP === "1";
26
- const TIMEOUT_MS = Number(process.env.SMOKE_TIMEOUT_MS || 15_000);
27
-
28
- const env = {
29
- ...loadEnvFile(),
30
- ...process.env,
31
- };
32
-
33
- const terraformDir = env.SMOKE_TERRAFORM_DIR || "terraform/examples/greenfield";
34
- const apiUrl = first(
35
- env.VITE_GRAPHQL_HTTP_URL,
36
- env.GRAPHQL_HTTP_URL,
37
- env.API_GRAPHQL_URL,
38
- );
39
- const apiSecret = first(env.API_AUTH_SECRET, env.THINKWORK_API_SECRET);
40
- const apiKey = first(
41
- env.VITE_GRAPHQL_API_KEY,
42
- env.APPSYNC_API_KEY,
43
- env.GRAPHQL_API_KEY,
44
- );
45
- const tenantId = first(env.SMOKE_TENANT_ID, env.TENANT_ID);
46
-
47
- if (!LIVE_ENABLED) {
48
- console.log(
49
- JSON.stringify(
50
- await attachSmokeEvidence(
51
- "cognee-managed-app",
52
- {
53
- ok: true,
54
- skippedLive: true,
55
- reason:
56
- "set SMOKE_ENABLE_COGNEE_MANAGED_APP=1 to run the deployed Cognee managed-app smoke",
57
- dryRun: {
58
- terraformDir,
59
- requiredWhenRunning: [
60
- "Terraform outputs in SMOKE_TERRAFORM_DIR or SMOKE_COGNEE_ENDPOINT",
61
- "Cognee enabled deployment status",
62
- "GraphQL health check credentials or SMOKE_ALLOW_PRIVATE_COGNEE_HTTP=1",
63
- ],
64
- optionalGraphqlEnv: [
65
- "SMOKE_TENANT_ID",
66
- "VITE_GRAPHQL_HTTP_URL or GRAPHQL_HTTP_URL or API_GRAPHQL_URL",
67
- "API_AUTH_SECRET or THINKWORK_API_SECRET or VITE_GRAPHQL_API_KEY or GRAPHQL_API_KEY",
68
- ],
69
- verifies: [
70
- "cognee_enabled false skips cleanly",
71
- "enabled Cognee resolves endpoint and log/status outputs",
72
- "Terraform and GraphQL cluster identity normalize to brain-cluster",
73
- "GraphQL knowledgeGraphHealthCheck reports healthy",
74
- "optional direct /health probe succeeds when explicitly enabled",
75
- ],
76
- },
77
- },
78
- env,
79
- ),
80
- null,
81
- 2,
82
- ),
83
- );
84
- process.exit(0);
85
- }
86
-
87
- try {
88
- const result = await runLiveSmoke();
89
- console.log(
90
- JSON.stringify(
91
- await attachSmokeEvidence(
92
- "cognee-managed-app",
93
- { ok: true, ...result },
94
- env,
95
- ),
96
- null,
97
- 2,
98
- ),
99
- );
100
- } catch (error) {
101
- fail(error instanceof Error ? error.message : String(error));
102
- }
103
-
104
- async function runLiveSmoke() {
105
- const terraform = readTerraformOutputs(terraformDir);
106
- const graphql = await readGraphqlStatus().catch((error) => ({
107
- error: error instanceof Error ? error.message : String(error),
108
- }));
109
- const status = resolveStatus({ terraform, graphql });
110
-
111
- if (!status.enabled) {
112
- return {
113
- skippedLive: true,
114
- reason: "Cognee is not enabled for this stage.",
115
- terraform,
116
- graphql,
117
- };
118
- }
119
-
120
- if (!status.endpoint) {
121
- throw new Error("Cognee is enabled but no endpoint was resolved.");
122
- }
123
- const clusterIdentity = assertClusterIdentity({ terraform, graphql, status });
124
-
125
- const graphqlHealth =
126
- apiUrl && (apiSecret || apiKey)
127
- ? await readGraphqlHealth().catch((error) => ({
128
- error: error instanceof Error ? error.message : String(error),
129
- }))
130
- : null;
131
- const directHealth =
132
- env.SMOKE_ALLOW_PRIVATE_COGNEE_HTTP === "1"
133
- ? await probeHealth(status.endpoint)
134
- : null;
135
-
136
- if (graphqlHealth && "healthy" in graphqlHealth && !graphqlHealth.healthy) {
137
- throw new Error(
138
- `GraphQL Cognee health reported unhealthy: ${graphqlHealth.message}`,
139
- );
140
- }
141
- if (graphqlHealth && "error" in graphqlHealth) {
142
- throw new Error(`GraphQL Cognee health failed: ${graphqlHealth.error}`);
143
- }
144
- if (directHealth && !directHealth.healthy) {
145
- throw new Error(
146
- `Cognee /health failed: HTTP ${directHealth.statusCode ?? "none"} ${directHealth.message}`,
147
- );
148
- }
149
- if (!graphqlHealth && !directHealth) {
150
- throw new Error(
151
- "Cognee is enabled; provide GraphQL smoke credentials or set SMOKE_ALLOW_PRIVATE_COGNEE_HTTP=1 for direct /health probing.",
152
- );
153
- }
154
-
155
- return {
156
- status,
157
- clusterIdentity,
158
- graphqlHealth,
159
- directHealth,
160
- terraform,
161
- graphql,
162
- };
163
- }
164
-
165
- function resolveStatus({ terraform, graphql }) {
166
- const app = graphql?.deploymentStatus?.managedApplications?.find(
167
- (entry) => entry.key === "cognee",
168
- );
169
- const terraformClusterName = clusterNameFromArnOrName(
170
- terraform.cognee_cluster_arn,
171
- );
172
- const deploymentClusterName = clusterNameFromArnOrName(
173
- graphql?.deploymentStatus?.cogneeClusterArn,
174
- );
175
- const managedAppClusterName = clusterNameFromArnOrName(app?.clusterArn);
176
- return {
177
- enabled: bool(
178
- firstDefined(
179
- app?.provisioned,
180
- terraform.cognee_enabled,
181
- !!env.SMOKE_COGNEE_ENDPOINT,
182
- ),
183
- ),
184
- endpoint: first(
185
- env.SMOKE_COGNEE_ENDPOINT,
186
- app?.url,
187
- graphql?.deploymentStatus?.cogneeEndpoint,
188
- terraform.cognee_endpoint,
189
- ),
190
- source: app ? "graphql" : terraform.available ? "terraform" : "env",
191
- status: app?.status ?? null,
192
- message: app?.message ?? null,
193
- serviceName: first(
194
- app?.serviceName,
195
- graphql?.deploymentStatus?.cogneeServiceName,
196
- terraform.cognee_service_name,
197
- ),
198
- terraformClusterName,
199
- deploymentClusterName,
200
- managedAppClusterName,
201
- healthCheckTargetCluster:
202
- deploymentClusterName || managedAppClusterName || terraformClusterName,
203
- };
204
- }
205
-
206
- function assertClusterIdentity({ terraform, graphql, status }) {
207
- if (!terraform.available) {
208
- throw new Error(
209
- `Cognee is enabled but Terraform output was not available: ${terraform.reason ?? "unknown reason"}`,
210
- );
211
- }
212
- if (!terraform.cognee_cluster_arn) {
213
- throw new Error(
214
- "Cognee is enabled but Terraform output cognee_cluster_arn is missing.",
215
- );
216
- }
217
-
218
- const app = graphql?.deploymentStatus?.managedApplications?.find(
219
- (entry) => entry.key === "cognee",
220
- );
221
- const entries = [
222
- ["terraform.cognee_cluster_arn", terraform.cognee_cluster_arn],
223
- [
224
- "deploymentStatus.cogneeClusterArn",
225
- graphql?.deploymentStatus?.cogneeClusterArn,
226
- ],
227
- ["managedApplications[cognee].clusterArn", app?.clusterArn],
228
- ].filter(([, value]) => Boolean(value));
229
-
230
- if (entries.length < 2) {
231
- throw new Error(
232
- "Cognee cluster identity needs Terraform output plus at least one GraphQL status source.",
233
- );
234
- }
235
-
236
- const names = entries.map(([label, value]) => [
237
- label,
238
- clusterNameFromArnOrName(value),
239
- ]);
240
- const [firstLabel, firstName] = names[0];
241
- if (!firstName) {
242
- throw new Error(`${firstLabel} did not include an ECS cluster name.`);
243
- }
244
-
245
- for (const [label, name] of names.slice(1)) {
246
- if (name !== firstName) {
247
- throw new Error(
248
- `Cognee cluster identity mismatch: ${firstLabel}=${firstName}, ${label}=${name}`,
249
- );
250
- }
251
- }
252
-
253
- if (!firstName.endsWith("-brain-cluster")) {
254
- const reason = first(env.SMOKE_COGNEE_CLUSTER_BREAK_GLASS_REASON);
255
- const owner = first(env.SMOKE_COGNEE_CLUSTER_BREAK_GLASS_OWNER);
256
- if (!reason || !owner) {
257
- throw new Error(
258
- `Cognee cluster ${firstName} is not Brain-named; set break-glass reason and owner only for temporary recovery.`,
259
- );
260
- }
261
- }
262
-
263
- return {
264
- expectedClusterName: firstName,
265
- serviceName: status.serviceName,
266
- terraformClusterArnPresent: Boolean(terraform.cognee_cluster_arn),
267
- deploymentStatusClusterArnPresent: Boolean(
268
- graphql?.deploymentStatus?.cogneeClusterArn,
269
- ),
270
- managedApplicationClusterArnPresent: Boolean(app?.clusterArn),
271
- healthCheckTargetCluster: status.healthCheckTargetCluster,
272
- breakGlass: firstName.endsWith("-brain-cluster")
273
- ? null
274
- : {
275
- owner: env.SMOKE_COGNEE_CLUSTER_BREAK_GLASS_OWNER,
276
- reason: env.SMOKE_COGNEE_CLUSTER_BREAK_GLASS_REASON,
277
- },
278
- };
279
- }
280
-
281
- async function probeHealth(baseUrl) {
282
- const endpoint = new URL("/health", baseUrl).toString();
283
- const started = Date.now();
284
- const controller = new AbortController();
285
- const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
286
- try {
287
- const response = await fetch(endpoint, { signal: controller.signal });
288
- const body = await response.text().catch(() => "");
289
- return {
290
- endpoint,
291
- healthy: response.ok,
292
- statusCode: response.status,
293
- latencyMs: Date.now() - started,
294
- message: body.slice(0, 300),
295
- };
296
- } finally {
297
- clearTimeout(timer);
298
- }
299
- }
300
-
301
- function readTerraformOutputs(dir) {
302
- const resolved = path.resolve(dir);
303
- if (!fs.existsSync(resolved)) {
304
- return { available: false, reason: `Terraform dir not found: ${dir}` };
305
- }
306
-
307
- try {
308
- const raw = execFileSync(
309
- "terraform",
310
- ["-chdir=" + resolved, "output", "-json"],
311
- {
312
- encoding: "utf8",
313
- stdio: ["ignore", "pipe", "pipe"],
314
- },
315
- );
316
- const parsed = JSON.parse(raw);
317
- return {
318
- available: true,
319
- cognee_enabled: outputValue(parsed.cognee_enabled),
320
- cognee_endpoint: outputValue(parsed.cognee_endpoint),
321
- cognee_log_group_name: outputValue(parsed.cognee_log_group_name),
322
- cognee_cluster_arn: outputValue(parsed.cognee_cluster_arn),
323
- cognee_service_name: outputValue(parsed.cognee_service_name),
324
- cognee_storage_file_system_id: outputValue(
325
- parsed.cognee_storage_file_system_id,
326
- ),
327
- };
328
- } catch (error) {
329
- return {
330
- available: false,
331
- reason: error instanceof Error ? error.message : String(error),
332
- };
333
- }
334
- }
335
-
336
- async function readGraphqlStatus() {
337
- if (!apiUrl || (!apiSecret && !apiKey)) return null;
338
- return gql(`
339
- query CogneeSmokeDeploymentStatus {
340
- deploymentStatus {
341
- stage
342
- region
343
- cogneeEnabled
344
- cogneeEndpoint
345
- cogneeClusterArn
346
- cogneeServiceName
347
- managedApplications {
348
- key
349
- status
350
- provisioned
351
- runtimeEnabled
352
- url
353
- clusterArn
354
- serviceName
355
- message
356
- }
357
- }
358
- }
359
- `);
360
- }
361
-
362
- async function readGraphqlHealth() {
363
- const data = await gql(`
364
- query CogneeSmokeManagedApplicationHealth {
365
- knowledgeGraphHealthCheck {
366
- healthy
367
- statusCode
368
- latencyMs
369
- endpoint
370
- message
371
- }
372
- }
373
- `);
374
- return data.knowledgeGraphHealthCheck;
375
- }
376
-
377
- async function gql(query) {
378
- const headers = { "content-type": "application/json" };
379
- if (tenantId) headers["x-tenant-id"] = tenantId;
380
- if (apiSecret) headers.authorization = `Bearer ${apiSecret}`;
381
- else headers["x-api-key"] = apiKey;
382
-
383
- const response = await fetch(apiUrl, {
384
- method: "POST",
385
- headers,
386
- body: JSON.stringify({ query }),
387
- });
388
- if (!response.ok) {
389
- throw new Error(
390
- `GraphQL HTTP ${response.status}: ${await response.text()}`,
391
- );
392
- }
393
- const body = await response.json();
394
- if (body.errors?.length) {
395
- throw new Error(`GraphQL errors: ${JSON.stringify(body.errors)}`);
396
- }
397
- return body.data;
398
- }
399
-
400
- function outputValue(entry) {
401
- return entry && Object.prototype.hasOwnProperty.call(entry, "value")
402
- ? entry.value
403
- : undefined;
404
- }
405
-
406
- function firstDefined(...values) {
407
- return values.find((value) => value !== undefined && value !== null);
408
- }
409
-
410
- function bool(value) {
411
- return value === true || value === "true" || value === "1";
412
- }
413
-
414
- function clusterNameFromArnOrName(value) {
415
- if (!value || typeof value !== "string") return null;
416
- const trimmed = value.trim();
417
- const slashIndex = trimmed.lastIndexOf("/");
418
- return slashIndex >= 0 ? trimmed.slice(slashIndex + 1) : trimmed;
419
- }
420
-
421
- function loadEnvFile() {
422
- const explicit = process.env.COMPUTER_ENV_FILE;
423
- if (explicit === "none") return {};
424
- const candidates = [explicit, "apps/web/.env", ".env"].filter(Boolean);
425
-
426
- for (const candidate of candidates) {
427
- const resolved = path.resolve(candidate);
428
- if (!fs.existsSync(resolved)) continue;
429
- return Object.fromEntries(
430
- fs
431
- .readFileSync(resolved, "utf8")
432
- .split(/\r?\n/)
433
- .map((line) => line.trim())
434
- .filter((line) => line && !line.startsWith("#") && line.includes("="))
435
- .map((line) => {
436
- const index = line.indexOf("=");
437
- const key = line.slice(0, index).trim();
438
- const value = line
439
- .slice(index + 1)
440
- .trim()
441
- .replace(/^['"]|['"]$/g, "");
442
- return [key, value];
443
- }),
444
- );
445
- }
446
- return {};
447
- }
448
-
449
- function first(...values) {
450
- return values.find(
451
- (value) => value !== undefined && value !== null && value !== "",
452
- );
453
- }
454
-
455
- function fail(message) {
456
- console.error(JSON.stringify({ ok: false, error: message }, null, 2));
457
- process.exit(1);
458
- }