diff --git a/packages/daemon/src/__tests__/support/handlers/session-command-harness.ts b/packages/daemon/src/__tests__/support/handlers/session-command-harness.ts index a74329053b..0d594f15ab 100644 --- a/packages/daemon/src/__tests__/support/handlers/session-command-harness.ts +++ b/packages/daemon/src/__tests__/support/handlers/session-command-harness.ts @@ -26,7 +26,7 @@ import { applicationLifecycleRuntimeFixture, type LifecycleOperationsLoader, } from '../application-lifecycle-runtime-fixture.ts'; -import { withClientReplayScriptSources } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { withClientReplayScriptSources } from '../replay-script-source-fixture.ts'; import { createUnavailableRuntimeFactsForTest } from '@agent-device/test-kit'; import { platformResourceCleanupFixture } from '../platform-resource-cleanup-fixture.ts'; diff --git a/packages/daemon/src/__tests__/support/replay-script-source-fixture.ts b/packages/daemon/src/__tests__/support/replay-script-source-fixture.ts new file mode 100644 index 0000000000..8e23bf18ce --- /dev/null +++ b/packages/daemon/src/__tests__/support/replay-script-source-fixture.ts @@ -0,0 +1,76 @@ +import fs from 'node:fs'; +import type { ReplayScriptSourceBundle } from '@agent-device/contracts/replay'; +import type { DaemonWireRequest } from '@agent-device/contracts/command'; +import { resolveUserPath } from '@agent-device/host-kit/file'; +import { loadReplayScriptSourceBundle } from '@agent-device/replay-port/script-source-bundle'; +import { discoverReplaySourcePaths } from '@agent-device/replay-port/source-discovery'; + +/** A native `.ad` script's one-entry source bundle for test requests. */ +export function replayScriptSourceBundleFor(filePath: string): ReplayScriptSourceBundle { + const entry = resolveUserPath(filePath, { cwd: process.cwd() }); + return { entry, files: { [entry]: fs.readFileSync(entry, 'utf8') } }; +} + +/** A Maestro flow's bundle — async because the engine that walks its includes loads on demand. */ +export async function maestroScriptSourceBundleFor( + filePath: string, +): Promise { + return await loadReplayScriptSourceBundle({ + inputPath: filePath, + cwd: process.cwd(), + replayBackend: 'maestro', + }); +} + +/** + * Attaches the script sources a real client would have collected for a `replay`/`test` request + * (#1802): the daemon opens no caller path, so every request that reaches one carries them. + * Test harnesses that stand in for "a request as it arrives at the daemon" call this so their + * cases keep expressing what they are about; a request that already carries its own sources (or + * deliberately carries none, to pin the daemon's refusal) is returned untouched. + * + * Collection that cannot succeed — a case driving `replay` at a path that deliberately does not + * exist — leaves the request alone rather than throwing: the real client raises that failure at + * the CLI boundary (pinned in `cli-client-commands.test.ts`), and a daemon-level harness must + * still deliver the request so the daemon's own response is what the case observes. + */ +export async function withClientReplayScriptSources( + req: DaemonWireRequest, +): Promise { + if (req.command !== 'replay' && req.command !== 'test') return req; + const inputs = req.positionals ?? []; + const entryPath = inputs[0]; + if (entryPath === undefined) return req; + const cwd = req.meta?.cwd ?? process.cwd(); + const replayBackend = req.flags?.replayBackend; + try { + if (req.command === 'replay') { + if (req.flags?.replayScriptSource) return req; + return withFlags(req, { + replayScriptSource: await loadReplayScriptSourceBundle({ + inputPath: entryPath, + cwd, + replayBackend, + }), + }); + } + if (req.flags?.replayScriptSources) return req; + return withFlags(req, { + replayScriptSources: await Promise.all( + discoverReplaySourcePaths({ inputs, cwd, replayBackend }).map( + async (inputPath) => + await loadReplayScriptSourceBundle({ inputPath, cwd, replayBackend }), + ), + ), + }); + } catch { + return req; + } +} + +function withFlags( + req: DaemonWireRequest, + flags: Partial>, +): DaemonWireRequest { + return { ...req, flags: { ...(req.flags ?? {}), ...flags } }; +} diff --git a/packages/daemon/src/__tests__/support/test-device-runtime-gateway.ts b/packages/daemon/src/__tests__/support/test-device-runtime-gateway.ts index 3076678496..82a4f381bc 100644 --- a/packages/daemon/src/__tests__/support/test-device-runtime-gateway.ts +++ b/packages/daemon/src/__tests__/support/test-device-runtime-gateway.ts @@ -25,7 +25,7 @@ import { type LifecycleOperationsLoader, } from './application-lifecycle-runtime-fixture.ts'; import { createUnavailableRuntimeFactsForTest } from '@agent-device/test-kit'; -import { withClientReplayScriptSources } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { withClientReplayScriptSources } from './replay-script-source-fixture.ts'; import type { DaemonInvokeFn } from '../../core/daemon-request.ts'; import { clearAndroidObservationFixture } from './android-observation-fixture.ts'; import { diff --git a/packages/daemon/src/core/__tests__/request-ended-leases.test.ts b/packages/daemon/src/core/__tests__/request-ended-leases.test.ts index b18b221fef..118325df52 100644 --- a/packages/daemon/src/core/__tests__/request-ended-leases.test.ts +++ b/packages/daemon/src/core/__tests__/request-ended-leases.test.ts @@ -3,7 +3,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from 'vitest'; import { mkdtempForTestSync } from '@agent-device/test-kit'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../__tests__/support/replay-script-source-fixture.ts'; import { makeSessionStore } from '../../__tests__/support/store-factory.ts'; import { makeIosSession } from '../../__tests__/support/session-factories.ts'; import { diff --git a/packages/daemon/src/execution/interaction/internal/interaction-ios-tap-outcome.test.ts b/packages/daemon/src/execution/interaction/internal/interaction-ios-tap-outcome.test.ts index 2947916412..e670207bef 100644 --- a/packages/daemon/src/execution/interaction/internal/interaction-ios-tap-outcome.test.ts +++ b/packages/daemon/src/execution/interaction/internal/interaction-ios-tap-outcome.test.ts @@ -18,7 +18,7 @@ import { import { makeSessionStore } from '../../../__tests__/support/store-factory.ts'; import { SessionScriptWriter } from '../../../core/session-script-writer.ts'; import { runReplayForTest } from '../../../sessions/__tests__/replay-runtime/replay-command-fixture.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { imageViewerNodes, profileNodes, diff --git a/packages/daemon/src/server/__tests__/replay-device-selection.test.ts b/packages/daemon/src/server/__tests__/replay-device-selection.test.ts index 92acff88c5..1f7e889e26 100644 --- a/packages/daemon/src/server/__tests__/replay-device-selection.test.ts +++ b/packages/daemon/src/server/__tests__/replay-device-selection.test.ts @@ -12,7 +12,7 @@ import { mkdtempForTestSync } from '@agent-device/test-kit'; import { maestroScriptSourceBundleFor, replayScriptSourceBundleFor, -} from '@agent-device/replay-port/replay-script-source-fixtures'; +} from '../../__tests__/support/replay-script-source-fixture.ts'; test('replay leaves deep-link opens to normal device resolution', async () => { const root = mkdtempForTestSync('agent-device-replay-device-selection-'); diff --git a/packages/daemon/src/server/__tests__/request-router-open.test.ts b/packages/daemon/src/server/__tests__/request-router-open.test.ts index dab08fb9e6..94d364b3ce 100644 --- a/packages/daemon/src/server/__tests__/request-router-open.test.ts +++ b/packages/daemon/src/server/__tests__/request-router-open.test.ts @@ -7,7 +7,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { getResolveTargetDeviceMock } from '../../__tests__/support/request-router-dispatch-mocks.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../__tests__/support/replay-script-source-fixture.ts'; import { fakeCreateCommandSurface } from '../../__tests__/support/command-surface-fake.ts'; vi.mock('../../core/device/device-ready.ts', () => ({ ensureDeviceReady: vi.fn(async () => {}) })); diff --git a/packages/daemon/src/server/__tests__/request-router-replay-env.test.ts b/packages/daemon/src/server/__tests__/request-router-replay-env.test.ts index a6d6abae34..41d46f6991 100644 --- a/packages/daemon/src/server/__tests__/request-router-replay-env.test.ts +++ b/packages/daemon/src/server/__tests__/request-router-replay-env.test.ts @@ -6,7 +6,7 @@ import { makeSessionStore } from '../../__tests__/support/store-factory.ts'; import { LeaseRegistry } from '../../resources/lease-registry.ts'; import { createRequestHandler } from '../../__tests__/support/test-device-runtime-gateway.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../__tests__/support/replay-script-source-fixture.ts'; import { fakeCreateCommandSurface } from '../../__tests__/support/command-surface-fake.ts'; function createHarness() { diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts index 98fbef51d1..35269909f5 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts @@ -6,7 +6,7 @@ import { getReplayBackend } from '@agent-device/replay-port/replay-backend-regis import { SessionStore } from '../../../core/session-store.ts'; import { replayCommandForTest } from '../replay-runtime/replay-command-fixture.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; -import { maestroScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { maestroScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-remote-evalscript.test.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-remote-evalscript.test.ts index 57f5a0b502..6c9ac99b12 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-remote-evalscript.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-remote-evalscript.test.ts @@ -7,7 +7,7 @@ import { LeaseRegistry } from '../../../resources/lease-registry.ts'; import { platformResourceCleanupFixture } from '../../../__tests__/support/platform-resource-cleanup-fixture.ts'; import { SessionStore } from '../../../core/session-store.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; -import { maestroScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { maestroScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; import { diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts index 7add259cb3..c8535c10f3 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts @@ -6,7 +6,7 @@ import { getReplayBackend } from '@agent-device/replay-port/replay-backend-regis import { SessionStore } from '../../../core/session-store.ts'; import { replayCommandForTest } from '../replay-runtime/replay-command-fixture.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; -import { maestroScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { maestroScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts index 8611419958..45d8ff4418 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts @@ -7,7 +7,7 @@ import { test } from 'vitest'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; import { SessionStore } from '../../../core/session-store.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; const { runReplayFixture, runReplayForTest, assertNoUnresolvedInterpolation } = diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-shell-artifacts.test.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-shell-artifacts.test.ts index 645acf364d..78c34fa7d0 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-shell-artifacts.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro-shell-artifacts.test.ts @@ -5,7 +5,7 @@ import path from 'node:path'; import { test } from 'vitest'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import { SessionStore } from '../../../core/session-store.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; const { runReplayFixture, runReplayForTest } = maestroReplayFixture; diff --git a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro.fixtures.ts b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro.fixtures.ts index 356601429d..8ba176c0a8 100644 --- a/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro.fixtures.ts +++ b/packages/daemon/src/sessions/__tests__/replay-maestro/session-replay-runtime-maestro.fixtures.ts @@ -52,7 +52,7 @@ import type { ReplayScriptSourceBundle } from '@agent-device/contracts/replay'; import { maestroScriptSourceBundleFor, replayScriptSourceBundleFor, -} from '@agent-device/replay-port/replay-script-source-fixtures'; +} from '../../../__tests__/support/replay-script-source-fixture.ts'; import { captureSnapshotThroughLegacyDispatchFixture } from '../../../__tests__/support/legacy-snapshot-capture-fixture.ts'; import { captureSnapshotWithInteractor } from '../../../core/snapshot-interactor-capture.ts'; import { seedReplayFixtureSession } from '../replay-runtime/session-replay-runtime.fixtures.ts'; diff --git a/packages/daemon/src/sessions/__tests__/replay-runtime/application.test.ts b/packages/daemon/src/sessions/__tests__/replay-runtime/application.test.ts index 1b265e3a66..356231cd54 100644 --- a/packages/daemon/src/sessions/__tests__/replay-runtime/application.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-runtime/application.test.ts @@ -11,7 +11,7 @@ import { } from '@agent-device/host-kit/request'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; -import { withClientReplayScriptSources } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { withClientReplayScriptSources } from '../../../__tests__/support/replay-script-source-fixture.ts'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; import { SessionStore } from '../../../core/session-store.ts'; import { diff --git a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime-failure.test.ts b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime-failure.test.ts index e382de1088..ace9f47e95 100644 --- a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime-failure.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime-failure.test.ts @@ -16,7 +16,7 @@ import { runReplayForTest } from './replay-command-fixture.ts'; import { SessionStore } from '../../../core/session-store.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; import { formatReplayDivergenceReport } from '@agent-device/ad-replay/divergence'; -import { maestroScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { maestroScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { captureSnapshotThroughLegacyDispatchFixture, legacyDispatchCapture, diff --git a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime.fixtures.ts b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime.fixtures.ts index f2dc5418e1..b2ad7357dc 100644 --- a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime.fixtures.ts +++ b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-runtime.fixtures.ts @@ -4,7 +4,7 @@ import { makeAndroidSession, makeIosSession, } from '../../../__tests__/support/session-factories.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import type { SessionStore } from '../../../core/session-store.ts'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; diff --git a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-script-source.test.ts b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-script-source.test.ts index 863cdd029c..5d72303d19 100644 --- a/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-script-source.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-runtime/session-replay-script-source.test.ts @@ -25,7 +25,7 @@ import { makeIosSession } from '../../../__tests__/support/session-factories.ts' import { maestroScriptSourceBundleFor, replayScriptSourceBundleFor, -} from '@agent-device/replay-port/replay-script-source-fixtures'; +} from '../../../__tests__/support/replay-script-source-fixture.ts'; import { REPLAY_SCRIPT_SOURCE_REQUIRED_MESSAGE } from '@agent-device/replay-port/script-source'; import { captureSnapshotThroughLegacyDispatchFixture, diff --git a/packages/daemon/src/sessions/__tests__/replay-suite/session-test-command-trust.test.ts b/packages/daemon/src/sessions/__tests__/replay-suite/session-test-command-trust.test.ts index 71728ea609..f085dbb5ee 100644 --- a/packages/daemon/src/sessions/__tests__/replay-suite/session-test-command-trust.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-suite/session-test-command-trust.test.ts @@ -12,7 +12,7 @@ import { } from '../../handlers/session-replay-command.ts'; import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import type { ReplayCommand, ReplayTestCommand } from '@agent-device/replay-port/command-types'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import type { DaemonInvokeFn, DaemonRequest } from '../../../core/daemon-request.ts'; diff --git a/packages/daemon/src/sessions/__tests__/replay-suite/session-test-suite-command-video.test.ts b/packages/daemon/src/sessions/__tests__/replay-suite/session-test-suite-command-video.test.ts index ad3a4e5910..afde24ba94 100644 --- a/packages/daemon/src/sessions/__tests__/replay-suite/session-test-suite-command-video.test.ts +++ b/packages/daemon/src/sessions/__tests__/replay-suite/session-test-suite-command-video.test.ts @@ -14,7 +14,7 @@ import { splitReplayCommandRequest, } from '@agent-device/replay-port/replay-dispatch-envelope'; import { mkdtempForTestSync } from '@agent-device/test-kit'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { unavailableBindDevice, unavailableBindExactDevice, diff --git a/packages/daemon/src/sessions/handlers/__tests__/session-command-replay.test.ts b/packages/daemon/src/sessions/handlers/__tests__/session-command-replay.test.ts index c151ad89ff..e653999fad 100644 --- a/packages/daemon/src/sessions/handlers/__tests__/session-command-replay.test.ts +++ b/packages/daemon/src/sessions/handlers/__tests__/session-command-replay.test.ts @@ -6,7 +6,7 @@ import { makeSessionStore } from '../../../__tests__/support/handlers/session-te import { handleSessionCommands } from '../../../__tests__/support/handlers/session-command-harness.ts'; import type { DaemonRequest } from '../../../core/daemon-request.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import { fakeCreateCommandSurface } from '../../../__tests__/support/command-surface-fake.ts'; diff --git a/packages/daemon/src/sessions/handlers/__tests__/session-replay-command.test.ts b/packages/daemon/src/sessions/handlers/__tests__/session-replay-command.test.ts index 1bbd4dd417..1ded68f43f 100644 --- a/packages/daemon/src/sessions/handlers/__tests__/session-replay-command.test.ts +++ b/packages/daemon/src/sessions/handlers/__tests__/session-replay-command.test.ts @@ -14,7 +14,7 @@ import { daemonPlatformServicesFixture } from '../../../__tests__/support/platfo import { makeSessionStore } from '../../../__tests__/support/handlers/session-test-harness.ts'; import { mkdtempForTestSync } from '@agent-device/test-kit'; import { fakeCreateCommandSurface } from '../../../__tests__/support/command-surface-fake.ts'; -import { withClientReplayScriptSources } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { withClientReplayScriptSources } from '../../../__tests__/support/replay-script-source-fixture.ts'; import { makeIosSession } from '../../../__tests__/support/session-factories.ts'; import { mockBindDeviceRuntime, diff --git a/packages/replay-port/package.json b/packages/replay-port/package.json index e5322c7016..23dbeafb58 100644 --- a/packages/replay-port/package.json +++ b/packages/replay-port/package.json @@ -135,10 +135,6 @@ "./source-discovery": { "types": "./src/source-discovery.ts", "default": "./src/source-discovery.ts" - }, - "./replay-script-source-fixtures": { - "types": "./src/replay-script-source.fixtures.ts", - "default": "./src/replay-script-source.fixtures.ts" } }, "devDependencies": { diff --git a/packages/replay-port/src/replay-script-source.fixtures.ts b/packages/replay-port/src/replay-script-source.fixtures.ts index d10529d1c2..0b826d84b1 100644 --- a/packages/replay-port/src/replay-script-source.fixtures.ts +++ b/packages/replay-port/src/replay-script-source.fixtures.ts @@ -1,19 +1,13 @@ -// The single owner of the client-collected replay source bundles test requests carry (#1802). import fs from 'node:fs'; import type { ReplayScriptSourceBundle } from '@agent-device/contracts/replay'; -import type { DaemonWireRequest } from '@agent-device/contracts/command'; -import type { MaestroSourceReader } from '@agent-device/maestro'; import { resolveUserPath } from '@agent-device/host-kit/file'; import { loadReplayScriptSourceBundle } from './script-source-bundle.ts'; -import { discoverReplaySourcePaths } from './source-discovery.ts'; -/** A native `.ad` script's one-entry source bundle for test requests. */ export function replayScriptSourceBundleFor(filePath: string): ReplayScriptSourceBundle { const entry = resolveUserPath(filePath, { cwd: process.cwd() }); return { entry, files: { [entry]: fs.readFileSync(entry, 'utf8') } }; } -/** A Maestro flow's bundle — async because the engine that walks its includes loads on demand. */ export async function maestroScriptSourceBundleFor( filePath: string, ): Promise { @@ -23,65 +17,3 @@ export async function maestroScriptSourceBundleFor( replayBackend: 'maestro', }); } - -/** - * `readSource` for a flow that declares no `runFlow` includes: the engine must - * never reach for one, so a call here means the fixture drifted rather than a - * missing file. - */ -export const noMaestroIncludeSources: MaestroSourceReader = (resolvedPath) => { - throw new Error(`unexpected Maestro include read: ${resolvedPath}`); -}; - -/** - * Attaches the script sources a real client would have collected for a `replay`/`test` request - * (#1802): the daemon opens no caller path, so every request that reaches one carries them. - * Test harnesses that stand in for "a request as it arrives at the daemon" call this so their - * cases keep expressing what they are about; a request that already carries its own sources (or - * deliberately carries none, to pin the daemon's refusal) is returned untouched. - * - * Collection that cannot succeed — a case driving `replay` at a path that deliberately does not - * exist — leaves the request alone rather than throwing: the real client raises that failure at - * the CLI boundary (pinned in `cli-client-commands.test.ts`), and a daemon-level harness must - * still deliver the request so the daemon's own response is what the case observes. - */ -export async function withClientReplayScriptSources( - req: DaemonWireRequest, -): Promise { - if (req.command !== 'replay' && req.command !== 'test') return req; - const inputs = req.positionals ?? []; - const entryPath = inputs[0]; - if (entryPath === undefined) return req; - const cwd = req.meta?.cwd ?? process.cwd(); - const replayBackend = req.flags?.replayBackend; - try { - if (req.command === 'replay') { - if (req.flags?.replayScriptSource) return req; - return withFlags(req, { - replayScriptSource: await loadReplayScriptSourceBundle({ - inputPath: entryPath, - cwd, - replayBackend, - }), - }); - } - if (req.flags?.replayScriptSources) return req; - return withFlags(req, { - replayScriptSources: await Promise.all( - discoverReplaySourcePaths({ inputs, cwd, replayBackend }).map( - async (inputPath) => - await loadReplayScriptSourceBundle({ inputPath, cwd, replayBackend }), - ), - ), - }); - } catch { - return req; - } -} - -function withFlags( - req: DaemonWireRequest, - flags: Partial>, -): DaemonWireRequest { - return { ...req, flags: { ...(req.flags ?? {}), ...flags } }; -} diff --git a/src/__tests__/daemon-composition/request-router-fill-text-stdin.test.ts b/src/__tests__/daemon-composition/request-router-fill-text-stdin.test.ts index 5da9c6d960..e3527c0557 100644 --- a/src/__tests__/daemon-composition/request-router-fill-text-stdin.test.ts +++ b/src/__tests__/daemon-composition/request-router-fill-text-stdin.test.ts @@ -20,7 +20,7 @@ import { } from '@agent-device/daemon/testing/__tests__/support/session-factories'; import { mkdtempForTestSync, WEB_DESKTOP_DEVICE } from '@agent-device/test-kit'; import { testCreateCommandSurface } from './command-surface-fixture.ts'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../test-utils/replay-script-source.fixtures.ts'; import { createPlatformRuntimeGateway, createRequestPlatformProviders, diff --git a/src/__tests__/daemon-composition/request-router-replay-test-ime.test.ts b/src/__tests__/daemon-composition/request-router-replay-test-ime.test.ts index 2c97fa005d..b76d96793c 100644 --- a/src/__tests__/daemon-composition/request-router-replay-test-ime.test.ts +++ b/src/__tests__/daemon-composition/request-router-replay-test-ime.test.ts @@ -38,7 +38,7 @@ vi.mock('@agent-device/platform-android/mechanics', async (importOriginal) => { import { ANDROID_DEVICE, mkdtempForTestSync } from '@agent-device/test-kit'; import { makeSessionStore } from '@agent-device/daemon/testing/__tests__/support/store-factory'; -import { replayScriptSourceBundleFor } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { replayScriptSourceBundleFor } from '../test-utils/replay-script-source.fixtures.ts'; import { LeaseRegistry } from '@agent-device/daemon/testing/lease-registry'; import { createRequestHandler } from '@agent-device/daemon/testing/__tests__/test-device-runtime-gateway'; import { realLifecycleDeviceRuntimeGateway } from './lifecycle-runtime-gateway.ts'; diff --git a/src/__tests__/test-utils/replay-script-source.fixtures.ts b/src/__tests__/test-utils/replay-script-source.fixtures.ts new file mode 100644 index 0000000000..322419ca41 --- /dev/null +++ b/src/__tests__/test-utils/replay-script-source.fixtures.ts @@ -0,0 +1,45 @@ +import fs from 'node:fs'; +import type { DaemonWireRequest } from '@agent-device/contracts/command'; +import type { ReplayScriptSourceBundle } from '@agent-device/contracts/replay'; +import { resolveUserPath } from '@agent-device/host-kit/file'; +import { loadReplayScriptSourceBundle } from '@agent-device/replay-port/script-source-bundle'; +import { discoverReplaySourcePaths } from '@agent-device/replay-port/source-discovery'; + +export function replayScriptSourceBundleFor(filePath: string): ReplayScriptSourceBundle { + const entry = resolveUserPath(filePath, { cwd: process.cwd() }); + return { entry, files: { [entry]: fs.readFileSync(entry, 'utf8') } }; +} + +/** Attaches the script sources a real client collects for `replay`/`test`; any other request passes through. */ +export async function withClientReplayScriptSources( + req: DaemonWireRequest, +): Promise { + const inputs = req.positionals ?? []; + if ((req.command !== 'replay' && req.command !== 'test') || inputs[0] === undefined) return req; + const cwd = req.meta?.cwd ?? process.cwd(); + const replayBackend = req.flags?.replayBackend; + const withFlags = (flags: NonNullable) => ({ + ...req, + flags: { ...req.flags, ...flags }, + }); + try { + if (req.command === 'replay') { + if (req.flags?.replayScriptSource) return req; + const replayScriptSource = await loadReplayScriptSourceBundle({ + inputPath: inputs[0], + cwd, + replayBackend, + }); + return withFlags({ replayScriptSource }); + } + if (req.flags?.replayScriptSources) return req; + const replayScriptSources = await Promise.all( + discoverReplaySourcePaths({ inputs, cwd, replayBackend }).map( + async (inputPath) => await loadReplayScriptSourceBundle({ inputPath, cwd, replayBackend }), + ), + ); + return withFlags({ replayScriptSources }); + } catch { + return req; + } +} diff --git a/test/integration/provider-scenarios/harness.ts b/test/integration/provider-scenarios/harness.ts index 41efc6bcef..702e3a97be 100644 --- a/test/integration/provider-scenarios/harness.ts +++ b/test/integration/provider-scenarios/harness.ts @@ -30,7 +30,7 @@ import type { DaemonInvokeFn } from '@agent-device/daemon'; import type { SessionState } from '@agent-device/daemon/testing/session-state'; import { runCmdBackground } from '@agent-device/host-kit/command'; import { createOwnedProcessRecordStore } from '@agent-device/host-kit/process'; -import { withClientReplayScriptSources } from '@agent-device/replay-port/replay-script-source-fixtures'; +import { withClientReplayScriptSources } from '../../../src/__tests__/test-utils/replay-script-source.fixtures.ts'; import type { DeviceInventoryProvider, ProviderDeviceRuntime,