Renames: - platform/ → workspace-server/ (Go module path stays as "platform" for external dep compat — will update after plugin module republish) - workspace-template/ → workspace/ Removed (moved to separate repos or deleted): - PLAN.md — internal roadmap (move to private project board) - HANDOFF.md, AGENTS.md — one-time internal session docs - .claude/ — gitignored entirely (local agent config) - infra/cloudflare-worker/ → Molecule-AI/molecule-tenant-proxy - org-templates/molecule-dev/ → standalone template repo - .mcp-eval/ → molecule-mcp-server repo - test-results/ — ephemeral, gitignored Security scrubbing: - Cloudflare account/zone/KV IDs → placeholders - Real EC2 IPs → <EC2_IP> in all docs - CF token prefix, Neon project ID, Fly app names → redacted - Langfuse dev credentials → parameterized - Personal runner username/machine name → generic Community files: - CONTRIBUTING.md — build, test, branch conventions - CODE_OF_CONDUCT.md — Contributor Covenant 2.1 All Dockerfiles, CI workflows, docker-compose, railway.toml, render.yaml, README, CLAUDE.md updated for new directory names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
89 lines
4.0 KiB
Go
89 lines
4.0 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
type Workspace struct {
|
|
ID string `json:"id" db:"id"`
|
|
Name string `json:"name" db:"name"`
|
|
Role sql.NullString `json:"role" db:"role"`
|
|
Tier int `json:"tier" db:"tier"`
|
|
AwarenessNamespace sql.NullString `json:"awareness_namespace" db:"awareness_namespace"`
|
|
Status string `json:"status" db:"status"`
|
|
SourceBundleID sql.NullString `json:"source_bundle_id" db:"source_bundle_id"`
|
|
AgentCard json.RawMessage `json:"agent_card" db:"agent_card"`
|
|
URL sql.NullString `json:"url" db:"url"`
|
|
ParentID *string `json:"parent_id" db:"parent_id"`
|
|
ForwardedTo *string `json:"forwarded_to" db:"forwarded_to"`
|
|
LastHeartbeatAt *time.Time `json:"last_heartbeat_at" db:"last_heartbeat_at"`
|
|
LastErrorRate float64 `json:"last_error_rate" db:"last_error_rate"`
|
|
LastSampleError sql.NullString `json:"last_sample_error" db:"last_sample_error"`
|
|
ActiveTasks int `json:"active_tasks" db:"active_tasks"`
|
|
UptimeSeconds int `json:"uptime_seconds" db:"uptime_seconds"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
// Canvas layout fields (from JOIN)
|
|
X float64 `json:"x"`
|
|
Y float64 `json:"y"`
|
|
Collapsed bool `json:"collapsed"`
|
|
}
|
|
|
|
type RegisterPayload struct {
|
|
ID string `json:"id" binding:"required"`
|
|
URL string `json:"url" binding:"required"`
|
|
AgentCard json.RawMessage `json:"agent_card" binding:"required"`
|
|
}
|
|
|
|
type HeartbeatPayload struct {
|
|
WorkspaceID string `json:"workspace_id" binding:"required"`
|
|
ErrorRate float64 `json:"error_rate"`
|
|
SampleError string `json:"sample_error"`
|
|
ActiveTasks int `json:"active_tasks"`
|
|
UptimeSeconds int `json:"uptime_seconds"`
|
|
CurrentTask string `json:"current_task"`
|
|
// MonthlySpend is cumulative USD spend for the current calendar month,
|
|
// denominated in cents (e.g. 1500 = $15.00). Zero means "no update" —
|
|
// the heartbeat handler never writes zero to avoid accidentally clearing
|
|
// a previously-reported spend value. Any non-zero value is clamped to
|
|
// [0, maxMonthlySpend] before the DB write. (#615)
|
|
MonthlySpend int64 `json:"monthly_spend"`
|
|
}
|
|
|
|
type UpdateCardPayload struct {
|
|
WorkspaceID string `json:"workspace_id" binding:"required"`
|
|
AgentCard json.RawMessage `json:"agent_card" binding:"required"`
|
|
}
|
|
|
|
type CreateWorkspacePayload struct {
|
|
Name string `json:"name" binding:"required"`
|
|
Role string `json:"role"`
|
|
Template string `json:"template"` // workspace-configs-templates folder name
|
|
Tier int `json:"tier"`
|
|
Model string `json:"model"`
|
|
Runtime string `json:"runtime"` // "langgraph" (default), "claude-code", etc.
|
|
External bool `json:"external"` // true = no Docker container, just a registered URL
|
|
URL string `json:"url"` // for external workspaces: the A2A endpoint URL
|
|
WorkspaceDir string `json:"workspace_dir"` // host path to mount as /workspace (empty = isolated volume)
|
|
WorkspaceAccess string `json:"workspace_access"` // "none" (default), "read_only", or "read_write" — see #65
|
|
ParentID *string `json:"parent_id"`
|
|
// BudgetLimit is the optional monthly spend ceiling in USD cents.
|
|
// NULL (omitted) means no limit. budget_limit=500 means $5.00/month.
|
|
BudgetLimit *int64 `json:"budget_limit"`
|
|
// Secrets is an optional map of key→plaintext-value pairs to persist as
|
|
// workspace secrets at creation time. Stored encrypted (same path as
|
|
// POST /workspaces/:id/secrets). Nil/empty map is a no-op.
|
|
Secrets map[string]string `json:"secrets"`
|
|
Canvas struct {
|
|
X float64 `json:"x"`
|
|
Y float64 `json:"y"`
|
|
} `json:"canvas"`
|
|
}
|
|
|
|
type CheckAccessPayload struct {
|
|
CallerID string `json:"caller_id" binding:"required"`
|
|
TargetID string `json:"target_id" binding:"required"`
|
|
}
|