← back to kuitang__opencode-client

Function bodies 85 total

All specs Real LLM only Function bodies
server.Server.handleQuestionReply method · go · L13-L82 (70 LOC)
internal/server/handlers_question.go
func (s *Server) handleQuestionReply(w http.ResponseWriter, r *http.Request) {
	requestID := r.PathValue("requestID")
	if requestID == "" {
		s.httpError(w, "Missing request ID", http.StatusBadRequest)
		return
	}

	if err := r.ParseForm(); err != nil {
		s.httpError(w, "Failed to parse form", http.StatusBadRequest)
		return
	}

	countStr := r.FormValue("question_count")
	questionCount, err := strconv.Atoi(countStr)
	if err != nil || questionCount < 1 {
		questionCount = 1
	}

	var answers [][]string
	var summaryParts []string

	for qi := 0; qi < questionCount; qi++ {
		key := fmt.Sprintf("q%d", qi)
		values := r.Form[key]
		customKey := fmt.Sprintf("q%d_custom", qi)
		customValue := strings.TrimSpace(r.FormValue(customKey))

		var answer []string
		for _, v := range values {
			if v == "__custom__" {
				if customValue != "" {
					answer = append(answer, customValue)
				}
			} else {
				answer = append(answer, v)
			}
		}
		if answer == nil {
			answer = []string{}
		}

		answers =
server.Server.handleQuestionReject method · go · L84-L101 (18 LOC)
internal/server/handlers_question.go
func (s *Server) handleQuestionReject(w http.ResponseWriter, r *http.Request) {
	requestID := r.PathValue("requestID")
	if requestID == "" {
		s.httpError(w, "Missing request ID", http.StatusBadRequest)
		return
	}

	url := fmt.Sprintf("%s/question/%s/reject", s.Sandbox.OpencodeURL(), requestID)
	resp, err := http.Post(url, "application/json", bytes.NewReader([]byte("{}")))
	if err != nil {
		log.Printf("handleQuestionReject: failed to proxy reject: %v", err)
		s.httpError(w, "Failed to send rejection", http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()

	s.renderHTML(w, "question-dismissed", nil)
}
server.Server.handleTabPreview method · go · L10-L25 (16 LOC)
internal/server/handlers_tabs.go
func (s *Server) handleTabPreview(w http.ResponseWriter, r *http.Request) {
	ports := s.detectOpenPorts()
	var previewPort int
	if len(ports) > 0 {
		previewPort = ports[0]
		log.Printf("Preview: Detected open port %d", previewPort)
	}

	data := struct {
		PreviewPort int
	}{
		PreviewPort: previewPort,
	}

	s.renderHTML(w, "tab-preview", data)
}
server.Server.handleTabCode method · go · L27-L43 (17 LOC)
internal/server/handlers_tabs.go
func (s *Server) handleTabCode(w http.ResponseWriter, r *http.Request) {
	files, err := s.fetchAllFiles()
	if err != nil {
		log.Printf("Failed to fetch files from OpenCode: %v", err)
		files = []models.FileNode{}
	}

	lineCount := s.calculateLineCount()

	data := models.CodeTabData{
		Files:     files,
		FileCount: len(files),
		LineCount: lineCount,
	}

	s.renderHTML(w, "tab-code", data)
}
server.Server.handleTabTerminal method · go · L45-L57 (13 LOC)
internal/server/handlers_tabs.go
func (s *Server) handleTabTerminal(w http.ResponseWriter, r *http.Request) {
	data := map[string]any{
		"GottyURL": "",
	}
	if s.Sandbox != nil && s.Sandbox.IsRunning() {
		gottyURL := s.Sandbox.GottyURL()
		log.Printf("Terminal tab: sandbox is running, GottyURL=%q", gottyURL)
		data["GottyURL"] = gottyURL
	} else {
		log.Printf("Terminal tab: sandbox=%v, IsRunning=%v", s.Sandbox != nil, s.Sandbox != nil && s.Sandbox.IsRunning())
	}
	s.renderHTML(w, "tab-terminal", data)
}
server.Server.opencodeGet method · go · L14-L25 (12 LOC)
internal/server/opcode_client.go
func (s *Server) opencodeGet(path string, result any) error {
	resp, err := http.Get(fmt.Sprintf("%s%s", s.Sandbox.OpencodeURL(), path))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if result != nil {
		return json.NewDecoder(resp.Body).Decode(result)
	}
	return nil
}
server.Server.opencodePost method · go · L28-L38 (11 LOC)
internal/server/opcode_client.go
func (s *Server) opencodePost(path string, payload any) (*http.Response, error) {
	jsonData, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}
	return http.Post(
		fmt.Sprintf("%s%s", s.Sandbox.OpencodeURL(), path),
		"application/json",
		bytes.NewReader(jsonData),
	)
}
Repobility analyzer · published findings · https://repobility.com
server.Server.loadProviders method · go · L41-L56 (16 LOC)
internal/server/opcode_client.go
func (s *Server) loadProviders() error {
	resp, err := http.Get(fmt.Sprintf("%s/config/providers", s.Sandbox.OpencodeURL()))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	var providersResp models.ProvidersResponse
	if err := json.NewDecoder(resp.Body).Decode(&providersResp); err != nil {
		return err
	}

	s.providers = providersResp.Providers
	s.defaultModel = providersResp.Default
	return nil
}
server.Server.getAllModels method · go · L59-L76 (18 LOC)
internal/server/opcode_client.go
func (s *Server) getAllModels() []models.ModelOption {
	var modelList []models.ModelOption

	for _, provider := range s.providers {
		for _, model := range provider.Models {
			modelList = append(modelList, models.ModelOption{
				Value: fmt.Sprintf("%s/%s", provider.ID, model.ID),
				Label: fmt.Sprintf("%s - %s", provider.Name, model.Name),
			})
		}
	}

	sort.Slice(modelList, func(i, j int) bool {
		return modelList[i].Value < modelList[j].Value
	})

	return modelList
}
server.Server.executeShellCommand method · go · L79-L106 (28 LOC)
internal/server/opcode_client.go
func (s *Server) executeShellCommand(sessionID, command string) (string, error) {
	shellURL := fmt.Sprintf("/session/%s/shell", sessionID)
	payload := map[string]string{"agent": "build", "command": command}

	resp, err := s.opencodePost(shellURL, payload)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return "", fmt.Errorf("command failed with status %d", resp.StatusCode)
	}

	var result models.MessageResponse
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return "", err
	}

	for _, part := range result.Parts {
		if part.Type == "tool" && part.Tool == "bash" {
			if output, ok := part.State["output"].(string); ok {
				return output, nil
			}
		}
	}
	return "", nil
}
server.Server.RegisterRoutes method · go · L11-L50 (40 LOC)
internal/server/routes.go
func (s *Server) RegisterRoutes() *http.ServeMux {
	mux := http.NewServeMux()

	// Main pages
	mux.HandleFunc("GET /{$}", s.handleIndex)
	mux.HandleFunc("GET /login", s.handleLoginGET)
	mux.HandleFunc("POST /login", s.handleLoginPOST)
	mux.HandleFunc("GET /logout", s.handleLogout)
	mux.HandleFunc("GET /projects", s.handleProjects)

	// Chat
	mux.HandleFunc("POST /send", s.handleSend)
	mux.HandleFunc("GET /events", s.handleSSE)
	mux.HandleFunc("POST /clear", s.handleClear)
	mux.HandleFunc("GET /download", s.handleDownload)

	// Question tool
	mux.HandleFunc("POST /question/{requestID}/reply", s.handleQuestionReply)
	mux.HandleFunc("POST /question/{requestID}/reject", s.handleQuestionReject)

	// Tabs
	mux.HandleFunc("GET /tab/preview", s.handleTabPreview)
	mux.HandleFunc("GET /tab/code", s.handleTabCode)
	mux.HandleFunc("GET /tab/terminal", s.handleTabTerminal)
	mux.HandleFunc("GET /tab/deployment", s.handleTabDeployment)

	// File API
	mux.HandleFunc("GET /tab/code/file", s.handleFileC
server.Server.WrapWithMiddleware method · go · L53-L59 (7 LOC)
internal/server/routes.go
func (s *Server) WrapWithMiddleware(mux *http.ServeMux) http.Handler {
	// Apply auth context middleware, then logging
	var handler http.Handler = mux
	handler = s.withAuth(handler)
	handler = middleware.LoggingMiddleware(handler)
	return handler
}
server.UpdateRateLimiter.TryUpdate method · go · L37-L78 (42 LOC)
internal/server/server.go
func (u *UpdateRateLimiter) TryUpdate(ctx context.Context, doUpdate func()) {
	u.mu.Lock()
	defer u.mu.Unlock()

	now := time.Now()
	elapsed := now.Sub(u.lastSent)

	if u.lastSent.IsZero() || elapsed >= u.minInterval {
		u.lastSent = now
		go func() {
			select {
			case <-ctx.Done():
				return
			default:
				doUpdate()
			}
		}()
		return
	}

	if u.pendingTimer != nil {
		u.pendingTimer.Stop()
		u.pendingTimer = nil
	}

	remainingWait := u.minInterval - elapsed
	u.pendingTimer = time.AfterFunc(remainingWait, func() {
		select {
		case <-ctx.Done():
			u.mu.Lock()
			u.pendingTimer = nil
			u.mu.Unlock()
			return
		default:
			u.mu.Lock()
			u.lastSent = time.Now()
			u.pendingTimer = nil
			u.mu.Unlock()
			doUpdate()
		}
	})
}
server.NewServer function · go · L95-L108 (14 LOC)
internal/server/server.go
func NewServer() (*Server, error) {
	tmpl, err := views.LoadTemplates()
	if err != nil {
		return nil, err
	}

	return &Server{
		sessions:          make(map[string]string),
		authSessions:      make(map[string]*auth.AuthSession),
		selectedFiles:     make(map[string]string),
		templates:         tmpl,
		codeUpdateLimiter: NewUpdateRateLimiter(200 * time.Millisecond),
	}, nil
}
server.Server.renderHTML method · go · L111-L117 (7 LOC)
internal/server/server.go
func (s *Server) renderHTML(w http.ResponseWriter, tmplName string, data any) {
	w.Header().Set("Content-Type", "text/html")
	if err := s.templates.ExecuteTemplate(w, tmplName, data); err != nil {
		http.Error(w, "Template error", http.StatusInternalServerError)
		log.Printf("Template error rendering %s: %v", tmplName, err)
	}
}
Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
server.Server.renderHTMLToString method · go · L126-L132 (7 LOC)
internal/server/server.go
func (s *Server) renderHTMLToString(tmplName string, data any) (string, error) {
	var buf bytes.Buffer
	if err := s.templates.ExecuteTemplate(&buf, tmplName, data); err != nil {
		return "", err
	}
	return buf.String(), nil
}
server.Server.getSessionCookie method · go · L15-L28 (14 LOC)
internal/server/session.go
func (s *Server) getSessionCookie(w http.ResponseWriter, r *http.Request) (*http.Cookie, bool) {
	cookie, err := r.Cookie("session")
	if err != nil {
		cookie = &http.Cookie{
			Name:     "session",
			Value:    fmt.Sprintf("sess_%d", time.Now().UnixNano()),
			HttpOnly: true,
			Path:     "/",
		}
		http.SetCookie(w, cookie)
		return cookie, true
	}
	return cookie, false
}
server.Server.getOrCreateSession method · go · L31-L67 (37 LOC)
internal/server/session.go
func (s *Server) getOrCreateSession(cookie string) (string, error) {
	s.mu.RLock()
	sessionID, exists := s.sessions[cookie]
	s.mu.RUnlock()

	if exists {
		log.Printf("getOrCreateSession: found existing session %s for cookie %s", sessionID, cookie)
		return sessionID, nil
	}

	s.mu.Lock()
	defer s.mu.Unlock()

	if sessionID, exists := s.sessions[cookie]; exists {
		log.Printf("getOrCreateSession: found existing session %s for cookie %s (double-check)", sessionID, cookie)
		return sessionID, nil
	}

	log.Printf("getOrCreateSession: creating new session at %s/session", s.Sandbox.OpencodeURL())

	resp, err := s.opencodePost("/session", map[string]string{})
	if err != nil {
		log.Printf("getOrCreateSession: failed to create session - %v", err)
		return "", err
	}
	defer resp.Body.Close()

	var session models.SessionResponse
	if err := json.NewDecoder(resp.Body).Decode(&session); err != nil {
		log.Printf("getOrCreateSession: failed to decode session response - %v", err)
		return "", err
	}
server.Server.InitWorkspaceSession method · go · L70-L102 (33 LOC)
internal/server/session.go
func (s *Server) InitWorkspaceSession() error {
	url := fmt.Sprintf("%s/session", s.Sandbox.OpencodeURL())
	log.Printf("initWorkspaceSession: creating workspace session at %s", url)

	payload := map[string]string{
		"title": "Workspace Operations",
	}
	jsonData, _ := json.Marshal(payload)

	resp, err := http.Post(
		url,
		"application/json",
		bytes.NewReader(jsonData),
	)
	if err != nil {
		log.Printf("initWorkspaceSession: failed to create session - %v", err)
		return err
	}
	defer resp.Body.Close()

	var session models.SessionResponse
	if err := json.NewDecoder(resp.Body).Decode(&session); err != nil {
		log.Printf("initWorkspaceSession: failed to decode session response - %v", err)
		return err
	}

	s.mu.Lock()
	s.workspaceSession = session.ID
	s.mu.Unlock()

	log.Printf("initWorkspaceSession: created workspace session %s", session.ID)
	return nil
}
sse.MessagePartsManager.UpdatePart method · go · L25-L50 (26 LOC)
internal/sse/parts.go
func (m *MessagePartsManager) UpdatePart(messageID, partID string, part views.MessagePartData) error {
	if messageID == "" {
		return fmt.Errorf("messageID cannot be empty")
	}
	if partID == "" {
		return fmt.Errorf("partID cannot be empty")
	}

	part.PartID = partID

	msgParts, exists := m.parts[messageID]
	if !exists {
		m.parts[messageID] = []views.MessagePartData{part}
		return nil
	}

	for i, existingPart := range msgParts {
		if existingPart.PartID == partID {
			m.parts[messageID][i] = part
			return nil
		}
	}

	m.parts[messageID] = append(msgParts, part)
	return nil
}
sse.MessagePartsManager.GetParts method · go · L53-L62 (10 LOC)
internal/sse/parts.go
func (m *MessagePartsManager) GetParts(messageID string) []views.MessagePartData {
	parts, exists := m.parts[messageID]
	if !exists {
		return nil
	}

	result := make([]views.MessagePartData, len(parts))
	copy(result, parts)
	return result
}
sse.ValidateAndExtractMessagePart function · go · L65-L97 (33 LOC)
internal/sse/parts.go
func ValidateAndExtractMessagePart(event map[string]any, sessionID string) (messageID, partID string, partData map[string]any, err error) {
	eventType, ok := event["type"].(string)
	if !ok || eventType != "message.part.updated" {
		return "", "", nil, fmt.Errorf("not a message.part.updated event")
	}

	props, ok := event["properties"].(map[string]any)
	if !ok {
		return "", "", nil, fmt.Errorf("missing or invalid properties")
	}

	part, ok := props["part"].(map[string]any)
	if !ok {
		return "", "", nil, fmt.Errorf("missing or invalid part data")
	}

	partSessionID, _ := part["sessionID"].(string)
	if partSessionID != sessionID {
		return "", "", nil, fmt.Errorf("session mismatch")
	}

	messageID, ok = part["messageID"].(string)
	if !ok || messageID == "" {
		return "", "", nil, fmt.Errorf("invalid or missing messageID")
	}

	partID, ok = part["id"].(string)
	if !ok || partID == "" {
		return "", "", nil, fmt.Errorf("invalid or missing partID")
	}

	return messageID, partID, part, nil
checkChatContent function · javascript · L2-L10 (9 LOC)
internal/templates/static/script.js
function checkChatContent() {
    const messages = document.getElementById('messages');
    if (messages) {
        // Check if there are any message bubbles (excluding the SSE connection div)
        const messageElements = messages.querySelectorAll('.bg-blue-100, .bg-gray-100');
        return messageElements.length > 0;
    }
    return false;
}
Repobility · open methodology · https://repobility.com/research/
handleAuthClick function · javascript · L13-L18 (6 LOC)
internal/templates/static/script.js
function handleAuthClick(e, isLogin) {
    e.preventDefault();
    const hasContent = checkChatContent();
    const url = hasContent ? '/login?hasContent=true' : '/login';
    window.location.href = url;
}
debounce function · javascript · L21-L31 (11 LOC)
internal/templates/static/script.js
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}
initializeChatState function · javascript · L41-L53 (13 LOC)
internal/templates/static/script.js
function initializeChatState() {
    const chat = document.getElementById('chat-container');
    if (!chat) return;
    
    if (window.innerWidth >= 1024) {
        // Desktop: Remove all mobile classes
        chat.classList.remove('chat-expanded', 'chat-minimized');
    } else {
        // Mobile: Set to expanded by default
        chat.classList.remove('chat-minimized');
        chat.classList.add('chat-expanded');
    }
}
showFlash function · javascript · L209-L245 (37 LOC)
internal/templates/static/script.js
function showFlash(message, type, autoHide) {
    const flash = document.getElementById('connection-flash');
    const messageEl = document.getElementById('flash-message');
    
    if (!flash || !messageEl) return;
    
    // Clear existing classes and state
    flash.classList.remove('hidden', 'bg-amber-500', 'bg-green-500', 'bg-red-500', 'flash-hidden', 'flash-visible');
    
    // Set message and show
    messageEl.textContent = message;
    flash.classList.add('flash-visible');
    
    // Apply color based on type
    switch(type) {
        case 'warning':
            flash.classList.add('bg-amber-500');
            break;
        case 'success':
            flash.classList.add('bg-green-500');
            break;
        case 'error':
            flash.classList.add('bg-red-500');
            break;
        default:
            flash.classList.add('bg-gray-500');
    }
    
    // Auto-hide if specified
    if (autoHide) {
        setTimeout(() => {
            flash.classList.
hideFlash function · javascript · L247-L254 (8 LOC)
internal/templates/static/script.js
function hideFlash() {
    const flash = document.getElementById('connection-flash');
    if (!flash) return;
    
    flash.classList.remove('flash-visible');
    flash.classList.add('flash-hidden');
    setTimeout(() => flash.classList.add('hidden'), 300);
}
views.RenderText function · go · L105-L117 (13 LOC)
internal/views/views.go
func RenderText(text string) template.HTML {
	html := blackfriday.Run([]byte(text),
		blackfriday.WithExtensions(
			blackfriday.CommonExtensions|blackfriday.Autolink))

	policy := bluemonday.UGCPolicy()
	safeHTML := policy.SanitizeBytes(html)

	if HasMarkdownElements(html) {
		return template.HTML(safeHTML)
	}
	return template.HTML(`<div class="preserve-breaks">` + string(safeHTML) + `</div>`)
}
views.HasMarkdownElements function · go · L121-L147 (27 LOC)
internal/views/views.go
func HasMarkdownElements(html []byte) bool {
	htmlStr := string(html)

	markdownIndicators := []string{
		"<h1", "<h2", "<h3", "<h4", "<h5", "<h6",
		"<ul", "<ol", "<li",
		"<blockquote",
		"<pre", "<code",
		"<table",
		"<strong", "<em",
		"<hr",
		"<a href=",
	}

	for _, indicator := range markdownIndicators {
		if strings.Contains(htmlStr, indicator) {
			return true
		}
	}

	pCount := strings.Count(htmlStr, "<p>")
	if pCount > 1 {
		return true
	}

	return false
}
views.RenderMessage function · go · L150-L156 (7 LOC)
internal/views/views.go
func RenderMessage(tmpl *template.Template, msg MessageData) (string, error) {
	var buf bytes.Buffer
	if err := tmpl.ExecuteTemplate(&buf, "message", msg); err != nil {
		return "", err
	}
	return buf.String(), nil
}
Repobility · MCP-ready · https://repobility.com
views.RenderTodoList function · go · L159-L172 (14 LOC)
internal/views/views.go
func RenderTodoList(tmpl *template.Template, output string) (template.HTML, error) {
	var todos []TodoItem
	if err := json.Unmarshal([]byte(output), &todos); err != nil {
		escapedOutput := template.HTMLEscapeString(output)
		return template.HTML(`<pre class="overflow-x-auto">` + escapedOutput + `</pre>`), nil
	}

	var buf bytes.Buffer
	if err := tmpl.ExecuteTemplate(&buf, "todo", todos); err != nil {
		return "", fmt.Errorf("failed to execute todo template: %w", err)
	}

	return template.HTML(buf.String()), nil
}
views.RenderToolDetails function · go · L175-L240 (66 LOC)
internal/views/views.go
func RenderToolDetails(tmpl *template.Template, toolName, status string, input map[string]any, output string) template.HTML {
	toolData := ToolData{
		Name:   strings.ToLower(toolName),
		Status: status,
		Output: output,
	}

	switch strings.ToLower(toolName) {
	case "bash":
		if cmd, ok := input["command"].(string); ok {
			toolData.Command = cmd
		}

	case "write", "read", "edit", "multiedit":
		if path, ok := input["path"].(string); ok {
			toolData.Filename = path
		} else if file, ok := input["file_path"].(string); ok {
			toolData.Filename = file
		} else if file, ok := input["filePath"].(string); ok {
			toolData.Filename = file
		}
		if strings.ToLower(toolName) == "write" {
			if content, ok := input["content"].(string); ok {
				toolData.Content = content
			}
		}

	case "grep":
		if pattern, ok := input["pattern"].(string); ok {
			toolData.Pattern = pattern
		}

	case "glob":
		if pattern, ok := input["pattern"].(string); ok {
			toolData.Pattern = pattern
		}

	case "task"
views.ParseRawMessagePart function · go · L243-L268 (26 LOC)
internal/views/views.go
func ParseRawMessagePart(partID string, partData map[string]any) models.MessagePart {
	msgPart := models.MessagePart{
		ID:   partID,
		Type: partData["type"].(string),
	}

	switch msgPart.Type {
	case "text", "reasoning":
		if text, ok := partData["text"].(string); ok {
			msgPart.Text = text
		}
	case "tool":
		if toolName, ok := partData["tool"].(string); ok {
			msgPart.Tool = toolName
		}
		if state, ok := partData["state"].(map[string]any); ok {
			msgPart.State = state
		}
	case "file", "snapshot", "patch", "agent":
		if state, ok := partData["state"].(map[string]any); ok {
			msgPart.State = state
		}
	}

	return msgPart
}
views.TransformMessagePart function · go · L271-L379 (109 LOC)
internal/views/views.go
func TransformMessagePart(tmpl *template.Template, part models.MessagePart) MessagePartData {
	switch part.Type {
	case "text":
		renderedHTML := RenderText(part.Text)
		return MessagePartData{
			Type:         "text",
			Content:      part.Text,
			RenderedHTML: renderedHTML,
			PartID:       part.ID,
		}

	case "tool":
		status, _ := part.State["status"].(string)
		input, _ := part.State["input"].(map[string]any)
		output, _ := part.State["output"].(string)

		renderedHTML := RenderToolDetails(tmpl, part.Tool, status, input, output)

		var toolContent strings.Builder
		toolContent.WriteString(fmt.Sprintf("Tool: %s (Status: %s)", part.Tool, status))
		if len(input) > 0 {
			toolContent.WriteString("\nInput: ")
			for key, value := range input {
				toolContent.WriteString(fmt.Sprintf("%s=%v ", key, value))
			}
		}
		if output != "" {
			toolContent.WriteString("\nOutput:\n" + output)
		}

		return MessagePartData{
			Type:         "tool",
			Content:      toolContent.String(),
			Ren
‹ prevpage 2 / 2