feat(tess): add configurable pi interaction service
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
Jarvis
2026-07-12 21:37:53 -05:00
parent 86a50138a9
commit c58e86e2b9
20 changed files with 550 additions and 7 deletions

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
AGENT_NAME=${MOSAIC_AGENT_NAME:-}
RUNTIME=${MOSAIC_AGENT_RUNTIME:-}
MODEL=${MOSAIC_AGENT_MODEL:-}
REASONING=${MOSAIC_AGENT_REASONING:-}
TOOL_POLICY=${MOSAIC_AGENT_TOOL_POLICY:-}
[ -n "$AGENT_NAME" ] || { echo 'ERROR: MOSAIC_AGENT_NAME is required' >&2; exit 64; }
[[ "$AGENT_NAME" =~ ^[A-Za-z0-9_.-]+$ ]] || { echo 'ERROR: invalid agent name' >&2; exit 64; }
[ "$RUNTIME" = 'pi' ] || { echo 'ERROR: invalid runtime policy' >&2; exit 64; }
[ "$MODEL" = 'openai/gpt-5.6-sol' ] || { echo 'ERROR: invalid model policy' >&2; exit 64; }
[ "$REASONING" = 'high' ] || { echo 'ERROR: invalid reasoning policy' >&2; exit 64; }
[ "$TOOL_POLICY" = 'operator-interaction' ] || { echo 'ERROR: invalid tool policy' >&2; exit 64; }
printf '{"agentName":"%s","runtime":"%s","model":"%s","reasoning":"%s","toolPolicy":"%s"}\n' \
"$AGENT_NAME" "$RUNTIME" "$MODEL" "$REASONING" "$TOOL_POLICY"

View File

@@ -8,6 +8,7 @@ AGENT_NAME=${1:-${MOSAIC_AGENT_NAME:-}}
MOSAIC_TMUX_SOCKET=${MOSAIC_TMUX_SOCKET:-}
MOSAIC_AGENT_RUNTIME=${MOSAIC_AGENT_RUNTIME:-pi}
MOSAIC_AGENT_MODEL=${MOSAIC_AGENT_MODEL:-}
MOSAIC_AGENT_REASONING=${MOSAIC_AGENT_REASONING:-}
MOSAIC_AGENT_WORKDIR=${MOSAIC_AGENT_WORKDIR:-$HOME}
MOSAIC_AGENT_COMMAND=${MOSAIC_AGENT_COMMAND:-}
MOSAIC_HEARTBEAT_RUN_DIR=${MOSAIC_HEARTBEAT_RUN_DIR:-${MOSAIC_HOME:-$HOME/.config/mosaic}/fleet/run}
@@ -18,6 +19,14 @@ if [ -z "$AGENT_NAME" ]; then
exit 64
fi
case "$MOSAIC_AGENT_REASONING" in
''|low|medium|high) ;;
*)
echo "ERROR: MOSAIC_AGENT_REASONING must be low, medium, or high" >&2
exit 64
;;
esac
if ! command -v tmux >/dev/null 2>&1; then
echo "ERROR: tmux is required" >&2
exit 69
@@ -41,7 +50,7 @@ fi
if [ -z "$MOSAIC_AGENT_COMMAND" ]; then
# Map the roster's per-agent model_hint to `--model` so workers launch on the
# configured model (e.g. pi on openai-codex/gpt-5.5:high). Omitted when unset.
MOSAIC_AGENT_COMMAND="mosaic yolo $MOSAIC_AGENT_RUNTIME${MOSAIC_AGENT_MODEL:+ --model $MOSAIC_AGENT_MODEL}"
MOSAIC_AGENT_COMMAND="mosaic yolo $MOSAIC_AGENT_RUNTIME${MOSAIC_AGENT_MODEL:+ --model $MOSAIC_AGENT_MODEL}${MOSAIC_AGENT_REASONING:+ --thinking $MOSAIC_AGENT_REASONING}"
fi
# ── Derive a runtime-bin PATH prefix ─────────────────────────────────────────
@@ -124,11 +133,12 @@ AGENT_NAME_Q=$(printf '%q' "$AGENT_NAME")
# safe single bash token; an empty/unset class %q-quotes to '' and is a harmless
# no-op downstream (readPersonaContractBlock returns '' for an empty class).
AGENT_CLASS_Q=$(printf '%q' "${MOSAIC_AGENT_CLASS:-}")
AGENT_TOOL_POLICY_Q=$(printf '%q' "${MOSAIC_AGENT_TOOL_POLICY:-}")
if [ -n "$MOSAIC_RUNTIME_BIN_PREFIX" ]; then
PANE_SHELL_SNIPPET="export MOSAIC_AGENT_NAME=${AGENT_NAME_Q}; export MOSAIC_AGENT_CLASS=${AGENT_CLASS_Q}; export PATH=\"${MOSAIC_RUNTIME_BIN_PREFIX}:\${PATH}\"; exec ${MOSAIC_AGENT_COMMAND}"
PANE_SHELL_SNIPPET="export MOSAIC_AGENT_NAME=${AGENT_NAME_Q}; export MOSAIC_AGENT_CLASS=${AGENT_CLASS_Q}; export MOSAIC_AGENT_TOOL_POLICY=${AGENT_TOOL_POLICY_Q}; export PATH=\"${MOSAIC_RUNTIME_BIN_PREFIX}:\${PATH}\"; exec ${MOSAIC_AGENT_COMMAND}"
else
PANE_SHELL_SNIPPET="export MOSAIC_AGENT_NAME=${AGENT_NAME_Q}; export MOSAIC_AGENT_CLASS=${AGENT_CLASS_Q}; exec ${MOSAIC_AGENT_COMMAND}"
PANE_SHELL_SNIPPET="export MOSAIC_AGENT_NAME=${AGENT_NAME_Q}; export MOSAIC_AGENT_CLASS=${AGENT_CLASS_Q}; export MOSAIC_AGENT_TOOL_POLICY=${AGENT_TOOL_POLICY_Q}; exec ${MOSAIC_AGENT_COMMAND}"
fi
mkdir -p "$MOSAIC_AGENT_WORKDIR"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
AGENT_NAME=${1:-}
fail() {
echo "ERROR: $*" >&2
exit 64
}
[ -n "$AGENT_NAME" ] || fail "agent name argument is required"
[[ "$AGENT_NAME" =~ ^[A-Za-z0-9_.-]+$ ]] || fail "agent name contains unsupported characters"
[ "${MOSAIC_AGENT_NAME:-}" = "$AGENT_NAME" ] || fail "configured agent name must exactly match the service instance"
[ "${MOSAIC_AGENT_RUNTIME:-}" = "pi" ] || fail "operator interaction service requires runtime pi"
[ "${MOSAIC_AGENT_MODEL:-}" = "openai/gpt-5.6-sol" ] || fail "operator interaction service requires the pinned model"
[ "${MOSAIC_AGENT_REASONING:-}" = "high" ] || fail "operator interaction service requires high reasoning"
[ "${MOSAIC_AGENT_TOOL_POLICY:-}" = "operator-interaction" ] || fail "operator interaction service requires the operator-interaction tool policy"
exec "$(cd -- "$(dirname -- "$0")" && pwd)/start-agent-session.sh" "$AGENT_NAME"

View File

@@ -105,6 +105,7 @@ MOSAIC_TMUX_SOCKET="$SOCKET3" \
MOSAIC_AGENT_WORKDIR="$WORKDIR3" \
MOSAIC_AGENT_RUNTIME="pi" \
MOSAIC_AGENT_CLASS="code" \
MOSAIC_AGENT_TOOL_POLICY="operator-interaction" \
MOSAIC_RUNTIME_BIN="$FAKE_RUNTIME_BIN" \
MOSAIC_AGENT_COMMAND="mosaic yolo pi --model openai-codex/gpt-5.5:high" \
MOSAIC_HEARTBEAT_RUN_DIR="$HB_RUN_DIR3" \
@@ -139,6 +140,8 @@ echo "$all_args" | grep -qF "export MOSAIC_AGENT_NAME=" || \
fail "pane command does not export MOSAIC_AGENT_NAME into the pane"
echo "$all_args" | grep -qF "export MOSAIC_AGENT_CLASS=code" || \
fail "pane command does not export MOSAIC_AGENT_CLASS into the pane (persona would silently drop)"
echo "$all_args" | grep -qF "export MOSAIC_AGENT_TOOL_POLICY=operator-interaction" || \
fail "pane command does not export MOSAIC_AGENT_TOOL_POLICY into the pane"
# ── Test 4: when no extra runtime-bin dirs exist, exec still appears ───────────
TMUX_ARGS_FILE2=$(mktemp)