From 38cd04ac1a00c0479700a9b948e02582127eb971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 28 Sep 2026 12:58:43 +0200 Subject: [PATCH] refactor(replay): move dispatch projections into replay-port --- packages/replay-port/package.json | 9 +++++++++ .../__tests__/replay-dispatch-envelope.test.ts | 11 +++++++---- .../__tests__/session-replay-maestro-request.test.ts | 0 .../src/daemon-port}/replay-dispatch-envelope.ts | 0 .../daemon-port}/session-replay-maestro-request.ts | 0 pnpm-lock.yaml | 3 +++ scripts/layering/architecture-ownership.ts | 2 -- src/daemon/handlers/session-replay-command.ts | 6 ++---- src/daemon/replay/__tests__/application.test.ts | 5 ++--- src/daemon/replay/__tests__/replay-command-fixture.ts | 6 +++++- src/daemon/replay/index.ts | 4 ---- .../session-test-suite-command-flag-policy.test.ts | 4 ++-- .../session-test-suite-command-video.test.ts | 4 ++-- .../replay/internal/session-replay-maestro-runtime.ts | 2 +- 14 files changed, 33 insertions(+), 23 deletions(-) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/__tests__/replay-dispatch-envelope.test.ts (84%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/__tests__/session-replay-maestro-request.test.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/replay-dispatch-envelope.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-maestro-request.ts (100%) diff --git a/packages/replay-port/package.json b/packages/replay-port/package.json index 98c90fadeb..64808197d2 100644 --- a/packages/replay-port/package.json +++ b/packages/replay-port/package.json @@ -10,6 +10,7 @@ "@agent-device/capture-kit": "workspace:*", "@agent-device/contracts": "workspace:*", "@agent-device/kernel": "workspace:*", + "@agent-device/maestro": "workspace:*", "@agent-device/replay-test": "workspace:*", "@agent-device/selectors": "workspace:*" }, @@ -22,10 +23,18 @@ "types": "./src/daemon-port/repair-hint.ts", "default": "./src/daemon-port/repair-hint.ts" }, + "./replay-dispatch-envelope": { + "types": "./src/daemon-port/replay-dispatch-envelope.ts", + "default": "./src/daemon-port/replay-dispatch-envelope.ts" + }, "./script-source": { "types": "./src/daemon-port/script-source.ts", "default": "./src/daemon-port/script-source.ts" }, + "./session-replay-maestro-request": { + "types": "./src/daemon-port/session-replay-maestro-request.ts", + "default": "./src/daemon-port/session-replay-maestro-request.ts" + }, "./session-replay-vars": { "types": "./src/session-replay-vars.ts", "default": "./src/session-replay-vars.ts" diff --git a/src/daemon/replay/internal/__tests__/replay-dispatch-envelope.test.ts b/packages/replay-port/src/daemon-port/__tests__/replay-dispatch-envelope.test.ts similarity index 84% rename from src/daemon/replay/internal/__tests__/replay-dispatch-envelope.test.ts rename to packages/replay-port/src/daemon-port/__tests__/replay-dispatch-envelope.test.ts index 90bb4cf8ab..02507c1939 100644 --- a/src/daemon/replay/internal/__tests__/replay-dispatch-envelope.test.ts +++ b/packages/replay-port/src/daemon-port/__tests__/replay-dispatch-envelope.test.ts @@ -1,9 +1,12 @@ import { expect, test } from 'vitest'; -import type { DaemonRequest } from '../../../daemon-request.ts'; +import type { ReplayDispatchOptions } from '@agent-device/contracts/replay'; +import type { ReplayPrivateAdmission, ReplayRequest } from '../replay-dispatch-envelope.ts'; import { replayInvokeOverDispatch } from '../replay-dispatch-envelope.ts'; +type TestRequest = ReplayRequest; + test('replayInvokeOverDispatch re-attaches the originating private half, then folds the dispatch bag over it', async () => { - const base: DaemonRequest = { + const base: TestRequest = { token: 'token', session: 'default', command: 'replay', @@ -16,7 +19,7 @@ test('replayInvokeOverDispatch re-attaches the originating private half, then fo }, }, }; - const invoked: DaemonRequest[] = []; + const invoked: TestRequest[] = []; const invoke = replayInvokeOverDispatch(async (request) => { invoked.push(request); return { ok: true, data: {} }; @@ -50,7 +53,7 @@ test('replayInvokeOverDispatch re-attaches the originating private half, then fo }); test('replayInvokeOverDispatch sends no private half when neither side carries one', async () => { - const invoked: DaemonRequest[] = []; + const invoked: TestRequest[] = []; const invoke = replayInvokeOverDispatch( async (request) => { invoked.push(request); diff --git a/src/daemon/replay/internal/__tests__/session-replay-maestro-request.test.ts b/packages/replay-port/src/daemon-port/__tests__/session-replay-maestro-request.test.ts similarity index 100% rename from src/daemon/replay/internal/__tests__/session-replay-maestro-request.test.ts rename to packages/replay-port/src/daemon-port/__tests__/session-replay-maestro-request.test.ts diff --git a/src/daemon/replay/internal/replay-dispatch-envelope.ts b/packages/replay-port/src/daemon-port/replay-dispatch-envelope.ts similarity index 100% rename from src/daemon/replay/internal/replay-dispatch-envelope.ts rename to packages/replay-port/src/daemon-port/replay-dispatch-envelope.ts diff --git a/src/daemon/replay/internal/session-replay-maestro-request.ts b/packages/replay-port/src/daemon-port/session-replay-maestro-request.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-maestro-request.ts rename to packages/replay-port/src/daemon-port/session-replay-maestro-request.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3236125e5..d13f54cd9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -518,6 +518,9 @@ importers: '@agent-device/kernel': specifier: workspace:* version: link:../kernel + '@agent-device/maestro': + specifier: workspace:* + version: link:../maestro '@agent-device/replay-test': specifier: workspace:* version: link:../replay-test diff --git a/scripts/layering/architecture-ownership.ts b/scripts/layering/architecture-ownership.ts index 7f27e29558..084aae0264 100644 --- a/scripts/layering/architecture-ownership.ts +++ b/scripts/layering/architecture-ownership.ts @@ -20,10 +20,8 @@ const DAEMON_REPLAY_FACADE = { 'buildReplayScriptPlatformFlags', 'healedScriptSiblingPath', 'readScriptReplaySelection', - 'replayInvokeOverDispatch', 'runReplayCommand', 'runReplayTestCommand', - 'splitReplayCommandRequest', ], } as const; diff --git a/src/daemon/handlers/session-replay-command.ts b/src/daemon/handlers/session-replay-command.ts index 276979ba5b..448a85ae2b 100644 --- a/src/daemon/handlers/session-replay-command.ts +++ b/src/daemon/handlers/session-replay-command.ts @@ -6,13 +6,11 @@ import { bindInternalObservationAuthority } from '../internal-observation.ts'; import type { LeaseRegistry } from '../lease-registry.ts'; import type { BindDeviceRuntime, InspectDeviceRuntimeFacts } from '../request-runtime-binding.ts'; import type { PlatformResourceCleanup } from '../platform-resource-cleanup.ts'; +import { bindReplaySession, runReplayCommand, runReplayTestCommand } from '../replay/index.ts'; import { - bindReplaySession, replayInvokeOverDispatch, - runReplayCommand, - runReplayTestCommand, splitReplayCommandRequest, -} from '../replay/index.ts'; +} from '@agent-device/replay-port/replay-dispatch-envelope'; import type { ReplayDaemonDependencies, ReplaySession, diff --git a/src/daemon/replay/__tests__/application.test.ts b/src/daemon/replay/__tests__/application.test.ts index c26bbf9730..490da59960 100644 --- a/src/daemon/replay/__tests__/application.test.ts +++ b/src/daemon/replay/__tests__/application.test.ts @@ -17,12 +17,11 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; +import { runReplayCommand, runReplayTestCommand } from '../index.ts'; import { replayInvokeOverDispatch, - runReplayCommand, - runReplayTestCommand, splitReplayCommandRequest, -} from '../index.ts'; +} from '@agent-device/replay-port/replay-dispatch-envelope'; import type { ReplayCommand, ReplayTestCommand } from '@agent-device/replay-port/command-types'; import { captureSnapshotWithInteractor } from '../../snapshot-interactor-capture.ts'; import { diff --git a/src/daemon/replay/__tests__/replay-command-fixture.ts b/src/daemon/replay/__tests__/replay-command-fixture.ts index e328861264..0797f7f534 100644 --- a/src/daemon/replay/__tests__/replay-command-fixture.ts +++ b/src/daemon/replay/__tests__/replay-command-fixture.ts @@ -5,7 +5,11 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; -import { replayInvokeOverDispatch, runReplayCommand, splitReplayCommandRequest } from '../index.ts'; +import { runReplayCommand } from '../index.ts'; +import { + replayInvokeOverDispatch, + splitReplayCommandRequest, +} from '@agent-device/replay-port/replay-dispatch-envelope'; import type { ReplayCommand } from '@agent-device/replay-port/command-types'; export type ReplayCommandTestInput = Readonly<{ diff --git a/src/daemon/replay/index.ts b/src/daemon/replay/index.ts index 1f9bcabd8a..d443840eed 100644 --- a/src/daemon/replay/index.ts +++ b/src/daemon/replay/index.ts @@ -2,10 +2,6 @@ export { runReplayCommand } from './internal/native-command.ts'; export { runReplayTestCommand } from './internal/test-command.ts'; export { bindReplaySession } from './internal/replay-session-binding.ts'; -export { - replayInvokeOverDispatch, - splitReplayCommandRequest, -} from './internal/replay-dispatch-envelope.ts'; export { healedScriptSiblingPath } from './internal/session-replay-heal.ts'; export { appTargetResolutionOptions, diff --git a/src/daemon/replay/internal/__tests__/session-test-suite-command-flag-policy.test.ts b/src/daemon/replay/internal/__tests__/session-test-suite-command-flag-policy.test.ts index 90a253a9b0..adf046e675 100644 --- a/src/daemon/replay/internal/__tests__/session-test-suite-command-flag-policy.test.ts +++ b/src/daemon/replay/internal/__tests__/session-test-suite-command-flag-policy.test.ts @@ -13,11 +13,11 @@ import { createReplaySession, replayDaemonDependencies, } from '../../../handlers/session-replay-command.ts'; +import { runReplayTestCommand } from '../../index.ts'; import { replayInvokeOverDispatch, - runReplayTestCommand, splitReplayCommandRequest, -} from '../../index.ts'; +} from '@agent-device/replay-port/replay-dispatch-envelope'; import type { ReplayTestCommand } from '@agent-device/replay-port/command-types'; import { REPLAY_ONLY_TEST_FLAG_REJECTIONS } from '../session-replay-test-policy.ts'; import { replayCommandFamily } from '../../../../commands/replay/index.ts'; diff --git a/src/daemon/replay/internal/__tests__/session-test-suite-command-video.test.ts b/src/daemon/replay/internal/__tests__/session-test-suite-command-video.test.ts index ff7792bf1c..874cf755bc 100644 --- a/src/daemon/replay/internal/__tests__/session-test-suite-command-video.test.ts +++ b/src/daemon/replay/internal/__tests__/session-test-suite-command-video.test.ts @@ -6,11 +6,11 @@ import { beforeEach, test, vi } from 'vitest'; import { SessionStore } from '../../../session-store.ts'; import type { DaemonRequest, DaemonResponse } from '../../../daemon-request.ts'; import { makeIosSession } from '../../../../__tests__/test-utils/session-factories.ts'; +import { runReplayTestCommand } from '../../index.ts'; import { replayInvokeOverDispatch, - runReplayTestCommand, splitReplayCommandRequest, -} from '../../index.ts'; +} from '@agent-device/replay-port/replay-dispatch-envelope'; import { mkdtempForTestSync } from '../../../../__tests__/test-utils/tmp-dir.ts'; import { replayScriptSourceBundleFor } from '../../../../__tests__/test-utils/replay-script-source.ts'; import { diff --git a/src/daemon/replay/internal/session-replay-maestro-runtime.ts b/src/daemon/replay/internal/session-replay-maestro-runtime.ts index 8c4a46a5c8..4980000e19 100644 --- a/src/daemon/replay/internal/session-replay-maestro-runtime.ts +++ b/src/daemon/replay/internal/session-replay-maestro-runtime.ts @@ -19,7 +19,7 @@ import { createDaemonMaestroRuntimePort } from '@agent-device/maestro/daemon-run import type { DeviceInfo } from '@agent-device/kernel/device'; import { buildReplayBuiltinVars } from '@agent-device/replay-port/session-replay-vars'; import { createMaestroReplayObserver } from './session-replay-maestro-observer.ts'; -import { maestroOperationDispatchRequest } from './session-replay-maestro-request.ts'; +import { maestroOperationDispatchRequest } from '@agent-device/replay-port/session-replay-maestro-request'; import { buildTypedMaestroReplayErrorResponse, buildTypedMaestroSuccessResponse,