Codync
무료 오픈소스 1:1 대안, Grok Bot과 Muse 대신
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Handoff: hand a headless VM checkout to a real person. Device actions trigger the SDK's merchant callbacks in the VM over Firebase RTDB; results stream back.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Live at https://handoff.solutionbyhour.com
The fallback for agentic checkout. An AI agent checks out in a headless VM; when it can't finish (it needs the user's address, a choice, or their approval), it sends the user a fallback URL. The user completes the paysheet on their own device while the checkout SDK keeps running in the VM. The SDK (and its callbacks) stay in the VM; the device sends semantic actions, the VM fires the real callbacks, and results + state stream back.
Device UI (/pay/[code]) ⇄ Firebase RTDB sessions/{sid} ⇄ VM paysheet + SDK (/vm)
How it works: see architecture/, starting with
the end-to-end flow (sequence diagrams from the
agent's fallback to the agent resuming), then components, protocol, data
model and security, session lifecycle, deployment, and testing.
npm install
npm run dev # Firebase emulators (auth, RTDB, UI :4000) + Next on :3000
npm run e2e # in another terminal: full relay test against the emulators
Open http://localhost:3000 (the session console). Launch VM paysheet boots a new session with its own cart and device link, in a new tab. The console updates live; reopen any session's VM to resume it, or hand its device link to someone else to run transactions in parallel. To use a real phone, open the console via your LAN IP so the links point there.
The device link opens the paysheet the user interacts with, laid out like a
familiar wallet checkout. The VM page shows no paysheet at all, like a real
headless VM: it shows the relay steps for each request (action in from the
device → callback_pending out → merchant callback fired in the VM → resolved
or rejected → callback_result out), each with its timing. The Merchant
simulator panel stands in for the merchant's backend: Hold responses
makes callbacks wait for you, so you can watch the device wait. Hold one past
10 s and the SDK times it out. Try SF (3 options + CA tax), Honolulu (express only), and Toronto
or ZIP 00000 (merchant rejects).
Resume and ownership: the VM rebuilds the SDK from the last persisted snapshot.
Opening a session in a second VM tab takes it over (newest wins). The old tab
stands down, and any callback it had in flight fails on the device with
INTERRUPTED instead of hanging.
| File | Role |
|---|---|
src/lib/protocol.ts | Wire types. Transport-agnostic. |
src/lib/channel.ts | Only file that knows about RTDB: queues, presence, state. Swap for WebSockets/Cloud Run later. |
src/lib/mock-paysheet-sdk.ts | Stand-in for the third-party SDK (PayPal-shaped onShippingAddressChange / onShippingOptionsChange / onApprove, actions.reject, callback timeout). |
src/lib/merchant.ts | Merchant's callback implementations. |
src/lib/vm-bridge.ts | VM side: device action → SDK call → callback fires → callback_result back. Publishes full state snapshots on every change. |
src/lib/device-client.ts | Device side: request/response with correlation ids and a relay timeout. |
src/app/api/sessions | Creates a session (cart, initial state, share link). |
src/app/api/sessions/[sid]/vm-token | VM-role token for a new or resumed session. |
src/app/api/operator-token | Read-only console token (demo: unauthenticated). |
src/app/api/sessions/redeem | Exchanges the share code for a device-role token. |
src/lib/vm-session.ts | Boots or resumes the SDK for one session: rehydrate, take the VM lease, bridge. |
src/lib/response-gate.ts | Lets you hold merchant responses by hand (replaces simulated latency). |
src/components/VmActivity.tsx | VM relay-steps view, built from the bridge's VmEvents. |
src/components/PaySheetView.tsx | The device paysheet (wallet-checkout layout). |
src/lib/console-feed.ts | Live session list for the console (operator token, read-only). |
deploy/ | Dockerfile, compose files, and deploy.sh for the VPS. |
database.rules.json | Per-session, per-role access. Device can't write state; nobody reads share codes; the operator token is read-only. |
RTDB layout:
sessions/{sid}/meta { status, createdAt, expiresAt } (admin creates, VM updates status)
sessions/{sid}/state { seq, paysheet } (VM writes, device renders)
sessions/{sid}/toVm/* action messages (device appends, VM consumes + deletes)
sessions/{sid}/toDevice/* callback_pending / callback_result (VM appends, device consumes + deletes)
sessions/{sid}/presence { vm, device } (onDisconnect clears)
sessions/{sid}/vmLease tab id of the VM that owns the SDK
shareCodes/{code} { sid, expiresAt } (admin only)
sessionIndex/{sid} { code, label, createdAt, ... } (admin writes, operator reads)
Design rules: the VM is the source of truth; the device renders snapshots and never applies optimistic state. Every action has an id; the VM dedupes by id; the device times out (15 s) after the SDK would (10 s), so the SDK's verdict wins. Those two deadlines are the only timers in the code: no sleeps, no polling.
Copy .env.live.example to .env.live and fill in your project's values (emulator
config is .env.emulators; there is no .env.local). .env.live is gitignored.
npm run rules:deploy # push database.rules.json to the project in .env.live
npm run dev:live # Next against the real project (no emulators)
npm run e2e:live # same suite, against real RTDB
Free tier (Spark): this uses only Realtime Database (1 instance, 100 simultaneous
connections, 1 GB stored, 10 GB/month download) and Firebase Auth custom tokens,
both free. No Cloud Functions, no Identity Platform upgrade. A full e2e:live
run opens about 25 connections and writes a few KB.
The server needs a service-account key to mint custom tokens; .env.live points
GOOGLE_APPLICATION_CREDENTIALS at it (outside the repo).
POST /api/sessions must be service-authenticated (it mints VM tokens).npm run cleanup:live deletes expired sessions by hand. A scheduled Cloud Function would automate it but needs the paid Blaze plan, so the demo doesn't use one. Delete on completion too, since addresses are PII.