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,312 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Read-only Company Brain Context Engine smoke (THNK-20 / U5a).
|
|
4
|
-
*
|
|
5
|
-
* Dry-run is the default. Set SMOKE_ENABLE_COMPANY_BRAIN_CONTEXT=1 to run live
|
|
6
|
-
* against a deployed stage. Live mode calls the existing MCP Context Engine
|
|
7
|
-
* endpoint with service auth and does not mutate production state.
|
|
8
|
-
*
|
|
9
|
-
* Live env:
|
|
10
|
-
* CONTEXT_ENGINE_MCP_URL or API_CONTEXT_ENGINE_MCP_URL
|
|
11
|
-
* Optional fallback: VITE_GRAPHQL_HTTP_URL / GRAPHQL_HTTP_URL / API_GRAPHQL_URL
|
|
12
|
-
* with /graphql replaced by /mcp/context-engine.
|
|
13
|
-
* API_AUTH_SECRET or THINKWORK_API_SECRET
|
|
14
|
-
* SMOKE_TENANT_ID=<tenant uuid>
|
|
15
|
-
* SMOKE_USER_ID=<users.id in that tenant>
|
|
16
|
-
*
|
|
17
|
-
* Optional:
|
|
18
|
-
* SMOKE_COMPANY_BRAIN_CONTEXT_QUERY="Acme renewal risk"
|
|
19
|
-
* SMOKE_COMPANY_BRAIN_EXPECTED_TERM="procurement"
|
|
20
|
-
* SMOKE_COMPANY_BRAIN_SOURCE_KIND=thread
|
|
21
|
-
* SMOKE_COMPANY_BRAIN_SOURCE_TYPE=thread_message
|
|
22
|
-
* SMOKE_COMPANY_BRAIN_DATASET_ID=<dataset/source scope>
|
|
23
|
-
* SMOKE_COMPANY_BRAIN_NODESETS=customer-success,renewals
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import fs from "node:fs";
|
|
27
|
-
import path from "node:path";
|
|
28
|
-
import process from "node:process";
|
|
29
|
-
import { attachSmokeEvidence } from "../../../scripts/smoke/deployment-evidence.mjs";
|
|
30
|
-
|
|
31
|
-
const LIVE_ENABLED = process.env.SMOKE_ENABLE_COMPANY_BRAIN_CONTEXT === "1";
|
|
32
|
-
const TIMEOUT_MS = Number(process.env.SMOKE_TIMEOUT_MS || 20_000);
|
|
33
|
-
const env = { ...loadEnvFile(), ...process.env };
|
|
34
|
-
|
|
35
|
-
const graphqlUrl = first(
|
|
36
|
-
env.VITE_GRAPHQL_HTTP_URL,
|
|
37
|
-
env.GRAPHQL_HTTP_URL,
|
|
38
|
-
env.API_GRAPHQL_URL,
|
|
39
|
-
);
|
|
40
|
-
const mcpUrl = first(
|
|
41
|
-
env.CONTEXT_ENGINE_MCP_URL,
|
|
42
|
-
env.API_CONTEXT_ENGINE_MCP_URL,
|
|
43
|
-
deriveMcpUrl(graphqlUrl),
|
|
44
|
-
);
|
|
45
|
-
const apiSecret = first(env.API_AUTH_SECRET, env.THINKWORK_API_SECRET);
|
|
46
|
-
const tenantId = first(env.SMOKE_TENANT_ID, env.TENANT_ID);
|
|
47
|
-
const userId = first(env.SMOKE_USER_ID, env.SMOKE_ADMIN_USER_ID);
|
|
48
|
-
const query = first(
|
|
49
|
-
env.SMOKE_COMPANY_BRAIN_CONTEXT_QUERY,
|
|
50
|
-
"Acme renewal risk and next best action",
|
|
51
|
-
);
|
|
52
|
-
const expectedTerm = first(env.SMOKE_COMPANY_BRAIN_EXPECTED_TERM);
|
|
53
|
-
|
|
54
|
-
const checks = [];
|
|
55
|
-
|
|
56
|
-
if (!LIVE_ENABLED) {
|
|
57
|
-
console.log(
|
|
58
|
-
JSON.stringify(
|
|
59
|
-
await attachSmokeEvidence(
|
|
60
|
-
"company-brain-context-engine",
|
|
61
|
-
{
|
|
62
|
-
ok: true,
|
|
63
|
-
skippedLive: true,
|
|
64
|
-
reason:
|
|
65
|
-
"set SMOKE_ENABLE_COMPANY_BRAIN_CONTEXT=1 to run the deployed read-only Context Engine Brain smoke",
|
|
66
|
-
dryRun: {
|
|
67
|
-
requiredWhenRunning: [
|
|
68
|
-
"CONTEXT_ENGINE_MCP_URL or GraphQL URL that can derive /mcp/context-engine",
|
|
69
|
-
"API_AUTH_SECRET or THINKWORK_API_SECRET",
|
|
70
|
-
"SMOKE_TENANT_ID",
|
|
71
|
-
"SMOKE_USER_ID",
|
|
72
|
-
],
|
|
73
|
-
optionalScope: [
|
|
74
|
-
"SMOKE_COMPANY_BRAIN_CONTEXT_QUERY",
|
|
75
|
-
"SMOKE_COMPANY_BRAIN_EXPECTED_TERM",
|
|
76
|
-
"SMOKE_COMPANY_BRAIN_SOURCE_KIND",
|
|
77
|
-
"SMOKE_COMPANY_BRAIN_SOURCE_TYPE",
|
|
78
|
-
"SMOKE_COMPANY_BRAIN_DATASET_ID",
|
|
79
|
-
"SMOKE_COMPANY_BRAIN_NODESETS",
|
|
80
|
-
],
|
|
81
|
-
verifies: [
|
|
82
|
-
"query_brain_context returns Company Brain hits through Context Engine",
|
|
83
|
-
"Brain provider status exposes active read route, shadow migration, vault provenance, and provider-local retrieval posture",
|
|
84
|
-
"Brain hits include untrusted source-data boundary metadata",
|
|
85
|
-
"Brain answer is better than memory-only for the named workflow by hit count or expected-term match",
|
|
86
|
-
"query_memory_context remains a separate Cognee-backed user/space memory path rather than an implicit Brain fallback",
|
|
87
|
-
],
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
env,
|
|
91
|
-
),
|
|
92
|
-
null,
|
|
93
|
-
2,
|
|
94
|
-
),
|
|
95
|
-
);
|
|
96
|
-
process.exit(0);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await runLiveSmoke();
|
|
101
|
-
const failed = checks.filter((check) => !check.ok);
|
|
102
|
-
console.log(
|
|
103
|
-
JSON.stringify(
|
|
104
|
-
await attachSmokeEvidence(
|
|
105
|
-
"company-brain-context-engine",
|
|
106
|
-
{
|
|
107
|
-
ok: failed.length === 0,
|
|
108
|
-
query,
|
|
109
|
-
checks,
|
|
110
|
-
},
|
|
111
|
-
env,
|
|
112
|
-
),
|
|
113
|
-
null,
|
|
114
|
-
2,
|
|
115
|
-
),
|
|
116
|
-
);
|
|
117
|
-
process.exit(failed.length === 0 ? 0 : 1);
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error(
|
|
120
|
-
JSON.stringify(
|
|
121
|
-
await attachSmokeEvidence(
|
|
122
|
-
"company-brain-context-engine",
|
|
123
|
-
{
|
|
124
|
-
ok: false,
|
|
125
|
-
query,
|
|
126
|
-
error: error instanceof Error ? error.message : String(error),
|
|
127
|
-
checks,
|
|
128
|
-
},
|
|
129
|
-
env,
|
|
130
|
-
),
|
|
131
|
-
null,
|
|
132
|
-
2,
|
|
133
|
-
),
|
|
134
|
-
);
|
|
135
|
-
process.exit(1);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async function runLiveSmoke() {
|
|
139
|
-
requireEnv("CONTEXT_ENGINE_MCP_URL", mcpUrl);
|
|
140
|
-
requireEnv("API_AUTH_SECRET or THINKWORK_API_SECRET", apiSecret);
|
|
141
|
-
requireEnv("SMOKE_TENANT_ID", tenantId);
|
|
142
|
-
requireEnv("SMOKE_USER_ID", userId);
|
|
143
|
-
|
|
144
|
-
const brain = await callTool("query_brain_context", {
|
|
145
|
-
query,
|
|
146
|
-
mode: "answer",
|
|
147
|
-
scope: "team",
|
|
148
|
-
limit: 5,
|
|
149
|
-
sourceKind: first(env.SMOKE_COMPANY_BRAIN_SOURCE_KIND),
|
|
150
|
-
sourceType: first(env.SMOKE_COMPANY_BRAIN_SOURCE_TYPE),
|
|
151
|
-
datasetId: first(env.SMOKE_COMPANY_BRAIN_DATASET_ID),
|
|
152
|
-
nodeSetIds: csv(env.SMOKE_COMPANY_BRAIN_NODESETS),
|
|
153
|
-
onlyContext: true,
|
|
154
|
-
});
|
|
155
|
-
const memory = await callTool("query_memory_context", {
|
|
156
|
-
query,
|
|
157
|
-
mode: "answer",
|
|
158
|
-
scope: "personal",
|
|
159
|
-
limit: 5,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const brainContent = brain.result?.structuredContent;
|
|
163
|
-
const memoryContent = memory.result?.structuredContent;
|
|
164
|
-
const brainHits = Array.isArray(brainContent?.hits) ? brainContent.hits : [];
|
|
165
|
-
const memoryHits = Array.isArray(memoryContent?.hits)
|
|
166
|
-
? memoryContent.hits
|
|
167
|
-
: [];
|
|
168
|
-
const brainProviders = Array.isArray(brainContent?.providers)
|
|
169
|
-
? brainContent.providers
|
|
170
|
-
: [];
|
|
171
|
-
const brainProvider = brainProviders.find(
|
|
172
|
-
(provider) => provider.providerId === "brain",
|
|
173
|
-
);
|
|
174
|
-
const brainText = JSON.stringify(brain.result ?? {});
|
|
175
|
-
|
|
176
|
-
assert("Brain provider returns at least one hit", brainHits.length > 0, {
|
|
177
|
-
brainHitCount: brainHits.length,
|
|
178
|
-
});
|
|
179
|
-
assert(
|
|
180
|
-
"Brain provider exposes provider-local status",
|
|
181
|
-
Boolean(brainProvider),
|
|
182
|
-
{ providers: brainProviders },
|
|
183
|
-
);
|
|
184
|
-
assert(
|
|
185
|
-
"Brain provider exposes migration-aware read posture",
|
|
186
|
-
Boolean(
|
|
187
|
-
brainProvider?.metadata?.readPosture?.active?.role === "active" &&
|
|
188
|
-
brainProvider.metadata.readPosture.vault?.role === "vault",
|
|
189
|
-
),
|
|
190
|
-
{ readPosture: brainProvider?.metadata?.readPosture ?? null },
|
|
191
|
-
);
|
|
192
|
-
assert(
|
|
193
|
-
"Brain hits carry untrusted source-data boundaries",
|
|
194
|
-
brainHits.every(
|
|
195
|
-
(hit) =>
|
|
196
|
-
hit?.metadata?.sourceDataPolicy ||
|
|
197
|
-
hit?.provenance?.metadata?.instructionBoundary ===
|
|
198
|
-
"untrusted_source_data",
|
|
199
|
-
),
|
|
200
|
-
{ sampleHit: brainHits[0] ?? null },
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
const betterByCount = brainHits.length > memoryHits.length;
|
|
204
|
-
const betterByTerm = expectedTerm
|
|
205
|
-
? brainText.toLowerCase().includes(expectedTerm.toLowerCase())
|
|
206
|
-
: false;
|
|
207
|
-
assert(
|
|
208
|
-
"Brain answer is materially better than memory-only for named workflow",
|
|
209
|
-
betterByCount || betterByTerm,
|
|
210
|
-
{
|
|
211
|
-
brainHitCount: brainHits.length,
|
|
212
|
-
memoryHitCount: memoryHits.length,
|
|
213
|
-
expectedTerm: expectedTerm ?? null,
|
|
214
|
-
betterByCount,
|
|
215
|
-
betterByTerm,
|
|
216
|
-
},
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async function callTool(name, args) {
|
|
221
|
-
const body = {
|
|
222
|
-
jsonrpc: "2.0",
|
|
223
|
-
id: name,
|
|
224
|
-
method: "tools/call",
|
|
225
|
-
params: {
|
|
226
|
-
name,
|
|
227
|
-
arguments: Object.fromEntries(
|
|
228
|
-
Object.entries(args).filter(
|
|
229
|
-
([, value]) =>
|
|
230
|
-
value !== undefined &&
|
|
231
|
-
value !== null &&
|
|
232
|
-
(!Array.isArray(value) || value.length > 0),
|
|
233
|
-
),
|
|
234
|
-
),
|
|
235
|
-
},
|
|
236
|
-
};
|
|
237
|
-
const response = await fetch(mcpUrl, {
|
|
238
|
-
method: "POST",
|
|
239
|
-
headers: {
|
|
240
|
-
"Content-Type": "application/json",
|
|
241
|
-
Authorization: `Bearer ${apiSecret}`,
|
|
242
|
-
"x-tenant-id": tenantId,
|
|
243
|
-
"x-user-id": userId,
|
|
244
|
-
},
|
|
245
|
-
body: JSON.stringify(body),
|
|
246
|
-
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
247
|
-
});
|
|
248
|
-
const payload = await response.json().catch(() => ({}));
|
|
249
|
-
if (!response.ok || payload.error) {
|
|
250
|
-
throw new Error(
|
|
251
|
-
`${name} failed: ${JSON.stringify(payload.error ?? payload)}`,
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
return payload;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function assert(name, ok, details = {}) {
|
|
258
|
-
checks.push({ name, ok, ...details });
|
|
259
|
-
if (!ok) {
|
|
260
|
-
throw new Error(`${name} failed`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function requireEnv(name, value) {
|
|
265
|
-
if (!value) throw new Error(`${name} is required`);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function deriveMcpUrl(url) {
|
|
269
|
-
if (!url) return null;
|
|
270
|
-
try {
|
|
271
|
-
const parsed = new URL(url);
|
|
272
|
-
parsed.pathname = parsed.pathname.replace(/\/graphql\/?$/, "");
|
|
273
|
-
parsed.pathname = `${parsed.pathname.replace(/\/$/, "")}/mcp/context-engine`;
|
|
274
|
-
parsed.search = "";
|
|
275
|
-
parsed.hash = "";
|
|
276
|
-
return parsed.toString();
|
|
277
|
-
} catch {
|
|
278
|
-
return null;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function csv(value) {
|
|
283
|
-
return value
|
|
284
|
-
? value
|
|
285
|
-
.split(",")
|
|
286
|
-
.map((item) => item.trim())
|
|
287
|
-
.filter(Boolean)
|
|
288
|
-
: undefined;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
function first(...values) {
|
|
292
|
-
return values
|
|
293
|
-
.find((value) => typeof value === "string" && value.trim())
|
|
294
|
-
?.trim();
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function loadEnvFile() {
|
|
298
|
-
const candidates = [
|
|
299
|
-
path.resolve("apps/web/.env"),
|
|
300
|
-
path.resolve("terraform/examples/greenfield/.env"),
|
|
301
|
-
];
|
|
302
|
-
const output = {};
|
|
303
|
-
for (const file of candidates) {
|
|
304
|
-
if (!fs.existsSync(file)) continue;
|
|
305
|
-
for (const line of fs.readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
306
|
-
const match = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*)\s*$/);
|
|
307
|
-
if (!match) continue;
|
|
308
|
-
output[match[1]] = match[2].replace(/^['"]|['"]$/g, "");
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
return output;
|
|
312
|
-
}
|