Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scripts/agentic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"@farmslot/adapter-sdk": "0.25.2",
"@farmslot/recipe-cli": "0.32.1",
"@farmslot/recipe-runner": "0.46.2",
"pngjs": "^7.0.0"
"pngjs": "^7.0.0",
"@farmslot/adapter-rn": "0.29.2"
}
}
8 changes: 7 additions & 1 deletion scripts/agentic/recipe/provider.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { ADAPTER_SDK_VERSION } from '@farmslot/adapter-sdk';
import { createCdpVideoRecorder } from '@farmslot/recipe-runner';
import { createAndroidVideoRecorder, createIosSimulatorVideoRecorder } from '@farmslot/adapter-rn';
import { contextPorts } from '@farmslot/recipe-cli/harness';
import { recordingTarget } from './recording-target.mjs';
import { runOwnedRecipeProcess, recipeExecutionSignal } from '@farmslot/recipe-runner/adapters/core';
Expand Down Expand Up @@ -165,7 +166,12 @@ export function createProvider(context) {
})),
},
recording: { target: () => recordingTarget({ platform, serial, simulator, device: explicitDevice, iosDevice, cdp, metro }),
...(platform === 'web' ? { videoRecorder: async () => createCdpVideoRecorder({ cdpPort: cdp, urlIncludes: `:${metro}` }) } : {}),
videoRecorder: async () => {
if (platform === 'web') return createCdpVideoRecorder({ cdpPort: cdp, urlIncludes: `:${metro}` });
if (platform === 'android') return createAndroidVideoRecorder(serial);
if (!iosDevice && !explicitDevice?.startsWith('device:'))
return createIosSimulatorVideoRecorder(simulator || explicitDevice);
},
},
},
cancel() { if (launchedMetro) stopMetro(appRoot, metro); },
Expand Down
24 changes: 23 additions & 1 deletion scripts/agentic/recipe/provider.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,32 @@ test('web recording selects the shared CDP recorder and binds its assigned endpo
outputPath: path.join(os.tmpdir(), 'audiolab-endpoint-refusal.mp4'),
}), /different endpoint/);
const native = createProvider(context('playground', 'ios'));
assert.equal(native.runtime.recording.videoRecorder, undefined);
assert.equal((await native.runtime.recording.videoRecorder()).name, 'simctl');
assert.deepEqual(await native.runtime.recording.target(), { kind: 'simulator', device: 'assigned-simulator' });
});

test('native recording uses the shared recorder bound to the assigned target', async t => {
const saved = process.env.ADB_SERIAL;
t.after(() => { if (saved === undefined) delete process.env.ADB_SERIAL;else process.env.ADB_SERIAL = saved; });
for (const [serial, expected] of [['assigned-physical-device', 'adb-screenrecord'], ['emulator-5554', 'adb-screenrecord']]) {
process.env.ADB_SERIAL = serial;
const recording = createProvider(context('playground', 'android')).runtime.recording;
assert.equal(typeof recording.videoRecorder, 'function');
const recorder = await recording.videoRecorder();
assert.equal(recorder.name, expected);
assert.deepEqual(await recording.target(), { kind: 'android-device', serial });
await assert.rejects(recorder.start({ target: { kind: 'android-device', serial: 'foreign-device' }, outputPath: '/unused.mp4' }), /does not match/);
}
const recording = createProvider(context('playground', 'ios')).runtime.recording;
assert.equal(typeof recording.videoRecorder, 'function');
assert.equal((await recording.videoRecorder()).name, 'simctl');
const physical = context('playground', 'ios');
physical.options.device = 'device:assigned-iphone';
const unsupported = createProvider(physical).runtime.recording;
assert.equal(await unsupported.videoRecorder(), undefined);
await assert.rejects(unsupported.target(), /Physical iOS video capture is not declared/);
});

test('built-in verification observes the bound bridge and refuses missing route readiness', async t => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'audiolab-provider-verify-'));
t.after(() => fs.rm(root, { recursive: true, force: true }));
Expand Down
30 changes: 30 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5136,6 +5136,35 @@ __metadata:
languageName: node
linkType: hard

"@farmslot/adapter-rn@npm:0.29.2":
version: 0.29.2
resolution: "@farmslot/adapter-rn@npm:0.29.2"
dependencies:
"@farmslot/agent-runtime": "npm:0.39.8"
"@farmslot/protocol": "npm:0.74.0"
"@farmslot/recipe-runner": "npm:0.46.2"
pngjs: "npm:^7.0.0"
ws: "npm:^8.18.0"
peerDependencies:
agent-device: ">=0.19.3"
react: ">=19"
react-native: ">=0.79"
react-native-safe-area-context: ">=5"
peerDependenciesMeta:
agent-device:
optional: true
react:
optional: true
react-native:
optional: true
react-native-safe-area-context:
optional: true
bin:
farmslot-adapter-rn: ./bin/farmslot-adapter-rn.mjs
checksum: 10/7cd64667d767185cfae24148da4de5174720b65de9fa9a020617df2d97c9cbabd2ae4a56678ce95edead2511c299c6c4f988e9900003c0c27b7486f55fbb0b03
languageName: node
linkType: hard

"@farmslot/adapter-sdk@npm:0.25.2":
version: 0.25.2
resolution: "@farmslot/adapter-sdk@npm:0.25.2"
Expand Down Expand Up @@ -8749,6 +8778,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@siteed/audiolab-agentic@workspace:scripts/agentic"
dependencies:
"@farmslot/adapter-rn": "npm:0.29.2"
"@farmslot/adapter-sdk": "npm:0.25.2"
"@farmslot/recipe-cli": "npm:0.32.1"
"@farmslot/recipe-runner": "npm:0.46.2"
Expand Down
Loading