fleet-memory/hindsight-clients/go/model_timestamp.go
Nicolò Boschi f903948a26
feat: support timestamp="unset" to retain content without a date (#465)
* feat: support timestamp="unset" to retain content without a date

When callers retain timeless content (e.g. fictional documents, static
reference material), passing timestamp="unset" now skips the utcnow()
default so mentioned_at is stored as NULL instead of an artificial date.

- HTTP: validate_timestamp recognises "unset" sentinel and threads it
  through api_retain as event_date=None (key present, value None), which
  the orchestrator distinguishes from key-absent (still defaults to now)
- Orchestrator: new branching logic separates "key absent" → utcnow()
  from "key present but None" → no date
- types.py: RetainContent.event_date and ProcessedFact.mentioned_at are
  now datetime | None; removed the unused _now_utc factory
- fact_extraction.py: all event_date params accept datetime | None;
  _build_user_message emits "Event Date: Unknown" when None; removed
  mentioned_at from the Fact LLM response model (LLM never sets it)
- embedding_processing: skip date suffix when fact_date is None
- entity_resolver: COALESCE(event_date, now()) for first_seen/last_seen
  so entities table NOT NULL constraint is preserved
- link_utils: skip temporal linking for units without event_date
- Migration aa2b3c4d5e6f: DROP NOT NULL on memory_units.event_date
- Tests: test_retain_no_timestamp and test_retain_omit_timestamp_defaults_to_now
- Docs + OpenAPI + TypeScript client updated

* refactor: replace _TIMESTAMP_UNKNOWN sentinel with plain string comparison

The sentinel object() was only needed to distinguish "unset" from None
at the boundary — but since the field type is datetime | str | None,
"unset" can pass through the validator unchanged and be compared directly.

* chore: regenerate OpenAPI spec and clients after timestamp type change

timestamp field is now datetime | str | None to accept the "unset" sentinel value.
2026-03-02 12:03:23 +01:00

113 lines
2.5 KiB
Go

/*
Hindsight HTTP API
HTTP API for Hindsight
API version: 0.4.14
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package hindsight
import (
"encoding/json"
"time"
"fmt"
)
// Timestamp When the content occurred. Accepts an ISO 8601 datetime string (e.g. '2024-01-15T10:30:00Z'), null/omitted (defaults to now), or the special string 'unset' to explicitly store without any timestamp (use this for timeless content such as fictional documents or static reference material).
type Timestamp struct {
String *string
TimeTime *time.Time
}
// Unmarshal JSON data into any of the pointers in the struct
func (dst *Timestamp) UnmarshalJSON(data []byte) error {
var err error
// this object is nullable so check if the payload is null or empty string
if string(data) == "" || string(data) == "{}" {
return nil
}
// try to unmarshal JSON data into String
err = json.Unmarshal(data, &dst.String);
if err == nil {
jsonString, _ := json.Marshal(dst.String)
if string(jsonString) == "{}" { // empty struct
dst.String = nil
} else {
return nil // data stored in dst.String, return on the first match
}
} else {
dst.String = nil
}
// try to unmarshal JSON data into TimeTime
err = json.Unmarshal(data, &dst.TimeTime);
if err == nil {
jsonTimeTime, _ := json.Marshal(dst.TimeTime)
if string(jsonTimeTime) == "{}" { // empty struct
dst.TimeTime = nil
} else {
return nil // data stored in dst.TimeTime, return on the first match
}
} else {
dst.TimeTime = nil
}
return fmt.Errorf("data failed to match schemas in anyOf(Timestamp)")
}
// Marshal data from the first non-nil pointers in the struct to JSON
func (src *Timestamp) MarshalJSON() ([]byte, error) {
if src.String != nil {
return json.Marshal(&src.String)
}
if src.TimeTime != nil {
return json.Marshal(&src.TimeTime)
}
return nil, nil // no data in anyOf schemas
}
type NullableTimestamp struct {
value *Timestamp
isSet bool
}
func (v NullableTimestamp) Get() *Timestamp {
return v.value
}
func (v *NullableTimestamp) Set(val *Timestamp) {
v.value = val
v.isSet = true
}
func (v NullableTimestamp) IsSet() bool {
return v.isSet
}
func (v *NullableTimestamp) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableTimestamp(val *Timestamp) *NullableTimestamp {
return &NullableTimestamp{value: val, isSet: true}
}
func (v NullableTimestamp) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableTimestamp) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}