426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
185 lines
5.8 KiB
TypeScript
185 lines
5.8 KiB
TypeScript
/**
|
|
* Test fixture run as a child process by the smithers-runtime suite: executes a
|
|
* workflow through `runWorkflowWithSmithers` and prints a prefixed result line the
|
|
* parent parses. Exercises the real Smithers execution adapter.
|
|
*/
|
|
import { writeFile } from 'node:fs/promises';
|
|
import {
|
|
runWorkflowWithSmithers,
|
|
type SmithersExecutionPlan,
|
|
type SmithersWorkflowRunOptions,
|
|
} from '../../src/services/smithers-runtime';
|
|
import type { WorkflowDefinition, WorkflowExecution, WorkflowNode } from '../../src/types/index';
|
|
|
|
const RESULT_PREFIX = 'SMITHERS_RUNTIME_CASE_RESULT ';
|
|
|
|
type RunNode = SmithersWorkflowRunOptions['runNode'];
|
|
type NodeInput = Parameters<RunNode>[1];
|
|
|
|
interface RunDataEntry {
|
|
data: { main: Array<Array<{ json: Record<string, unknown> }>> };
|
|
}
|
|
|
|
function node(name: string, extra: Partial<WorkflowNode> = {}): WorkflowNode {
|
|
return { name, type: 'test.node', typeVersion: 1, position: [0, 0], parameters: {}, ...extra };
|
|
}
|
|
|
|
function pendingExecution(workflowId: string): WorkflowExecution {
|
|
return {
|
|
id: `exec-${workflowId}`,
|
|
finished: false,
|
|
mode: 'manual',
|
|
startedAt: new Date().toISOString(),
|
|
workflowId,
|
|
status: 'running',
|
|
};
|
|
}
|
|
|
|
function run(
|
|
id: string,
|
|
nodes: WorkflowNode[],
|
|
plan: SmithersExecutionPlan,
|
|
runNode: RunNode
|
|
): Promise<WorkflowExecution> {
|
|
const uid = `${id}-${Math.random().toString(36).slice(2, 10)}`;
|
|
const workflow: WorkflowDefinition = { id: uid, name: uid, nodes, connections: {} };
|
|
return runWorkflowWithSmithers({
|
|
workflow,
|
|
executionId: `run-${uid}`,
|
|
pending: pendingExecution(uid),
|
|
mode: 'manual',
|
|
triggerData: {},
|
|
plan,
|
|
runNode,
|
|
});
|
|
}
|
|
|
|
async function fanoutCase(): Promise<Record<string, unknown>> {
|
|
const calls: string[] = [];
|
|
const inputs = new Map<string, NodeInput>();
|
|
const nodes = [node('trigger'), node('A'), node('B'), node('C')];
|
|
const plan: SmithersExecutionPlan = {
|
|
enabledNodes: nodes,
|
|
startNodes: ['trigger'],
|
|
incoming: {
|
|
A: [{ source: 'trigger', sourceOutputIndex: 0, destinationInputIndex: 0 }],
|
|
B: [{ source: 'trigger', sourceOutputIndex: 0, destinationInputIndex: 0 }],
|
|
C: [
|
|
{ source: 'A', sourceOutputIndex: 0, destinationInputIndex: 0 },
|
|
{ source: 'B', sourceOutputIndex: 0, destinationInputIndex: 1 },
|
|
],
|
|
},
|
|
};
|
|
const result = await run('wf-fanout', nodes, plan, async (n, inputData) => {
|
|
calls.push(n.name);
|
|
inputs.set(n.name, inputData);
|
|
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
return [[{ json: { node: n.name } }]];
|
|
});
|
|
const cInput = inputs.get('C');
|
|
return {
|
|
status: result.status,
|
|
finished: result.finished,
|
|
calls: [...calls].sort(),
|
|
lastNodeExecuted: result.data?.resultData?.lastNodeExecuted,
|
|
cInput0: cInput?.[0]?.[0]?.json,
|
|
cInput1: cInput?.[1]?.[0]?.json,
|
|
engine: result.data?.resultData?.engine,
|
|
};
|
|
}
|
|
|
|
async function retryCase(): Promise<Record<string, unknown>> {
|
|
let attempts = 0;
|
|
const nodes = [
|
|
node('trigger'),
|
|
node('R', { retryOnFail: true, maxTries: 3, waitBetweenTries: 1 }),
|
|
];
|
|
const plan: SmithersExecutionPlan = {
|
|
enabledNodes: nodes,
|
|
startNodes: ['trigger'],
|
|
incoming: { R: [{ source: 'trigger', sourceOutputIndex: 0, destinationInputIndex: 0 }] },
|
|
};
|
|
const result = await run('wf-retry', nodes, plan, async (n) => {
|
|
if (n.name === 'R') {
|
|
attempts += 1;
|
|
if (attempts < 2) throw new Error('transient');
|
|
}
|
|
return [[{ json: { node: n.name } }]];
|
|
});
|
|
return {
|
|
attempts,
|
|
status: result.status,
|
|
retries: result.data?.resultData?.engine?.retries,
|
|
};
|
|
}
|
|
|
|
async function continueCase(): Promise<Record<string, unknown>> {
|
|
const nodes = [node('trigger'), node('F', { continueOnFail: true })];
|
|
const plan: SmithersExecutionPlan = {
|
|
enabledNodes: nodes,
|
|
startNodes: ['trigger'],
|
|
incoming: { F: [{ source: 'trigger', sourceOutputIndex: 0, destinationInputIndex: 0 }] },
|
|
};
|
|
const result = await run('wf-continue', nodes, plan, async (n) => {
|
|
if (n.name === 'F') throw new Error('boom');
|
|
return [[{ json: { node: n.name } }]];
|
|
});
|
|
const fRun = result.data?.resultData?.runData?.F as RunDataEntry[] | undefined;
|
|
return {
|
|
status: result.status,
|
|
errorItem: fRun?.[0]?.data.main[0][0].json.error,
|
|
};
|
|
}
|
|
|
|
async function failCase(): Promise<Record<string, unknown>> {
|
|
const nodes = [node('trigger'), node('X')];
|
|
const plan: SmithersExecutionPlan = {
|
|
enabledNodes: nodes,
|
|
startNodes: ['trigger'],
|
|
incoming: { X: [{ source: 'trigger', sourceOutputIndex: 0, destinationInputIndex: 0 }] },
|
|
};
|
|
try {
|
|
await run('wf-fail', nodes, plan, async (n) => {
|
|
if (n.name === 'X') throw new Error('fatal');
|
|
return [[{ json: { node: n.name } }]];
|
|
});
|
|
} catch (error) {
|
|
return {
|
|
threw: true,
|
|
message: error instanceof Error ? error.message : String(error),
|
|
};
|
|
}
|
|
return { threw: false };
|
|
}
|
|
|
|
const cases: Record<string, () => Promise<Record<string, unknown>>> = {
|
|
fanout: fanoutCase,
|
|
retry: retryCase,
|
|
continue: continueCase,
|
|
fail: failCase,
|
|
};
|
|
|
|
const caseName = process.argv[2];
|
|
const selected = caseName ? cases[caseName] : undefined;
|
|
|
|
async function writeResult(result: Record<string, unknown>): Promise<void> {
|
|
const serialized = JSON.stringify(result);
|
|
const outputPath = process.env.SMITHERS_RUNTIME_CASE_OUTPUT;
|
|
if (outputPath) await writeFile(outputPath, serialized, 'utf8');
|
|
process.stdout.write(`${RESULT_PREFIX}${serialized}\n`);
|
|
}
|
|
|
|
if (!selected) {
|
|
process.stderr.write(`Unknown Smithers runtime case: ${caseName ?? '<missing>'}\n`);
|
|
process.exitCode = 2;
|
|
} else {
|
|
try {
|
|
const result = await selected();
|
|
await writeResult(result);
|
|
} catch (error) {
|
|
process.stderr.write(error instanceof Error ? (error.stack ?? error.message) : String(error));
|
|
process.stderr.write('\n');
|
|
process.exitCode = 1;
|
|
}
|
|
}
|