Answer the agents' questions on the page
Menus and permission prompts are read off a seat's screen and shown as labelled buttons (plus Esc); an agent that stopped with a question gets a reply box; queue items blocked on a human seat are decisions recorded with rig queue resolve. Notifications now carry the question itself. Claude-Session: https://claude.ai/code/session_01QhLkBGEip8wQdaZ54z4AqJ
This commit is contained in:
+85
-3
@@ -50,9 +50,91 @@ class WatcherTest(unittest.TestCase):
|
||||
w.events(snap(waiting=True))
|
||||
self.assertEqual(len(w.events(snap(waiting=True))), 1)
|
||||
|
||||
def test_prompt_pattern(self):
|
||||
self.assertTrue(server.PROMPT.search(" Do you want to proceed?\n ❯ 1. Yes"))
|
||||
self.assertFalse(server.PROMPT.search("❯ yes, launch it"))
|
||||
def test_gate_notifies_once(self):
|
||||
w = server.Watcher()
|
||||
w.events(snap())
|
||||
gate = {**q("7", "blocked", "operator-human@kernel"), "gate": True}
|
||||
self.assertEqual(w.events(snap(queue=[gate]))[-1][0], "Beslutning til dig")
|
||||
self.assertEqual(w.events(snap(queue=[gate])), [])
|
||||
|
||||
|
||||
PERMISSION = """[rig capture: operator-agent@kernel: 23 earlier lines not shown]
|
||||
● Bash(rig queue show qitem-1 --json)
|
||||
⎿ Waiting…
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
Bash command
|
||||
Tip: auto mode handles these prompts for you — choose "switch to auto mode"
|
||||
below
|
||||
Check whether the Chromium libraries are installed
|
||||
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
|
||||
│ dpkg-query -W -f='${Package} ${Status}\\n' libatk1.0-0t64
|
||||
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
|
||||
This command requires approval
|
||||
|
||||
Do you want to proceed?
|
||||
❯ 1. Yes
|
||||
2. Yes, and don’t ask again for: dpkg-query *
|
||||
3. Yes, and switch to auto mode · auto mode handles these prompts for you
|
||||
4. No
|
||||
|
||||
Esc to cancel · Tab to amend
|
||||
"""
|
||||
|
||||
QUESTION = """ - Install location: ~/rigs/workshop.
|
||||
|
||||
● Once it's running: I'll give the lead the whole task as a durable work item
|
||||
(spec file, branch, local commits only, no push). When it's done, I'll report
|
||||
back the commits and test results.
|
||||
|
||||
● Should I launch workshop like this (all Claude, prompts off, in
|
||||
/home/rig/work/wpp)?
|
||||
|
||||
✻ Churned for 1m 24s · done 4:26 PM
|
||||
|
||||
──────────────────────────────────────────────────────── operator-agent@kernel ─
|
||||
❯ yes, launch workshop all-claude
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
⏵⏵ accept edits on (shift+tab to cycle)
|
||||
"""
|
||||
|
||||
WORKING = """● Bash(cargo test --locked)
|
||||
⎿ Running…
|
||||
|
||||
✻ Crunching… (1m 7s · ↓ 3.3k tokens · thinking)
|
||||
|
||||
──────────────────────────────────────────────────────── dev-build@team ─
|
||||
❯
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
"""
|
||||
|
||||
|
||||
class ParseAskTest(unittest.TestCase):
|
||||
def test_permission_prompt(self):
|
||||
a = server.parse_ask(PERMISSION, idle=False)
|
||||
self.assertEqual(a["kind"], "menu")
|
||||
self.assertEqual(a["title"], "Do you want to proceed?")
|
||||
self.assertEqual([o["key"] for o in a["options"]], ["1", "2", "3", "4"])
|
||||
self.assertEqual(a["options"][1]["label"], "Yes, and don’t ask again for: dpkg-query *")
|
||||
|
||||
def test_question_when_idle(self):
|
||||
a = server.parse_ask(QUESTION, idle=True)
|
||||
self.assertEqual(a["kind"], "question")
|
||||
self.assertTrue(a["text"].startswith("Should I launch workshop"))
|
||||
self.assertTrue(a["text"].endswith("?"))
|
||||
|
||||
def test_question_needs_idle(self):
|
||||
self.assertIsNone(server.parse_ask(QUESTION, idle=False))
|
||||
|
||||
def test_working_is_not_a_question(self):
|
||||
self.assertIsNone(server.parse_ask(WORKING, idle=True))
|
||||
self.assertIsNone(server.parse_ask(WORKING, idle=False))
|
||||
|
||||
def test_numbered_list_without_cursor_is_not_a_menu(self):
|
||||
self.assertIsNone(server.parse_ask("● Plan:\n 1. engine\n 2. rooms\n", idle=False))
|
||||
|
||||
def test_ask_text_for_notifications(self):
|
||||
self.assertIn("2. Yes, and", server.ask_text(server.parse_ask(PERMISSION, idle=False)))
|
||||
|
||||
def test_seat_names(self):
|
||||
self.assertTrue(server.SEAT.match("dev-qa@ubl-workshop"))
|
||||
|
||||
Reference in New Issue
Block a user