Skip to content

feat: Expo 多端客户端与移动端远程连接 - #2

Merged
nanaco666 merged 1 commit into
mainfrom
feat/expo-universal-client
Sep 8, 2026
Merged

feat: Expo 多端客户端与移动端远程连接#2
nanaco666 merged 1 commit into
mainfrom
feat/expo-universal-client

Conversation

@nanaco666

@nanaco666 nanaco666 commented Sep 8, 2026

Copy link
Copy Markdown
Owner

No description provided.

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.
@nanaco666
nanaco666 marked this pull request as ready for review September 8, 2026 03:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/server/runtime.ts
Comment on lines +173 to +174
for (let iteration = 0; iteration < 50; iteration++) {
if (run.abort.signal.aborted) break

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment thread src/server/runtime.ts
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'])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment thread apps/universal/App.tsx
Comment on lines +144 to +145
setConfirm({ title: '删除这个会话?', body: '此操作会删除服务端的会话记录,所有设备都会同步。', action: () => void attempt(async () => {
await rpc.request('session_delete', { sessionId: activeId.current }); activeId.current = null; setSnapshot(null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/server/http.ts
Comment on lines +115 to +116
const memory = await buildMemoryContext(config, '').catch(() => '')
const runtime = new MonkeyRuntime(config, memory)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@nanaco666
nanaco666 merged commit 60086e1 into main Sep 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant