TOpenCode (OpenCode Zen)

Fuente: source/classes/topencode.prg

TOpenCode usa la API de chat OpenCode Zen (https://opencode.ai/zen/v1/chat/completions) con Authorization: Bearer public. Sin clave API. Modelos gratuitos (mimo-v2.6-flash-free, space-bunny-free, big-pickle, beam-free, glm-5.3-flash-free, deepseek-v4.1-flash-free; comprobado el 2026-10-17). SendAsync exige la VM Harbour MT (build_new.bat <sample> hb32 mt).

Transporte: hbcurl sobre un libcurl estático (Schannel): no hace falta distribuir libcurl.dll. Los fuentes de curl y los scripts de build están en 3rdparty/ (salidas: lib/libcurl_static*.{lib,a} para bcc32/bcc64/msvc32/msvc64/gcc).

Métodos

MétodoDescripción
New( cModel )Un handle curl por instancia (varios agentes en paralelo).
Send( cPrompt ) / SendWithSystem()Síncrono; si hay rate limit, prueba otro modelo free.
SendAsync() / SendWithSystemAsync()Vuelve al momento. Consultar IsRunning(); si el hilo termina sin resultado devuelve .F. y GetValue() informa del error.
GetValue()Texto del asistente (UTF-8 → ACP).
lVerifySSLVerifica el certificado del servidor (por defecto .T.). Déjalo activado.
SetServer( cBaseUrl [, cProviderID [, cModel ]] )Usa un servidor local opencode serve en lugar de Zen (URL vacía = volver a Zen).
SessionStart() / SessionEnd()Maneja la sesión del servidor a mano (automático en Send() / End()).
SetTimeout( nMs )Timeout de cada petición en milisegundos (nTimeout, por defecto 90000).
ClearMessages()Olvida la conversación; en modo servidor el siguiente Send() abre una sesión nueva.

Async escribe oc_<ms>_<seq>.json vía .part + rename: tres SendAsync() en el mismo tick no chocan.

Mejor esfuerzo: el nivel gratuito de OpenCode Zen solo responde a peticiones que parecen venir del cliente OpenCode, y TOpenCode envía las cabeceras y la lista de herramientas que ese nivel espera. Zen puede cambiarlo, o la lista de modelos gratuitos, en cualquier momento; si un modelo deja de responder, usa SetModel() con otro modelo gratuito.

Modo servidor local (opencode serve)

Con SetServer() la clase habla con un opencode serve local (por defecto http://127.0.0.1:4096) en lugar de OpenCode Zen. Mantiene una sesión persistente (POST /session), así que el servidor recuerda toda la conversación y se puede usar cualquier proveedor/modelo configurado en opencode (cProviderID + cModel; vacíos = modelo por defecto del servidor). Si la sesión se pierde (HTTP 404) se recrea una vez automáticamente, y End() la borra (DELETE /session/{id}). Admite autenticación básica con cServerUser / cServerPass (OPENCODE_SERVER_PASSWORD). En este modo SendAsync() funciona de forma síncrona. Este backend sigue el enfoque de la clase TOpenCode de Charly 9000 (licencia MIT).

o := TOpenCode():New()
o:SetServer( "http://127.0.0.1:4096" )
o:Send( "Hola" )
o:Send( "¿Qué te acabo de decir?" )   // el servidor lo recuerda
o:End()

Historial de conversación

Por defecto (lHistory := .T.) cada Send()/SendWithSystem() con éxito añade el turno a aMessages y la siguiente petición lleva toda la conversación: el modelo tiene memoria. ClearMessages() empieza una conversación nueva; lHistory := .F. vuelve a peticiones sin estado.

Samples

cd samples\ai
build_new.bat opencode2 hb32 mt

Ejecutar desde samples\ai para encontrar libcurl.dll.

Véase también