@opengeni/interaction 4.4.1 → 4.5.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.
@@ -119,6 +119,10 @@ export type InteractionControllerCoreOptions<TCommand extends InteractionCoreCom
119
119
  * The callback must bind every non-secret semantic input while excluding the
120
120
  * value bytes themselves and return lowercase SHA-256. */
121
121
  commandDigest?: (command: TCommand) => string;
122
+ /** Operator logging for a dispatch that threw something the driver did not
123
+ * classify. The caller still sees only outcome_unknown; this hook keeps the
124
+ * cause from disappearing. It never changes the operation's outcome. */
125
+ onUnexpectedDispatchError?: (error: unknown, command: TCommand) => void;
122
126
  };
123
127
  /**
124
128
  * Resource-neutral placement mutation authority. Public Browser and Computer
@@ -133,6 +137,7 @@ export declare class InteractionControllerCore<TCommand extends InteractionCoreC
133
137
  private readonly now;
134
138
  private readonly onJournalRecord;
135
139
  private readonly commandDigest;
140
+ private readonly onUnexpectedDispatchError;
136
141
  private readonly loadJournalRecord;
137
142
  private readonly journal;
138
143
  private readonly targetTails;
package/dist/index.d.ts CHANGED
@@ -23,6 +23,8 @@ export type BrowserInteractionControllerOptions = {
23
23
  onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;
24
24
  /** Reads the same durable authority as onJournalRecord and initialJournal. */
25
25
  loadJournalRecord?: (operationId: string) => BrowserOperationJournalRecord | null;
26
+ /** Operator logging for a dispatch error the driver did not classify. */
27
+ onUnexpectedDispatchError?: (error: unknown, command: BrowserActionCommandValue) => void;
26
28
  };
27
29
  /** Placement-resident BrowserSession mutation authority. */
28
30
  export declare class BrowserInteractionController {
@@ -61,6 +63,8 @@ export type ComputerInteractionControllerOptions = {
61
63
  onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;
62
64
  /** Reads the same durable authority as onJournalRecord and initialJournal. */
63
65
  loadJournalRecord?: (operationId: string) => ComputerOperationJournalRecord | null;
66
+ /** Operator logging for a dispatch error the driver did not classify. */
67
+ onUnexpectedDispatchError?: (error: unknown, command: ComputerOperationCommand) => void;
64
68
  };
65
69
  /** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,
66
70
  * macOS AX/ScreenCaptureKit, and later UIA adapters share this exact core. */
package/dist/index.js CHANGED
@@ -72,6 +72,7 @@ var InteractionControllerCore = class {
72
72
  now;
73
73
  onJournalRecord;
74
74
  commandDigest;
75
+ onUnexpectedDispatchError;
75
76
  loadJournalRecord;
76
77
  journal = /* @__PURE__ */ new Map();
77
78
  targetTails = /* @__PURE__ */ new Map();
@@ -84,6 +85,7 @@ var InteractionControllerCore = class {
84
85
  this.onJournalRecord = options.onJournalRecord;
85
86
  this.loadJournalRecord = options.loadJournalRecord;
86
87
  this.commandDigest = options.commandDigest ?? digestJson;
88
+ this.onUnexpectedDispatchError = options.onUnexpectedDispatchError;
87
89
  if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {
88
90
  throw new Error("maxJournalEntries must be a positive safe integer");
89
91
  }
@@ -288,6 +290,10 @@ var InteractionControllerCore = class {
288
290
  )
289
291
  );
290
292
  }
293
+ try {
294
+ this.onUnexpectedDispatchError?.(error, command);
295
+ } catch {
296
+ }
291
297
  return await this.settle(
292
298
  entry,
293
299
  this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
@@ -551,6 +557,7 @@ var BrowserInteractionController = class {
551
557
  ...options.initialJournal ? { initialJournal: options.initialJournal } : {},
552
558
  ...options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {},
553
559
  ...options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {},
560
+ ...options.onUnexpectedDispatchError ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError } : {},
554
561
  commandDigest: (command) => secretFreeCommandDigest(command),
555
562
  adapter: {
556
563
  resourceLabel: "browser",
@@ -732,6 +739,7 @@ var ComputerInteractionController = class {
732
739
  ...options.initialJournal ? { initialJournal: options.initialJournal } : {},
733
740
  ...options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {},
734
741
  ...options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {},
742
+ ...options.onUnexpectedDispatchError ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError } : {},
735
743
  commandDigest: (command) => secretFreeCommandDigest(command),
736
744
  adapter: {
737
745
  resourceLabel: "computer",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/controller-core.ts","../src/native-result.ts"],"sourcesContent":["import {\n BrowserActionCommand,\n BrowserActionReceipt,\n INTERACTION_MAX_RESOLVED_ACTION_TARGETS,\n BrowserObservation,\n BrowserTarget,\n ComputerNativeCommand,\n ComputerNativeReceipt,\n ComputerOperationCommand,\n ComputerOperationReceipt,\n ComputerOperationObservation,\n type ComputerNativeResult,\n ComputerActionCommand,\n ComputerObservation,\n ComputerTarget,\n type BrowserActionCommand as BrowserActionCommandValue,\n type BrowserActionReceipt as BrowserActionReceiptValue,\n type BrowserObservation as BrowserObservationValue,\n type BrowserTarget as BrowserTargetValue,\n type ComputerActionCommand as ComputerActionCommandValue,\n type ComputerActionReceipt as ComputerActionReceiptValue,\n type ComputerObservation as ComputerObservationValue,\n type ComputerTarget as ComputerTargetValue,\n} from \"@opengeni/contracts\";\nimport {\n InteractionControllerCore,\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n recoverInteractionReceipt,\n secretFreeCommandDigest,\n type InteractionControllerErrorCode,\n type InteractionDispatchTrace,\n type InteractionOperationJournalRecord,\n} from \"./controller-core\";\n\nexport {\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n secretFreeCommandDigest,\n type InteractionControllerErrorCode,\n type InteractionDispatchTrace,\n};\n\nexport type BrowserInteractionDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserObservationValue>;\n validate?(command: BrowserActionCommandValue, target: BrowserTargetValue): Promise<void> | void;\n /** Drivers that resolve locators record each resolved element on `trace`. */\n dispatch(\n command: BrowserActionCommandValue,\n trace?: InteractionDispatchTrace,\n ): Promise<BrowserObservationValue | null>;\n};\n\nexport type BrowserInteractionAuthority = {\n authorizeDispatch(command: BrowserActionCommandValue): Promise<void> | void;\n};\n\nexport type BrowserOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserActionReceiptValue>;\n\nexport type BrowserInteractionControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserInteractionDriver;\n authority?: BrowserInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<BrowserOperationJournalRecord>;\n onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;\n /** Reads the same durable authority as onJournalRecord and initialJournal. */\n loadJournalRecord?: (operationId: string) => BrowserOperationJournalRecord | null;\n};\n\n/** Placement-resident BrowserSession mutation authority. */\nexport class BrowserInteractionController {\n private readonly core: InteractionControllerCore<\n BrowserActionCommandValue,\n BrowserTargetValue,\n BrowserObservationValue,\n BrowserActionReceiptValue\n >;\n\n constructor(options: BrowserInteractionControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),\n commandDigest: (command) => secretFreeCommandDigest(command),\n adapter: {\n resourceLabel: \"browser\",\n parseCommand: (value) => BrowserActionCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserObservation.parse(value),\n parseReceipt: (value) => BrowserActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"browser command targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before the command could dispatch\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.browserSessionId !== browserSessionId ||\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"browser driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n maxDispatchTraceItems: INTERACTION_MAX_RESOLVED_ACTION_TARGETS,\n attachDispatchTrace(receipt, items) {\n return BrowserActionReceipt.parse({ ...receipt, targets: items });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<BrowserObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: BrowserActionCommandValue): Promise<BrowserActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n isIdle(): boolean {\n return this.core.isIdle();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserOperationJournalRecord(\n record: BrowserOperationJournalRecord,\n settledAt: string,\n): BrowserOperationJournalRecord {\n const receipt = BrowserActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n ),\n };\n}\n\n/** Deterministic JSON with sorted object keys and undefined entries dropped. */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport type ComputerInteractionDriver = {\n target(targetId: string): Promise<ComputerTargetValue | null>;\n observe(targetId: string): Promise<ComputerObservationValue>;\n validate?(command: ComputerActionCommandValue, target: ComputerTargetValue): Promise<void> | void;\n dispatch(command: ComputerActionCommandValue): Promise<ComputerObservationValue | null>;\n validateNative?(command: ComputerNativeCommand): Promise<void>;\n dispatchNative?(command: ComputerNativeCommand): Promise<ComputerNativeResult>;\n};\n\nexport type ComputerInteractionAuthority = {\n authorizeDispatch(command: ComputerOperationCommand): Promise<void> | void;\n};\n\nexport type ComputerOperationJournalRecord =\n InteractionOperationJournalRecord<ComputerOperationReceipt>;\n\nexport type ComputerInteractionControllerOptions = {\n computerSessionId: string;\n controllerGeneration: string;\n driver: ComputerInteractionDriver;\n authority?: ComputerInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<ComputerOperationJournalRecord>;\n onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;\n /** Reads the same durable authority as onJournalRecord and initialJournal. */\n loadJournalRecord?: (operationId: string) => ComputerOperationJournalRecord | null;\n};\n\n/** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,\n * macOS AX/ScreenCaptureKit, and later UIA adapters share this exact core. */\nexport class ComputerInteractionController {\n // Ephemeral causal metadata, never reconstructed from a terminal receipt.\n // Native input additionally verifies and consumes its exact delivery proof.\n private readonly firstClicks = new Map<string, ComputerActionCommandValue>();\n private readonly core: InteractionControllerCore<\n ComputerOperationCommand,\n ComputerTargetValue,\n ComputerOperationObservation,\n ComputerOperationReceipt\n >;\n\n constructor(options: ComputerInteractionControllerOptions) {\n const { computerSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: {\n target: (id) => options.driver.target(id),\n observe: (id) => options.driver.observe(id),\n validate: (command, target) => {\n if (command.targetId !== null) return options.driver.validate?.(command, target);\n },\n validateSession: async (command) => {\n if (\n command.targetId !== null ||\n !options.driver.validateNative ||\n !options.driver.dispatchNative\n )\n throw new InteractionControllerError(\n \"unsupported\",\n \"Native CUA calls require a CUA ComputerSession\",\n );\n await options.driver.validateNative(command);\n },\n dispatch: (command) =>\n command.targetId === null\n ? options.driver.dispatchNative!(command)\n : options.driver.dispatch(command),\n },\n authority: {\n authorizeDispatch: async (command) => {\n await options.authority?.authorizeDispatch(command);\n if (command.targetId === null) return;\n if (\n command.action.type === \"pointer\" &&\n command.action.action === \"click\" &&\n (command.action.clickCount ?? 1) === 1\n ) {\n // Only a journal-admitted command reaches dispatch authority.\n // Conflicting retries cannot replace an earlier operation's kind.\n this.firstClicks.set(command.operationId, ComputerActionCommand.parse(command));\n while (this.firstClicks.size > 512) {\n this.firstClicks.delete(this.firstClicks.keys().next().value!);\n }\n }\n if (command.action.type !== \"pointer\" || command.action.clickCount !== 2) return;\n const firstId = command.action.continuationOfOperationId;\n const first = firstId ? this.firstClicks.get(firstId) : null;\n const receipt = firstId ? this.core.receipt(firstId) : null;\n if (\n !first ||\n receipt?.state !== \"completed\" ||\n first.computerSessionId !== command.computerSessionId ||\n first.controllerGeneration !== command.controllerGeneration ||\n first.targetId !== command.targetId ||\n first.expectedTargetGeneration !== command.expectedTargetGeneration ||\n JSON.stringify(first.actor) !== JSON.stringify(command.actor)\n ) {\n throw new InteractionControllerError(\n \"invalid_action\",\n \"click continuation requires its exact completed first click\",\n );\n }\n },\n },\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),\n commandDigest: (command) => secretFreeCommandDigest(command),\n adapter: {\n resourceLabel: \"computer\",\n parseCommand: (value) => ComputerOperationCommand.parse(value),\n parseTarget: (value) => ComputerTarget.parse(value),\n parseObservation: (value) => ComputerOperationObservation.parse(value),\n parseReceipt: (value) => ComputerOperationReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.computerSessionId !== computerSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"computer command targets another computer session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.computerSessionId !== computerSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.targetId === null) return;\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"computer target changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (observation.target === null) {\n if (\n targetId !== null ||\n observation.computerSessionId !== computerSessionId ||\n observation.controllerGeneration !== controllerGeneration\n )\n throw new InteractionControllerError(\n \"driver_failed\",\n \"native result belongs to another computer controller\",\n );\n return;\n }\n if (\n observation.computerSessionId !== computerSessionId ||\n observation.target.id !== targetId ||\n observation.target.computerSessionId !== computerSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"computer driver returned an observation outside controller authority\",\n );\n }\n },\n assertActionObservationAuthority(observation, command) {\n // An action that opened a window (a launch, a new document, a\n // dialog) returns that window, which is not the window the command\n // named, so any target of this controller.\n this.assertObservationAuthority(observation, observation.target?.id ?? command.targetId);\n },\n outcome(observation) {\n return observation.target === null\n ? { state: observation.outcome, error: observation.error }\n : { state: \"completed\", error: null };\n },\n makeReceipt(input) {\n return ComputerOperationReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n computerSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.computerSessionId !== computerSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerOperationReceipt.parse(value),\n );\n },\n },\n });\n }\n\n async observe(targetId: string): Promise<ComputerObservationValue> {\n return ComputerObservation.parse(await this.core.observe(targetId));\n }\n\n run(command: ComputerActionCommandValue): Promise<ComputerActionReceiptValue> {\n // The command discriminant fixes the receipt variant; retain replay Promise identity.\n return this.core.run(command) as Promise<ComputerActionReceiptValue>;\n }\n\n runNative(command: ComputerNativeCommand): Promise<ComputerNativeReceipt> {\n return this.core.run(command) as Promise<ComputerNativeReceipt>;\n }\n\n receipt(operationId: string): ComputerOperationReceipt | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): ComputerOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n isIdle(): boolean {\n return this.core.isIdle();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverComputerOperationJournalRecord(\n record: ComputerOperationJournalRecord,\n settledAt: string,\n): ComputerOperationJournalRecord {\n const receipt = ComputerOperationReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerOperationReceipt.parse(value),\n ),\n };\n}\nexport { boundComputerNativeReceipt } from \"./native-result\";\n","import { createHash } from \"node:crypto\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport type { InteractionError, InteractionOperationState } from \"@opengeni/contracts\";\n\nexport type InteractionControllerErrorCode = InteractionError[\"code\"] | \"journal_full\";\n\n/** A safe, typed rejection known not to have dispatched a side effect. */\nexport class InteractionControllerError extends Error {\n constructor(\n readonly code: InteractionControllerErrorCode,\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionControllerError\";\n }\n}\n\n/** Driver proof that a dispatched command definitively failed without an ambiguous outcome. */\nexport class InteractionDefiniteDriverError extends Error {\n /** Optional page or screen state the driver observed after the failure, so\n * the caller can act on it without another observation round trip. */\n observation: unknown = null;\n /** Optional structured facts about the failure, kept in the receipt's error. */\n details: InteractionError[\"details\"] = undefined;\n\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionDefiniteDriverError\";\n }\n}\n\n/** Driver proof that dispatch occurred but the exact native outcome could not\n * be confirmed. Unlike an arbitrary transport exception, this preserves the\n * adapter's bounded, user-actionable diagnosis without pretending certainty. */\nexport class InteractionOutcomeUnknownDriverError extends Error {\n /** Optional state observed after the failure; see InteractionDefiniteDriverError. */\n observation: unknown = null;\n /** Optional structured facts; see InteractionDefiniteDriverError. */\n details: InteractionError[\"details\"] = undefined;\n\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionOutcomeUnknownDriverError\";\n }\n}\n\nexport type InteractionCoreCommand = {\n operationId: string;\n controllerGeneration: string;\n targetId: string | null;\n};\n\nexport type InteractionCoreTarget = {\n id: string;\n controllerGeneration: string;\n};\n\nexport type InteractionCoreObservation<TTarget extends InteractionCoreTarget> = {\n target: TTarget | null;\n};\n\nexport type InteractionCoreReceipt<TObservation> = {\n operationId: string;\n controllerGeneration: string;\n targetId: string | null;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n};\n\nexport type InteractionOperationJournalRecord<TReceipt> = {\n operationId: string;\n commandDigest: string;\n receipt: TReceipt;\n};\n\n/** Side channel a driver may use to describe what a dispatch acted on, such\n * as the element a locator resolved to. Recording never affects dispatch. */\nexport type InteractionDispatchTrace = {\n record(item: unknown): void;\n};\n\nclass BoundedDispatchTrace implements InteractionDispatchTrace {\n readonly items: unknown[] = [];\n\n constructor(private readonly limit: number) {}\n\n record(item: unknown): void {\n if (this.items.length < this.limit) this.items.push(item);\n }\n}\n\ntype InteractionDriver<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n> = {\n target(targetId: string): Promise<TTarget | null>;\n observe(targetId: string): Promise<TObservation>;\n validate?(command: TCommand, target: TTarget): Promise<void> | void;\n validateSession?(command: TCommand): Promise<void> | void;\n dispatch(command: TCommand, trace?: InteractionDispatchTrace): Promise<TObservation | null>;\n};\n\ntype InteractionCoreAdapter<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n resourceLabel: string;\n parseCommand(value: unknown): TCommand;\n parseTarget(value: unknown): TTarget;\n parseObservation(value: unknown): TObservation;\n parseReceipt(value: unknown): TReceipt;\n assertCommandAuthority(command: TCommand): void;\n assertTargetAuthority(target: TTarget): void;\n assertExpectedGenerations(command: TCommand, target: TTarget): void;\n assertObservationAuthority(observation: TObservation, targetId: string | null): void;\n /** Authority for the observation a dispatched command returns. Defaults to\n * an observation of the command's own target. */\n assertActionObservationAuthority?(observation: TObservation, command: TCommand): void;\n outcome?(observation: TObservation): {\n state: \"completed\" | \"failed\" | \"outcome_unknown\";\n error: InteractionError | null;\n };\n makeReceipt(input: {\n command: TCommand;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n }): TReceipt;\n recoverReceipt(receipt: TReceipt, settledAt: string): TReceipt;\n /** Upper bound on recorded dispatch trace items; zero disables tracing. */\n maxDispatchTraceItems?: number;\n /** Decorates the returned receipt with recorded trace items. It may throw\n * on invalid items; the undecorated receipt is then returned unchanged. */\n attachDispatchTrace?(receipt: TReceipt, items: readonly unknown[]): TReceipt;\n};\n\ntype InteractionCoreAuthority<TCommand> = {\n authorizeDispatch(command: TCommand): Promise<void> | void;\n};\n\nexport type InteractionControllerCoreOptions<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n driver: InteractionDriver<TCommand, TTarget, TObservation>;\n adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n authority?: InteractionCoreAuthority<TCommand>;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<InteractionOperationJournalRecord<TReceipt>>;\n onJournalRecord?: (record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void;\n /** Read the same durable journal used by onJournalRecord. Terminal receipts\n * may leave RAM only after that writer succeeds. Missing/corrupt reads fail\n * closed and never cause a command to dispatch again. */\n loadJournalRecord?: (operationId: string) => InteractionOperationJournalRecord<TReceipt> | null;\n /** Override only when a private command contains ephemeral secret material.\n * The callback must bind every non-secret semantic input while excluding the\n * value bytes themselves and return lowercase SHA-256. */\n commandDigest?: (command: TCommand) => string;\n};\n\ntype JournalEntry<TReceipt> = InteractionOperationJournalRecord<TReceipt> & {\n kind: \"materialized\";\n completion: Promise<TReceipt>;\n preparationPersisted: Promise<boolean>;\n terminalPersisted: boolean;\n};\n\ntype PersistedJournalEntry = {\n kind: \"persisted\";\n operationId: string;\n commandDigest: string;\n state: InteractionOperationState;\n receiptDigest: string;\n};\n\ntype CompactJournalEntry = {\n kind: \"compact\";\n operationId: string;\n commandDigest: string;\n state: InteractionOperationState;\n receiptBytes: number;\n compressedReceipt: Uint8Array;\n};\n\n// Keep small receipts and all in-flight promises untouched. Large settled AX\n// trees otherwise remain live as thousands of JS objects per past operation.\nconst COMPACT_RECEIPT_MIN_BYTES = 16 * 1024;\n\nconst terminalStates = new Set<InteractionOperationState>([\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n]);\n\n/**\n * Resource-neutral placement mutation authority. Public Browser and Computer\n * controllers supply only their schemas and generation semantics; journaling,\n * idempotency, target-local serialization, and crash policy stay identical.\n */\nexport class InteractionControllerCore<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> {\n private readonly driver: InteractionDriver<TCommand, TTarget, TObservation>;\n private readonly adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n private readonly authority: InteractionCoreAuthority<TCommand> | undefined;\n private readonly maxJournalEntries: number;\n private readonly now: () => Date;\n private readonly onJournalRecord:\n | ((record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void)\n | undefined;\n private readonly commandDigest: (command: TCommand) => string;\n private readonly loadJournalRecord:\n | ((operationId: string) => InteractionOperationJournalRecord<TReceipt> | null)\n | undefined;\n private readonly journal = new Map<\n string,\n JournalEntry<TReceipt> | CompactJournalEntry | PersistedJournalEntry\n >();\n private readonly targetTails = new Map<string | null, Promise<void>>();\n\n constructor(\n options: InteractionControllerCoreOptions<TCommand, TTarget, TObservation, TReceipt>,\n ) {\n this.driver = options.driver;\n this.adapter = options.adapter;\n this.authority = options.authority;\n this.maxJournalEntries = options.maxJournalEntries ?? 10_000;\n this.now = options.now ?? (() => new Date());\n this.onJournalRecord = options.onJournalRecord;\n this.loadJournalRecord = options.loadJournalRecord;\n this.commandDigest = options.commandDigest ?? digestJson;\n if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {\n throw new Error(\"maxJournalEntries must be a positive safe integer\");\n }\n for (const record of options.initialJournal ?? []) this.restoreJournalRecord(record);\n }\n\n async observe(targetId: string): Promise<TObservation> {\n const target = await this.requireCurrentTarget(targetId);\n const observed = this.adapter.parseObservation(await this.driver.observe(target.id));\n this.adapter.assertObservationAuthority(observed, target.id);\n return observed;\n }\n\n run(commandInput: TCommand): Promise<TReceipt> {\n const command = this.adapter.parseCommand(commandInput);\n this.adapter.assertCommandAuthority(command);\n const commandDigest = this.commandDigest(command);\n if (!/^[0-9a-f]{64}$/u.test(commandDigest)) {\n throw new Error(`${this.adapter.resourceLabel} command digest must be lowercase SHA-256`);\n }\n const existing = this.journal.get(command.operationId);\n if (existing) {\n if (existing.commandDigest !== commandDigest) {\n throw new InteractionControllerError(\n \"operation_conflict\",\n `operation id is already bound to a different ${this.adapter.resourceLabel} command`,\n );\n }\n return existing.kind === \"materialized\"\n ? existing.completion\n : Promise.resolve(this.readReceipt(existing));\n }\n\n this.makeJournalSpace();\n const prepared = this.makeReceipt(command, \"prepared\", null, null, null, null);\n const entry: JournalEntry<TReceipt> = {\n kind: \"materialized\",\n operationId: command.operationId,\n commandDigest,\n receipt: prepared,\n terminalPersisted: false,\n completion: Promise.resolve(prepared),\n preparationPersisted: this.publish(command.operationId, commandDigest, prepared).then(\n () => true,\n () => false,\n ),\n };\n this.journal.set(command.operationId, entry);\n\n const previous = this.targetTails.get(command.targetId) ?? Promise.resolve();\n entry.completion = previous.then(async () => await this.execute(entry, command));\n const tail = entry.completion.then(\n () => undefined,\n () => undefined,\n );\n this.targetTails.set(command.targetId, tail);\n void tail.finally(() => {\n if (this.targetTails.get(command.targetId) === tail)\n this.targetTails.delete(command.targetId);\n this.compactJournalEntry(entry);\n });\n return entry.completion;\n }\n\n receipt(operationId: string): TReceipt | null {\n const entry = this.journal.get(operationId);\n return entry ? this.readReceipt(entry) : null;\n }\n\n journalSnapshot(): InteractionOperationJournalRecord<TReceipt>[] {\n return [...this.journal.values()].map((entry) => ({\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n receipt: this.readReceipt(entry),\n }));\n }\n\n /** True when no admitted command is queued or running on any target. */\n isIdle(): boolean {\n return this.targetTails.size === 0;\n }\n\n /** Wait until every command already admitted to a target queue settles.\n * Callers must fence new dispatch through `authority` before awaiting this. */\n async waitForIdle(): Promise<void> {\n while (this.targetTails.size > 0) await Promise.all([...this.targetTails.values()]);\n }\n\n private async execute(entry: JournalEntry<TReceipt>, command: TCommand): Promise<TReceipt> {\n if (!(await entry.preparationPersisted)) {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal rejected the command before dispatch`,\n );\n }\n\n try {\n await this.authority?.authorizeDispatch(command);\n if (command.targetId === null) {\n if (!this.driver.validateSession)\n throw new InteractionControllerError(\n \"invalid_action\",\n \"session-scoped commands are unsupported\",\n );\n await this.driver.validateSession(command);\n } else {\n const target = await this.requireCurrentTarget(command.targetId);\n this.adapter.assertExpectedGenerations(command, target);\n await this.driver.validate?.(command, target);\n }\n } catch (error) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n null,\n this.timestamp(),\n null,\n safePredispatchError(error, this.adapter.resourceLabel),\n ),\n );\n }\n\n const dispatchedAt = this.timestamp();\n const dispatched = this.makeReceipt(command, \"dispatched\", dispatchedAt, null, null, null);\n try {\n await this.publish(entry.operationId, entry.commandDigest, dispatched);\n entry.receipt = dispatched;\n } catch {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal became unavailable before dispatch`,\n );\n }\n\n const trace = new BoundedDispatchTrace(this.adapter.maxDispatchTraceItems ?? 0);\n const receipt = await this.dispatchAndSettle(entry, command, dispatchedAt, trace);\n return this.attachDispatchTrace(receipt, trace.items);\n }\n\n /** Dispatch diagnostics decorate only the returned receipt. The journal keeps\n * the undecorated receipt, so an older controller can always read it back. */\n private attachDispatchTrace(receipt: TReceipt, items: readonly unknown[]): TReceipt {\n if (items.length === 0 || !this.adapter.attachDispatchTrace) return receipt;\n try {\n return this.adapter.attachDispatchTrace(receipt, items);\n } catch {\n // Diagnostics never change an operation's outcome.\n return receipt;\n }\n }\n\n private async dispatchAndSettle(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n dispatchedAt: string,\n trace: InteractionDispatchTrace,\n ): Promise<TReceipt> {\n try {\n const dispatchedObservation = await this.driver.dispatch(command, trace);\n const observation =\n dispatchedObservation === null\n ? null\n : this.adapter.parseObservation(dispatchedObservation);\n if (observation) this.assertActionObservation(observation, command);\n const outcome = observation ? this.adapter.outcome?.(observation) : undefined;\n const completed = this.makeReceipt(\n command,\n outcome?.state ?? \"completed\",\n dispatchedAt,\n this.timestamp(),\n observation,\n outcome?.error ?? null,\n );\n try {\n await this.publish(entry.operationId, entry.commandDigest, completed);\n entry.receipt = completed;\n entry.terminalPersisted = this.onJournalRecord !== undefined;\n return completed;\n } catch {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command completed but its durable outcome could not be recorded`,\n retryable: false,\n }),\n );\n }\n } catch (error) {\n if (error instanceof InteractionDefiniteDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n dispatchedAt,\n this.timestamp(),\n this.failureObservation(error.observation, command),\n {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n },\n ),\n );\n }\n if (error instanceof InteractionOutcomeUnknownDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"outcome_unknown\",\n dispatchedAt,\n this.timestamp(),\n this.failureObservation(error.observation, command),\n {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n },\n ),\n );\n }\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command outcome is unknown after dispatch`,\n retryable: false,\n }),\n );\n }\n }\n\n private assertActionObservation(observation: TObservation, command: TCommand): void {\n if (this.adapter.assertActionObservationAuthority)\n this.adapter.assertActionObservationAuthority(observation, command);\n else this.adapter.assertObservationAuthority(observation, command.targetId);\n }\n\n /** A failure's observation is optional context. One that does not parse or\n * belongs to another target is dropped; it never changes the failure. */\n private failureObservation(observation: unknown, command: TCommand): TObservation | null {\n if (observation === null || observation === undefined) return null;\n try {\n const parsed = this.adapter.parseObservation(observation);\n this.assertActionObservation(parsed, command);\n return parsed;\n } catch {\n return null;\n }\n }\n\n private async requireCurrentTarget(targetId: string): Promise<TTarget> {\n const target = await this.driver.target(targetId);\n if (!target) {\n throw new InteractionControllerError(\n \"target_not_found\",\n `${this.adapter.resourceLabel} target ${JSON.stringify(targetId)} does not exist; list the current targets and use one of their ids`,\n );\n }\n const parsed = this.adapter.parseTarget(target);\n this.adapter.assertTargetAuthority(parsed);\n return parsed;\n }\n\n private makeReceipt(\n command: TCommand,\n state: InteractionOperationState,\n dispatchedAt: string | null,\n settledAt: string | null,\n observation: TObservation | null,\n error: InteractionError | null,\n ): TReceipt {\n return this.adapter.makeReceipt({\n command,\n state,\n dispatchedAt,\n settledAt,\n observation,\n error,\n });\n }\n\n private async settle(entry: JournalEntry<TReceipt>, receipt: TReceipt): Promise<TReceipt> {\n entry.receipt = receipt;\n try {\n await this.publish(entry.operationId, entry.commandDigest, receipt);\n entry.terminalPersisted = this.onJournalRecord !== undefined;\n } catch {\n // Controller-lifetime terminal truth remains authoritative. A restored\n // dispatched receipt is always recovered as outcome_unknown, never replayed.\n }\n return receipt;\n }\n\n private async failBeforeDispatch(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n message: string,\n ): Promise<TReceipt> {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", null, this.timestamp(), null, {\n code: \"driver_failed\",\n message,\n retryable: true,\n }),\n );\n }\n\n private async publish(\n operationId: string,\n commandDigest: string,\n receipt: TReceipt,\n ): Promise<void> {\n await this.onJournalRecord?.({ operationId, commandDigest, receipt });\n }\n\n private timestamp(): string {\n return this.now().toISOString();\n }\n\n private makeJournalSpace(): void {\n while (this.journal.size >= this.maxJournalEntries) {\n const terminal = [...this.journal.entries()].find(([, entry]) =>\n terminalStates.has(entry.kind === \"materialized\" ? entry.receipt.state : entry.state),\n );\n if (!terminal) {\n throw new InteractionControllerError(\n \"journal_full\",\n `${this.adapter.resourceLabel} operation journal has no safely evictable terminal entry`,\n true,\n );\n }\n this.journal.delete(terminal[0]);\n }\n }\n\n private restoreJournalRecord(record: InteractionOperationJournalRecord<TReceipt>): void {\n if (this.journal.has(record.operationId)) {\n throw new Error(`duplicate restored operation id: ${record.operationId}`);\n }\n const parsed = this.adapter.parseReceipt(record.receipt);\n if (parsed.operationId !== record.operationId) {\n throw new Error(`restored operation ${record.operationId} has another receipt id`);\n }\n const receipt = this.adapter.recoverReceipt(parsed, this.timestamp());\n const entry: JournalEntry<TReceipt> = {\n kind: \"materialized\",\n operationId: record.operationId,\n commandDigest: record.commandDigest,\n receipt,\n terminalPersisted: terminalStates.has(parsed.state),\n completion: Promise.resolve(receipt),\n preparationPersisted: Promise.resolve(true),\n };\n this.journal.set(record.operationId, entry);\n this.compactJournalEntry(entry);\n }\n\n private readReceipt(\n entry: JournalEntry<TReceipt> | CompactJournalEntry | PersistedJournalEntry,\n ): TReceipt {\n if (entry.kind === \"materialized\") return entry.receipt;\n if (entry.kind === \"persisted\") {\n const record = this.loadJournalRecord?.(entry.operationId);\n if (\n !record ||\n record.operationId !== entry.operationId ||\n record.commandDigest !== entry.commandDigest\n ) {\n throw new Error(`${this.adapter.resourceLabel} durable operation receipt is unavailable`);\n }\n const receipt = this.adapter.parseReceipt(record.receipt);\n if (digestJson(receipt) !== entry.receiptDigest) {\n throw new Error(`${this.adapter.resourceLabel} durable operation receipt changed`);\n }\n return receipt;\n }\n const json = inflateRawSync(entry.compressedReceipt, {\n maxOutputLength: entry.receiptBytes,\n });\n return this.adapter.parseReceipt(JSON.parse(json.toString(\"utf8\")));\n }\n\n private compactJournalEntry(entry: JournalEntry<TReceipt>): void {\n if (this.journal.get(entry.operationId) !== entry || !terminalStates.has(entry.receipt.state))\n return;\n try {\n if (entry.terminalPersisted && this.loadJournalRecord) {\n this.journal.set(entry.operationId, {\n kind: \"persisted\",\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n state: entry.receipt.state,\n receiptDigest: digestJson(entry.receipt),\n });\n return;\n }\n const json = JSON.stringify(entry.receipt);\n const receiptBytes = Buffer.byteLength(json);\n if (receiptBytes < COMPACT_RECEIPT_MIN_BYTES) return;\n const compressedReceipt = deflateRawSync(json, { level: 1 });\n this.journal.set(entry.operationId, {\n kind: \"compact\",\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n state: entry.receipt.state,\n receiptBytes,\n compressedReceipt,\n });\n } catch {\n // Cache optimization must never change a settled mutation's outcome.\n // Retain the original receipt if serialization/compression is unavailable.\n }\n }\n}\n\nexport function recoverInteractionReceipt<TReceipt extends InteractionCoreReceipt<unknown>>(\n receipt: TReceipt,\n settledAt: string,\n resourceLabel: string,\n parse: (value: unknown) => TReceipt,\n): TReceipt {\n if (terminalStates.has(receipt.state)) return receipt;\n return parse({\n ...receipt,\n state: receipt.state === \"dispatched\" ? \"outcome_unknown\" : \"failed\",\n settledAt,\n observation: null,\n error:\n receipt.state === \"dispatched\"\n ? {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted after command dispatch`,\n retryable: false,\n }\n : {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted before command dispatch`,\n retryable: true,\n },\n });\n}\n\nfunction safePredispatchError(error: unknown, resourceLabel: string): InteractionError {\n if (error instanceof InteractionControllerError && error.code !== \"journal_full\") {\n return {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n };\n }\n return {\n code: \"driver_failed\",\n message: `${resourceLabel} command failed before dispatch`,\n retryable: false,\n };\n}\n\nfunction digestJson(value: unknown): string {\n return createHash(\"sha256\").update(canonicalJson(value), \"utf8\").digest(\"hex\");\n}\n\n/** Digest of every command field except the controller-private `secretValues`\n * side map: replays with fresh values (a new TOTP code) stay idempotent and\n * the journal never binds plaintext. Equals the default digest of the same\n * command without the map. */\nexport function secretFreeCommandDigest(command: object): string {\n if (!(\"secretValues\" in command)) return digestJson(command);\n const { secretValues: _private, ...rest } = command as { secretValues?: unknown };\n return digestJson(rest);\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n","import type { ComputerOperationReceipt } from \"@opengeni/contracts\";\n\nconst MAX_RESULT_BYTES = 12 * 1024 * 1024;\nconst bytes = (value: unknown) => new TextEncoder().encode(JSON.stringify(value)).byteLength;\n\n/** Transport projection only. The controller journal retains the original result.\n * Keep below Code Mode's 16 MiB completion bound as well as the HTTP envelope. */\nexport function boundComputerNativeReceipt<T extends ComputerOperationReceipt>(receipt: T): T {\n if (receipt.targetId !== null || !receipt.observation || bytes(receipt) <= MAX_RESULT_BYTES)\n return receipt;\n const original = receipt.observation.result;\n let remaining = 8 * 1024 * 1024;\n const content = original.content.filter((part) => {\n const size = bytes(part);\n if (size > remaining) return false;\n remaining -= size;\n return true;\n });\n content.push({\n type: \"text\",\n text: JSON.stringify({\n outputTruncated: true,\n operationId: receipt.operationId,\n state: receipt.state,\n guidance:\n \"Some CUA output exceeded the response limit. The original result remains in the controller journal. Do not repeat the action to retrieve output. Read current state with a smaller image or tree, or inspect the retained journal.\",\n }),\n });\n return {\n ...receipt,\n observation: {\n ...receipt.observation,\n result: {\n content,\n // The operation state is unchanged; only this response is incomplete.\n // Skip the upstream output-schema check for the truncated projection.\n isError: true,\n ...(original.structuredContent && bytes(original.structuredContent) <= 1024 * 1024\n ? { structuredContent: original.structuredContent }\n : {}),\n _meta: { opengeniOutputTruncated: true },\n },\n },\n } as T;\n}\n"],"mappings":"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","names":["canonicalJson","canonicalJsonValue"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/controller-core.ts","../src/native-result.ts"],"sourcesContent":["import {\n BrowserActionCommand,\n BrowserActionReceipt,\n INTERACTION_MAX_RESOLVED_ACTION_TARGETS,\n BrowserObservation,\n BrowserTarget,\n ComputerNativeCommand,\n ComputerNativeReceipt,\n ComputerOperationCommand,\n ComputerOperationReceipt,\n ComputerOperationObservation,\n type ComputerNativeResult,\n ComputerActionCommand,\n ComputerObservation,\n ComputerTarget,\n type BrowserActionCommand as BrowserActionCommandValue,\n type BrowserActionReceipt as BrowserActionReceiptValue,\n type BrowserObservation as BrowserObservationValue,\n type BrowserTarget as BrowserTargetValue,\n type ComputerActionCommand as ComputerActionCommandValue,\n type ComputerActionReceipt as ComputerActionReceiptValue,\n type ComputerObservation as ComputerObservationValue,\n type ComputerTarget as ComputerTargetValue,\n} from \"@opengeni/contracts\";\nimport {\n InteractionControllerCore,\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n recoverInteractionReceipt,\n secretFreeCommandDigest,\n type InteractionControllerErrorCode,\n type InteractionDispatchTrace,\n type InteractionOperationJournalRecord,\n} from \"./controller-core\";\n\nexport {\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n secretFreeCommandDigest,\n type InteractionControllerErrorCode,\n type InteractionDispatchTrace,\n};\n\nexport type BrowserInteractionDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserObservationValue>;\n validate?(command: BrowserActionCommandValue, target: BrowserTargetValue): Promise<void> | void;\n /** Drivers that resolve locators record each resolved element on `trace`. */\n dispatch(\n command: BrowserActionCommandValue,\n trace?: InteractionDispatchTrace,\n ): Promise<BrowserObservationValue | null>;\n};\n\nexport type BrowserInteractionAuthority = {\n authorizeDispatch(command: BrowserActionCommandValue): Promise<void> | void;\n};\n\nexport type BrowserOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserActionReceiptValue>;\n\nexport type BrowserInteractionControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserInteractionDriver;\n authority?: BrowserInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<BrowserOperationJournalRecord>;\n onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;\n /** Reads the same durable authority as onJournalRecord and initialJournal. */\n loadJournalRecord?: (operationId: string) => BrowserOperationJournalRecord | null;\n /** Operator logging for a dispatch error the driver did not classify. */\n onUnexpectedDispatchError?: (error: unknown, command: BrowserActionCommandValue) => void;\n};\n\n/** Placement-resident BrowserSession mutation authority. */\nexport class BrowserInteractionController {\n private readonly core: InteractionControllerCore<\n BrowserActionCommandValue,\n BrowserTargetValue,\n BrowserObservationValue,\n BrowserActionReceiptValue\n >;\n\n constructor(options: BrowserInteractionControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),\n ...(options.onUnexpectedDispatchError\n ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError }\n : {}),\n commandDigest: (command) => secretFreeCommandDigest(command),\n adapter: {\n resourceLabel: \"browser\",\n parseCommand: (value) => BrowserActionCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserObservation.parse(value),\n parseReceipt: (value) => BrowserActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"browser command targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before the command could dispatch\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.browserSessionId !== browserSessionId ||\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"browser driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n maxDispatchTraceItems: INTERACTION_MAX_RESOLVED_ACTION_TARGETS,\n attachDispatchTrace(receipt, items) {\n return BrowserActionReceipt.parse({ ...receipt, targets: items });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<BrowserObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: BrowserActionCommandValue): Promise<BrowserActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n isIdle(): boolean {\n return this.core.isIdle();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserOperationJournalRecord(\n record: BrowserOperationJournalRecord,\n settledAt: string,\n): BrowserOperationJournalRecord {\n const receipt = BrowserActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n ),\n };\n}\n\n/** Deterministic JSON with sorted object keys and undefined entries dropped. */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport type ComputerInteractionDriver = {\n target(targetId: string): Promise<ComputerTargetValue | null>;\n observe(targetId: string): Promise<ComputerObservationValue>;\n validate?(command: ComputerActionCommandValue, target: ComputerTargetValue): Promise<void> | void;\n dispatch(command: ComputerActionCommandValue): Promise<ComputerObservationValue | null>;\n validateNative?(command: ComputerNativeCommand): Promise<void>;\n dispatchNative?(command: ComputerNativeCommand): Promise<ComputerNativeResult>;\n};\n\nexport type ComputerInteractionAuthority = {\n authorizeDispatch(command: ComputerOperationCommand): Promise<void> | void;\n};\n\nexport type ComputerOperationJournalRecord =\n InteractionOperationJournalRecord<ComputerOperationReceipt>;\n\nexport type ComputerInteractionControllerOptions = {\n computerSessionId: string;\n controllerGeneration: string;\n driver: ComputerInteractionDriver;\n authority?: ComputerInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<ComputerOperationJournalRecord>;\n onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;\n /** Reads the same durable authority as onJournalRecord and initialJournal. */\n loadJournalRecord?: (operationId: string) => ComputerOperationJournalRecord | null;\n /** Operator logging for a dispatch error the driver did not classify. */\n onUnexpectedDispatchError?: (error: unknown, command: ComputerOperationCommand) => void;\n};\n\n/** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,\n * macOS AX/ScreenCaptureKit, and later UIA adapters share this exact core. */\nexport class ComputerInteractionController {\n // Ephemeral causal metadata, never reconstructed from a terminal receipt.\n // Native input additionally verifies and consumes its exact delivery proof.\n private readonly firstClicks = new Map<string, ComputerActionCommandValue>();\n private readonly core: InteractionControllerCore<\n ComputerOperationCommand,\n ComputerTargetValue,\n ComputerOperationObservation,\n ComputerOperationReceipt\n >;\n\n constructor(options: ComputerInteractionControllerOptions) {\n const { computerSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: {\n target: (id) => options.driver.target(id),\n observe: (id) => options.driver.observe(id),\n validate: (command, target) => {\n if (command.targetId !== null) return options.driver.validate?.(command, target);\n },\n validateSession: async (command) => {\n if (\n command.targetId !== null ||\n !options.driver.validateNative ||\n !options.driver.dispatchNative\n )\n throw new InteractionControllerError(\n \"unsupported\",\n \"Native CUA calls require a CUA ComputerSession\",\n );\n await options.driver.validateNative(command);\n },\n dispatch: (command) =>\n command.targetId === null\n ? options.driver.dispatchNative!(command)\n : options.driver.dispatch(command),\n },\n authority: {\n authorizeDispatch: async (command) => {\n await options.authority?.authorizeDispatch(command);\n if (command.targetId === null) return;\n if (\n command.action.type === \"pointer\" &&\n command.action.action === \"click\" &&\n (command.action.clickCount ?? 1) === 1\n ) {\n // Only a journal-admitted command reaches dispatch authority.\n // Conflicting retries cannot replace an earlier operation's kind.\n this.firstClicks.set(command.operationId, ComputerActionCommand.parse(command));\n while (this.firstClicks.size > 512) {\n this.firstClicks.delete(this.firstClicks.keys().next().value!);\n }\n }\n if (command.action.type !== \"pointer\" || command.action.clickCount !== 2) return;\n const firstId = command.action.continuationOfOperationId;\n const first = firstId ? this.firstClicks.get(firstId) : null;\n const receipt = firstId ? this.core.receipt(firstId) : null;\n if (\n !first ||\n receipt?.state !== \"completed\" ||\n first.computerSessionId !== command.computerSessionId ||\n first.controllerGeneration !== command.controllerGeneration ||\n first.targetId !== command.targetId ||\n first.expectedTargetGeneration !== command.expectedTargetGeneration ||\n JSON.stringify(first.actor) !== JSON.stringify(command.actor)\n ) {\n throw new InteractionControllerError(\n \"invalid_action\",\n \"click continuation requires its exact completed first click\",\n );\n }\n },\n },\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),\n ...(options.onUnexpectedDispatchError\n ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError }\n : {}),\n commandDigest: (command) => secretFreeCommandDigest(command),\n adapter: {\n resourceLabel: \"computer\",\n parseCommand: (value) => ComputerOperationCommand.parse(value),\n parseTarget: (value) => ComputerTarget.parse(value),\n parseObservation: (value) => ComputerOperationObservation.parse(value),\n parseReceipt: (value) => ComputerOperationReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.computerSessionId !== computerSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"computer command targets another computer session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.computerSessionId !== computerSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.targetId === null) return;\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"computer target changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (observation.target === null) {\n if (\n targetId !== null ||\n observation.computerSessionId !== computerSessionId ||\n observation.controllerGeneration !== controllerGeneration\n )\n throw new InteractionControllerError(\n \"driver_failed\",\n \"native result belongs to another computer controller\",\n );\n return;\n }\n if (\n observation.computerSessionId !== computerSessionId ||\n observation.target.id !== targetId ||\n observation.target.computerSessionId !== computerSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"computer driver returned an observation outside controller authority\",\n );\n }\n },\n assertActionObservationAuthority(observation, command) {\n // An action that opened a window (a launch, a new document, a\n // dialog) returns that window, which is not the window the command\n // named, so any target of this controller.\n this.assertObservationAuthority(observation, observation.target?.id ?? command.targetId);\n },\n outcome(observation) {\n return observation.target === null\n ? { state: observation.outcome, error: observation.error }\n : { state: \"completed\", error: null };\n },\n makeReceipt(input) {\n return ComputerOperationReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n computerSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.computerSessionId !== computerSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerOperationReceipt.parse(value),\n );\n },\n },\n });\n }\n\n async observe(targetId: string): Promise<ComputerObservationValue> {\n return ComputerObservation.parse(await this.core.observe(targetId));\n }\n\n run(command: ComputerActionCommandValue): Promise<ComputerActionReceiptValue> {\n // The command discriminant fixes the receipt variant; retain replay Promise identity.\n return this.core.run(command) as Promise<ComputerActionReceiptValue>;\n }\n\n runNative(command: ComputerNativeCommand): Promise<ComputerNativeReceipt> {\n return this.core.run(command) as Promise<ComputerNativeReceipt>;\n }\n\n receipt(operationId: string): ComputerOperationReceipt | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): ComputerOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n isIdle(): boolean {\n return this.core.isIdle();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverComputerOperationJournalRecord(\n record: ComputerOperationJournalRecord,\n settledAt: string,\n): ComputerOperationJournalRecord {\n const receipt = ComputerOperationReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerOperationReceipt.parse(value),\n ),\n };\n}\nexport { boundComputerNativeReceipt } from \"./native-result\";\n","import { createHash } from \"node:crypto\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport type { InteractionError, InteractionOperationState } from \"@opengeni/contracts\";\n\nexport type InteractionControllerErrorCode = InteractionError[\"code\"] | \"journal_full\";\n\n/** A safe, typed rejection known not to have dispatched a side effect. */\nexport class InteractionControllerError extends Error {\n constructor(\n readonly code: InteractionControllerErrorCode,\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionControllerError\";\n }\n}\n\n/** Driver proof that a dispatched command definitively failed without an ambiguous outcome. */\nexport class InteractionDefiniteDriverError extends Error {\n /** Optional page or screen state the driver observed after the failure, so\n * the caller can act on it without another observation round trip. */\n observation: unknown = null;\n /** Optional structured facts about the failure, kept in the receipt's error. */\n details: InteractionError[\"details\"] = undefined;\n\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionDefiniteDriverError\";\n }\n}\n\n/** Driver proof that dispatch occurred but the exact native outcome could not\n * be confirmed. Unlike an arbitrary transport exception, this preserves the\n * adapter's bounded, user-actionable diagnosis without pretending certainty. */\nexport class InteractionOutcomeUnknownDriverError extends Error {\n /** Optional state observed after the failure; see InteractionDefiniteDriverError. */\n observation: unknown = null;\n /** Optional structured facts; see InteractionDefiniteDriverError. */\n details: InteractionError[\"details\"] = undefined;\n\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionOutcomeUnknownDriverError\";\n }\n}\n\nexport type InteractionCoreCommand = {\n operationId: string;\n controllerGeneration: string;\n targetId: string | null;\n};\n\nexport type InteractionCoreTarget = {\n id: string;\n controllerGeneration: string;\n};\n\nexport type InteractionCoreObservation<TTarget extends InteractionCoreTarget> = {\n target: TTarget | null;\n};\n\nexport type InteractionCoreReceipt<TObservation> = {\n operationId: string;\n controllerGeneration: string;\n targetId: string | null;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n};\n\nexport type InteractionOperationJournalRecord<TReceipt> = {\n operationId: string;\n commandDigest: string;\n receipt: TReceipt;\n};\n\n/** Side channel a driver may use to describe what a dispatch acted on, such\n * as the element a locator resolved to. Recording never affects dispatch. */\nexport type InteractionDispatchTrace = {\n record(item: unknown): void;\n};\n\nclass BoundedDispatchTrace implements InteractionDispatchTrace {\n readonly items: unknown[] = [];\n\n constructor(private readonly limit: number) {}\n\n record(item: unknown): void {\n if (this.items.length < this.limit) this.items.push(item);\n }\n}\n\ntype InteractionDriver<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n> = {\n target(targetId: string): Promise<TTarget | null>;\n observe(targetId: string): Promise<TObservation>;\n validate?(command: TCommand, target: TTarget): Promise<void> | void;\n validateSession?(command: TCommand): Promise<void> | void;\n dispatch(command: TCommand, trace?: InteractionDispatchTrace): Promise<TObservation | null>;\n};\n\ntype InteractionCoreAdapter<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n resourceLabel: string;\n parseCommand(value: unknown): TCommand;\n parseTarget(value: unknown): TTarget;\n parseObservation(value: unknown): TObservation;\n parseReceipt(value: unknown): TReceipt;\n assertCommandAuthority(command: TCommand): void;\n assertTargetAuthority(target: TTarget): void;\n assertExpectedGenerations(command: TCommand, target: TTarget): void;\n assertObservationAuthority(observation: TObservation, targetId: string | null): void;\n /** Authority for the observation a dispatched command returns. Defaults to\n * an observation of the command's own target. */\n assertActionObservationAuthority?(observation: TObservation, command: TCommand): void;\n outcome?(observation: TObservation): {\n state: \"completed\" | \"failed\" | \"outcome_unknown\";\n error: InteractionError | null;\n };\n makeReceipt(input: {\n command: TCommand;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n }): TReceipt;\n recoverReceipt(receipt: TReceipt, settledAt: string): TReceipt;\n /** Upper bound on recorded dispatch trace items; zero disables tracing. */\n maxDispatchTraceItems?: number;\n /** Decorates the returned receipt with recorded trace items. It may throw\n * on invalid items; the undecorated receipt is then returned unchanged. */\n attachDispatchTrace?(receipt: TReceipt, items: readonly unknown[]): TReceipt;\n};\n\ntype InteractionCoreAuthority<TCommand> = {\n authorizeDispatch(command: TCommand): Promise<void> | void;\n};\n\nexport type InteractionControllerCoreOptions<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n driver: InteractionDriver<TCommand, TTarget, TObservation>;\n adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n authority?: InteractionCoreAuthority<TCommand>;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: Iterable<InteractionOperationJournalRecord<TReceipt>>;\n onJournalRecord?: (record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void;\n /** Read the same durable journal used by onJournalRecord. Terminal receipts\n * may leave RAM only after that writer succeeds. Missing/corrupt reads fail\n * closed and never cause a command to dispatch again. */\n loadJournalRecord?: (operationId: string) => InteractionOperationJournalRecord<TReceipt> | null;\n /** Override only when a private command contains ephemeral secret material.\n * The callback must bind every non-secret semantic input while excluding the\n * value bytes themselves and return lowercase SHA-256. */\n commandDigest?: (command: TCommand) => string;\n /** Operator logging for a dispatch that threw something the driver did not\n * classify. The caller still sees only outcome_unknown; this hook keeps the\n * cause from disappearing. It never changes the operation's outcome. */\n onUnexpectedDispatchError?: (error: unknown, command: TCommand) => void;\n};\n\ntype JournalEntry<TReceipt> = InteractionOperationJournalRecord<TReceipt> & {\n kind: \"materialized\";\n completion: Promise<TReceipt>;\n preparationPersisted: Promise<boolean>;\n terminalPersisted: boolean;\n};\n\ntype PersistedJournalEntry = {\n kind: \"persisted\";\n operationId: string;\n commandDigest: string;\n state: InteractionOperationState;\n receiptDigest: string;\n};\n\ntype CompactJournalEntry = {\n kind: \"compact\";\n operationId: string;\n commandDigest: string;\n state: InteractionOperationState;\n receiptBytes: number;\n compressedReceipt: Uint8Array;\n};\n\n// Keep small receipts and all in-flight promises untouched. Large settled AX\n// trees otherwise remain live as thousands of JS objects per past operation.\nconst COMPACT_RECEIPT_MIN_BYTES = 16 * 1024;\n\nconst terminalStates = new Set<InteractionOperationState>([\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n]);\n\n/**\n * Resource-neutral placement mutation authority. Public Browser and Computer\n * controllers supply only their schemas and generation semantics; journaling,\n * idempotency, target-local serialization, and crash policy stay identical.\n */\nexport class InteractionControllerCore<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> {\n private readonly driver: InteractionDriver<TCommand, TTarget, TObservation>;\n private readonly adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n private readonly authority: InteractionCoreAuthority<TCommand> | undefined;\n private readonly maxJournalEntries: number;\n private readonly now: () => Date;\n private readonly onJournalRecord:\n | ((record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void)\n | undefined;\n private readonly commandDigest: (command: TCommand) => string;\n private readonly onUnexpectedDispatchError:\n | ((error: unknown, command: TCommand) => void)\n | undefined;\n private readonly loadJournalRecord:\n | ((operationId: string) => InteractionOperationJournalRecord<TReceipt> | null)\n | undefined;\n private readonly journal = new Map<\n string,\n JournalEntry<TReceipt> | CompactJournalEntry | PersistedJournalEntry\n >();\n private readonly targetTails = new Map<string | null, Promise<void>>();\n\n constructor(\n options: InteractionControllerCoreOptions<TCommand, TTarget, TObservation, TReceipt>,\n ) {\n this.driver = options.driver;\n this.adapter = options.adapter;\n this.authority = options.authority;\n this.maxJournalEntries = options.maxJournalEntries ?? 10_000;\n this.now = options.now ?? (() => new Date());\n this.onJournalRecord = options.onJournalRecord;\n this.loadJournalRecord = options.loadJournalRecord;\n this.commandDigest = options.commandDigest ?? digestJson;\n this.onUnexpectedDispatchError = options.onUnexpectedDispatchError;\n if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {\n throw new Error(\"maxJournalEntries must be a positive safe integer\");\n }\n for (const record of options.initialJournal ?? []) this.restoreJournalRecord(record);\n }\n\n async observe(targetId: string): Promise<TObservation> {\n const target = await this.requireCurrentTarget(targetId);\n const observed = this.adapter.parseObservation(await this.driver.observe(target.id));\n this.adapter.assertObservationAuthority(observed, target.id);\n return observed;\n }\n\n run(commandInput: TCommand): Promise<TReceipt> {\n const command = this.adapter.parseCommand(commandInput);\n this.adapter.assertCommandAuthority(command);\n const commandDigest = this.commandDigest(command);\n if (!/^[0-9a-f]{64}$/u.test(commandDigest)) {\n throw new Error(`${this.adapter.resourceLabel} command digest must be lowercase SHA-256`);\n }\n const existing = this.journal.get(command.operationId);\n if (existing) {\n if (existing.commandDigest !== commandDigest) {\n throw new InteractionControllerError(\n \"operation_conflict\",\n `operation id is already bound to a different ${this.adapter.resourceLabel} command`,\n );\n }\n return existing.kind === \"materialized\"\n ? existing.completion\n : Promise.resolve(this.readReceipt(existing));\n }\n\n this.makeJournalSpace();\n const prepared = this.makeReceipt(command, \"prepared\", null, null, null, null);\n const entry: JournalEntry<TReceipt> = {\n kind: \"materialized\",\n operationId: command.operationId,\n commandDigest,\n receipt: prepared,\n terminalPersisted: false,\n completion: Promise.resolve(prepared),\n preparationPersisted: this.publish(command.operationId, commandDigest, prepared).then(\n () => true,\n () => false,\n ),\n };\n this.journal.set(command.operationId, entry);\n\n const previous = this.targetTails.get(command.targetId) ?? Promise.resolve();\n entry.completion = previous.then(async () => await this.execute(entry, command));\n const tail = entry.completion.then(\n () => undefined,\n () => undefined,\n );\n this.targetTails.set(command.targetId, tail);\n void tail.finally(() => {\n if (this.targetTails.get(command.targetId) === tail)\n this.targetTails.delete(command.targetId);\n this.compactJournalEntry(entry);\n });\n return entry.completion;\n }\n\n receipt(operationId: string): TReceipt | null {\n const entry = this.journal.get(operationId);\n return entry ? this.readReceipt(entry) : null;\n }\n\n journalSnapshot(): InteractionOperationJournalRecord<TReceipt>[] {\n return [...this.journal.values()].map((entry) => ({\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n receipt: this.readReceipt(entry),\n }));\n }\n\n /** True when no admitted command is queued or running on any target. */\n isIdle(): boolean {\n return this.targetTails.size === 0;\n }\n\n /** Wait until every command already admitted to a target queue settles.\n * Callers must fence new dispatch through `authority` before awaiting this. */\n async waitForIdle(): Promise<void> {\n while (this.targetTails.size > 0) await Promise.all([...this.targetTails.values()]);\n }\n\n private async execute(entry: JournalEntry<TReceipt>, command: TCommand): Promise<TReceipt> {\n if (!(await entry.preparationPersisted)) {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal rejected the command before dispatch`,\n );\n }\n\n try {\n await this.authority?.authorizeDispatch(command);\n if (command.targetId === null) {\n if (!this.driver.validateSession)\n throw new InteractionControllerError(\n \"invalid_action\",\n \"session-scoped commands are unsupported\",\n );\n await this.driver.validateSession(command);\n } else {\n const target = await this.requireCurrentTarget(command.targetId);\n this.adapter.assertExpectedGenerations(command, target);\n await this.driver.validate?.(command, target);\n }\n } catch (error) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n null,\n this.timestamp(),\n null,\n safePredispatchError(error, this.adapter.resourceLabel),\n ),\n );\n }\n\n const dispatchedAt = this.timestamp();\n const dispatched = this.makeReceipt(command, \"dispatched\", dispatchedAt, null, null, null);\n try {\n await this.publish(entry.operationId, entry.commandDigest, dispatched);\n entry.receipt = dispatched;\n } catch {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal became unavailable before dispatch`,\n );\n }\n\n const trace = new BoundedDispatchTrace(this.adapter.maxDispatchTraceItems ?? 0);\n const receipt = await this.dispatchAndSettle(entry, command, dispatchedAt, trace);\n return this.attachDispatchTrace(receipt, trace.items);\n }\n\n /** Dispatch diagnostics decorate only the returned receipt. The journal keeps\n * the undecorated receipt, so an older controller can always read it back. */\n private attachDispatchTrace(receipt: TReceipt, items: readonly unknown[]): TReceipt {\n if (items.length === 0 || !this.adapter.attachDispatchTrace) return receipt;\n try {\n return this.adapter.attachDispatchTrace(receipt, items);\n } catch {\n // Diagnostics never change an operation's outcome.\n return receipt;\n }\n }\n\n private async dispatchAndSettle(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n dispatchedAt: string,\n trace: InteractionDispatchTrace,\n ): Promise<TReceipt> {\n try {\n const dispatchedObservation = await this.driver.dispatch(command, trace);\n const observation =\n dispatchedObservation === null\n ? null\n : this.adapter.parseObservation(dispatchedObservation);\n if (observation) this.assertActionObservation(observation, command);\n const outcome = observation ? this.adapter.outcome?.(observation) : undefined;\n const completed = this.makeReceipt(\n command,\n outcome?.state ?? \"completed\",\n dispatchedAt,\n this.timestamp(),\n observation,\n outcome?.error ?? null,\n );\n try {\n await this.publish(entry.operationId, entry.commandDigest, completed);\n entry.receipt = completed;\n entry.terminalPersisted = this.onJournalRecord !== undefined;\n return completed;\n } catch {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command completed but its durable outcome could not be recorded`,\n retryable: false,\n }),\n );\n }\n } catch (error) {\n if (error instanceof InteractionDefiniteDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n dispatchedAt,\n this.timestamp(),\n this.failureObservation(error.observation, command),\n {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n },\n ),\n );\n }\n if (error instanceof InteractionOutcomeUnknownDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"outcome_unknown\",\n dispatchedAt,\n this.timestamp(),\n this.failureObservation(error.observation, command),\n {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n ...(error.details ? { details: error.details } : {}),\n },\n ),\n );\n }\n try {\n this.onUnexpectedDispatchError?.(error, command);\n } catch {\n // Diagnostics never change an operation's outcome.\n }\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command outcome is unknown after dispatch`,\n retryable: false,\n }),\n );\n }\n }\n\n private assertActionObservation(observation: TObservation, command: TCommand): void {\n if (this.adapter.assertActionObservationAuthority)\n this.adapter.assertActionObservationAuthority(observation, command);\n else this.adapter.assertObservationAuthority(observation, command.targetId);\n }\n\n /** A failure's observation is optional context. One that does not parse or\n * belongs to another target is dropped; it never changes the failure. */\n private failureObservation(observation: unknown, command: TCommand): TObservation | null {\n if (observation === null || observation === undefined) return null;\n try {\n const parsed = this.adapter.parseObservation(observation);\n this.assertActionObservation(parsed, command);\n return parsed;\n } catch {\n return null;\n }\n }\n\n private async requireCurrentTarget(targetId: string): Promise<TTarget> {\n const target = await this.driver.target(targetId);\n if (!target) {\n throw new InteractionControllerError(\n \"target_not_found\",\n `${this.adapter.resourceLabel} target ${JSON.stringify(targetId)} does not exist; list the current targets and use one of their ids`,\n );\n }\n const parsed = this.adapter.parseTarget(target);\n this.adapter.assertTargetAuthority(parsed);\n return parsed;\n }\n\n private makeReceipt(\n command: TCommand,\n state: InteractionOperationState,\n dispatchedAt: string | null,\n settledAt: string | null,\n observation: TObservation | null,\n error: InteractionError | null,\n ): TReceipt {\n return this.adapter.makeReceipt({\n command,\n state,\n dispatchedAt,\n settledAt,\n observation,\n error,\n });\n }\n\n private async settle(entry: JournalEntry<TReceipt>, receipt: TReceipt): Promise<TReceipt> {\n entry.receipt = receipt;\n try {\n await this.publish(entry.operationId, entry.commandDigest, receipt);\n entry.terminalPersisted = this.onJournalRecord !== undefined;\n } catch {\n // Controller-lifetime terminal truth remains authoritative. A restored\n // dispatched receipt is always recovered as outcome_unknown, never replayed.\n }\n return receipt;\n }\n\n private async failBeforeDispatch(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n message: string,\n ): Promise<TReceipt> {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", null, this.timestamp(), null, {\n code: \"driver_failed\",\n message,\n retryable: true,\n }),\n );\n }\n\n private async publish(\n operationId: string,\n commandDigest: string,\n receipt: TReceipt,\n ): Promise<void> {\n await this.onJournalRecord?.({ operationId, commandDigest, receipt });\n }\n\n private timestamp(): string {\n return this.now().toISOString();\n }\n\n private makeJournalSpace(): void {\n while (this.journal.size >= this.maxJournalEntries) {\n const terminal = [...this.journal.entries()].find(([, entry]) =>\n terminalStates.has(entry.kind === \"materialized\" ? entry.receipt.state : entry.state),\n );\n if (!terminal) {\n throw new InteractionControllerError(\n \"journal_full\",\n `${this.adapter.resourceLabel} operation journal has no safely evictable terminal entry`,\n true,\n );\n }\n this.journal.delete(terminal[0]);\n }\n }\n\n private restoreJournalRecord(record: InteractionOperationJournalRecord<TReceipt>): void {\n if (this.journal.has(record.operationId)) {\n throw new Error(`duplicate restored operation id: ${record.operationId}`);\n }\n const parsed = this.adapter.parseReceipt(record.receipt);\n if (parsed.operationId !== record.operationId) {\n throw new Error(`restored operation ${record.operationId} has another receipt id`);\n }\n const receipt = this.adapter.recoverReceipt(parsed, this.timestamp());\n const entry: JournalEntry<TReceipt> = {\n kind: \"materialized\",\n operationId: record.operationId,\n commandDigest: record.commandDigest,\n receipt,\n terminalPersisted: terminalStates.has(parsed.state),\n completion: Promise.resolve(receipt),\n preparationPersisted: Promise.resolve(true),\n };\n this.journal.set(record.operationId, entry);\n this.compactJournalEntry(entry);\n }\n\n private readReceipt(\n entry: JournalEntry<TReceipt> | CompactJournalEntry | PersistedJournalEntry,\n ): TReceipt {\n if (entry.kind === \"materialized\") return entry.receipt;\n if (entry.kind === \"persisted\") {\n const record = this.loadJournalRecord?.(entry.operationId);\n if (\n !record ||\n record.operationId !== entry.operationId ||\n record.commandDigest !== entry.commandDigest\n ) {\n throw new Error(`${this.adapter.resourceLabel} durable operation receipt is unavailable`);\n }\n const receipt = this.adapter.parseReceipt(record.receipt);\n if (digestJson(receipt) !== entry.receiptDigest) {\n throw new Error(`${this.adapter.resourceLabel} durable operation receipt changed`);\n }\n return receipt;\n }\n const json = inflateRawSync(entry.compressedReceipt, {\n maxOutputLength: entry.receiptBytes,\n });\n return this.adapter.parseReceipt(JSON.parse(json.toString(\"utf8\")));\n }\n\n private compactJournalEntry(entry: JournalEntry<TReceipt>): void {\n if (this.journal.get(entry.operationId) !== entry || !terminalStates.has(entry.receipt.state))\n return;\n try {\n if (entry.terminalPersisted && this.loadJournalRecord) {\n this.journal.set(entry.operationId, {\n kind: \"persisted\",\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n state: entry.receipt.state,\n receiptDigest: digestJson(entry.receipt),\n });\n return;\n }\n const json = JSON.stringify(entry.receipt);\n const receiptBytes = Buffer.byteLength(json);\n if (receiptBytes < COMPACT_RECEIPT_MIN_BYTES) return;\n const compressedReceipt = deflateRawSync(json, { level: 1 });\n this.journal.set(entry.operationId, {\n kind: \"compact\",\n operationId: entry.operationId,\n commandDigest: entry.commandDigest,\n state: entry.receipt.state,\n receiptBytes,\n compressedReceipt,\n });\n } catch {\n // Cache optimization must never change a settled mutation's outcome.\n // Retain the original receipt if serialization/compression is unavailable.\n }\n }\n}\n\nexport function recoverInteractionReceipt<TReceipt extends InteractionCoreReceipt<unknown>>(\n receipt: TReceipt,\n settledAt: string,\n resourceLabel: string,\n parse: (value: unknown) => TReceipt,\n): TReceipt {\n if (terminalStates.has(receipt.state)) return receipt;\n return parse({\n ...receipt,\n state: receipt.state === \"dispatched\" ? \"outcome_unknown\" : \"failed\",\n settledAt,\n observation: null,\n error:\n receipt.state === \"dispatched\"\n ? {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted after command dispatch`,\n retryable: false,\n }\n : {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted before command dispatch`,\n retryable: true,\n },\n });\n}\n\nfunction safePredispatchError(error: unknown, resourceLabel: string): InteractionError {\n if (error instanceof InteractionControllerError && error.code !== \"journal_full\") {\n return {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n };\n }\n return {\n code: \"driver_failed\",\n message: `${resourceLabel} command failed before dispatch`,\n retryable: false,\n };\n}\n\nfunction digestJson(value: unknown): string {\n return createHash(\"sha256\").update(canonicalJson(value), \"utf8\").digest(\"hex\");\n}\n\n/** Digest of every command field except the controller-private `secretValues`\n * side map: replays with fresh values (a new TOTP code) stay idempotent and\n * the journal never binds plaintext. Equals the default digest of the same\n * command without the map. */\nexport function secretFreeCommandDigest(command: object): string {\n if (!(\"secretValues\" in command)) return digestJson(command);\n const { secretValues: _private, ...rest } = command as { secretValues?: unknown };\n return digestJson(rest);\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n","import type { ComputerOperationReceipt } from \"@opengeni/contracts\";\n\nconst MAX_RESULT_BYTES = 12 * 1024 * 1024;\nconst bytes = (value: unknown) => new TextEncoder().encode(JSON.stringify(value)).byteLength;\n\n/** Transport projection only. The controller journal retains the original result.\n * Keep below Code Mode's 16 MiB completion bound as well as the HTTP envelope. */\nexport function boundComputerNativeReceipt<T extends ComputerOperationReceipt>(receipt: T): T {\n if (receipt.targetId !== null || !receipt.observation || bytes(receipt) <= MAX_RESULT_BYTES)\n return receipt;\n const original = receipt.observation.result;\n let remaining = 8 * 1024 * 1024;\n const content = original.content.filter((part) => {\n const size = bytes(part);\n if (size > remaining) return false;\n remaining -= size;\n return true;\n });\n content.push({\n type: \"text\",\n text: JSON.stringify({\n outputTruncated: true,\n operationId: receipt.operationId,\n state: receipt.state,\n guidance:\n \"Some CUA output exceeded the response limit. The original result remains in the controller journal. Do not repeat the action to retrieve output. Read current state with a smaller image or tree, or inspect the retained journal.\",\n }),\n });\n return {\n ...receipt,\n observation: {\n ...receipt.observation,\n result: {\n content,\n // The operation state is unchanged; only this response is incomplete.\n // Skip the upstream output-schema check for the truncated projection.\n isError: true,\n ...(original.structuredContent && bytes(original.structuredContent) <= 1024 * 1024\n ? { structuredContent: original.structuredContent }\n : {}),\n _meta: { opengeniOutputTruncated: true },\n },\n },\n } as T;\n}\n"],"mappings":"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","names":["canonicalJson","canonicalJsonValue"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/interaction",
3
- "version": "4.4.1",
3
+ "version": "4.5.0",
4
4
  "description": "Provider-neutral browser and computer interaction controller for Opengeni.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -36,7 +36,7 @@
36
36
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
37
37
  },
38
38
  "dependencies": {
39
- "@opengeni/contracts": "4.4.1"
39
+ "@opengeni/contracts": "4.5.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=18"
@@ -176,6 +176,10 @@ export type InteractionControllerCoreOptions<
176
176
  * The callback must bind every non-secret semantic input while excluding the
177
177
  * value bytes themselves and return lowercase SHA-256. */
178
178
  commandDigest?: (command: TCommand) => string;
179
+ /** Operator logging for a dispatch that threw something the driver did not
180
+ * classify. The caller still sees only outcome_unknown; this hook keeps the
181
+ * cause from disappearing. It never changes the operation's outcome. */
182
+ onUnexpectedDispatchError?: (error: unknown, command: TCommand) => void;
179
183
  };
180
184
 
181
185
  type JournalEntry<TReceipt> = InteractionOperationJournalRecord<TReceipt> & {
@@ -232,6 +236,9 @@ export class InteractionControllerCore<
232
236
  | ((record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void)
233
237
  | undefined;
234
238
  private readonly commandDigest: (command: TCommand) => string;
239
+ private readonly onUnexpectedDispatchError:
240
+ | ((error: unknown, command: TCommand) => void)
241
+ | undefined;
235
242
  private readonly loadJournalRecord:
236
243
  | ((operationId: string) => InteractionOperationJournalRecord<TReceipt> | null)
237
244
  | undefined;
@@ -252,6 +259,7 @@ export class InteractionControllerCore<
252
259
  this.onJournalRecord = options.onJournalRecord;
253
260
  this.loadJournalRecord = options.loadJournalRecord;
254
261
  this.commandDigest = options.commandDigest ?? digestJson;
262
+ this.onUnexpectedDispatchError = options.onUnexpectedDispatchError;
255
263
  if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {
256
264
  throw new Error("maxJournalEntries must be a positive safe integer");
257
265
  }
@@ -481,6 +489,11 @@ export class InteractionControllerCore<
481
489
  ),
482
490
  );
483
491
  }
492
+ try {
493
+ this.onUnexpectedDispatchError?.(error, command);
494
+ } catch {
495
+ // Diagnostics never change an operation's outcome.
496
+ }
484
497
  return await this.settle(
485
498
  entry,
486
499
  this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
package/src/index.ts CHANGED
@@ -72,6 +72,8 @@ export type BrowserInteractionControllerOptions = {
72
72
  onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;
73
73
  /** Reads the same durable authority as onJournalRecord and initialJournal. */
74
74
  loadJournalRecord?: (operationId: string) => BrowserOperationJournalRecord | null;
75
+ /** Operator logging for a dispatch error the driver did not classify. */
76
+ onUnexpectedDispatchError?: (error: unknown, command: BrowserActionCommandValue) => void;
75
77
  };
76
78
 
77
79
  /** Placement-resident BrowserSession mutation authority. */
@@ -95,6 +97,9 @@ export class BrowserInteractionController {
95
97
  ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),
96
98
  ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),
97
99
  ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),
100
+ ...(options.onUnexpectedDispatchError
101
+ ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError }
102
+ : {}),
98
103
  commandDigest: (command) => secretFreeCommandDigest(command),
99
104
  adapter: {
100
105
  resourceLabel: "browser",
@@ -274,6 +279,8 @@ export type ComputerInteractionControllerOptions = {
274
279
  onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;
275
280
  /** Reads the same durable authority as onJournalRecord and initialJournal. */
276
281
  loadJournalRecord?: (operationId: string) => ComputerOperationJournalRecord | null;
282
+ /** Operator logging for a dispatch error the driver did not classify. */
283
+ onUnexpectedDispatchError?: (error: unknown, command: ComputerOperationCommand) => void;
277
284
  };
278
285
 
279
286
  /** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,
@@ -358,6 +365,9 @@ export class ComputerInteractionController {
358
365
  ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),
359
366
  ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),
360
367
  ...(options.loadJournalRecord ? { loadJournalRecord: options.loadJournalRecord } : {}),
368
+ ...(options.onUnexpectedDispatchError
369
+ ? { onUnexpectedDispatchError: options.onUnexpectedDispatchError }
370
+ : {}),
361
371
  commandDigest: (command) => secretFreeCommandDigest(command),
362
372
  adapter: {
363
373
  resourceLabel: "computer",