feat: Expo 多端客户端与移动端远程连接 - #2
Conversation
Add a shared Expo client for iOS, Android, web, and desktop, backed by an authenticated WebSocket service with per-session concurrency, reconnect recovery, attachments, tool approvals, tests, and migration documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b958be2ad1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (let iteration = 0; iteration < 50; iteration++) { | ||
| if (run.abort.signal.aborted) break |
There was a problem hiding this comment.
Stop repeated tool calls before executing them again
When a provider repeatedly returns the same tool call, this loop executes it again on every iteration until the 50-iteration cap. In Wild mode, a stuck model can therefore repeat a destructive write, command, reminder, or note operation up to 50 times; the existing daemon guards this case with a tool-call signature check in src/core/daemon.ts:383-389. Detect an identical consecutive call before executing it in the network runtime.
Useful? React with 👍 / 👎.
| id: string; initialLength: number; abort: AbortController; text: string; approval?: Approval; | ||
| tools: Data[]; usage: Data; finished?: Promise<void> | ||
| } | ||
| const MUTATING = new Set(['bash', 'write', 'edit', 'notes', 'reminders']) |
There was a problem hiding this comment.
Require approval for mutating web requests
In a tame session, approve() automatically permits every tool absent from this set, but web_fetch supports POST, PUT, and DELETE. If the model invokes one of those methods against an API, the external mutation executes without the per-operation confirmation expected from the new approval boundary. Classify non-GET web_fetch calls as mutating based on their input.
Useful? React with 👍 / 👎.
| setConfirm({ title: '删除这个会话?', body: '此操作会删除服务端的会话记录,所有设备都会同步。', action: () => void attempt(async () => { | ||
| await rpc.request('session_delete', { sessionId: activeId.current }); activeId.current = null; setSnapshot(null) |
There was a problem hiding this comment.
Bind delete confirmations to the original session
The confirmation callback reads activeId.current only when the user confirms, rather than capturing the session being shown when the dialog opened. With the advertised multi-device synchronization, another client can delete that session while this dialog is open; refresh() then selects a replacement, and confirming the stale dialog deletes that replacement instead. Capture the intended session ID when constructing the action.
Useful? React with 👍 / 👎.
| const memory = await buildMemoryContext(config, '').catch(() => '') | ||
| const runtime = new MonkeyRuntime(config, memory) |
There was a problem hiding this comment.
Refresh memory context during the server lifetime
The server builds its memory context only once at startup and stores that fixed string in MonkeyRuntime. If a conversation invokes memory_write, a newly opened session on the same long-running server will not receive the saved knowledge in its system context until the entire service is restarted, undermining cross-session persistent memory. Rebuild or invalidate the context after memory changes or before starting a run.
Useful? React with 👍 / 👎.
No description provided.