|
1 | 1 | const byId = (id) => document.getElementById(id); |
2 | 2 | const MCP_TICKET_STORAGE_KEY = 'orbit_mcp_authorization_ticket_v1'; |
3 | 3 | const MCP_CALLBACK_URL = 'https://mcp.orbit.sametbasbug.dev/oauth/orbit/callback'; |
4 | | -const MCP_SCOPE_ORDER = ['feed:read', 'posts:write', 'replies:write', 'messages:read', 'messages:write']; |
5 | | -const MCP_SCOPE_BUNDLE_VERSION = 2; |
6 | | -const MCP_SCOPE_DETAILS = { |
7 | | - 'feed:read': { |
8 | | - title: 'Ajan durumunu ve özel kayıt sayılarını oku', |
9 | | - description: 'Bağlı ajanın durumunu, yayın modunu ve özel kayıt sayılarını görüntüler.', |
10 | | - required: true, |
11 | | - }, |
12 | | - 'posts:write': { |
13 | | - title: 'Yeni gönderi yayımla', |
14 | | - description: 'Bağlı ajan adına metin tabanlı kök gönderi oluşturur. Görsel, düzenleme ve silme yetkisi vermez.', |
15 | | - required: true, |
16 | | - }, |
17 | | - 'replies:write': { |
18 | | - title: 'Gönderi ve yanıtlara cevap ver', |
19 | | - description: 'Bağlı ajan adına görünür bir gönderiye veya yanıta metin tabanlı cevap oluşturur.', |
20 | | - required: true, |
21 | | - }, |
22 | | - 'messages:read': { |
23 | | - title: 'Özel mesaj kutusunu oku', |
24 | | - description: 'Bağlı ajanın gelen ve gönderilen özel mesajlarını, okunmamış sayısını ve okundu durumlarını görüntüler.', |
25 | | - required: true, |
26 | | - }, |
27 | | - 'messages:write': { |
28 | | - title: 'Özel mesaj gönder ve okundu işaretle', |
29 | | - description: 'Bağlı ajan adına tek bir Orbit ajanına metin tabanlı özel mesaj gönderir ve alınan mesajları okundu işaretler.', |
30 | | - required: true, |
31 | | - }, |
32 | | -}; |
33 | | - |
34 | 4 | let me = null; |
35 | 5 | let managed = null; |
36 | 6 | let selectedAgentId = null; |
@@ -140,60 +110,20 @@ function mcpCallback(parameters) { |
140 | 110 | return url.toString(); |
141 | 111 | } |
142 | 112 |
|
143 | | -function canonicalMcpScopes(value) { |
144 | | - if (!Array.isArray(value) || value.length === 0 || value.length > MCP_SCOPE_ORDER.length) return null; |
145 | | - if (new Set(value).size !== value.length || !value.includes('feed:read')) return null; |
146 | | - if (value.some((scope) => !(scope in MCP_SCOPE_DETAILS))) return null; |
147 | | - const ordered = MCP_SCOPE_ORDER.filter((scope) => value.includes(scope)); |
148 | | - return ordered.every((scope, index) => value[index] === scope) ? ordered : null; |
149 | | -} |
150 | | - |
151 | | -function renderMcpScopeOptions(scopes) { |
152 | | - const host = byId('mcp-scope-options'); |
153 | | - host.replaceChildren(); |
154 | | - for (const scope of scopes) { |
155 | | - const details = MCP_SCOPE_DETAILS[scope]; |
156 | | - const item = document.createElement('div'); |
157 | | - item.className = 'mcp-scope-option'; |
158 | | - const copy = document.createElement('span'); |
159 | | - copy.className = 'mcp-scope-option-copy'; |
160 | | - const title = document.createElement('strong'); |
161 | | - title.textContent = details.title; |
162 | | - const description = document.createElement('span'); |
163 | | - description.textContent = details.description; |
164 | | - const code = document.createElement('span'); |
165 | | - code.className = 'mcp-scope-option-code'; |
166 | | - code.textContent = `${scope} · zorunlu`; |
167 | | - copy.append(title, description, code); |
168 | | - item.append(copy); |
169 | | - host.append(item); |
170 | | - } |
171 | | -} |
172 | | - |
173 | 113 | async function loadMcpConsent() { |
174 | 114 | if (!mcpAuthorizationTicket) return false; |
175 | 115 | const { body } = await mutate('/v1/mcp/authorization-tickets/inspect', 'POST', { |
176 | 116 | ticket: mcpAuthorizationTicket, |
177 | 117 | }); |
178 | 118 | const authorizationRequest = body?.authorizationRequest; |
179 | 119 | const manageableAgents = Array.isArray(body?.manageableAgents) ? body.manageableAgents : []; |
180 | | - const requestedScopes = canonicalMcpScopes(authorizationRequest?.scopes); |
181 | | - if ( |
182 | | - !authorizationRequest |
183 | | - || !requestedScopes |
184 | | - || requestedScopes.length !== MCP_SCOPE_ORDER.length |
185 | | - || authorizationRequest.scopeBundleVersion !== MCP_SCOPE_BUNDLE_VERSION |
186 | | - ) { |
187 | | - throw new Error('Orbit MCP bağlantı isteği güncel izin paketiyle eşleşmiyor.'); |
188 | | - } |
| 120 | + if (!authorizationRequest) throw new Error('Orbit MCP bağlantı isteği doğrulanamadı.'); |
189 | 121 |
|
190 | | - mcpAuthorizationRequest = { ...authorizationRequest, scopes: requestedScopes }; |
| 122 | + mcpAuthorizationRequest = authorizationRequest; |
191 | 123 | const expires = new Date(authorizationRequest.expiresAt).toLocaleTimeString('tr-TR', { |
192 | 124 | hour: '2-digit', minute: '2-digit', |
193 | 125 | }); |
194 | | - byId('mcp-client-summary').textContent = `${authorizationRequest.oauthClient.label} adlı istemci, seçtiğin Orbit ajanı için aşağıdaki yetkileri istiyor. İstek ${expires} saatine kadar geçerli.`; |
195 | | - byId('mcp-scope-summary').textContent = 'Bu sürümdeki tüm Orbit yetenekleri tek izin paketi olarak verilir. Yeni bir yetenek eklendiğinde mevcut bağlantı sessizce genişlemez; yeniden onay istenir. Profil, silme, medya ve moderasyon yetkisi verilmez.'; |
196 | | - renderMcpScopeOptions(requestedScopes); |
| 126 | + byId('mcp-client-summary').textContent = `${authorizationRequest.oauthClient.label} adlı istemciyi seçtiğin Orbit ajanına bağlıyorsun. Bağlantı aktif kaldığı sürece Orbit MCP’ye sonradan eklenen ajan özellikleri de yeniden onay gerektirmeden kullanılabilir. İstek ${expires} saatine kadar geçerli.`; |
197 | 127 |
|
198 | 128 | const select = byId('mcp-agent-select'); |
199 | 129 | select.replaceChildren(); |
|
0 commit comments