# `Snodo.Extensions.Tasks.Client.Status`
[🔗](https://github.com/joshrotenberg/snodo/blob/v0.4.0/extensions/tasks/lib/snodo/extensions/tasks/client/status.ex#L1)

A task's status as a client reads it: from the creation result of a
task-augmented `tools/call`, from `tasks/get`, or from a `notifications/tasks`
event.

The fields mirror the wire shape with atom keys:

  * `task_id` - the server's `taskId`.
  * `status` - `:working`, `:input_required`, `:completed`, `:failed`, or
    `:cancelled`.
  * `status_message` - the server's `statusMessage`, or `nil`.
  * `created_at`, `last_updated_at` - the ISO 8601 timestamps as sent.
  * `ttl_ms` - `ttlMs`, or `nil` for a task the server keeps indefinitely.
  * `poll_interval_ms` - `pollIntervalMs`, or `nil` when the server sent none.
  * `input_requests` - for `:input_required`, the outstanding requests keyed
    by the key to answer them under in `tasks/update`; `%{}` otherwise.
  * `result` - for `:completed`, the final `CallToolResult` map as the server
    sent it; `nil` otherwise.
  * `error` - for `:failed`, the JSON-RPC error object the task failed with;
    `nil` otherwise.

  * `raw` - the decoded map, `_meta` included, for fields this struct does
    not name.

A creation result (`"resultType" => "task"`) is the flat task and need not
carry these three payloads, so a status decoded from one can have
`input_requests: %{}`, `result: nil`, and `error: nil` whatever its status.
`detailed?/1` tells whether a status carries the payload its status implies.

# `status`

```elixir
@type status() :: :working | :input_required | :completed | :failed | :cancelled
```

# `t`

```elixir
@type t() :: %Snodo.Extensions.Tasks.Client.Status{
  created_at: String.t() | nil,
  error: map() | nil,
  input_requests: %{optional(String.t()) =&gt; map()},
  last_updated_at: String.t() | nil,
  poll_interval_ms: pos_integer() | nil,
  raw: map(),
  result: map() | nil,
  status: status(),
  status_message: String.t() | nil,
  task_id: String.t(),
  ttl_ms: pos_integer() | nil
}
```

# `detailed?`

```elixir
@spec detailed?(t()) :: boolean()
```

Returns true when the status carries the payload its status implies:
`input_requests` for `:input_required`, `result` for `:completed`, and
`error` for `:failed`. A status decoded from a creation result may not.

# `from_map`

```elixir
@spec from_map(map()) :: {:ok, t()} | {:error, term()}
```

Decodes a task map from the wire.

Returns `{:error, reason}` when `taskId` is not a non-empty string, when
`status` is not one of the five statuses, or, for anything but a creation
result, when the payload its status requires is missing: an
`inputRequests` object for `input_required`, a `result` object for
`completed`, and an `error` object with an integer `code` and a string
`message` for `failed`. A creation result needs no payload, and a payload
it does carry is checked the same way.

# `terminal?`

```elixir
@spec terminal?(t()) :: boolean()
```

Returns true for `:completed`, `:failed`, and `:cancelled`, which never change.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
