Address #122 review: pageable read_journal, service-clock removal
Build image / build-and-push (push) Successful in 20s
Build image / build-and-push (push) Successful in 20s
- read_journal now takes an offset, so the hasMore it returns is actionable — an agent can page a journal longer than 50 entries. - remove_planting goes through a new service RemovePlanting that stamps removed_at from s.now() (the injectable clock ClearObject and the fill path use), instead of the adapter computing the date off the wall clock. It delegates to UpdatePlanting, so the role check, version guard and history record are unchanged. Drops the now-unused time import. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
This commit is contained in:
@@ -2,7 +2,6 @@ package agent
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
|
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
|
||||||
|
|
||||||
@@ -218,8 +217,9 @@ func (a *adapter) readJournal(ctx context.Context, args struct {
|
|||||||
ObjectID *int64 `json:"objectId" description:"optional bed to narrow to; omit for the whole garden"`
|
ObjectID *int64 `json:"objectId" description:"optional bed to narrow to; omit for the whole garden"`
|
||||||
From string `json:"from" description:"optional earliest observed date, YYYY-MM-DD"`
|
From string `json:"from" description:"optional earliest observed date, YYYY-MM-DD"`
|
||||||
To string `json:"to" description:"optional latest observed date, YYYY-MM-DD"`
|
To string `json:"to" description:"optional latest observed date, YYYY-MM-DD"`
|
||||||
|
Offset int `json:"offset" description:"how many entries to skip; pass the count you've already seen to page when hasMore is true"`
|
||||||
}) (any, error) {
|
}) (any, error) {
|
||||||
q := service.JournalQuery{ObjectID: args.ObjectID, Limit: 50}
|
q := service.JournalQuery{ObjectID: args.ObjectID, Limit: 50, Offset: args.Offset}
|
||||||
if args.From != "" {
|
if args.From != "" {
|
||||||
q.From = &args.From
|
q.From = &args.From
|
||||||
}
|
}
|
||||||
@@ -230,6 +230,7 @@ func (a *adapter) readJournal(ctx context.Context, args struct {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// hasMore is actionable now: re-call with offset += len(entries) to page.
|
||||||
return map[string]any{"entries": entries, "hasMore": hasMore}, nil
|
return map[string]any{"entries": entries, "hasMore": hasMore}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,11 +262,9 @@ func (a *adapter) removePlanting(ctx context.Context, args struct {
|
|||||||
PlantingID int64 `json:"plantingId" description:"plop to remove (its id from describe_garden)"`
|
PlantingID int64 `json:"plantingId" description:"plop to remove (its id from describe_garden)"`
|
||||||
Version int64 `json:"version" description:"the plop's current version (from describe_garden)"`
|
Version int64 `json:"version" description:"the plop's current version (from describe_garden)"`
|
||||||
}) (any, error) {
|
}) (any, error) {
|
||||||
// Soft-remove: set removed_at to today, mirroring clear_object, so the plop
|
// Soft-remove via the service, so removed_at is stamped from the same
|
||||||
// stays in the planting history and the change is undoable.
|
// (injectable) clock clear_object uses rather than the adapter's wall clock.
|
||||||
today := time.Now().UTC().Format("2006-01-02")
|
return a.svc.RemovePlanting(ctx, a.actor, args.PlantingID, args.Version)
|
||||||
return a.svc.UpdatePlanting(ctx, a.actor, args.PlantingID,
|
|
||||||
service.PlantingPatch{SetRemovedAt: true, RemovedAt: &today}, args.Version)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *adapter) listSeedLots(ctx context.Context, args struct {
|
func (a *adapter) listSeedLots(ctx context.Context, args struct {
|
||||||
|
|||||||
@@ -178,6 +178,17 @@ func (s *Service) UpdatePlanting(ctx context.Context, actorID, plantingID int64,
|
|||||||
return updated, nil
|
return updated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemovePlanting soft-removes a single plop — the one-plop counterpart to
|
||||||
|
// ClearObject, used by the agent's remove_planting tool. It stamps removed_at
|
||||||
|
// from the service clock (s.now()), same as ClearObject and the fill path, so the
|
||||||
|
// removal date can't diverge by which caller set it; then delegates to
|
||||||
|
// UpdatePlanting for the editor-role check, version guard and history record.
|
||||||
|
func (s *Service) RemovePlanting(ctx context.Context, actorID, plantingID, version int64) (*domain.Planting, error) {
|
||||||
|
today := s.now().UTC().Format(dateLayout)
|
||||||
|
return s.UpdatePlanting(ctx, actorID, plantingID,
|
||||||
|
PlantingPatch{SetRemovedAt: true, RemovedAt: &today}, version)
|
||||||
|
}
|
||||||
|
|
||||||
// plantingEditSummary describes a plop edit for the history list. Soft-removal
|
// plantingEditSummary describes a plop edit for the history list. Soft-removal
|
||||||
// ("clear bed", harvested) is the one edit worth naming specifically — it reads
|
// ("clear bed", harvested) is the one edit worth naming specifically — it reads
|
||||||
// as a removal to the person who did it, not as an edit.
|
// as a removal to the person who did it, not as an edit.
|
||||||
|
|||||||
Reference in New Issue
Block a user