feat: add typing-time autosuggest to slash commands - #38
Conversation
|
Thanks for the detailed PR! The autosuggest feature is a nice idea, but there are several issues that prevent merging as-is:
If you'd like to revisit this, I'd suggest:
Thanks again for the contribution! |
…ar import Addresses all five points raised in PR SAIL-Research-Lab#38 review: 1. Hard dep vs fallback contradiction — move prompt_toolkit out of [project.dependencies] into [project.optional-dependencies] under a new `autosuggest` extra. requirements.txt marks it optional with a comment. The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path. 2. History file format conflict — introduce a sibling history file for prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(), leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no longer risks corrupting either file. 3. Circular import risk — ui/input.py no longer imports cheetahclaws. Providers are injected via ui.input.setup(commands_provider, meta_provider) from repl(); SlashCompleter reads module-level providers (or ctor overrides for tests). Added test_module_does_not_import_cheetahclaws as a structural regression guard. 4. Multi-line paste notification parity — after _pt_read_line returns, _read_input counts embedded \\n and emits the same info("(pasted N lines)") message as the readline phase-2 path, preserving user-visible behavior. 5. Bug fix mixed with feature — setup_readline reverted to its pre-patch state. The /c/cwd readline glue fix now lives entirely on main; this PR only adds the prompt_toolkit input path. Folded in self-review items: reset_session() helper to drop a stale cached session after a prompt_toolkit failure; richer exception context in the fallback warn; session cache now invalidates on history_path change; completer cache keyed on full sorted tuple of command names. Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards for setup injection and no-circular-import); full suite 306 passing (test_voice and test_diff_view excluded — pre-existing, unrelated).
1d8b463 to
4f3305e
Compare
|
Thanks for the careful review — all five points addressed in the latest push. |
Replace the Tab-only readline completer with a prompt_toolkit
PromptSession that renders an inline ghost suggestion while typing
and a keyboard-selectable completion menu.
Fixes three user-visible defects in the REPL:
1. No as-you-type suggestion — completion only fired on Tab.
2. The popped-up match list was not selectable (no menu-complete
binding, no arrow-key handling; the display hook was pure stdout.write).
3. Typing `/c` followed by more input dispatched as `/c/cwd` →
"Unknown command", because `/` had been removed from readline's
word delimiters and `handle_slash` splits only on whitespace.
Also surfaces modular/plugin/skill commands in completion for the first time.
The previous completer read only the hand-maintained `_CMD_META` dict,
while the dispatcher consulted the full live `COMMANDS` registry.
…ar import Addresses all five points raised in PR SAIL-Research-Lab#38 review: 1. Hard dep vs fallback contradiction — move prompt_toolkit out of [project.dependencies] into [project.optional-dependencies] under a new `autosuggest` extra. requirements.txt marks it optional with a comment. The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path. 2. History file format conflict — introduce a sibling history file for prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(), leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no longer risks corrupting either file. 3. Circular import risk — ui/input.py no longer imports cheetahclaws. Providers are injected via ui.input.setup(commands_provider, meta_provider) from repl(); SlashCompleter reads module-level providers (or ctor overrides for tests). Added test_module_does_not_import_cheetahclaws as a structural regression guard. 4. Multi-line paste notification parity — after _pt_read_line returns, _read_input counts embedded \\n and emits the same info("(pasted N lines)") message as the readline phase-2 path, preserving user-visible behavior. 5. Bug fix mixed with feature — setup_readline reverted to its pre-patch state. The /c/cwd readline glue fix now lives entirely on main; this PR only adds the prompt_toolkit input path. Folded in self-review items: reset_session() helper to drop a stale cached session after a prompt_toolkit failure; richer exception context in the fallback warn; session cache now invalidates on history_path change; completer cache keyed on full sorted tuple of command names. Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards for setup injection and no-circular-import); full suite 306 passing (test_voice and test_diff_view excluded — pre-existing, unrelated).
4f3305e to
59dc9f1
Compare
…0-3.13 compat `Path.read_text` gained a `newline=` parameter only in Python 3.14, but this project supports 3.10+. Three call sites in tools/fs.py were passing newline="" to read_text and failing at runtime on every supported version, surfacing as `test_diff_view` CI failures. Extracted a small `_read_preserving_newlines(p)` helper using `p.open(..., newline="")` (accepted since pathlib's inception) and routed the three callers through it. Same semantics — \\r\\n preserved so _edit's CRLF detection still works — now portable across 3.10-3.14. Unrelated to the autosuggest feature in this PR, but required to unblock CI. Full suite: 341/341 pass.
|
Rebased onto v3.05.70 — no merge conflicts after the Also included a small CI-unblocking compat fix for Happy to pull that fix into a separate PR if you'd prefer; it's a standalone 1-file, +14/-5 change. Full suite: 341/341 pass locally. Ready for merge whenever you have a moment. |
|
Thanks a lot! Already merged. |
…ar import Addresses all five points raised in PR SAIL-Research-Lab#38 review: 1. Hard dep vs fallback contradiction — move prompt_toolkit out of [project.dependencies] into [project.optional-dependencies] under a new `autosuggest` extra. requirements.txt marks it optional with a comment. The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path. 2. History file format conflict — introduce a sibling history file for prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(), leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no longer risks corrupting either file. 3. Circular import risk — ui/input.py no longer imports cheetahclaws. Providers are injected via ui.input.setup(commands_provider, meta_provider) from repl(); SlashCompleter reads module-level providers (or ctor overrides for tests). Added test_module_does_not_import_cheetahclaws as a structural regression guard. 4. Multi-line paste notification parity — after _pt_read_line returns, _read_input counts embedded \\n and emits the same info("(pasted N lines)") message as the readline phase-2 path, preserving user-visible behavior. 5. Bug fix mixed with feature — setup_readline reverted to its pre-patch state. The /c/cwd readline glue fix now lives entirely on main; this PR only adds the prompt_toolkit input path. Folded in self-review items: reset_session() helper to drop a stale cached session after a prompt_toolkit failure; richer exception context in the fallback warn; session cache now invalidates on history_path change; completer cache keyed on full sorted tuple of command names. Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards for setup injection and no-circular-import); full suite 306 passing (test_voice and test_diff_view excluded — pre-existing, unrelated).
… deps Pre-POC bundle wires Silverhawk fork MVP core into cheetahclaws runtime: 1. cheetahclaws.py: import bridges.matrix + tools.a2a_delegate, COMMANDS['matrix']=cmd_matrix, COMMAND_HELP entry 2. web/api.py: add bridges.matrix to bridge auto-discovery 3. pyproject.toml: silverhawk-matrix optional = matrix-nio>=0.24.0 4. bootstrap.py: step 2.b register_a2a_handler logging POC handler, non-fatal if bridge absent Smoke PASS: COMMANDS wired, tools registered, bootstrap runs clean, pip install -e '.[silverhawk-matrix]' installable. MVP core pre-POC wiring complete. Ready SAIL-Research-Lab#38 E2E. refs SAIL-Research-Lab#33 SAIL-Research-Lab#35 SAIL-Research-Lab#38
…-matrix-serve.py + launch runbook Wire Path B option δ for POC SAIL-Research-Lab#38: cheetahclaws runs standalone Matrix agent bypassing chat-server-bin. Adds: - CLAUDE.md at fork root: pilot role overlay (Cas A forward-verbatim + MXID roster + A2A rules) sourced from DevopMaster agent/roles/prompts/ pilot.md. Cheetahclaws reads it as system context. - scripts/silverhawk-matrix-serve.py: standalone launcher binding matrix bridge inbound queue → agent.run() → mx_send outbound reply. Bypasses chat-server-bin entirely. SIGTERM-safe, accept_all permissions for POC. - docs-silverhawk/poc-38-launch-spec.md: runbook for devop-master (new Matrix token generation via Dendrite login, stop classic supervisor units, launch cheetahclaws standalone, smoke probe, observation setup, POC run plan, rollback). Closes wiring gap flagged post-SAIL-Research-Lab#37 (cheetahclaws installed but not active runtime). Enables true POC thesis validation. refs SAIL-Research-Lab#33 SAIL-Research-Lab#34 SAIL-Research-Lab#35 SAIL-Research-Lab#37 SAIL-Research-Lab#38
…AIL-Research-Lab#56 Add scripts/silverhawk-launch.sh (bash wrapper): - Sources /usr/local/bin/glm to export ANTHROPIC_AUTH_TOKEN + BASE_URL (z.ai gateway Anthropic-compat for glm-* models) - Parses /home/ide/.config/matrix/credentials.json for MATRIX_* - Uses pkill pattern for stop-start swap (supervisorctl broken in these containers per preflight audit SAIL-Research-Lab#56) - Execs silverhawk-matrix-serve.py in foreground Update runbook poc-38-launch-spec.md per preflight findings: - No new Matrix token generation needed (reuse credentials.json + stop-start swap frees the @testbot session cleanly) - pkill stop pattern (supervisord lacks [supervisorctl] section) - Cred sourcing inline from /usr/local/bin/glm + credentials.json - Simplified 6-step checklist (fork pull → matrix-nio install → creds confirm → stop classic via launcher → launch → smoke) - Rollback procedure (pkill serve + nohup restart classic) refs SAIL-Research-Lab#33 SAIL-Research-Lab#34 SAIL-Research-Lab#35 SAIL-Research-Lab#37 SAIL-Research-Lab#38 SAIL-Research-Lab#56
…m-5 prefix Devop-master blocker SAIL-Research-Lab#1 (SAIL-Research-Lab#56 preflight): plain 'glm-5' routes via cheetahclaws _PREFIXES auto-detect to zhipu provider (bigmodel.cn native API) — wrong endpoint. Prod uses z.ai gateway Anthropic-compat (ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic + same token pattern as /usr/local/bin/glm wrapper). Fix: explicit provider prefix 'anthropic/glm-5'. cheetahclaws' detect_provider() returns 'anthropic' (via '/' split), bare_model() strips to 'glm-5' before API call. anthropic SDK Anthropic() client auto-reads ANTHROPIC_BASE_URL env var → routes to z.ai gateway. No providers.py patch needed. 2 file changes: - silverhawk-matrix-serve.py: CHEETAHCLAWS_MODEL default 'anthropic/glm-5' - silverhawk-launch.sh: log message reflects provider routing Verified: detect_provider('anthropic/glm-5') = 'anthropic', bare_model = 'glm-5', Anthropic() SDK honors ANTHROPIC_BASE_URL env (smoke test returns base_url=<env value>). refs SAIL-Research-Lab#38 SAIL-Research-Lab#56
Devop-master live test caught history-replay spam: on bootstrap, nio's initial sync returned full pending history for joined rooms, triggering callback on past RoomMessageText events. Side-effect: cheetahclaws auto-responded to stale A2A envelopes from earlier orchestrator cycles (6 mx_send_ok events before kill). Fix: prime client.next_batch via a single-shot sync(timeout=0) BEFORE registering the event callback. Events in that initial sync are discarded (callback not registered yet). sync_forever(since=...) then only dispatches fresh events. Safe for repeat boots: nio auto-reuses next_batch if store exists, so returning clients pick up where they left off. First-time boot skips history as intended. refs SAIL-Research-Lab#33 SAIL-Research-Lab#38 SAIL-Research-Lab#56
…uest grant Run 2 bot promised but never executed tools. Dual bug: 1. Config key typo: 'permissions_mode' → 'permission_mode' (singular, per agent.py:294). Value 'accept_all' → 'accept-all' (hyphen, per _check_permission line 301). Wrong keys fell through to 'auto'. 2. 'auto' yields PermissionRequest event per tool; our loop discarded it → req.granted default False → tool denied → LLM saw denial. Fixes serve.py: correct config keys + consume PermissionRequest + grant=True as defense belt. TurnDone now loop-marker not loop-end (agent.run multi-turn for tool workflows). refs SAIL-Research-Lab#38 SAIL-Research-Lab#60
…activation POC SAIL-Research-Lab#38 L1 live test validated: model name choice gates z.ai tool_use schema emission. Devop forensic: - model=glm-5 → z.ai returns text-only, 0 tool_use blocks (in=36k out=33) - model=claude-sonnet-4-6 → z.ai server-side maps to glm backing model AND activates tool_use. Bash/Read/Edit/etc. all work. Changes: - serve.py default CHEETAHCLAWS_MODEL → anthropic/claude-sonnet-4-6 - launcher log reflects new default + gotcha explanation - CLAUDE.md adds model-name note for fleet operators Keep anthropic/ prefix: prefix auto-detect would otherwise route plain glm-5 to bigmodel.cn (wrong endpoint). Anthropic SDK auto-reads ANTHROPIC_BASE_URL env → z.ai gateway. refs SAIL-Research-Lab#38 SAIL-Research-Lab#60 SAIL-Research-Lab#61
… prose-prefixed bodies POC SAIL-Research-Lab#38 L3 diagnosis (devop evidence): cheetahclaws-sending peer emits prose+JSON single message ('Je vais contacter @Reviewer... {envelope}'). Classic bridge.py AND pre-fix matrix.py both reject with strict lstrip().startswith('{"a2a":"1"') check. Fix: _extract_a2a_envelope() tolerant scanner. - Fast path preserves strict-JSON hot path (pure JSON body unchanged behavior) - Tolerant path: content.find('{"a2a":"1"') + balanced-brace walker handling nested {}, strings with braces, escapes - Returns parsed dict or None Smoke 9/9 PASS: - Pure JSON ✓ - Pure JSON leading whitespace ✓ - Prose prefix ✓ (pilot SAIL-Research-Lab#6 / L3 case) - Prose prefix multi-line ✓ - Nested braces in payload ✓ - Strings containing braces ✓ - No envelope → None ✓ - Malformed JSON → None ✓ - Wrong version a2a:2 → None ✓ Critical pre-Step-I3 L3-repeat: ide-0081 recycle cheetahclaws-native needs matching tolerant detection on both sides. refs SAIL-Research-Lab#71 SAIL-Research-Lab#38
… filter POC SAIL-Research-Lab#38 L3 Run 2 root causes identified: - Both bots loaded CLAUDE.md (pilot role) → @Reviewer self-ID as pilot - No fleet-peer filter → text echo loop testbot↔reviewer Fixes: 1. ROLE SPLIT — serve.py _load_system_prompt: SILVERHAWK_ROLE env OR MATRIX_USER_ID localpart inference (@testbot→pilot, @Reviewer→ reviewer) → roles/<role>.md. Same image, different per-role context. 2. FLEET-PEER FILTER — matrix.py drops prose-only messages from known fleet peers (SILVERHAWK_FLEET_PEERS env OR roster fallback). Envelopes always route. Operators always queue. Added roles/pilot.md (239L) + roles/reviewer.md (230L) from canonical. Smoke 4/4 PASS (peers default+env, role no-env/pilot/reviewer/architech). refs SAIL-Research-Lab#73 SAIL-Research-Lab#38
…t emit POC SAIL-Research-Lab#38 L3 unblocker: reviewer detected envelope but never emitted ack/result (detect-only handler). Wire active-agent protocol. matrix.py: register_a2a_handler sig extended (env, item) — item has room_id/sender/event_id for ack/result routing. serve.py: _make_a2a_handler factory with closure over config + system_prompt. On delegate/query: 1. emit ack envelope immediately via mx.mx_send 2. build prompt = payload.task + payload.context 3. dispatch fresh AgentState + _run_one_turn (no contamination) 4. emit result envelope (status, summary cap 6000 chars) 5. non-actionable actions log only (result handled elsewhere) main() wires handler overriding bootstrap detect-only (idempotent). Smoke OK. Acceptance L3-repeat 6/6 GREEN post hot-patch. refs SAIL-Research-Lab#75 SAIL-Research-Lab#38
… L3 final patterns Append 10 entries post-POC SAIL-Research-Lab#38 L3 Final GREEN (corr=f90a6e5d) : Handler wiring & L3 final (41-50): - 41 detect-only handler != active handler (keystone L3 FINAL) - 42 fresh AgentState for delegates = session isolation - 43 immediate ack emit <1s pattern - 44 TurnDone → symmetric result envelope swap - 45 SILVERHAWK_FLEET_PEERS empty != opt-out caveat (config doc follow-up) - 46 cheetahclaws-native end-to-end vs classic WS-delegated architecture - 47 tolerant balanced-brace parser > regex (nested braces + strings) - 48 role split SILVERHAWK_ROLE + MXID fallback = 1-to-1 identity - 49 cross-instance A2A full cycle ~65s budget (Opus tier) - 50 POC L1→L2→L3 canonical progression rule Total 50 entries from session. Sign-off updated. refs SAIL-Research-Lab#77
Architecture spec for polymarket bot team deploy post-POC SAIL-Research-Lab#38 ratif. Spec-before-deploy pattern: architech specs, devop-master deploys. 8 sections: 1. Container strategy — 3 dedicated ide-0090/0091/0092 per strategy 2. Virtual wallet persistence — JSON file + hourly memory.save backup 3. Strategy execution loop — cheetahclaws REPL + cron-like polling 4. Polymarket API rate limits — shared 52/min budget across 3 strategies 5. Risk management — per-position caps + 20% HWM drawdown halt + blocklist 6. Deploy checklist for devop-master — 6-step container spawn + code deploy + launch + smoke 7. Open questions for user (inherited from 054182e research) 8. Success criteria POC polymarket — 7-day uptime + PnL baseline comparison Ratification required: PO approval container strategy + user approval virtual allocation + news API deferred + real-trading held. refs SAIL-Research-Lab#69
Audit cheetahclaws cross-turn persistence post-BLUEFOX42 fail. Current: main() single AgentState shared across _run_one_turn calls. state.messages accumulated via agent.py:86+187. 3 hypotheses for test fail: thread race, sanitize stripping, CLI-vs-Matrix path. Options: - A (native): per-room AgentState map, thread-safe lock, 40-60 LOC — RECOMMENDED (canonical, self-contained, aligns POC SAIL-Research-Lab#38 arch) - B (shim): REST fetch chat.db history + prepend, 60-80 LOC — fallback if A reveals agent-loop gap Plan: (1) re-test BLUEFOX42 via real Matrix DMs; (2) if fails ship A; (3) gates baseline+scale+isolation. refs SAIL-Research-Lab#76
…e refusal User catch 2026-04-19 morning: delegate 'envoyer message user' → reviewer refused textually 'je ne peux pas envoyer Matrix DM' instead of composing message as payload.summary. Analog Pilot SAIL-Research-Lab#6 retract gap, reviewer-side this time. reviewer.md only had Cas A (audit) canon, no user-message path. Fix: explicit Cas A/B/C: - A: audit/review → 🔴/🟡/🟢 buckets in summary - B: user-facing message → THE message text, pilot forwards verbatim - C: technical non-review → short direct answer Anti-pattern Cas B = exact refusal text from L3 FINAL corr=f90a6e5d. Global rule: never refuse by tool-use timidity. Scope: +76 / -8 LOC, prompt-only. refs SAIL-Research-Lab#79 SAIL-Research-Lab#38
User test corr=4bf697fe: testbot emitted delegate but reviewer never received. Root cause: a2a_delegate.py passed target_mxid as room_id to mx_send. Matrix room_id starts '!' not '@' — nio silent-rejects. Fix matrix.py: - _mx_resolve_dm_room_async(client, mxid): scan rooms for 2-member DM, else room_create(is_direct, invite=[mxid], trusted_private_chat) - mx_send_to_mxid(mxid, text) -> (ok, room_id): resolve + send - mx_send docstring warns MXID-as-room_id pitfall Fix a2a_delegate.py: - call mx_send_to_mxid not mx_send(room_id=mxid) - emit a2a_delegate_emitted log (corr+target+room) observability - return room_id in JSON Smoke 4/4 PASS. refs SAIL-Research-Lab#80 SAIL-Research-Lab#38

Replace the Tab-only readline completer with a prompt_toolkit PromptSession that renders an inline ghost suggestion while typing and a keyboard-selectable completion menu.
Fixes three user-visible defects in the REPL:
Also surfaces modular/plugin/skill commands in completion for the first time. The previous completer read only the hand-maintained
_CMD_METAdict, while the dispatcher consulted the full liveCOMMANDSregistry.