thinkwork-cli 0.12.16 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +517 -10403
- package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
- package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
- package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
- package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
- package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
- package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
- package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
- package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
- package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
- package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
- package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
- package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
- package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
- package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
- package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
- package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
- package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
- package/dist/drizzle/0203_threads_mode_override.sql +61 -0
- package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
- package/dist/drizzle/0205_routines_git_python.sql +185 -0
- package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
- package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
- package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
- package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
- package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
- package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
- package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
- package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
- package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
- package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
- package/dist/drizzle/0218_document_plates.sql +30 -0
- package/dist/drizzle/0219_document_section_waivers.sql +29 -0
- package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
- package/dist/drizzle/0221_artifact_shares.sql +29 -0
- package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
- package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
- package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
- package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
- package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
- package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
- package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
- package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
- package/dist/drizzle/0230_analyst_rls.sql +1613 -0
- package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
- package/dist/plugins/catalog/package.json +0 -1
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
- package/dist/plugins/catalog/src/contracts.ts +112 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/plugins/n8n/README.md +4 -36
- package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
- package/dist/plugins/n8n/src/manifest.ts +0 -5
- package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
- package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
- package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
- package/dist/plugins/n8n/test/manifest.test.ts +0 -1
- package/dist/plugins/twenty/package.json +5 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
- package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
- package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
- package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
- package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
- package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
- package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
- package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
- package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
- package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
- package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
- package/dist/plugins/twenty/src/manifest.ts +99 -0
- package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
- package/dist/plugins/twenty/test/manifest.test.ts +12 -2
- package/dist/terraform/examples/greenfield/main.tf +90 -380
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
- package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
- package/dist/terraform/modules/app/agentcore-pi/main.tf +29 -38
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
- package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
- package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
- package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
- package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
- package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
- package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
- package/dist/terraform/modules/app/ses-email/main.tf +14 -2
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
- package/dist/terraform/modules/thinkwork/README.md +0 -1
- package/dist/terraform/modules/thinkwork/main.tf +167 -446
- package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
- package/dist/terraform/modules/thinkwork/variables.tf +55 -309
- package/dist/terraform/schema.graphql +4 -0
- package/dist/workspace-defaults/files/AGENTS.md +45 -31
- package/dist/workspace-defaults/files/CONTEXT.md +48 -4
- package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
- package/dist/workspace-defaults/files/SPACE.md +34 -19
- package/dist/workspace-defaults/files/TOOLS.md +30 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
- package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
- package/package.json +1 -1
- package/dist/plugins/company-brain/README.md +0 -37
- package/dist/plugins/company-brain/package.json +0 -33
- package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
- package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
- package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
- package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
- package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
- package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
- package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
- package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
- package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
- package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
- package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
- package/dist/plugins/company-brain/src/api/migration.ts +0 -665
- package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
- package/dist/plugins/company-brain/src/index.ts +0 -62
- package/dist/plugins/company-brain/src/manifest.ts +0 -112
- package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
- package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
- package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
- package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
- package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
- package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
- package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
- package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
- package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
- 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
|
-
}
|