Hello @hexiongwu1995.
This is a very common question on this forum and you will find everything you need about state and context in posts like:
The important bit to understand is that context theme-color.final() does not produce a color value. It produces opaque contextual content.
See this very similar case for an example.
Edit:
To demonstrate how this works, especially with auto:
// template.typ
#let _theme-color = state("theme-color", red)
#let _update-theme-color(color) = _theme-color.update(color)
#let _thmbox(color: auto, it) = {
let color = if color == auto {
_theme-color.get()
} else {
color
}
figure(
block()[#text(fill: color)[#it]],
)
}
#let definition(color: auto, it) = context _thmbox(color: color, it)
#let template(color: auto, doc) = {
if color != auto { _update-theme-color(color) }
doc
}
// main.typ
#import "state-forum.typ": template, definition
#show: template
#definition()[Red]
#show: template.with(color: green)
#definition()[Green]
#definition(color: blue)[Blue]
Another method could be to use metadata.
Note that auto is not a color so you need special handling if you want to avoid getting the error you were reporting.