-
Notifications
You must be signed in to change notification settings - Fork 1
Remote phone-control pairing + account/sandbox restructure #90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
8e11019
feat: Remote phone-control pairing (RemoteRelay) + account/sandbox re…
Ravikxx bc64d42
feat: publish remote-pairing (RemoteRelay) + account/sandbox restruct…
Ravikxx 064a9f7
fix: close remote-relay sockets when the pairing TTL expires
Ravikxx ff6962e
Add guardrail-flag observability log and announcement send-history to…
Ravikxx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| # Inter-Session Communication — Design Spec | ||
|
|
||
| Status: **IMPLEMENTED** (CLI). Built on the existing `BUS`/`send_message` | ||
| infrastructure rather than a parallel channel. | ||
|
|
||
| ## What shipped | ||
| - `src/agent/sessionRegistry.js` — live session registry (keyed by agent label). | ||
| `registerSession()` broadcasts a creation notice to every other session's | ||
| mailbox; `trackToolFiles()` records recently-touched files per session. | ||
| - `src/agent/agent.js` — every `Agent` registers itself (with model) and updates | ||
| its goal/status each turn; file-touching tools feed `trackToolFiles`. | ||
| - `src/agent/tools.js` — `list_sessions` (peer discovery) and `query_session` | ||
| (returns a peer's goal/status + recently-touched files; optional `question` | ||
| delivered to the peer's inbox). Both added to the hosted-model allowlist and | ||
| the grant-independent set. | ||
| - `src/tui/App.jsx` — hidden `/create-external-model <https://url> <model> <key>` | ||
| dev command (absent from `COMMANDS`, so it never tab-completes). | ||
|
|
||
| ## Known gap | ||
| - The user-facing `main` agent does not see creation notices via `read_messages` | ||
| (BUS routes `to:"main"` to an internal inbox that `read_messages` doesn't read; | ||
| `main` can still call `list_sessions` to discover peers). Spawned sub-agents | ||
| *are* notified correctly. Fixing `main` would require changing `read_messages` | ||
| and risks colliding with the spawn flow's own `readMain()` consumption. | ||
|
|
||
| ## Original design notes (kept for reference) | ||
|
|
||
|
|
||
| ## Goal (from request) | ||
|
|
||
| 1. Code-chat **sessions** can talk to each other. | ||
| 2. A model is **notified when another session is created**. | ||
| 3. A session can **ask another session what it's doing / how to avoid each other**. | ||
| 4. A **tool** the model can call to do the above. | ||
| 5. A **developer command** `/create-external-model <https://url> <model name> <api key>` | ||
| that registers an external OpenAI-compatible model — and is **deliberately NOT | ||
| tab-completable**. | ||
|
|
||
| ## Integration reality (from reading the code) | ||
|
|
||
| - Slash-command dispatch = `runCommand(raw)` in `src/tui/App.jsx` (big `switch`). | ||
| - `src/ui/commands.js` `COMMANDS` array is **only** for suggestions + tab | ||
| completion (`getSuggestions` / `getTabCompletion`). A command omitted from | ||
| `COMMANDS` still runs via the `runCommand` switch but never autocompletes. | ||
| → `/create-external-model` is hidden simply by not listing it in `COMMANDS`. | ||
| - Custom endpoints live in `CUSTOM_ENDPOINTS` (mutable, `src/config.js`); the | ||
| `/endpoint` handler (App.jsx ~2168) shows the exact mutate + `saveCustomEndpoints(...)` | ||
| pattern to mirror. | ||
| - Tools are defined in `src/agent/tools.js`; agents get them filtered via | ||
| `agentRegistry.filterTools` (permission rulesets). | ||
| - Sessions/agent loop: `src/agent/agentRegistry.js` (named agents, not live | ||
| sessions) + the live chat loop in `src/tui/App.jsx` / `src/agent/agent.js`. | ||
|
|
||
| ## Proposed design | ||
|
|
||
| ### 1. `src/agent/sessionRegistry.js` (new, process-wide singleton) | ||
| In-memory registry of **currently-running** sessions (live coordination only — | ||
| no persistence needed). | ||
|
|
||
| Record shape: | ||
| ``` | ||
| { id, name, model, goal, status, owner, createdAt, lastActivity, running, turnCount } | ||
| ``` | ||
| API: | ||
| - `register(session)` / `unregister(id)` | ||
| - `list()` → public descriptors (omit sensitive fields) | ||
| - `get(id)` | ||
| - `updateStatus(id, { goal, status })` — called each turn so peers can answer | ||
| "what are you doing" | ||
| - `notifyCreation(session)` — enqueue a creation notice into every *other* | ||
| session's `inbound` queue | ||
| - per-session `inbound` queue drained at the start of each agent turn | ||
|
|
||
| ### 2. Creation notifications | ||
| Hook `register()` + `notifyCreation()` wherever a new chat/code-session spawns | ||
| (new chat in App.jsx; any spawned agent loop in agent.js). Each other live | ||
| session drains its `inbound` queue at the top of its next turn and surfaces the | ||
| notice as a `system` message: | ||
| `"New session '<name>' started on model <model> — goal: <goal>."` | ||
| (Draining at turn-start avoids interrupting a mid-turn agent.) | ||
|
|
||
| ### 3. Model tools (`src/agent/tools.js`) | ||
| - `list_sessions` → returns peer sessions (id, name, model, status, goal), | ||
| **excluding the calling session itself**. | ||
| - `query_session({ sessionId, question })` → "what are you working on / how | ||
| should we avoid conflicts?". **v1 = synchronous status lookup**: returns the | ||
| target's last `goal` + `status` + recent file activity (from the registry | ||
| record), not a full back-and-forth. True async peer-to-peer chat = v2. | ||
| - Both gated through `agentRegistry.filterTools` so denied/allowed tool rules | ||
| still apply. `query_session` must never return another session's full message | ||
| history — only goal/status + summarized activity (privacy boundary). | ||
|
|
||
| ### 4. `/create-external-model` (hidden dev command) | ||
| Signature: `/create-external-model <https://url> <model name> <api key>` | ||
| Handler (new `case` in `runCommand`, App.jsx), mirroring `/endpoint`: | ||
| ``` | ||
| CUSTOM_ENDPOINTS[name] = { baseURL: url, model: name, apiKey: key, context: 0 } | ||
| CONTEXT_WINDOWS[name] = <fetched or default> | ||
| saveCustomEndpoints({ ...CUSTOM_ENDPOINTS }) | ||
| setModel(name); agentRef.current?.setModel(name); saveModel(name) | ||
|
Ravikxx marked this conversation as resolved.
|
||
| ``` | ||
| Validation: `url` must start with `http(s)://`. Gated as developer-only | ||
| (undocumented; always available but absent from `COMMANDS`, so no tab-complete). | ||
|
Ravikxx marked this conversation as resolved.
Ravikxx marked this conversation as resolved.
|
||
|
|
||
| ## Open questions to resolve before implementing | ||
| - **Scope**: CLI sessions only, or also the desktop "code chats" (Axion App | ||
| Code tab)? Tools/slash-commands here are CLI-only. | ||
| - **Session definition**: a whole chat, or a spawned sub-agent? Affects where | ||
| `register()` is hooked. | ||
| - **v1 vs v2** for `query_session`: status-polling (simple, synchronous) vs. | ||
| real async agent-to-agent messaging (needs a request/response channel + | ||
| timeout). Recommend v1 status-polling first. | ||
| - Notification timing: turn-start drain (chosen) vs. push interrupt. | ||
|
|
||
| ## Files touched (when implemented) | ||
| - new: `src/agent/sessionRegistry.js` | ||
| - `src/agent/tools.js` (2 tools) | ||
| - `src/tui/App.jsx` (runCommand: creation hook + `/create-external-model` case; | ||
| model tool available to tools list) | ||
| - `src/agent/agent.js` (drain `inbound` + `updateStatus` each turn) | ||
| - `src/ui/commands.js` — **NOT** modified for the hidden command (intentionally | ||
| absent so it stays out of tab-completion). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| -- Client-side error reports from the iPhone app (and any future native client). | ||
| -- The app shows the user only a generic "Something went wrong" and ships the | ||
| -- real failure here so we can triage crashes and exceptions without ever | ||
| -- exposing internal details (stacks, underlying errors) to users. | ||
| CREATE TABLE client_errors ( | ||
| id TEXT PRIMARY KEY, | ||
| user_id TEXT, | ||
| app_version TEXT, | ||
| build_number TEXT, | ||
| os_version TEXT, | ||
| device_model TEXT, | ||
| type TEXT, | ||
| message TEXT, | ||
| stack TEXT, | ||
| context TEXT, | ||
| created_at INTEGER NOT NULL | ||
| ); | ||
|
|
||
| CREATE INDEX idx_client_errors_created ON client_errors (created_at DESC); | ||
| CREATE INDEX idx_client_errors_user ON client_errors (user_id, created_at DESC); |
29 changes: 29 additions & 0 deletions
29
api-proxy-cf/migrations/043_usage_boost_and_bulk_reset.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| -- Migration 043: admin-controlled temporary usage-limit boost, plus an audit | ||
| -- trail for the bulk "reset usage for everyone" action. | ||
| -- | ||
| -- usage_boost is a singleton row (id always 1) rather than a general | ||
| -- key/value settings table, since there's exactly one thing to configure | ||
| -- right now and a singleton is simpler to reason about and query than a | ||
| -- generic table would be for a single value. percent=0 or expires_at in the | ||
| -- past both mean "no boost currently active" — the app doesn't need a | ||
| -- separate enabled flag, an expired/zero boost already reads as inactive. | ||
| CREATE TABLE usage_boost ( | ||
| id INTEGER PRIMARY KEY CHECK (id = 1), | ||
| percent INTEGER NOT NULL DEFAULT 0, | ||
| expires_at INTEGER, | ||
| set_by TEXT, | ||
| set_at INTEGER | ||
| ); | ||
| INSERT INTO usage_boost (id, percent, expires_at, set_by, set_at) VALUES (1, 0, NULL, NULL, NULL); | ||
|
|
||
| -- One row per bulk reset, not one row per affected user — this is an audit | ||
| -- record of the admin action itself ("who did this, when, how many people | ||
| -- did it touch"), not a per-user log; per-user history isn't needed since | ||
| -- the reset just zeroes usage_week/usage_window the same way a normal | ||
| -- period rollover would. | ||
| CREATE TABLE admin_bulk_usage_resets ( | ||
| id TEXT PRIMARY KEY, | ||
| admin_email TEXT NOT NULL, | ||
| affected_users INTEGER NOT NULL, | ||
| created_at INTEGER NOT NULL | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| -- Migration 044: admin kill switch for a specific model, independent of any | ||
| -- code deploy. Presence of a row means that model_id is disabled — this is | ||
| -- deliberately a real DB row (audit-visible: who, when, why) rather than a | ||
| -- boolean column somewhere, so disabling something always leaves a record | ||
| -- of who did it and, ideally, why. | ||
| CREATE TABLE disabled_models ( | ||
| model_id TEXT PRIMARY KEY, | ||
| disabled_by TEXT NOT NULL, | ||
| disabled_at INTEGER NOT NULL, | ||
| reason TEXT | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| -- Migration 045: observability log for the Fresco 1.3 real-time output | ||
| -- guardrail (judgeFlagged in chatGeneration.js). One row per moderated | ||
| -- generation (every MODERATED_MODELS reply that actually produced text), | ||
| -- not just the flagged ones — logging SAFE verdicts too is what lets an | ||
| -- admin see the guardrail's true fire rate and spot false positives, not | ||
| -- just count how many replies got blocked. | ||
| CREATE TABLE guardrail_flags ( | ||
| id TEXT PRIMARY KEY, | ||
| generation_id TEXT NOT NULL, | ||
| user_id TEXT NOT NULL, | ||
| model TEXT NOT NULL, | ||
| flagged INTEGER NOT NULL, | ||
| user_text TEXT, | ||
| assistant_text TEXT, | ||
| created_at INTEGER NOT NULL | ||
| ); | ||
| CREATE INDEX idx_guardrail_flags_created_at ON guardrail_flags (created_at); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| -- Migration 046: send-history visibility for announcement emails, closing | ||
| -- the exact blind spot behind the 2026-08 incident where a GitHub Actions | ||
| -- run reported success but the announcement email never actually queued | ||
| -- (only caught by reading raw workflow logs, not the green checkmark). | ||
| -- recipient_count and send_status let an admin confirm from the dashboard | ||
| -- that a given announcement actually reached subscribers, without needing | ||
| -- to go dig through Actions logs again. | ||
| ALTER TABLE announcements ADD COLUMN recipient_count INTEGER; | ||
| ALTER TABLE announcements ADD COLUMN send_status TEXT; | ||
| ALTER TABLE announcements ADD COLUMN send_error TEXT; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.