mirror of
https://github.com/block/buzz.git
synced 2026-10-29 21:41:33 +00:00
58 lines
2.5 KiB
Python
Executable File
58 lines
2.5 KiB
Python
Executable File
#!/usr/bin/python3
|
|
"""Bounded text-only CLI adapter for the pinned Accumulator (macOS/Unix)."""
|
|
import os
|
|
import selectors
|
|
import shutil
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
|
|
def main():
|
|
# The upstream runner starts this adapter as a process-group leader.
|
|
# Keep the CLI in that group so the daemon's deadline contains both.
|
|
if os.getpgrp() != os.getpid():
|
|
sys.exit('The model adapter must be launched by the Accumulator.')
|
|
args = sys.argv[1:]
|
|
codex = args[:1] == ['exec']
|
|
binary = shutil.which('codex' if codex else 'claude')
|
|
if not binary:
|
|
sys.exit('Install and sign in to the selected model CLI.')
|
|
if codex:
|
|
args = args[:-1] + ['--ignore-user-config', '--disable', 'shell_tool', '--disable', 'multi_agent', '--disable', 'apps', '--disable', 'plugins', '-c', 'web_search="disabled"', '-c', 'tools.view_image=false', '-c', 'project_doc_max_bytes=0', '-c', 'model_reasoning_effort="low"', '-']
|
|
else:
|
|
args += ['--strict-mcp-config', '--mcp-config', '{"mcpServers":{}}', '--no-session-persistence', '--disable-slash-commands']
|
|
allowed = {'PATH', 'HOME', 'USER', 'TMPDIR', 'CODEX_HOME', 'HTTPS_PROXY', 'HTTP_PROXY', 'NO_PROXY', 'SSL_CERT_FILE', 'SSL_CERT_DIR', 'MAX_THINKING_TOKENS'}
|
|
env = {key: value for key, value in os.environ.items() if key in allowed}
|
|
child = subprocess.Popen([binary, *args], stdin=sys.stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
|
|
poller = selectors.DefaultSelector()
|
|
poller.register(child.stdout, selectors.EVENT_READ, sys.stdout.buffer)
|
|
poller.register(child.stderr, selectors.EVENT_READ, sys.stderr.buffer)
|
|
deadline = time.monotonic() + 590
|
|
size = 0
|
|
while poller.get_map():
|
|
if time.monotonic() > deadline:
|
|
os.killpg(os.getpgrp(), signal.SIGKILL)
|
|
for key, _ in poller.select(timeout=0.2):
|
|
chunk = os.read(key.fileobj.fileno(), 8192)
|
|
if not chunk:
|
|
poller.unregister(key.fileobj)
|
|
continue
|
|
size += len(chunk)
|
|
if size > 1_000_000:
|
|
sys.stderr.write('Model output exceeded the local briefing limit.\n')
|
|
sys.stderr.flush()
|
|
os.killpg(os.getpgrp(), signal.SIGKILL)
|
|
key.data.write(chunk)
|
|
key.data.flush()
|
|
while child.poll() is None:
|
|
if time.monotonic() > deadline:
|
|
os.killpg(os.getpgrp(), signal.SIGKILL)
|
|
time.sleep(0.05)
|
|
sys.exit(child.returncode)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|