'array', ]; protected $attributes = [ 'type' => self::TYPE_JSON, 'metadata' => '{}', ]; public function plan(): BelongsTo { return $this->belongsTo(AgentPlan::class, 'agent_plan_id'); } /** * Get typed value. */ public function getTypedValue(): mixed { return match ($this->type) { self::TYPE_JSON => json_decode($this->value, true), default => $this->value, }; } /** * Set typed value. */ public function setTypedValue(mixed $value): void { $storedValue = match ($this->type) { self::TYPE_JSON => json_encode($value), default => (string) $value, }; $this->update(['value' => $storedValue]); } /** * Get or create state for a plan. */ public static function getOrCreate(AgentPlan $plan, string $key, mixed $default = null, string $type = self::TYPE_JSON): self { $state = static::where('agent_plan_id', $plan->id) ->where('key', $key) ->first(); if (! $state) { $value = match ($type) { self::TYPE_JSON => json_encode($default), default => (string) ($default ?? ''), }; $state = static::create([ 'agent_plan_id' => $plan->id, 'key' => $key, 'value' => $value, 'type' => $type, ]); } return $state; } /** * Set state value for a plan. */ public static function set(AgentPlan $plan, string $key, mixed $value, string $type = self::TYPE_JSON): self { $storedValue = match ($type) { self::TYPE_JSON => json_encode($value), default => (string) $value, }; return static::updateOrCreate( ['agent_plan_id' => $plan->id, 'key' => $key], ['value' => $storedValue, 'type' => $type] ); } /** * Get state value for a plan. */ public static function get(AgentPlan $plan, string $key, mixed $default = null): mixed { $state = static::where('agent_plan_id', $plan->id) ->where('key', $key) ->first(); if (! $state) { return $default; } return $state->getTypedValue(); } /** * Scope: for plan. */ public function scopeForPlan($query, int $planId) { return $query->where('agent_plan_id', $planId); } /** * Scope: by type. */ public function scopeByType($query, string $type) { return $query->where('type', $type); } }