<?php
require 'examples/boot.php';
$controller = __DIR__.'/controller.sh';
$command = [
'bash',
$controller,
'Reply exactly: protocol ready',
];
$process = proc_open(
$command,
[0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes,
dirname(__DIR__, 3),
);
if (! is_resource($process)) {
throw new RuntimeException('Unable to start the Tell shell controller.');
}
fclose($pipes[0]);
$nextSequence = 1;
$terminal = null;
while (($line = fgets($pipes[1])) !== false) {
$frame = json_decode($line, true, flags: JSON_THROW_ON_ERROR);
assert($frame['schema'] === 'tell.agent.frame.v2');
assert($frame['sequence'] === $nextSequence);
$nextSequence++;
if (in_array($frame['type'], ['result', 'error', 'cancelled'], true)) {
assert($terminal === null, 'Expected exactly one terminal protocol frame');
$terminal = $frame;
}
echo $frame['sequence'].' '.$frame['type']."\n";
}
$errors = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$exit = proc_close($process);
if ($errors !== '') {
fwrite(STDERR, $errors);
}
if ($exit !== 0) {
$details = json_encode($terminal['error'] ?? [], JSON_UNESCAPED_SLASHES);
throw new RuntimeException("Tell agent protocol exited with {$exit}: {$details}");
}
assert($terminal !== null, 'Expected a terminal protocol frame');
assert($terminal['type'] === 'result', 'Expected a successful result frame');
assert($terminal['result']['outcome'] === 'completed');
assert(str_contains(strtolower($terminal['result']['answer']), 'protocol ready'));
?>