Repository navigation
feat(providers): provider OpenCode Go con cuotas 5 h/semana/ciclo (#187) - #201
Conversation
egdev6
left a comment
There was a problem hiding this comment.
@SrStamm gracias por la PR. Está muy alineada con el plan v2. Integraste todo lo previsto: secreto en ALL y for_provider, ACCOUNT_PROVIDERS, CONFIG_KEY/MainKey, dataKey, clave aislada en cuentas adicionales, OFFICIAL_USAGE_URL y monograma. El módulo está registrado desde T7, sin dead_code. La precedencia HTTP, el Warning único compuesto y S1b fuera respetan el contrato. También corregiste la etiqueta de evidencia de «ventana no iniciada» en el documento ODD. CI en verde en las cinco plataformas.
Un cambio necesario antes de integrar y algunos ajustes menores.
Bloqueante: validación de resetsAt (criterio 6)
parse_usage acepta cualquier string no vacío como resetsAt. Un valor como "garbage" pasa sin diagnóstico y llega al frontend, donde Date.parse devuelve NaN (src/lib/pace.ts). El contrato indica que un resetsAt inválido o ausente conserva el porcentaje, deja el reinicio como desconocido y lo advierte. chrono ya es dependencia del proyecto (zai.rs); con DateTime::parse_from_rfc3339 se resuelve. Añade un test con un string no interpretable que verifique: porcentaje conservado, resets_at: None y aviso emitido.
Cobertura de S4 (no bloqueante, pero estaba comprometida en el plan)
- Faltan casos: el límite
percent: 100, que S4 nombra explícitamente, y el JSON vacío o renombrado ({}ousagecon otra clave). - Aserciones más estrictas:
rate_limited_window_warning_keeps_metersusacontains("rolling") || contains("tarifa"). Con||, el test no garantiza que se nombre la ventana.percent_validation_boundsdebería verificar queweeklyymonthlyse conservan y que no se crea el medidor defive_hour.unknown_status_or_missing_statusdebería comprobar que se diagnostican ambas ventanas,weeklyymonthly.
- Estado final del informe: ningún test verifica que el
UsageReporttermine enStatus::Warning; solo se comprueba el vector de avisos. La nota 2 de la revisión del plan pedía que el test lo verificara. Extraer el tramo final defetcha una función pura (por ejemplobuild_report) permite probarlo sin red. - Procedencia de fixtures: el comentario de
entitlement_body()describe la procedencia del 429 («no reproducido en vivo…»). El cuerpo del 403 es documental (openusage), no sintético.
Mensajes y copy (sugerencias)
- Los avisos usan las claves internas del payload (
rolling,monthly), pero el usuario ve «5 h» y «ciclo de facturación». Sugiero usar la etiqueta del medidor para que el mensaje sea accionable. - «Ventana limitada por tarifa» no transmite bien rate-limited. Una alternativa: «Límite de uso alcanzado en la ventana de 5 h».
- La descripción de la pestaña dice «mensual», mientras la sección y el README hablan de «ciclo de facturación». Conviene unificarlo.
- El guard de informe vacío (
meters.is_empty() && warnings.is_empty()) no se cumple nunca, porqueparse_usagesiempre emite avisos cuando no hay medidores. El resultado actual es razonable (unWarningcon diagnóstico), pero conviene eliminar esa rama o documentar que el diagnóstico la sustituye.
Tamaño
Teniendo en cuenta que el documento ODD y el inventario i18n son mecánicos, el código propio queda en un tamaño revisable. Mantenemos PR única, sin necesidad de partirla.
Con el ajuste de resetsAt y los tests reforzados, vuelvo a revisar. Esta revisión no autoriza merge ni release.
- resetsAt no interpretable ya no llega tal cual al frontend (Date.parse daria NaN): reinicio desconocido + aviso, conservando un percent valido (criterio 6). Test dedicado con strings no interpretables (RED observado antes del fix). - Avisos con la etiqueta visible del medidor (Cuota · 5 h / semana / ciclo de facturacion) en lugar de claves internas del payload (rolling/monthly); el limite de uso ahora se anuncia como tal. - Extraer build_report del tramo final de fetch: tests verifican el Estado final del informe (Status::Warning) sin red. - Cobertura S4 reforzada: percent 100 como limite valido, JSON vacio y usage renombrado, aserciones de ventanas diagnósticadas (percent_validation_bounds, unknown_status_or_missing_status), comentario del 403 con procedencia documental. Refs: egdev6#187, feedback de review en PR egdev6#201
Pestaña decia 'mensual' donde la sección y los READMEs dicen 'ciclo de facturación' (sugerencia de review en PR egdev6#201). Refs: egdev6#187, egdev6#201
…o-provider) Refs: egdev6#187
|
Gracias por la revisión, muy fina. Resuelto el bloqueante y aplicados los refuerzos, en 3 commits ( Bloqueante: validación de
|
|
@SrStamm gracias por la respuesta tan completa. He revisado de nuevo el diff (
Falta un paso: rebase sobre
|
…dev6#187) Backend opencode_go.rs: GET https://opencode.ai/zen/go/v1/usage con API key de Go (sin x-opencode-org-id), parseo tolerante por ventana (rolling/weekly/ monthly) con ids estables five_hour/weekly/monthly, validación de percent (finito en [0,100]) y resetsAt independiente, degradación parcial explícita con un único Warning que nombra todas las ventanas afectadas, y precedencia de errores HTTP sobre el parseo (status_for_http puro, testeable sin red). Estados: sin key y 401 → Unconfigured; 403 EntitlementError → Warning; 403 genérico → Unconfigured; 429 → Warning (fixture sintético marcado); otro HTTP / no JSON → Error. S1b (heurística «ventana no iniciada») queda fuera: el reset recibido se muestra tal cual. Registrado en providers/mod.rs (fetch_all/fetch_one/fetch_account) en este mismo commit para que quede verde. 15 tests propios; cargo test 322 OK, fmt y clippy limpios. Ref: egdev6#187
…gdev6#187) S2: OpenCodeGoConfig { enabled } en AppConfig + ACCOUNT_PROVIDERS 11→12; OPENCODE_GO_API_KEY en secrets.rs (ALL 13→14, for_provider); tipos TS (opencodeGo, AccountProvider, SecretKey), MainKey + CONFIG_KEY en settings-visibility, dataKey en widget-refresh, ACCOUNT_SECRETS + accountReady en accounts.ts. S3: pestaña «OpenCode Go» en PROVIDER_TABS (grupo sub), sección en Settings con Toggle de visibilidad, SecretInput y HealthStep con enlace a Console, rama scoped en AccountEditor, OFFICIAL_USAGE_URL a opencode.ai/console, monograma OC en ProviderLogo, filas en README.md/README.es.md. Los % se presentan como contabilidad de OpenCode, sin desglose por modelo. accountReady con rama opencode_go (exigida por el plan aprobado) y monograma explícito 'OC' (Grok resuelve vía grok.svg en este repo). Verificado: npm test 225 OK, typecheck limpio, inventario i18n OK, cargo test 322 OK, cargo fmt --check y clippy limpios. Ref: egdev6#187
…gdev6#187) Los 6 textos nuevos de la UI (a40a158) no estaban en el inventario commiteado; el contrato de CI de egdev6#186 (i18n-inventory --check) lo marca como drift. React 770/915 → 776/930. Ref: egdev6#187
- resetsAt no interpretable ya no llega tal cual al frontend (Date.parse daria NaN): reinicio desconocido + aviso, conservando un percent valido (criterio 6). Test dedicado con strings no interpretables (RED observado antes del fix). - Avisos con la etiqueta visible del medidor (Cuota · 5 h / semana / ciclo de facturacion) en lugar de claves internas del payload (rolling/monthly); el limite de uso ahora se anuncia como tal. - Extraer build_report del tramo final de fetch: tests verifican el Estado final del informe (Status::Warning) sin red. - Cobertura S4 reforzada: percent 100 como limite valido, JSON vacio y usage renombrado, aserciones de ventanas diagnósticadas (percent_validation_bounds, unknown_status_or_missing_status), comentario del 403 con procedencia documental. Refs: egdev6#187, feedback de review en PR egdev6#201
…o-provider) Refs: egdev6#187
7f91f67 to
359f9c3
Compare
|
Rebase hecho sobre Al resolver el conflicto adapté lo que pediste: Un extra que apareció: el fixture de Nota sobre el historial: Con esto quedo pendiente de tu aprobación para que el review deje de bloquear el merge. |
egdev6
left a comment
There was a problem hiding this comment.
Aprobado sobre 359f9c3. Los cambios pedidos en la revisión del 28 (validación de resetsAt con RFC 3339, cobertura de S4, build_report y textos de los avisos) quedan resueltos, y el rebase sobre #204 incorpora descKey, locale en los SecretInput e inventario regenerado. CI en verde en las cinco comprobaciones.
|
@SrStamm ¡muchas gracias por esta PR! He revisado el rebase ( Ha sido un trabajo de manual de principio a fin: evidencia real con tu API key, un plan ODD claro, tests escritos primero y respuestas a cada punto de la revisión sin dejar nada en el aire. Incluso el detalle del commit que quedó vacío al rebasear lo explicaste antes de que nadie preguntara. Así da gusto revisar. Queda aprobada. Bienvenido OpenCode Go a la tira 🎉 |
Related issue / Issue relacionada
Issue: #187
ODD: plan v2 aprobado como fuente única en #187 (comment); evidencia de implementación y smoke con API key real en #187 (comment)
Scope / Alcance
Provider nativo OpenCode Go (
Kind::Subscription, grupo «sub»): cuotas de 5 h, semanal y mensual (ciclo de facturación) víaGET https://opencode.ai/zen/go/v1/usagecon la API key de Go, sinx-opencode-org-id.src-tauri/src/providers/opencode_go.rs): fetch, parseo tolerante por ventana con ids estables (five_hour/weekly/monthly), validación depercent(finito en [0,100]) yresetsAtindependiente, degradación parcial explícita con un únicoWarningque nombra todas las ventanas afectadas, y precedencia de errores HTTP sobre el parseo (status_for_httppuro, testeable sin red).OpenCodeGoConfig,OPENCODE_GO_API_KEY,ACCOUNT_PROVIDERS11→12, tipos TS, toggle de visibilidad, cuentas adicionales con clave scoped.SecretInput/HealthStepy enlace a Console, monogramaOC, filas en README.md/README.es.md.ODD
feat/opencode-go-providercompleto (T1–T9).Coordination / Coordinación
status:approved; sin PR solapadas (verificado contra issues/PRs abiertas del repo antes de arrancar).Contributor / Contribuidor: @SrStamm
Claim or agreement evidence / Evidencia de asignación o acuerdo: asignación del mantenedor egdev6 en #187 (2026-10-27) y aprobación del plan v2 (2026-10-28, issuecomment-6472310756: «Plan aprobado: OK de arranque de T7»).
Acceptance and validation / Aceptación y validación
mainvigente, chore(i18n): inventario estable, contrato de CI estructural y mensajes de drift (#160) #186/feat(i18n): migrar la tira y el detalle a los catálogos ES/EN — T2c slice 1 (#66) #195/feat(i18n): migrar las secciones no-provider de Ajustes a los catálogos ES/EN — T2c slice 2 PR-A (#66) #199/chore(release): prepare 0.8.0 #200):cargo test: 322 passed, 0 failed (15 tests propios del provider).cargo fmt --check: OK.cargo clippy --all-targets: 0 warnings enopencode_go.rsy en los archivos tocados.npm test: 715 (vitest) + 240 (node scripts) passed, 0 failed — incluye elit.eachde settings-visibility cubriendoopencode_go.npm run typecheck: limpio.node scripts/i18n-inventory.mjs --check(contrato CI de chore(i18n): inventario estable, contrato de CI estructural y mensajes de drift (#160) #186): OK tras regenerar el inventario (React 770→776 textos).An open PR does not mean integration. Release, secrets and signing operations require separate authorization.
Una PR abierta no implica integración. Release, secretos y firma requieren autorización separada.