baa-conductor


baa-conductor / apps / conductor-daemon / src / instructions
codex@macbookpro  ·  2026-04-01

normalize.ts

 1import {
 2  buildBaaInstructionDedupeBasis,
 3  buildBaaInstructionDedupeKey,
 4  buildBaaInstructionId
 5} from "./dedupe.js";
 6import type {
 7  BaaInstructionEnvelope,
 8  BaaInstructionSourceMessage,
 9  BaaParsedInstruction
10} from "./types.js";
11
12function requireNonEmptyField(name: string, value: string): string {
13  const normalized = value.trim();
14
15  if (normalized === "") {
16    throw new Error(`${name} must be a non-empty string.`);
17  }
18
19  return normalized;
20}
21
22function normalizeOptionalStringField(value: string | null): string | null {
23  if (value == null) {
24    return null;
25  }
26
27  const normalized = value.trim();
28  return normalized === "" ? null : normalized;
29}
30
31export function normalizeBaaInstructionSourceMessage(
32  source: BaaInstructionSourceMessage
33): BaaInstructionSourceMessage {
34  return {
35    assistantMessageId: requireNonEmptyField("assistantMessageId", source.assistantMessageId),
36    conversationId: normalizeOptionalStringField(source.conversationId),
37    platform: requireNonEmptyField("platform", source.platform)
38  };
39}
40
41export function normalizeBaaInstruction(
42  source: BaaInstructionSourceMessage,
43  instruction: BaaParsedInstruction
44): BaaInstructionEnvelope {
45  const normalizedSource = normalizeBaaInstructionSourceMessage(source);
46  const dedupeBasis = buildBaaInstructionDedupeBasis(normalizedSource, instruction);
47  const dedupeKey = buildBaaInstructionDedupeKey(dedupeBasis);
48
49  return {
50    assistantMessageId: normalizedSource.assistantMessageId,
51    blockIndex: instruction.blockIndex,
52    conversationId: normalizedSource.conversationId,
53    dedupeBasis,
54    dedupeKey,
55    envelopeVersion: "baa.v1",
56    instructionId: buildBaaInstructionId(dedupeKey),
57    params: instruction.params,
58    paramsKind: instruction.paramsKind,
59    platform: normalizedSource.platform,
60    rawBlock: instruction.rawBlock,
61    rawInstruction: instruction.rawInstruction,
62    target: instruction.target,
63    tool: instruction.tool
64  };
65}