74 lines
3.7 KiB
TypeScript
74 lines
3.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
const route = readFileSync(new URL("../src/app/api/consult/route.ts", import.meta.url), "utf8");
|
|
const reportsRoute = readFileSync(new URL("../src/app/api/reports/route.ts", import.meta.url), "utf8");
|
|
const mastra = readFileSync(new URL("../src/mastra/index.ts", import.meta.url), "utf8");
|
|
const tools = readFileSync(new URL("../src/mastra/consultation-tools.ts", import.meta.url), "utf8");
|
|
const workflow = readFileSync(new URL("../src/mastra/consultation-workflow.ts", import.meta.url), "utf8");
|
|
const stagingCompose = readFileSync(new URL("../../deploy/docker-compose.staging.yml", import.meta.url), "utf8");
|
|
|
|
test("personal consultation lets the Agent invoke the server-bound workflow tool", () => {
|
|
const agenticStart = route.indexOf("async function runAgenticConsultation");
|
|
const agenticBranch = route.slice(
|
|
agenticStart,
|
|
route.indexOf(" const { history } = parsed.data;", agenticStart),
|
|
);
|
|
assert.match(agenticBranch, /createConsultationAgentContext/);
|
|
assert.match(agenticBranch, /getJyotishAgent\(selectedModel, agentContext\)/);
|
|
assert.doesNotMatch(agenticBranch, /await runConsultationWorkflow/);
|
|
assert.doesNotMatch(agenticBranch, /JSON\.stringify\(toolInput\)/);
|
|
assert.match(tools, /\(ctx\.runWorkflow \?\? runConsultationWorkflow\)\(toolInput, \{/);
|
|
assert.match(tools, /return \{ "run-jyotish-consultation": consultationTool \};/);
|
|
assert.match(agenticBranch, /state\.workflowReceipt\?\.preciseTiming === "allowed"/);
|
|
});
|
|
|
|
test("defers optional external evidence only for foreground chat", () => {
|
|
assert.match(workflow, /defer_optional_external_evidence: options\?\.foreground === true/);
|
|
assert.match(reportsRoute, /runWorkflow: \(input\) => runConsultationWorkflow\(input\)/);
|
|
assert.doesNotMatch(reportsRoute, /foreground:\s*true/);
|
|
});
|
|
|
|
test("personal Agent owns the Skill and context-bound calculation tool", () => {
|
|
const personalFactory = mastra.slice(
|
|
mastra.indexOf("export function getJyotishAgent"),
|
|
mastra.indexOf("export function getLegacyJyotishAgent"),
|
|
);
|
|
assert.match(personalFactory, /getJyotishAgent\(model: ResolvedLanguageModel, context: ConsultationAgentContext\)/);
|
|
assert.match(personalFactory, /skills: \[jyotishSkillPath\]/);
|
|
assert.match(personalFactory, /tools: createConsultationTools\(context\)/);
|
|
assert.doesNotMatch(personalFactory, /server-computed-jyotish-workflow/);
|
|
});
|
|
|
|
test("validates and emits non-sensitive workflow and execution receipts", () => {
|
|
assert.match(workflow, /consultationWorkflowResponseSchema/);
|
|
assert.match(workflow, /safeParse\(data\)/);
|
|
assert.match(workflow, /consultationWorkflowReceipt/);
|
|
assert.match(route, /agentExecutionReceipt/);
|
|
assert.match(route, /streamAgentResponse/);
|
|
});
|
|
|
|
test("carries commercial technique truth into the model contract", () => {
|
|
assert.match(workflow, /technique_truth/);
|
|
assert.match(mastra, /deterministic_claims_forbidden_for/);
|
|
assert.match(mastra, /reference_only/);
|
|
assert.match(mastra, /Do not use a restricted technique/);
|
|
});
|
|
|
|
test("projects consultation themes through explicit strict workflow taxonomy", () => {
|
|
const projection = readFileSync(new URL("../src/lib/consultation-workflow-request.ts", import.meta.url), "utf8");
|
|
assert.match(projection, /strictWorkflowRoute/);
|
|
assert.match(projection, /claimBoundary/);
|
|
assert.match(projection, /requiredLayers/);
|
|
assert.match(projection, /negative holdout gate/);
|
|
});
|
|
|
|
|
|
test("staging enables the agentic consultation runtime without changing production compose", () => {
|
|
assert.match(stagingCompose, /CONSULTATION_AGENTIC_RUNTIME: enabled/);
|
|
assert.match(route, /CONSULTATION_AGENTIC_RUNTIME/);
|
|
assert.match(route, /legacy/);
|
|
assert.match(route, /canary/);
|
|
});
|