# Remote Mode (ខ្មែរ) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/REMOTE-MODE.md) · 🇪🇹 [am](../../../am/docs/guides/REMOTE-MODE.md) · 🇸🇦 [ar](../../../ar/docs/guides/REMOTE-MODE.md) · 🇦🇿 [az](../../../az/docs/guides/REMOTE-MODE.md) · 🇧🇬 [bg](../../../bg/docs/guides/REMOTE-MODE.md) · 🇧🇩 [bn](../../../bn/docs/guides/REMOTE-MODE.md) · 🇧🇦 [bs](../../../bs/docs/guides/REMOTE-MODE.md) · 🇨🇿 [cs](../../../cs/docs/guides/REMOTE-MODE.md) · 🇩🇰 [da](../../../da/docs/guides/REMOTE-MODE.md) · 🇩🇪 [de](../../../de/docs/guides/REMOTE-MODE.md) · 🇬🇷 [el](../../../el/docs/guides/REMOTE-MODE.md) · 🇪🇸 [es](../../../es/docs/guides/REMOTE-MODE.md) · 🇪🇪 [et](../../../et/docs/guides/REMOTE-MODE.md) · 🇮🇷 [fa](../../../fa/docs/guides/REMOTE-MODE.md) · 🇫🇮 [fi](../../../fi/docs/guides/REMOTE-MODE.md) · 🇫🇷 [fr](../../../fr/docs/guides/REMOTE-MODE.md) · 🇮🇪 [ga](../../../ga/docs/guides/REMOTE-MODE.md) · 🇮🇳 [gu](../../../gu/docs/guides/REMOTE-MODE.md) · 🇳🇬 [ha](../../../ha/docs/guides/REMOTE-MODE.md) · 🇮🇱 [he](../../../he/docs/guides/REMOTE-MODE.md) · 🇮🇳 [hi](../../../hi/docs/guides/REMOTE-MODE.md) · 🇭🇷 [hr](../../../hr/docs/guides/REMOTE-MODE.md) · 🇭🇺 [hu](../../../hu/docs/guides/REMOTE-MODE.md) · 🇦🇲 [hy](../../../hy/docs/guides/REMOTE-MODE.md) · 🇮🇩 [id](../../../id/docs/guides/REMOTE-MODE.md) · 🇳🇬 [ig](../../../ig/docs/guides/REMOTE-MODE.md) · 🇮🇹 [it](../../../it/docs/guides/REMOTE-MODE.md) · 🇯🇵 [ja](../../../ja/docs/guides/REMOTE-MODE.md) · 🇬🇪 [ka](../../../ka/docs/guides/REMOTE-MODE.md) · 🇮🇳 [kn](../../../kn/docs/guides/REMOTE-MODE.md) · 🇰🇷 [ko](../../../ko/docs/guides/REMOTE-MODE.md) · 🇱🇹 [lt](../../../lt/docs/guides/REMOTE-MODE.md) · 🇱🇻 [lv](../../../lv/docs/guides/REMOTE-MODE.md) · 🇮🇳 [ml](../../../ml/docs/guides/REMOTE-MODE.md) · 🇮🇳 [mr](../../../mr/docs/guides/REMOTE-MODE.md) · 🇲🇾 [ms](../../../ms/docs/guides/REMOTE-MODE.md) · 🇲🇹 [mt](../../../mt/docs/guides/REMOTE-MODE.md) · 🇲🇲 [my](../../../my/docs/guides/REMOTE-MODE.md) · 🇳🇵 [ne](../../../ne/docs/guides/REMOTE-MODE.md) · 🇳🇱 [nl](../../../nl/docs/guides/REMOTE-MODE.md) · 🇳🇴 [no](../../../no/docs/guides/REMOTE-MODE.md) · 🇮🇳 [or](../../../or/docs/guides/REMOTE-MODE.md) · 🇮🇳 [pa](../../../pa/docs/guides/REMOTE-MODE.md) · 🇵🇭 [phi](../../../phi/docs/guides/REMOTE-MODE.md) · 🇵🇱 [pl](../../../pl/docs/guides/REMOTE-MODE.md) · 🇵🇹 [pt](../../../pt/docs/guides/REMOTE-MODE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/REMOTE-MODE.md) · 🇷🇴 [ro](../../../ro/docs/guides/REMOTE-MODE.md) · 🇷🇺 [ru](../../../ru/docs/guides/REMOTE-MODE.md) · 🇱🇰 [si](../../../si/docs/guides/REMOTE-MODE.md) · 🇸🇰 [sk](../../../sk/docs/guides/REMOTE-MODE.md) · 🇸🇮 [sl](../../../sl/docs/guides/REMOTE-MODE.md) · 🇷🇸 [sr](../../../sr/docs/guides/REMOTE-MODE.md) · 🇸🇪 [sv](../../../sv/docs/guides/REMOTE-MODE.md) · 🇰🇪 [sw](../../../sw/docs/guides/REMOTE-MODE.md) · 🇮🇳 [ta](../../../ta/docs/guides/REMOTE-MODE.md) · 🇮🇳 [te](../../../te/docs/guides/REMOTE-MODE.md) · 🇹🇭 [th](../../../th/docs/guides/REMOTE-MODE.md) · 🇹🇷 [tr](../../../tr/docs/guides/REMOTE-MODE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/REMOTE-MODE.md) · 🇵🇰 [ur](../../../ur/docs/guides/REMOTE-MODE.md) · 🇺🇿 [uz](../../../uz/docs/guides/REMOTE-MODE.md) · 🇻🇳 [vi](../../../vi/docs/guides/REMOTE-MODE.md) · 🇳🇬 [yo](../../../yo/docs/guides/REMOTE-MODE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/REMOTE-MODE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/REMOTE-MODE.md) --- ដំណើរការ CLI `omniroute` នៅលើកុំព្យូទ័រយួរដៃរបស់អ្នក ខណៈដែល OmniRoute ដំណើរការនៅកន្លែងផ្សេង (VPS, ម៉ាស៊ីនមេនៅផ្ទះ ឬម៉ាស៊ីនមួយផ្សេងទៀតនៅលើ Tailnet របស់អ្នក)។ អ្នកចូលប្រើតែម្តងដោយប្រើ `omniroute connect` ហើយចាប់ពីពេលនោះតទៅ ពាក្យបញ្ជា CLI **ទាំងអស់** នឹងកំណត់គោលដៅទៅកាន់ម៉ាស៊ីនមេពីចម្ងាយនោះ — ពាក្យបញ្ជាដូចគ្នា លទ្ធផលដូចគ្នា គ្រាន់តែប្រតិបត្តិប្រឆាំងនឹងម៉ាស៊ីនមេពីចម្ងាយប៉ុណ្ណោះ។ មិនមានឧបករណ៍ទីពីរដែលត្រូវដំឡើងទេ៖ របៀបពីចម្ងាយគឺជា CLI `omniroute` ធម្មតា បូកនឹង **ថូខឹនចូលប្រើ** ដែលមានវិសាលភាពកំណត់។ ```bash npm install -g omniroute # CLI ធម្មតា omniroute connect 192.168.0.15 # ចូលប្រើ (ពាក្យសម្ងាត់ → ថូខឹនមានវិសាលភាពកំណត់) omniroute models list # ← ឥឡូវនេះរាយម៉ូដែលរបស់ម៉ាស៊ីនមេពីចម្ងាយ omniroute configure codex # ← សរសេរប្រូហ្វាល់ Codex មូលដ្ឋានពីកាតាឡុកពីចម្ងាយ ``` --- ## របៀបដែលវាដំណើរការ ``` កុំព្យូទ័រយួរដៃរបស់អ្នក OmniRoute ពីចម្ងាយ (VPS) ┌────────────────────┐ ┌───────────────────────────────┐ │ omniroute CLI │ POST /api/cli/connect (ពាក្យសម្ងាត់ → ថូខឹន) │ │ បរិបទ៖ vps │ ───────────────► │ បង្កើតថូខឹនចូលប្រើមានវិសាលភាពកំណត់ │ │ baseUrl, token │ Authorization: Bearer oma_live_… │ │ │ ───────────────► │ គ្រប់ route គ្រប់គ្រង ត្រូវបានពិនិត្យ │ │ សរសេរការកំណត់រចនាសម្ព័ន្ធ │ ◄─────────────── │ តាមវិសាលភាពរបស់ថូខឹន │ │ នៅក្នុងម៉ាស៊ីនមូលដ្ឋាន │ └───────────────────────────────┘ └────────────────────┘ ``` - **បរិបទ** នីមួយៗរក្សាទុកម៉ាស៊ីនមេមួយ (`~/.omniroute/config.json`, `chmod 600`)។ `omniroute contexts use ` ប្តូរម៉ាស៊ីនមេដែលកំពុងសកម្ម។ `default` គឺជាម៉ាស៊ីនមូលដ្ឋាន។ - **ថូខឹនចូលប្រើ** (`oma_live_…`) ផ្តល់សិទ្ធិដល់ពាក្យបញ្ជាគ្រប់គ្រង។ ពួកវា ខុសពីកូនសោ API សម្រាប់ inference (`sk-…` ដែលប្រើសម្រាប់ `/v1/chat/completions`)។ - មានតែ hash SHA-256 របស់ថូខឹនប៉ុណ្ណោះដែលត្រូវបានរក្សាទុកនៅខាងម៉ាស៊ីនមេ។ អត្ថបទធម្មតាត្រូវបានបង្ហាញ **តែម្តងគត់** នៅពេលបង្កើត។ --- ## ការតភ្ជាប់ ### ជាមួយពាក្យសម្ងាត់គ្រប់គ្រង (ការចាប់ផ្ដើមដំបូង) ```bash omniroute connect 192.168.0.15 # ពាក្យសម្ងាត់គ្រប់គ្រងសម្រាប់ http://192.168.0.15:20128: ******** # ✔ បានតភ្ជាប់ទៅ http://192.168.0.15:20128 — បរិបទ '192.168.0.15' (វិសាលភាព៖ admin) ``` លំហូរដែលប្រើពាក្យសម្ងាត់នឹងបង្កើតថូខឹន **admin** តាមលំនាំដើម (អ្នកកាន់ពាក្យសម្ងាត់ ដូច្នេះ អ្នកមានការគ្រប់គ្រងពេញលេញរួចហើយ)។ បន្ថយវិសាលភាពដោយប្រើ `--scope`៖ ```bash omniroute connect 192.168.0.15 --scope write ``` ជម្រើស៖ `--port

` (នៅពេល host មិនមាន port), `--name ` (ឈ្មោះបរិបទ), `--scope read|write|admin`។ URL ពេញលេញត្រូវបានគោរពតាមដូចដែលបានផ្តល់៖ `omniroute connect https://omni.example.com`។ ### ជាមួយថូខឹនដែលបានបង្កើតជាមុន បង្កើតថូខឹនមានវិសាលភាពកំណត់នៅក្នុង dashboard (ឬដោយប្រើ `omniroute tokens create`) ហើយ បិទភ្ជាប់វា — មិនត្រូវការពាក្យសម្ងាត់ទេ៖ ```bash omniroute connect 192.168.0.15 --key oma_live_xxxxxxxx ``` CLI ផ្ទៀងផ្ទាត់វាតាមរយៈ `GET /api/cli/whoami` ហើយរក្សាទុកវាជាបរិបទសកម្ម។ --- ## វិសាលភាព មានបីកម្រិត តាមឋានានុក្រម (`admin ⊃ write ⊃ read`)៖ | វិសាលភាព | អាចធ្វើបាន | | -------- | ------------------------------------------------------------------------------------- | | `read` | រាយ/ត្រួតពិនិត្យ — `models list`, `providers status`, `logs`, `usage`, `cost` | | `write` | read **+** កំណត់រចនាសម្ព័ន្ធ/អនុវត្ត — `setup-codex`, `keys add`, `config set`, បន្សំ | | `admin` | write **+** គ្រប់គ្រង — CRUD របស់ `tokens`, បន្ថែម providers, services, policy, oauth | ម៉ាស៊ីនមេកំណត់វិសាលភាពដែល route នីមួយៗត្រូវការ ដោយផ្អែកលើ HTTP method (`GET`→read, ការកែប្រែ→write) បូកនឹងបញ្ជីអនុញ្ញាត admin សម្រាប់ផ្នែកសំខាន់ៗ (`/api/cli/tokens`, ការកែប្រែ `/api/providers`, `/api/oauth`, `/api/services`, …)។ ថូខឹនដែលមានវិសាលភាពមិនគ្រប់គ្រាន់នឹងទទួលបាន `403` ជាមួយសារច្បាស់លាស់។ > Routes ដែលបង្កើត process (`/api/services/*`, `/api/mcp/*`, …) នៅតែ > **អាចចូលប្រើបានតែពី loopback** — ថូខឹនពីចម្ងាយមិនអាចចូលដល់ពួកវាបានឡើយ ទោះមានវិសាលភាពកម្រិតណាក៏ដោយ។ --- ## ការតភ្ជាប់ Antigravity លើការដំឡើងពីចម្ងាយ Antigravity ប្រើអេក្រង់យល់ព្រម firstparty/nativeapp របស់ Google។ Google បញ្ចេញ កូដអនុញ្ញាតតែនៅពេលដែល **loopback redirect** (`http://127.0.0.1:/callback`) **អាចចូលដំណើរការបានពីកម្មវិធីរុករកដែល អនុម័តការចូលគណនី**។ លើការដំឡើង VPS ពីចម្ងាយ loopback នោះស្ថិតនៅលើ ម៉ាស៊ីនមេ មិនមែនលើម៉ាស៊ីនរបស់អ្នកទេ ដូច្នេះអេក្រង់យល់ព្រម **ជាប់គាំងជារៀងរហូត និងមិន បញ្ចេញកូដឡើយ** — ជម្រើសបម្រុងធម្មតា "បិទភ្ជាប់ callback URL" គ្មានអ្វីសម្រាប់ បិទភ្ជាប់ទេ។ (នេះជាកំហិតពីខាង Google៖ ការជាប់គាំងដូចគ្នានេះកើតឡើងនៅក្នុង proxy ណាមួយដែលប្រើ bundled Antigravity desktop client មិនមែនតែ OmniRoute ប៉ុណ្ណោះទេ។) ផ្ទាំងគ្រប់គ្រងរកឃើញបញ្ហានេះមុនពេលអ្នកជាប់គាំង៖ ការបើក **Providers → Antigravity → Connect** ពីអាសយដ្ឋានដែលមិនមែនជា localhost នឹងជំនួសសេចក្តីជូនដំណឹងទូទៅ "ចម្លង callback URL" ដោយដំណោះស្រាយពីរខាងក្រោម ដែលដំណោះស្រាយនីមួយៗបានបំពេញ host និង port របស់អ្នករួចជាស្រេច។ (អាសយដ្ឋាន LAN ក៏ត្រូវបានរាប់បញ្ចូលដែរ — `192.168.x.x` មិនមែនជា localhost ទេ សម្រាប់ callback នេះ។) មានវិធីដែលគាំទ្រចំនួនពីរ ដើម្បីតភ្ជាប់ Antigravity ទៅកាន់ OmniRoute ពីចម្ងាយ។ ### ជម្រើស A — កម្មវិធីជំនួយចូលគណនីក្នុងម៉ាស៊ីនមូលដ្ឋាន (បានណែនាំ) ដំណើរការ OAuth លើ **កុំព្យូទ័ររបស់អ្នកផ្ទាល់** ដែលអាចចូលដំណើរការ `127.0.0.1` បាន។ កម្មវិធីជំនួយ ទាក់ទងជាមួយ Google ដោយផ្ទាល់ ដូច្នេះការយល់ព្រមអាចបញ្ចប់នៅទីដែលកំណែរបស់ផ្ទាំងគ្រប់គ្រង មិនអាចធ្វើបាន។ **ប្រសិនបើអ្នកបានតភ្ជាប់រួចហើយ** (`omniroute connect `) អ្នកមិនចាំបាច់ ចម្លងអ្វីទេ — កម្មវិធីជំនួយបញ្ជូនព័ត៌មានសម្គាល់ទៅកាន់ការដំឡើងនោះឱ្យអ្នក៖ ```bash # លើម៉ាស៊ីន LOCAL របស់អ្នក (ត្រូវការ Node.js + កម្មវិធីរុករក)៖ omniroute connect 192.168.0.15 # ម្តង — បង្កើត context token ដែលមានវិសាលភាពជា admin npx omniroute login antigravity # ↳ បើកការយល់ព្រមរបស់ Google ចាប់យក callback លើ loopback port មូលដ្ឋាន # ប្តូរវា និង POST ព័ត៌មានសម្គាល់ទៅកាន់ context ដែលកំពុងសកម្ម៖ # # Antigravity បានតភ្ជាប់នៅលើ http://192.168.0.15:20128 (ការតភ្ជាប់ abc123)។ # មិនចាំបាច់បិទភ្ជាប់អ្វីទេ — អ្នកអាចបិទ terminal នេះបាន។ ``` ការបញ្ជូនកើតឡើងដោយស្វ័យប្រវត្តិ នៅពេលណាដែល context សកម្មចង្អុលទៅម៉ាស៊ីនផ្សេង។ បង្ខំវាតាមទិសណាមួយដោយប្រើ `--push` / `--no-push` ឬកំណត់គោលដៅទៅ context ជាក់លាក់ ដោយប្រើ `--context `។ **ប្រសិនបើម៉ាស៊ីនរបស់អ្នកមិនអាចចូលដំណើរការ VPS បាន** (ត្រូវបានរារាំងដោយ firewall គ្មាន SSH ឬតុការងារដែលផ្តាច់ពីបណ្តាញ) កម្មវិធីជំនួយនៅតែដំណើរការ — វា _ត្រូវការ_ តែ Google ប៉ុណ្ណោះ។ ប្រើ `--no-push` ឬគ្រាន់តែអនុញ្ញាតឱ្យការបញ្ជូនបរាជ័យ៖ វានឹងត្រឡប់ទៅបោះពុម្ព blob ជំនួសឱ្យការបោះបង់ការអនុញ្ញាតដែលអ្នកបានបញ្ចប់រួចហើយ។ ```bash npx omniroute login antigravity --no-push # omniroute-cred-v1.eyJ2IjoxLCJ... ``` បន្ទាប់មក នៅក្នុងផ្ទាំងគ្រប់គ្រង **ពីចម្ងាយ**៖ **Providers → Antigravity → Connect** ហើយបិទភ្ជាប់ blob `omniroute-cred-v1.…` ទៅក្នុងវាល **Step 2** (វាទទួលយកទាំង callback URL ឬ credential blob)។ OmniRoute ឌិកូដវា ដំណើរការ Cloud Code onboarding នៅខាងម៉ាស៊ីនមេ និងរក្សាទុកការតភ្ជាប់។ > blob មាន refresh token — ចាត់ទុកវាដូចជាពាក្យសម្ងាត់។ តាមផ្លូវបញ្ជូន វា > ត្រូវបានផ្ញើម្តងតាមការតភ្ជាប់ដែលបានផ្ទៀងផ្ទាត់របស់ context អ្នក ហើយតាមផ្លូវបិទភ្ជាប់ វាត្រូវបានផ្ញើតាម > ការតភ្ជាប់ផ្ទាំងគ្រប់គ្រងរបស់អ្នក។ មិនថាតាមវិធីណាក៏ដោយ វាត្រូវបានរក្សាទុកដោយអ៊ិនគ្រីបនៅពេលសម្រាក ហើយ > ការបញ្ជូនដែលជោគជ័យមិនបោះពុម្ពវាទៅកាន់ terminal របស់អ្នកឡើយ។ Flags៖ `--no-browser` (បោះពុម្ព URL ជំនួសឱ្យការបើកដោយស្វ័យប្រវត្តិ), `--port ` (កំណត់ loopback port), `--timeout `, `--push` / `--no-push` (សរសេរជាន់លើ ការបញ្ជូនដោយស្វ័យប្រវត្តិ), `--context ` (កំណត់គោលដៅទៅ context ជាក់លាក់)។ ### ជម្រើស B — SSH local-forward tunnel ប្រសិនបើអ្នកមានសិទ្ធិចូលប្រើ SSH ទៅកាន់ VPS សូមបញ្ជូនបន្ត port របស់ផ្ទាំងគ្រប់គ្រង ដើម្បីឱ្យ loopback callback ត្រូវបានបញ្ជូនត្រឡប់ទៅម៉ាស៊ីនមេតាម tunnel៖ ```bash # លើម៉ាស៊ីន LOCAL របស់អ្នក៖ ssh -L 20128:127.0.0.1:20128 user@your-vps # បន្ទាប់មកបើក http://localhost:20128 ក្នុងកម្មវិធីរុករក LOCAL របស់អ្នក ហើយតភ្ជាប់ Antigravity # តាមធម្មតា — ឥឡូវនេះ 127.0.0.1:20128/callback redirect អាចទៅដល់ VPS តាមរយៈ SSH។ ``` ដោយសារអ្នកចូលទៅកាន់ផ្ទាំងគ្រប់គ្រងជា `localhost:20128` ការយល់ព្រមរបស់ Google នឹងបញ្ចប់ ហើយ callback ត្រូវបានបញ្ជូនទៅម៉ាស៊ីនមេតាម tunnel ដដែល — មិនត្រូវការ blob ទេ។ ទុក tunnel ឱ្យបើករហូតដល់ការតភ្ជាប់បង្ហាញថាសកម្ម។ ខុសពី providers ដែលមាន fixed-loopback ខាងក្រោម **ការបញ្ជូនបន្តតែមួយគឺគ្រប់គ្រាន់** នៅទីនេះ៖ callback របស់ Antigravity ប្រើ port របស់ផ្ទាំងគ្រប់គ្រងផ្ទាល់ ដូច្នេះមិនមាន port ទីពីរដែលជាក់លាក់សម្រាប់ provider ដើម្បីធ្វើ tunnel ទេ។ > ជម្រើស headless ពេញលេញ (គ្មានកម្មវិធីជំនួយ គ្មាន tunnel) គឺកំណត់រចនាសម្ព័ន្ធព័ត៌មានសម្គាល់ > Google OAuth web **ផ្ទាល់ខ្លួន** របស់អ្នក + base URL សាធារណៈ។ សូមមើល environment variables > OAuth របស់ provider។ ជម្រើសពីរខាងលើមិនត្រូវការការដំឡើង Google បន្ថែមទេ។ --- ## ការភ្ជាប់ Codex / Grok លើការដំឡើងពីចម្ងាយ (អ្នកផ្តល់សេវាដែលប្រើ loopback ថេរ) Codex, xAI (`xai-oauth`) និង Grok CLI (`grok-cli`) ចុះឈ្មោះ `redirect_uri` ជា loopback **ថេរ** ជាមួយកម្មវិធី OAuth ដើមរបស់ពួកគេ។ OmniRoute មិនអាចផ្លាស់ប្តូរវាបានទេ — អ្នកផ្តល់សេវាតែងតែបញ្ជូនកម្មវិធីរុករកត្រឡប់ទៅអាសយដ្ឋានដែលបានកំណត់ថេរដូចគ្នា៖ | អ្នកផ្តល់សេវា | callback ថេរដែលអ្នកផ្តល់សេវាបញ្ជូនបន្តទៅ | | ------------- | ---------------------------------------- | | `codex` | `http://localhost:1455/auth/callback` | | `xai-oauth` | `http://127.0.0.1:56121/callback` | | `grok-cli` | `http://127.0.0.1:56122/callback` | `localhost` នៅទីនោះសំដៅលើ **ម៉ាស៊ីនដែលកំពុងដំណើរការកម្មវិធីរុករក** ខណៈដែលម៉ាស៊ីនមេ callback PKCE របស់ OmniRoute ស្តាប់នៅលើ loopback របស់ **ម៉ាស៊ីនមេ**។ បើកផ្ទាំងគ្រប់គ្រងនៅអាសយដ្ឋាន LAN ដូចជា `http://192.168.0.15:20128` នោះទាំងពីរនឹងមិនអាចភ្ជាប់គ្នាបានទេ៖ កូដអនុញ្ញាតត្រូវបានបញ្ជូនទៅ `localhost:1455` របស់កុំព្យូទ័រយួរដៃផ្ទាល់ខ្លួនរបស់អ្នក ដែលគ្មានអ្វីកំពុងស្តាប់ ហើយអ្នកផ្តល់សេវានឹងបរាជ័យក្នុងការចូលដោយមិនបង្ហាញកំហុស។ ផ្ទាំងគ្រប់គ្រងរកឃើញបញ្ហានេះមុនពេលបើកផ្ទាំងលេចឡើង ហើយបង្ហាញពាក្យបញ្ជា tunnel ជំនួសឱ្យការអនុញ្ញាតឱ្យការចូលបរាជ័យដោយស្ងៀមស្ងាត់ (#8046)។ ### ដំណោះស្រាយ — បញ្ជូនបន្តច្រក **ទាំងពីរ** ```bash # នៅលើម៉ាស៊ីនដែលកំពុងដំណើរការកម្មវិធីរុករក៖ ssh -L 20128:127.0.0.1:20128 -L 1455:127.0.0.1:1455 @192.168.0.15 # បន្ទាប់មកចូលទៅ http://localhost:20128 ហើយភ្ជាប់ Codex ពីទីនោះ ``` ត្រូវការការបញ្ជូនបន្តពីរ ហើយការបញ្ជូនបន្តតែមួយនៅតែបរាជ័យ៖ - **`20128`** (ច្រកផ្ទាំងគ្រប់គ្រង) ធ្វើឱ្យ origin ក្លាយជា localhost ពិតប្រាកដ ដែលជាអ្វីដែលធ្វើឱ្យ OmniRoute ចាប់ផ្តើមម៉ាស៊ីនមេ callback PKCE — origin LAN មិនដែលឈានដល់ branch នោះទេ។ - **`1455`** (ច្រក callback ថេររបស់អ្នកផ្តល់សេវា) គឺជាកន្លែងដែលកម្មវិធីរុករកត្រូវបានបញ្ជូនត្រឡប់ទៅ ហើយវាត្រូវតែឆ្លងកាត់ tunnel ទៅកាន់ loopback របស់ម៉ាស៊ីនមេ។ ប្តូរ `1455` ជា `56121`/`56122` នៅពេលភ្ជាប់ xAI ឬ Grok CLI ហើយប្តូរ `20128` ជាច្រកផ្ទាំងគ្រប់គ្រងជាក់ស្តែងរបស់អ្នក។ រក្សា tunnel ឱ្យបើករហូតដល់ការតភ្ជាប់បង្ហាញថាសកម្ម។ > **មិនមានសិទ្ធិចូលប្រើ SSH មែនទេ?** Codex និង Grok CLI ក៏ទទួលយក token ដែលបានបិទភ្ជាប់ផងដែរ — ផ្ទាំង **Paste API > Key** / **Import auth.json** នៅក្នុងប្រអប់តភ្ជាប់។ វិធីនេះមិនមាន callback > loopback ទេ ដូច្នេះវាដំណើរការពី origin ណាមួយ។ Codex ក៏ទទួលយក access > token ធម្មតា ឬទិន្នន័យ session `~/.codex/auth.json` ផងដែរ។ --- ## ការគ្រប់គ្រង token ```bash omniroute tokens create --name "laptop" --scope write [--expires 30] # ↳ បង្ហាញ secret តែ ១ ដង — ចម្លងឥឡូវនេះ omniroute tokens list # masked: id, name, scope, prefix, status, expiry omniroute tokens revoke # ដកចេញភ្លាមៗ omniroute tokens scopes # ពន្យល់ scope ទាំងបី ``` ពាក្យបញ្ជា `tokens` ត្រូវការ credential **admin**។ អ្នកក៏អាចគ្រប់គ្រង token នៅក្នុង dashboard នៅ **Settings → Access Tokens** (បង្កើត, ដកចេញ, ចម្លងតែមួយដង)។ Token មិនអាចបង្កើតដោយមានសិទ្ធិខ្ពស់ជាងអ្នកបង្កើតវាទេ។ Token `admin` អាចបង្កើតបានតែដោយ operator — session dashboard, CLI មូលដ្ឋានលើ server ខ្លួនឯង ឬ `omniroute connect` ជាមួយ password។ Credential ម៉ាស៊ីន (access token `admin` ឬ API key ដែលមាន scope `manage`/`admin`) អាចបង្កើត token `write` និង `read` តែប៉ុណ្ណោះ; ការស្នើ `--scope admin` ពួកវាទទួល `403`។ ការបិទការចូលមិនបើកការបង្កើត token ទេ៖ access token នៃ scope ណាមួយគឺជា credential ដែល route ដែលត្រូវផ្ទៀងផ្ទាត់ជានិច្ចទទួលយក ដូច្នេះការហៅដោយអនាមិកទទួល `401` នៅ scope ណាក៏ដោយ។ --- ## ការកំណត់ CLI សម្រាប់ coding ពី catalog ពីចម្ងាយ `omniroute configure` អានបញ្ជីម៉ូដែល live catalog របស់ **server ដែលសកម្ម** ហើយសរសេរ config នៅលើ **ម៉ាស៊ីនរបស់អ្នក**។ ```bash omniroute configure codex # Providers: glm, kmc, ollamacloud, opencode-go, … # Provider: glm # Model id: glm/glm-5.2 # ✔ បានសរសេរ ~/.codex/glm52.config.toml # ប្រើវា: codex --profile glm52 # non-interactive omniroute configure codex --provider glm --model glm/glm-5.2 --name glm52 # រក្សាម៉ូដែលដែលប្រើញឹកញាប់នៅកំពូល interactive picker omniroute configure codex --provider glm --model glm/glm-5.2 --favorite --yes ``` Picker រក្សាតែ model ID ប៉ុណ្ណោះ (មិនដែល URL ឬ credential) នៅក្នុងឯកសារ `model-preferences.json` ក្នុងម៉ាស៊ីន ដែលកំណត់វិសាលភាពតាម context និង CLI target។ ម៉ូដែលចូលចិត្តត្រូវបានបង្ហាញមុនការជ្រើសថ្មីៗ; ប្រើ `--unfavorite` ដើម្បីលុបម៉ូដែលដែលបានជ្រើសចេញពីបញ្ជី context/target នោះ។ Profile ដែលបានសរសេរយោង key សម្រាប់ inference តាម env var (`OMNIROUTE_API_KEY`) — secret មិនត្រូវបានសរសេរទៅ disk ឡើយ។ សម្រាប់ការកំណត់ Codex មូលដ្ឋានតែម្ដង (block `[model_providers.omniroute]`) មើល [CODEX-CLI-CONFIGURATION.md](./CODEX-CLI-CONFIGURATION.md)។ ### ចាប់ផ្ដើម CLI ទៅ remote (មិនសរសេរ config) `omniroute run ` ក៏គោរព context ដែលសកម្មដែរ: remote base URL និង credential context ត្រូវបាន inject ទៅតែ process ដែលបានចាប់ផ្ដើមប៉ុណ្ណោះ។ ```bash omniroute connect 192.168.0.15 omniroute run claude --model openai/gpt-5.4 # Claude Code → remote omniroute run gemini --model glm/glm-5.2 -- --skip-trust -p "hello" omniroute run opencode --model glm/glm-5.2 -- run "reply OK" # មើលជាក់ស្ដែងថាអ្វីនឹងត្រូវចាប់ផ្ដើម (ឈ្មោះ env KEY ប៉ុណ្ណោះ មិនមែនតម្លៃ): omniroute run codex --dry-run --json ``` Target: `claude`, `codex`, `aider`, `goose`, `opencode`, `qwen`, `gemini` (ប្រភពតែមួយ: `bin/cli/cli-manifest.mjs`)។ Qwen និង Gemini ដំណើរការជាមួយ home ដាច់ដោយឡែកបណ្ដោះអាសន្ន ដែលត្រូវបានលុបនៅពេលចេញ ដូច្នេះការចាប់ផ្ដើមមិនដែលប៉ះ ឬលេចចេញទៅក្នុង config ឧបករណ៍ផ្ទាល់ខ្លួនរបស់អ្នកឡើយ។ ### ពាក្យបញ្ជាកំណត់រចនាសម្ព័ន្ធតាម CLI CLI ដែលគាំទ្រនីមួយៗមានពាក្យបញ្ជាកំណត់រចនាសម្ព័ន្ធដែលដឹងពី remote (គោរព context ដែលសកម្ម ឬ `--remote --api-key `): | CLI | Command | អ្វីដែលវាសរសេរ | | ----------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Codex | `omniroute setup-codex` | profile `~/.codex/.config.toml` (តាមម៉ូដែល) | | Claude Code | `omniroute setup-claude` | `~/.claude/profiles//settings.json` (តាមម៉ូដែល) | | OpenCode | `omniroute setup-opencode` | `~/.config/opencode/opencode.json` — provider `omniroute` openai-compatible ជាមួយម៉ូដែល catalog ទាំងអស់ (ដំណើរការ `opencode -m omniroute/`) | | Cline | `omniroute setup-cline` | `~/.cline/data/{globalState,secrets}.json` (CLI mode) + បង្ហាញការកំណត់ extension VS Code ដើម្បីបិទភ្ជាប់ (OpenAI-compatible, Base URL **ដោយគ្មាន** `/v1`) | | Kilo Code | `omniroute setup-kilo` | `~/.local/share/kilo/auth.json` (CLI) + ការកំណត់ VS Code `kilocode.*` — OpenAI-compatible, Base URL **ជាមួយ** `/v1` | | Continue | `omniroute setup-continue` | `~/.continue/config.yaml` (VS Code/JetBrains + CLI `cn`) — `provider: openai`, `apiBase` **ជាមួយ** `/v1`, key តាម `${{ secrets.OMNIROUTE_API_KEY }}` | | Cursor | `omniroute setup-cursor` | បង្ហាញជំហានក្នុងកម្មវិធី (Settings → Models → Override OpenAI Base URL **ជាមួយ** `/v1` + key + model)។ Config Cursor គឺ SQLite អាចមើលមិនឃើញ — chat panel តែប៉ុណ្ណោះ | | Roo Code | `omniroute setup-roo` | សរសេរ JSON នាំចូល Roo (`~/.omniroute/roo-settings.json`) + កំណត់ `roo-cline.autoImportSettingsPath` + បង្ហាញជំហាន UI (OpenAI-compatible, Base URL **ជាមួយ** `/v1`) | | Crush | `omniroute setup-crush` | `~/.config/crush/crush.json` — provider `openai-compat`, `base_url` **ជាមួយ** `/v1`, key តាម `$OMNIROUTE_API_KEY` | | Zed | `omniroute setup-zed` | `~/.config/zed/settings.json` — `language_models.openai_compatible.omniroute`, `api_url` **ជាមួយ** `/v1`, key ត្រូវបាន Zed អានពី `$OMNIROUTE_API_KEY` (មិនដែលសរសេរ) | | Goose | `omniroute setup-goose` | `~/.config/goose/config.yaml` (`GOOSE_PROVIDER=openai` + `OPENAI_HOST` **ដោយគ្មាន** `/v1` + `GOOSE_MODEL`) + env recipe | | Aider | `omniroute setup-aider` | `~/.aider.conf.yml` (`openai-api-base` **ដោយគ្មាន** `/v1` + `model: openai/`) + env recipe (`aider --message --yes`) | | Qwen Code | `omniroute setup-qwen` | `~/.qwen/settings.json` entry V4 `modelProviders.openai` + `OMNIROUTE_API_KEY` នៅ `~/.qwen/.env` | ```bash # OpenCode (provider openai-compatible, ម៉ូដែល catalog ទាំងអស់, VPS ពីចម្ងាយ) omniroute setup-opencode --remote http://192.168.0.15:20128 --api-key oma_live_xxx omniroute setup-opencode --only glm,kimi # រក្សាតែម៉ូដែលដែលត្រូវគ្នា opencode -m omniroute/glm/glm-5.2 "..." # export OMNIROUTE_API_KEY ជាមុនសិន ``` --- > OpenCode ក៏មានការរួមបញ្ចូល **plugin** ដែលសម្បូរបែបជាងដែរ: `omniroute setup opencode` (ឥឡូវ remote-aware តាម `--remote`) ដំឡើង `@omniroute/opencode-plugin`។ > `setup-opencode` ជាជម្រើស openai-compatible ដែលស្រាលជាង។ API key ត្រូវបានយោងតាម `{env:OMNIROUTE_API_KEY}` — មិនដែលសរសេរទៅ disk ឡើយ។ > > នៅ OpenCode v2 ប្រើ `@omniroute/opencode-plugin-v2` ជំនួសវិញ: catalog ដូចគ្នា ប៉ុន្តែ contract loader ខុសគ្នា។ វាអានកូដ key ពី credential store របស់ OpenCode ផ្ទាល់ នៅពេលការរួមបញ្ចូលត្រូវបានភ្ជាប់ ដូច្នេះ gateway ពីចម្ងាយមិនត្រូវការ key ក្នុង `opencode.json` ទាល់តែសោះ។ --- ## ការគ្រប់គ្រងបរិបទ (ប្តូររវាងម៉ាស៊ីនមេ) **បរិបទ (context)** គឺជាម៉ាស៊ីនមេដែលបានរក្សាទុក (baseUrl + credential + scope)។ `omniroute connect` បង្កើតបរិបទមួយហើយធ្វើឱ្យវាសកម្ម; ចាប់ពីពេលនោះមក រាល់ពាក្យបញ្ជាទាំងអស់នឹងកំណត់គោលដៅទៅវា។ គ្រប់គ្រង និងប្តូររវាងពួកវាដោយប្រើ `omniroute contexts`៖ ```bash omniroute contexts list # all contexts; the active one is marked ● omniroute contexts current # the active server, auth status, scope ``` ```text | Name | Base URL | Auth | Scope | Description ● | vps | http://100.67.86.91:20128 | token | admin | Remote OmniRoute (…) | default | http://localhost:20128 | ✗ | | ``` **ប្តូរម៉ាស៊ីនមេ** — រាល់ពាក្យបញ្ជាបន្តបន្ទាប់ទាំងអស់នឹងអនុវត្តតាមបរិបទដែលសកម្ម៖ ```bash omniroute contexts use vps # → all commands now hit the remote VPS omniroute tokens list # (runs against the VPS) omniroute contexts use default # → back to localhost omniroute tokens list # (runs against the local server) ``` **បន្ថែមបរិបទដោយដៃ** (ជំនួសឱ្យ `connect`) ពិនិត្យមើល ឬប្តូរឈ្មោះ៖ ```bash omniroute contexts add staging --url https://staging.example.com:20128 \ --access-token oma_live_xxxx --scope write --description "staging box" omniroute contexts show staging # full details for one context omniroute contexts rename staging stg ``` **លុបបរិបទ** — នឹងសួររកការបញ្ជាក់; ប្រើ `--yes` ដើម្បីរំលងវា (តម្រូវសម្រាប់ស្គ្រីប / shells ដែលមិនអន្តរកម្ម ដែលបើមិនដូច្នេះទេនឹងបដិសេធដោយសុវត្ថិភាព)៖ ```bash omniroute contexts remove stg --yes ``` > `default` (localhost) មិនអាចលុបបានទេ។ ការលុបបរិបទដែលសកម្មនឹងត្រឡប់ទៅ `default` វិញ។ គន្លឹះ៖ ការលុបបរិបទគ្រាន់តែលុប credentials ដែលបានរក្សាទុក **ក្នុងមូលដ្ឋាន** ប៉ុណ្ណោះ — ដកហូត token នៅលើម៉ាស៊ីនមេដោយប្រើ `omniroute tokens revoke ` ដើម្បីបិទការចូលប្រើប្រាស់ពិតប្រាកដ។ **នាំចេញ / នាំចូលបរិបទ** (ឧទាហរណ៍ ដើម្បីផ្លាស់ទីពួកវាទៅរវាងម៉ាស៊ីន)។ ការនាំចេញនឹងលុប credentials ចេញតាមលំនាំដើម រួមទាំង credentials ដែលបានរក្សាទុកដោយ file fallback។ ប្រើ `--include-secrets` ដោយផ្ទាល់នៅពេលដែលត្រូវការការបម្រុងទុកដែលមាន credentials ដែលអាចចល័តបាន៖ ```bash omniroute contexts export --out contexts.json # redacted; default destination: stdout omniroute contexts export --include-secrets --out private-contexts.json omniroute contexts import contexts.json # overwrite; --merge to keep existing omniroute contexts migrate --yes # move legacy plaintext tokens to keychain ``` `--include-secrets` ដោះស្រាយឯកសារយោង keychain មុនពេលនាំចេញ ហើយនឹងបរាជ័យប្រសិនបើ credentials ដែលបានយោងណាមួយមិនអាចអានបាន។ `--no-secrets` តែងតែមានអាទិភាព។ ឯកសារនាំចេញត្រូវបានសរសេរដោយស្វ័យប្រវត្តិជាមួយនឹង mode `0600`។ ចាត់ទុកការនាំចេញដែលមានសម្ងាត់ដោយផ្ទាល់ថាជាសម្ភារៈសម្ងាត់។ នៅលើប្រព័ន្ធ headless ដែលគ្មាន OS keychain ដែលអាចប្រើបាន CLI នឹងត្រឡប់ទៅ `config.json` វិញជាមួយនឹង mode `0600` ហើយបោះពុម្ពការព្រមានតែមួយដង; ការនាំចេញតាមលំនាំដើមនៅតែត្រូវបានកែសម្រួលក្នុងរបៀបនេះ។ --- ## ការត្រួតពិនិត្យពីដើមដល់ចប់យ៉ាងរហ័ស វដ្ដជីវិតដែលអាចចម្លង-បិទភ្ជាប់បាន ដើម្បីផ្ទៀងផ្ទាត់ការដំឡើងពីចម្ងាយតាំងពីដំបូង — ភ្ជាប់ បង្កើត token ដែលមានវិសាលភាព បញ្ជូនពាក្យបញ្ជា ប្ដូរត្រឡប់ និងរុះរើ។ ជំនួស `192.168.0.15` ដោយ host/IP របស់ម៉ាស៊ីនមេរបស់អ្នក (Tailscale, LAN ឬ URL សាធារណៈ `https://…`)។ ```bash # 1. ភ្ជាប់ (ពាក្យសម្ងាត់ → admin token ដែលបានរក្សាទុកជាបរិបទ ហើយក្លាយជាបរិបទសកម្ម) omniroute connect 192.168.0.15 # ឬ៖ --key oma_live_xxxx (មិនប្រើពាក្យសម្ងាត់) omniroute contexts current # បង្ហាញម៉ាស៊ីនមេពីចម្ងាយ + វិសាលភាព # 2. ប្រើវា — ឥឡូវនេះ ពាក្យបញ្ជាគ្រប់គ្រងដំណើរការជាមួយម៉ាស៊ីនមេពីចម្ងាយ omniroute tokens create --name laptop --scope read # បង្កើត token ដែលមានវិសាលភាពកាន់តែចង្អៀត omniroute tokens list # បញ្ជីដែលបានបិទបាំង ពីម៉ាស៊ីនមេពីចម្ងាយ # 3. ប្ដូរទៅមក omniroute contexts use default # → មូលដ្ឋាន omniroute contexts use 192-168-0-15 # → ពីចម្ងាយម្ដងទៀត (ឈ្មោះពី `contexts list`) # 4. រុះរើ។ ចំណាំ៖ `contexts remove` លុបតែព័ត៌មានសម្គាល់អត្តសញ្ញាណក្នុងម៉ាស៊ីនមូលដ្ឋានប៉ុណ្ណោះ — # វាមិនដកហូត token នៅលើម៉ាស៊ីនមេទេ។ ដកហូតនៅផ្នែកម៉ាស៊ីនមេជាមុន ប្រសិនបើអ្នក # ចង់បញ្ឈប់សិទ្ធិចូលប្រើប្រាស់ជាក់ស្ដែង។ omniroute tokens revoke # បញ្ឈប់សិទ្ធិចូលប្រើប្រាស់នៅលើម៉ាស៊ីនមេ omniroute contexts remove 192-168-0-15 --yes # លុបបរិបទមូលដ្ឋាន (ទោះបីជាសកម្មក៏ដោយ → ត្រឡប់ទៅ default) ដោយគ្មានការសួរបញ្ជាក់ ``` > `--yes` ធ្វើឱ្យ `contexts remove` មិនមានអន្តរកម្ម (តម្រូវក្នុងស្គ្រីប/CI; បើគ្មាន > វា shell ដែលមិនអន្តរកម្មនឹងបដិសេធដោយសុវត្ថិភាព ជំនួសឱ្យការជាប់គាំង)។ ការលុប > បរិបទ **សកម្ម** នឹងត្រឡប់ទៅ `default` ដោយស្វ័យប្រវត្តិ។ --- ## កំណត់សម្គាល់អំពីសុវត្ថិភាព - ថូខឹនជាអត្ថបទធម្មតាត្រូវបានបង្ហាញតែម្តងប៉ុណ្ណោះ ហើយមានតែហាស SHA-256 ប៉ុណ្ណោះដែលត្រូវបានរក្សាទុកជាអចិន្ត្រៃយ៍ (ដូចគ្នានឹង API keys)។ - `omniroute connect` ប្រើឡើងវិញនូវការចាក់សោទប់ស្កាត់ការសាកល្បងចូលប្រើដោយប្រើកម្លាំងបង្ខំ + ការកត់ត្រាសវនកម្ម។ - គួរប្រើ HTTPS ឬ Tailnet សម្រាប់ការបញ្ជូនទិន្នន័យ។ ម៉ាស៊ីនមេដែលមិនមាន protocol កំណត់ នឹងប្រើ `http://` តាមលំនាំដើម ដើម្បីផ្តល់ភាពងាយស្រួលសម្រាប់ LAN/Tailscale — សូមបញ្ជូន URL `https://…` ពេញលេញ ដើម្បីប្រើ TLS។ - ឯកសារបរិបទមូលដ្ឋានដែលបានណែនាំគឺ `~/.omniroute/config.json` (`chmod 600`) ដែលមានតែ `credentialRef` មួយប៉ុណ្ណោះ។ ថូខឹនផ្ទាល់ត្រូវបានរក្សាទុកក្នុងឃ្លាំងសោរបស់ប្រព័ន្ធប្រតិបត្តិការ (`keytar`) ហើយមិនត្រូវបានបោះពុម្ពក្នុងកំណត់ហេតុឡើយ។ ការដំឡើងបែបគ្មានចំណុចប្រទាក់ដែលមិនមាន ឃ្លាំងសោដើមដែលដំណើរការ នឹងប្រើឯកសារ `0600` ដូចគ្នាជាជម្រើសបម្រុងដែលបានកំណត់យ៉ាងច្បាស់ និង បញ្ចេញការព្រមានម្តង។ ប្រើ `omniroute contexts migrate --yes` បន្ទាប់ពីដំឡើង ផ្នែកខាងក្រោយនៃឃ្លាំងសោ។ --- ## ចំណុចបញ្ចប់ API (ឯកសារយោង) | វិធីសាស្ត្រ | ផ្លូវ | ការផ្ទៀងផ្ទាត់អត្តសញ្ញាណ | វិសាលភាព | | ----------- | --------------------- | ------------------------ | ------------------------------------ | | POST | `/api/cli/connect` | ពាក្យសម្ងាត់គ្រប់គ្រង | — (សាធារណៈ តម្រូវឱ្យមានពាក្យសម្ងាត់) | | GET | `/api/cli/whoami` | ថូខឹនចូលប្រើ | អាន | | GET | `/api/cli/tokens` | ថូខឹនចូលប្រើ | អ្នកគ្រប់គ្រង | | POST | `/api/cli/tokens` | ថូខឹនចូលប្រើ | អ្នកគ្រប់គ្រង | | DELETE | `/api/cli/tokens/:id` | ថូខឹនចូលប្រើ | អ្នកគ្រប់គ្រង | សូមមើល [openapi.yaml](../openapi.yaml) សម្រាប់គ្រោងការណ៍ពេញលេញ។