Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
161 lines
5.6 KiB
Go
161 lines
5.6 KiB
Go
package workspace
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
collabrunbiz "github.com/tutti-os/tutti/services/tuttid/biz/collabrun"
|
|
)
|
|
|
|
// ErrCollaborationRunNotFound reports a missing collaboration run row.
|
|
var ErrCollaborationRunNotFound = errors.New("collaboration run not found")
|
|
|
|
const collaborationRunColumns = `workspace_id, run_id, mode, trigger_source, trigger_reason,
|
|
source_session_id, target_session_id, target_agent_target_id, model_plan_id, model,
|
|
context_scope, prompt, result_text, failure_reason, status, adoption,
|
|
input_tokens, output_tokens, started_at_unix_ms, completed_at_unix_ms, duration_ms,
|
|
created_at_unix_ms, updated_at_unix_ms`
|
|
|
|
// ListCollaborationRuns returns workspace runs newest first. A non-empty
|
|
// sourceSessionID narrows to one source session; limit <= 0 means no limit.
|
|
func (s *SQLiteStore) ListCollaborationRuns(ctx context.Context, workspaceID string, sourceSessionID string, limit int) ([]collabrunbiz.Run, error) {
|
|
if s == nil || s.readDB == nil {
|
|
return nil, errors.New("workspace database is not initialized")
|
|
}
|
|
query := `
|
|
SELECT ` + collaborationRunColumns + `
|
|
FROM collaboration_runs
|
|
WHERE workspace_id = ?`
|
|
args := []any{workspaceID}
|
|
if sourceSessionID != "" {
|
|
query += ` AND source_session_id = ?`
|
|
args = append(args, sourceSessionID)
|
|
}
|
|
query += `
|
|
ORDER BY created_at_unix_ms DESC, run_id DESC`
|
|
if limit > 0 {
|
|
query += `
|
|
LIMIT ?`
|
|
args = append(args, limit)
|
|
}
|
|
rows, err := s.readDB.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list collaboration runs: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var runs []collabrunbiz.Run
|
|
for rows.Next() {
|
|
run, err := scanCollaborationRun(rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
runs = append(runs, run)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("list collaboration run rows: %w", err)
|
|
}
|
|
return runs, nil
|
|
}
|
|
|
|
func (s *SQLiteStore) GetCollaborationRun(ctx context.Context, workspaceID string, runID string) (collabrunbiz.Run, error) {
|
|
if s == nil || s.readDB == nil {
|
|
return collabrunbiz.Run{}, errors.New("workspace database is not initialized")
|
|
}
|
|
row := s.readDB.QueryRowContext(ctx, `
|
|
SELECT `+collaborationRunColumns+`
|
|
FROM collaboration_runs
|
|
WHERE workspace_id = ? AND run_id = ?
|
|
`, workspaceID, runID)
|
|
run, err := scanCollaborationRun(row)
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return collabrunbiz.Run{}, ErrCollaborationRunNotFound
|
|
}
|
|
return collabrunbiz.Run{}, err
|
|
}
|
|
return run, nil
|
|
}
|
|
|
|
func (s *SQLiteStore) PutCollaborationRun(ctx context.Context, run collabrunbiz.Run) error {
|
|
if s == nil || s.writeDB == nil {
|
|
return errors.New("workspace database is not initialized")
|
|
}
|
|
_, err := s.writeDB.ExecContext(ctx, `
|
|
INSERT INTO collaboration_runs (
|
|
`+collaborationRunColumns+`
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(workspace_id, run_id) DO UPDATE SET
|
|
mode = excluded.mode,
|
|
trigger_source = excluded.trigger_source,
|
|
trigger_reason = excluded.trigger_reason,
|
|
source_session_id = excluded.source_session_id,
|
|
target_session_id = excluded.target_session_id,
|
|
target_agent_target_id = excluded.target_agent_target_id,
|
|
model_plan_id = excluded.model_plan_id,
|
|
model = excluded.model,
|
|
context_scope = excluded.context_scope,
|
|
prompt = excluded.prompt,
|
|
result_text = excluded.result_text,
|
|
failure_reason = excluded.failure_reason,
|
|
status = excluded.status,
|
|
adoption = excluded.adoption,
|
|
input_tokens = excluded.input_tokens,
|
|
output_tokens = excluded.output_tokens,
|
|
started_at_unix_ms = excluded.started_at_unix_ms,
|
|
completed_at_unix_ms = excluded.completed_at_unix_ms,
|
|
duration_ms = excluded.duration_ms,
|
|
updated_at_unix_ms = excluded.updated_at_unix_ms
|
|
`, run.WorkspaceID, run.ID, string(run.Mode), string(run.TriggerSource), run.TriggerReason,
|
|
run.SourceSessionID, run.TargetSessionID, run.TargetAgentTargetID, run.ModelPlanID, run.Model,
|
|
run.ContextScope, run.Prompt, run.ResultText, run.FailureReason, string(run.Status), string(run.Adoption),
|
|
run.Usage.InputTokens, run.Usage.OutputTokens, unixMsOrZero(run.StartedAt), unixMsOrZero(run.CompletedAt), run.DurationMs,
|
|
unixMs(run.CreatedAt), unixMs(run.UpdatedAt))
|
|
if err != nil {
|
|
return fmt.Errorf("put collaboration run: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func scanCollaborationRun(row managedProviderScanner) (collabrunbiz.Run, error) {
|
|
var run collabrunbiz.Run
|
|
var mode string
|
|
var triggerSource string
|
|
var status string
|
|
var adoption string
|
|
var startedAtUnixMS int64
|
|
var completedAtUnixMS int64
|
|
var createdAtUnixMS int64
|
|
var updatedAtUnixMS int64
|
|
if err := row.Scan(&run.WorkspaceID, &run.ID, &mode, &triggerSource, &run.TriggerReason,
|
|
&run.SourceSessionID, &run.TargetSessionID, &run.TargetAgentTargetID, &run.ModelPlanID, &run.Model,
|
|
&run.ContextScope, &run.Prompt, &run.ResultText, &run.FailureReason, &status, &adoption,
|
|
&run.Usage.InputTokens, &run.Usage.OutputTokens, &startedAtUnixMS, &completedAtUnixMS, &run.DurationMs,
|
|
&createdAtUnixMS, &updatedAtUnixMS); err != nil {
|
|
return collabrunbiz.Run{}, err
|
|
}
|
|
run.Mode = collabrunbiz.Mode(mode)
|
|
run.TriggerSource = collabrunbiz.TriggerSource(triggerSource)
|
|
run.Status = collabrunbiz.Status(status)
|
|
run.Adoption = collabrunbiz.Adoption(adoption)
|
|
if startedAtUnixMS > 0 {
|
|
run.StartedAt = time.UnixMilli(startedAtUnixMS).UTC()
|
|
}
|
|
if completedAtUnixMS > 0 {
|
|
run.CompletedAt = time.UnixMilli(completedAtUnixMS).UTC()
|
|
}
|
|
run.CreatedAt = time.UnixMilli(createdAtUnixMS).UTC()
|
|
run.UpdatedAt = time.UnixMilli(updatedAtUnixMS).UTC()
|
|
return run, nil
|
|
}
|
|
|
|
func unixMsOrZero(value time.Time) int64 {
|
|
if value.IsZero() {
|
|
return 0
|
|
}
|
|
return unixMs(value)
|
|
}
|