feat(oauth): ARIA kann Provider selbst registrieren + Custom-Provider in Diagnostic & App
ARIA hat jetzt das META-Tool oauth_register_provider. Wenn Stefan einen Service nutzen will, der nicht in den (auf Spotify reduzierten) Defaults ist, kann sie auth_url/token_url/scopes/client_auth selbst eintragen — ARIA kennt typische OAuth-Endpunkte (Dropbox, Discord, Notion, Slack, Zoom, Trello, LinkedIn, Reddit, Twitch) aus ihrem Training. Sie traegt NUR die URLs ein, client_id/secret bleiben Stefans Job (Diagnostic / App-UI) — bewusste Trennung damit Credentials nicht im Chat-Verlauf landen. DEFAULT_PROVIDERS auf Spotify reduziert — Rest war aktuell ungenutzt und macht den Code unnoetig "groß". ARIA registriert on-demand. Diagnostic-UI: - Custom-Provider zeigen auth_url/token_url/scopes als sichtbare Felder - Defaults verstecken die Felder hinter "Default-URLs ueberschreiben (advanced)" damit man die Spotify-URLs nicht versehentlich loescht - "+ Custom OAuth-Provider hinzufuegen" Button mit Prompts fuer Name/URLs/Scopes - 🗑-Icon bei Custom-Services (Service komplett entfernen) App-UI (neu fuer unterwegs): - Settings → Sektion 🔑 "OAuth-Apps" zwischen Skills und Protokoll - OAuthBrowser-Komponente analog zu Trigger/Skill-Browser: Liste mit Status, Tap → Edit-Modal mit client_id/secret + Advanced-Toggle fuer URLs. "Autorisieren ↗" oeffnet System-Browser via Linking.openURL, redirected zur RVS-Callback-Page, Status-Refresh nach 8s. - "+ Custom"-Button → Full-Screen-Modal fuer Service-Anlage. - brainApi um listOAuthServices/getOAuthApps/saveOAuthApp/ deleteOAuthApp/authorizeOAuth/revokeOAuth erweitert. Workflow ist jetzt: "verbinde mich mit Dropbox" → ARIA registriert Provider → "trag client_id/secret in Settings ein" → Stefan macht das in App oder Diagnostic → "Autorisieren ↗" → fertig. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -307,6 +307,65 @@ META_TOOLS = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "oauth_register_provider",
|
||||
"description": (
|
||||
"Registriert einen NEUEN OAuth2-Provider in oauth_apps.json — "
|
||||
"nutze das wenn Stefan einen Service nutzen will, der noch nicht "
|
||||
"in der Default-Liste (spotify, google, github, strava, microsoft) "
|
||||
"ist. Du kennst typische OAuth-Endpunkte aus deinem Training "
|
||||
"(Dropbox, Twitch, Discord, Slack, Reddit, LinkedIn, Notion, "
|
||||
"Zoom, Trello, ...). Trag NUR die URLs ein — client_id / "
|
||||
"client_secret bleiben Stefans Job (Diagnostic > OAuth-Apps oder "
|
||||
"App > Settings > OAuth-Apps).\n\n"
|
||||
"**Workflow bei neuem Service:**\n"
|
||||
"1. `oauth_register_provider` mit auth_url + token_url + scopes\n"
|
||||
"2. Sag Stefan: \"Service '{name}' ist eingerichtet. Trag in "
|
||||
"Diagnostic/App > OAuth-Apps deine client_id + client_secret aus "
|
||||
"dem {name}-Developer-Dashboard ein. Plus die Callback-URL "
|
||||
"{callback} musst Du dort einmal als Redirect-URI eintragen.\"\n"
|
||||
"3. Warten bis Stefan fertig ist\n"
|
||||
"4. `oauth_authorize` rufen\n\n"
|
||||
"**`client_auth`-Wert:** Die meisten Provider wollen client_id+"
|
||||
"secret im Body (`body`, default). Spotify und manche andere "
|
||||
"wollen Basic-Auth-Header (`basic`). Wenn du unsicher bist, "
|
||||
"nimm `body` — schlaegt der Token-Request dann mit 401 fehl, "
|
||||
"switch auf `basic`.\n\n"
|
||||
"Bei Provider die du wirklich nicht kennst: frag Stefan oder "
|
||||
"such die Docs raus statt zu raten."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": {
|
||||
"type": "string",
|
||||
"description": "Service-Name (a-z 0-9 _ -, kurz, z.B. 'dropbox', 'discord')",
|
||||
},
|
||||
"auth_url": {
|
||||
"type": "string",
|
||||
"description": "Authorize-Endpoint, z.B. 'https://www.dropbox.com/oauth2/authorize'",
|
||||
},
|
||||
"token_url": {
|
||||
"type": "string",
|
||||
"description": "Token-Endpoint, z.B. 'https://api.dropboxapi.com/oauth2/token'",
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Default-Scopes die der User beim Auth zustimmen muss",
|
||||
},
|
||||
"client_auth": {
|
||||
"type": "string",
|
||||
"enum": ["body", "basic"],
|
||||
"description": "Wie der Provider client_id/secret erwartet (Default 'body')",
|
||||
},
|
||||
},
|
||||
"required": ["service", "auth_url", "token_url"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
@@ -927,6 +986,37 @@ class Agent:
|
||||
else:
|
||||
lines.append(f"- {t['name']} ({t['type']}, {state})")
|
||||
return "\n".join(lines)
|
||||
if name == "oauth_register_provider":
|
||||
svc = (arguments.get("service") or "").strip()
|
||||
auth_url = (arguments.get("auth_url") or "").strip()
|
||||
token_url = (arguments.get("token_url") or "").strip()
|
||||
scopes = arguments.get("scopes") if isinstance(arguments.get("scopes"), list) else None
|
||||
client_auth = (arguments.get("client_auth") or "body").strip().lower()
|
||||
if not svc or not auth_url or not token_url:
|
||||
return "FEHLER: service, auth_url, token_url sind Pflicht."
|
||||
try:
|
||||
entry = oauth_mod.register_provider(
|
||||
svc, auth_url, token_url, scopes=scopes, client_auth=client_auth,
|
||||
)
|
||||
except ValueError as exc:
|
||||
return f"FEHLER: {exc}"
|
||||
except Exception as exc:
|
||||
logger.exception("oauth_register_provider fehlgeschlagen")
|
||||
return f"FEHLER: {exc}"
|
||||
cb = oauth_mod._callback_url(svc) if os.environ.get("RVS_HOST") else f"<RVS_HOST nicht gesetzt>/oauth/callback/{svc}"
|
||||
scopes_str = ", ".join(entry.get("scopes") or []) or "(keine)"
|
||||
return (
|
||||
f"OK — Provider '{svc}' registriert.\n"
|
||||
f" auth_url: {entry['auth_url']}\n"
|
||||
f" token_url: {entry['token_url']}\n"
|
||||
f" scopes: {scopes_str}\n"
|
||||
f" client_auth: {entry['client_auth']}\n\n"
|
||||
f"Sage Stefan: Trag in Diagnostic > OAuth-Apps (oder App > "
|
||||
f"Settings > OAuth-Apps) deine client_id + client_secret aus "
|
||||
f"dem {svc}-Developer-Dashboard ein. Plus die Callback-URL "
|
||||
f"`{cb}` musst Du dort einmal als Redirect-URI registrieren.\n"
|
||||
f"Sobald Stefan das gemacht hat, rufe `oauth_authorize` auf."
|
||||
)
|
||||
if name == "oauth_authorize":
|
||||
svc = (arguments.get("service") or "").strip()
|
||||
if not svc:
|
||||
|
||||
Reference in New Issue
Block a user