Merge the internal/ipc sweep (#216)

V-575. dispatch held 13 arms of one shape: nil check, unmarshal, call, marshal,
and a hand-written unknown-method error repeated eight times. callDirect,
callDirectNoParams, callDirectVoid and unknownMethod give the switch one line
per method naming the Server field behind it. The nil-field-means-unconfigured
contract is unchanged.

withParamsSlice holds the nil-slice normalisation the method table repeated 14
times. MethodTurnDecisions and MethodMorningStatus keep their own, because one
normalises on error and the other must still emit null.

mapRows replaces the same three lines in 11 store methods. RevertFact sent a
map[string]string against a server marshalling map[string]int64, so both sides
now share revertReq and revertResp. Wire bytes are identical throughout.

The 45 client shims stay. They mirror CoreAPI one to one on purpose.

156 insertions, 362 deletions. go test -race passes.
This commit is contained in:
2026-08-06 01:33:05 +04:00
4 changed files with 171 additions and 385 deletions
+6 -9
View File
@@ -594,7 +594,7 @@ type setTaskFieldsReq struct {
BlockedOn string `json:"blocked_on,omitempty"`
}
// idReq — methods keyed by a single id.
// idReq — methods keyed by a single id, which is every routine transition.
type idReq struct {
ID int64 `json:"id"`
}
@@ -652,6 +652,11 @@ type calendarEventsReq struct {
type revertReq struct {
Key string `json:"key"`
}
// revertResp — the id of the voiding fact the revert wrote.
type revertResp struct {
NewID int64 `json:"new_id"`
}
type writeNoteReq struct {
Ts time.Time `json:"ts"`
Text string `json:"text"`
@@ -780,14 +785,6 @@ type listProposedRoutinesResp struct {
Routines []ProposedRoutine `json:"routines"`
}
type dismissProposedRoutineReq struct {
ID int64 `json:"id"`
}
type acceptProposedRoutineReq struct {
ID int64 `json:"id"`
}
// IntakeEvent — one entry of the unified intake journal on the wire. Mirrors
// event.Event field for field; the ipc package does not import internal/event
// so the wire shape stays independent of the in-process type.
+5 -7
View File
@@ -649,11 +649,11 @@ func (c *Client) ModelStatus(ctx context.Context) (ModelStatusResp, error) {
}
func (c *Client) DismissProposedRoutine(ctx context.Context, id int64) error {
return c.call(ctx, MethodDismissProposedRoutine, dismissProposedRoutineReq{ID: id}, nil)
return c.call(ctx, MethodDismissProposedRoutine, idReq{ID: id}, nil)
}
func (c *Client) AcceptProposedRoutine(ctx context.Context, id int64) error {
return c.call(ctx, MethodAcceptProposedRoutine, acceptProposedRoutineReq{ID: id}, nil)
return c.call(ctx, MethodAcceptProposedRoutine, idReq{ID: id}, nil)
}
func (c *Client) Chat(ctx context.Context, conversation, text string) (ChatReply, error) {
@@ -713,13 +713,11 @@ func (c *Client) DayPlan(ctx context.Context) (DayPlan, error) {
}
func (c *Client) RevertFact(ctx context.Context, key string) (int64, error) {
var result struct {
NewID int64 `json:"new_id"`
}
if err := c.call(ctx, MethodRevertFact, map[string]string{"key": key}, &result); err != nil {
var r revertResp
if err := c.call(ctx, MethodRevertFact, revertReq{Key: key}, &r); err != nil {
return 0, err
}
return result.NewID, nil
return r.NewID, nil
}
// Ping asks whether the daemon is there, and whether it is locked. It is not a
+126 -264
View File
@@ -335,6 +335,22 @@ func withoutParams[R any](fn func(ctx context.Context, api CoreAPI) (R, error))
}
}
// withParamsSlice is withParams for a list read. It replaces a nil slice with
// an empty one so the wire carries [] rather than null, which every reader of
// these methods relies on.
func withParamsSlice[P any, E any](fn func(ctx context.Context, api CoreAPI, p P) ([]E, error)) handlerFunc {
return withParams(func(ctx context.Context, api CoreAPI, p P) ([]E, error) {
out, err := fn(ctx, api, p)
if err != nil {
return nil, err
}
if out == nil {
out = []E{}
}
return out, nil
})
}
// methodTable — one entry per CoreAPI-backed method. Built once at package
// init, not per-Server and not per-dispatch: entries close over nothing but
// the CoreAPI method being called, and dispatch passes in the *current*
@@ -373,15 +389,8 @@ var methodTable = map[Method]handlerFunc{
MethodMarkReminder: withParamsVoid(func(ctx context.Context, api CoreAPI, p markReminderReq) error {
return api.MarkReminder(ctx, p.ID, p.Status)
}),
MethodListReminders: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]Reminder, error) {
out, err := api.ListReminders(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Reminder{}
}
return out, nil
MethodListReminders: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]Reminder, error) {
return api.ListReminders(ctx, p.N)
}),
MethodRecordNudge: withParams(func(ctx context.Context, api CoreAPI, p recordNudgeReq) (idResp, error) {
id, err := api.RecordNudge(ctx, p.Rule, p.Channel, p.Message, p.Ts)
@@ -390,109 +399,39 @@ var methodTable = map[Method]handlerFunc{
MethodResolveNudge: withParamsVoid(func(ctx context.Context, api CoreAPI, p resolveNudgeReq) error {
return api.ResolveNudge(ctx, p.ID, p.Outcome, p.Ts)
}),
MethodRecentOutcomes: withParams(func(ctx context.Context, api CoreAPI, p outcomesReq) ([]string, error) {
out, err := api.RecentOutcomes(ctx, p.Rule, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []string{} // stable non-null on the wire
}
return out, nil
MethodRecentOutcomes: withParamsSlice(func(ctx context.Context, api CoreAPI, p outcomesReq) ([]string, error) {
return api.RecentOutcomes(ctx, p.Rule, p.N)
}),
MethodRecentFacts: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]Fact, error) {
out, err := api.RecentFacts(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Fact{}
}
return out, nil
MethodRecentFacts: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]Fact, error) {
return api.RecentFacts(ctx, p.N)
}),
MethodRecentActiveFacts: withParams(func(ctx context.Context, api CoreAPI, p kindNReq) ([]Fact, error) {
out, err := api.RecentActiveFactsByKind(ctx, p.Kind, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Fact{}
}
return out, nil
MethodRecentActiveFacts: withParamsSlice(func(ctx context.Context, api CoreAPI, p kindNReq) ([]Fact, error) {
return api.RecentActiveFactsByKind(ctx, p.Kind, p.N)
}),
MethodCalendarEvents: withParams(func(ctx context.Context, api CoreAPI, p calendarEventsReq) ([]Fact, error) {
out, err := api.CalendarEvents(ctx, p.From, p.To)
if err != nil {
return nil, err
}
if out == nil {
out = []Fact{}
}
return out, nil
MethodCalendarEvents: withParamsSlice(func(ctx context.Context, api CoreAPI, p calendarEventsReq) ([]Fact, error) {
return api.CalendarEvents(ctx, p.From, p.To)
}),
MethodRecentEcoTraces: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]EcosystemTrace, error) {
out, err := api.RecentEcosystemTraces(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []EcosystemTrace{}
}
return out, nil
MethodRecentEcoTraces: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]EcosystemTrace, error) {
return api.RecentEcosystemTraces(ctx, p.N)
}),
MethodDeliveryAttempts: withParams(func(ctx context.Context, api CoreAPI, p deliveryAttemptsReq) ([]DeliveryAttempt, error) {
out, err := api.DeliveryAttempts(ctx, p.Status, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []DeliveryAttempt{}
}
return out, nil
MethodDeliveryAttempts: withParamsSlice(func(ctx context.Context, api CoreAPI, p deliveryAttemptsReq) ([]DeliveryAttempt, error) {
return api.DeliveryAttempts(ctx, p.Status, p.N)
}),
MethodRecentNudges: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]Nudge, error) {
out, err := api.RecentNudges(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Nudge{}
}
return out, nil
MethodRecentNudges: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]Nudge, error) {
return api.RecentNudges(ctx, p.N)
}),
MethodWriteNote: withParams(func(ctx context.Context, api CoreAPI, p writeNoteReq) (idResp, error) {
id, err := api.WriteNote(ctx, p.Ts, p.Text, p.Embedding, p.Source)
return idResp{ID: id}, err
}),
MethodQueryNotes: withParams(func(ctx context.Context, api CoreAPI, p queryNotesReq) ([]Note, error) {
out, err := api.QueryNotes(ctx, p.Embedding, p.K)
if err != nil {
return nil, err
}
if out == nil {
out = []Note{}
}
return out, nil
MethodQueryNotes: withParamsSlice(func(ctx context.Context, api CoreAPI, p queryNotesReq) ([]Note, error) {
return api.QueryNotes(ctx, p.Embedding, p.K)
}),
MethodRecentNotesFromSource: withParams(func(ctx context.Context, api CoreAPI, p sourceNReq) ([]Note, error) {
out, err := api.RecentNotesFromSource(ctx, p.Prefix, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Note{}
}
return out, nil
MethodRecentNotesFromSource: withParamsSlice(func(ctx context.Context, api CoreAPI, p sourceNReq) ([]Note, error) {
return api.RecentNotesFromSource(ctx, p.Prefix, p.N)
}),
MethodRecentNotes: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]Note, error) {
out, err := api.RecentNotes(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []Note{}
}
return out, nil
MethodRecentNotes: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]Note, error) {
return api.RecentNotes(ctx, p.N)
}),
MethodProposeTool: withParams(func(ctx context.Context, api CoreAPI, p proposeToolReq) (proposeToolResp, error) {
ok, err := api.ProposeTool(ctx, p.Name, p.Utterance, p.Scope, p.Ts)
@@ -563,18 +502,15 @@ var methodTable = map[Method]handlerFunc{
}
return listProposedRoutinesResp{Routines: out}, nil
}),
MethodDismissProposedRoutine: withParamsVoid(func(ctx context.Context, api CoreAPI, p dismissProposedRoutineReq) error {
MethodDismissProposedRoutine: withParamsVoid(func(ctx context.Context, api CoreAPI, p idReq) error {
return api.DismissProposedRoutine(ctx, p.ID)
}),
MethodAcceptProposedRoutine: withParamsVoid(func(ctx context.Context, api CoreAPI, p acceptProposedRoutineReq) error {
MethodAcceptProposedRoutine: withParamsVoid(func(ctx context.Context, api CoreAPI, p idReq) error {
return api.AcceptProposedRoutine(ctx, p.ID)
}),
MethodRevertFact: withParams(func(ctx context.Context, api CoreAPI, p revertReq) (map[string]int64, error) {
MethodRevertFact: withParams(func(ctx context.Context, api CoreAPI, p revertReq) (revertResp, error) {
newID, err := api.RevertFact(ctx, p.Key)
if err != nil {
return nil, err
}
return map[string]int64{"new_id": newID}, nil
return revertResp{NewID: newID}, err
}),
MethodChat: withParams(func(ctx context.Context, api CoreAPI, p chatReq) (chatResp, error) {
reply, err := api.Chat(ctx, p.Conversation, p.Text)
@@ -599,15 +535,8 @@ var methodTable = map[Method]handlerFunc{
MethodMorningStatus: withoutParams(func(ctx context.Context, api CoreAPI) ([]MorningRoutineStatus, error) {
return api.MorningStatus(ctx)
}),
MethodRecentEvents: withParams(func(ctx context.Context, api CoreAPI, p nReq) ([]IntakeEvent, error) {
out, err := api.RecentEvents(ctx, p.N)
if err != nil {
return nil, err
}
if out == nil {
out = []IntakeEvent{}
}
return out, nil
MethodRecentEvents: withParamsSlice(func(ctx context.Context, api CoreAPI, p nReq) ([]IntakeEvent, error) {
return api.RecentEvents(ctx, p.N)
}),
MethodMCPServers: withoutParams(func(ctx context.Context, api CoreAPI) ([]MCPServerStatus, error) {
out, err := api.MCPServers(ctx)
@@ -654,180 +583,113 @@ func (s *Server) dispatch(ctx context.Context, req Request) (json.RawMessage, er
return marshalResult(PingResp{Alive: true, Locked: locked}), nil
case MethodAssertStepUp:
if s.StepUp != nil {
return marshalResult(nil), s.StepUp(ctx)
if s.StepUp == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return marshalResult(nil), s.StepUp(ctx)
case MethodStoreEncryptionKey:
if s.WrapKeyFn != nil {
var p storeEncryptionKeyReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.WrapKeyFn(ctx, p.Secret, p.Explicit)
if s.WrapKeyFn == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
var p storeEncryptionKeyReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.WrapKeyFn(ctx, p.Secret, p.Explicit)
case MethodUnlock:
if s.UnlockFn != nil {
var p unlockReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.UnlockFn(ctx, p.Secret)
if s.UnlockFn == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
var p unlockReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.UnlockFn(ctx, p.Secret)
case MethodIngestMail:
if s.IngestMailFn != nil {
var p IngestMailReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.IngestMailFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.IngestMailFn)
case MethodSwapModel:
if s.SwapModelFn != nil {
var p SwapModelReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.SwapModelFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.SwapModelFn)
case MethodDescribeImage:
if s.DescribeImageFn != nil {
var p DescribeImageReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.DescribeImageFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.DescribeImageFn)
case MethodCaptureStart:
if s.CaptureStartFn != nil {
var p CaptureStartReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureStartFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureStartFn)
case MethodCaptureAppend:
if s.CaptureAppendFn != nil {
var p CaptureAppendReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureAppendFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureAppendFn)
case MethodCaptureStop:
if s.CaptureStopFn != nil {
var p CaptureStopReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureStopFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
case MethodCaptureStatus:
if s.CaptureStatusFn != nil {
resp, err := s.CaptureStatusFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureStopFn)
case MethodEnrollSpeaker:
if s.EnrollSpeakerFn != nil {
var p EnrollSpeakerReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.EnrollSpeakerFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.EnrollSpeakerFn)
case MethodCaptureStatus:
return callDirectNoParams(ctx, req, s.CaptureStatusFn)
case MethodListSpeakers:
if s.ListSpeakersFn != nil {
resp, err := s.ListSpeakersFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
case MethodForgetSpeaker:
if s.ForgetSpeakerFn != nil {
var p ForgetSpeakerReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
if err := s.ForgetSpeakerFn(ctx, p); err != nil {
return nil, err
}
return marshalResult(nil), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirectNoParams(ctx, req, s.ListSpeakersFn)
case MethodModelStatus:
if s.ModelStatusFn != nil {
resp, err := s.ModelStatusFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirectNoParams(ctx, req, s.ModelStatusFn)
case MethodForgetSpeaker:
return callDirectVoid(ctx, req, s.ForgetSpeakerFn)
}
h, ok := methodTable[req.Method]
if !ok {
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return nil, unknownMethod(req.Method)
}
return h(ctx, api, req.Params)
}
// callDirect runs a daemon-supplied handler that bypasses CoreAPI: unmarshal
// the params, call it, marshal the reply. A nil handler is the capability being
// unconfigured on this box, and the wire says so as an unknown method.
func callDirect[P any, R any](ctx context.Context, req Request, fn func(context.Context, P) (R, error)) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
var p P
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
r, err := fn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(r), nil
}
// callDirectNoParams is callDirect for a handler that reads no params. Like
// withoutParams it never touches req.Params.
func callDirectNoParams[R any](ctx context.Context, req Request, fn func(context.Context) (R, error)) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
r, err := fn(ctx)
if err != nil {
return nil, err
}
return marshalResult(r), nil
}
// callDirectVoid is callDirect for a handler with nothing to report back. The
// wire reply is always null.
func callDirectVoid[P any](ctx context.Context, req Request, fn func(context.Context, P) error) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
var p P
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
if err := fn(ctx, p); err != nil {
return nil, err
}
return marshalResult(nil), nil
}
func unknownMethod(m Method) error {
return fmt.Errorf("%w: %s", ErrUnknownMethod, m)
}
func unmarshalParams(raw json.RawMessage, v any) error {
if len(raw) == 0 {
raw = []byte("null")
+34 -105
View File
@@ -77,18 +77,24 @@ func (a *storeAPI) MarkReminder(ctx context.Context, id int64, status string) er
return mapErr(a.s.MarkReminder(ctx, id, status))
}
func (a *storeAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
rs, err := a.s.ListReminders(ctx, n)
// mapRows carries a store read's error through mapErr and converts the rows to
// their wire shape. Every list method here is that one shape.
func mapRows[S any, W any](rows []S, err error, conv func(S) W) ([]W, error) {
if err != nil {
return nil, mapErr(err)
}
out := make([]Reminder, len(rs))
for i, r := range rs {
out[i] = toReminder(r)
out := make([]W, len(rows))
for i, r := range rows {
out[i] = conv(r)
}
return out, nil
}
func (a *storeAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
rs, err := a.s.ListReminders(ctx, n)
return mapRows(rs, err, toReminder)
}
func (a *storeAPI) RescheduleReminder(ctx context.Context, id int64, now time.Time) error {
return mapErr(a.s.RescheduleReminder(ctx, id, now))
}
@@ -109,85 +115,48 @@ func (a *storeAPI) RecentOutcomes(ctx context.Context, rule string, n int) ([]st
func (a *storeAPI) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
fs, err := a.s.RecentFacts(ctx, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Fact, len(fs))
for i, f := range fs {
out[i] = toFact(f)
}
return out, nil
return mapRows(fs, err, toFact)
}
func (a *storeAPI) RecentActiveFactsByKind(ctx context.Context, kind string, n int) ([]Fact, error) {
fs, err := a.s.RecentActiveFactsByKind(ctx, store.FactKind(kind), n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Fact, len(fs))
for i, f := range fs {
out[i] = toFact(f)
}
return out, nil
return mapRows(fs, err, toFact)
}
func (a *storeAPI) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
fs, err := a.s.CalendarEvents(ctx, from, to)
if err != nil {
return nil, mapErr(err)
}
out := make([]Fact, len(fs))
for i, f := range fs {
out[i] = toFact(f)
}
return out, nil
return mapRows(fs, err, toFact)
}
func (a *storeAPI) RecentEcosystemTraces(ctx context.Context, n int) ([]EcosystemTrace, error) {
trs, err := a.s.RecentEcosystemTraces(ctx, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]EcosystemTrace, len(trs))
for i, tr := range trs {
out[i] = EcosystemTrace{
return mapRows(trs, err, func(tr store.EcosystemTrace) EcosystemTrace {
return EcosystemTrace{
ID: tr.ID, Ts: tr.Ts, Service: tr.Service, Operation: tr.Operation,
Status: tr.Status, DurationMs: tr.DurationMs, CorrelationID: tr.CorrelationID,
CausationID: tr.CausationID, HTTPStatus: tr.HTTPStatus, Fields: tr.Fields,
}
}
return out, nil
})
}
func (a *storeAPI) RecentNudges(ctx context.Context, n int) ([]Nudge, error) {
ns, err := a.s.RecentNudges(ctx, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Nudge, len(ns))
for i, ng := range ns {
out[i] = toNudge(ng)
}
return out, nil
return mapRows(ns, err, toNudge)
}
func (a *storeAPI) DeliveryAttempts(ctx context.Context, status string, n int) ([]DeliveryAttempt, error) {
as, err := a.s.ListDeliveryAttempts(ctx, status, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]DeliveryAttempt, len(as))
for i, at := range as {
out[i] = DeliveryAttempt{
return mapRows(as, err, func(at store.DeliveryAttempt) DeliveryAttempt {
out := DeliveryAttempt{
ID: at.ID, Kind: at.Kind, Rule: at.Rule, ReminderID: at.ReminderID,
Channel: at.Channel, Status: at.Status, Created: at.Created,
}
if at.HasComplete {
t := at.Completed
out[i].Completed = &t
out.Completed = &t
}
}
return out, nil
return out
})
}
func (a *storeAPI) WriteNote(ctx context.Context, ts time.Time, text string, embedding []float32, source string) (int64, error) {
@@ -197,38 +166,17 @@ func (a *storeAPI) WriteNote(ctx context.Context, ts time.Time, text string, emb
func (a *storeAPI) QueryNotes(ctx context.Context, embedding []float32, k int) ([]Note, error) {
ns, err := a.s.QueryNotes(ctx, embedding, k)
if err != nil {
return nil, mapErr(err)
}
out := make([]Note, len(ns))
for i, n := range ns {
out[i] = toNote(n)
}
return out, nil
return mapRows(ns, err, toNote)
}
func (a *storeAPI) RecentNotesFromSource(ctx context.Context, prefix string, n int) ([]Note, error) {
ns, err := a.s.RecentNotesFromSource(ctx, prefix, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Note, len(ns))
for i, note := range ns {
out[i] = toNote(note)
}
return out, nil
return mapRows(ns, err, toNote)
}
func (a *storeAPI) RecentNotes(ctx context.Context, n int) ([]Note, error) {
ns, err := a.s.RecentNotes(ctx, n)
if err != nil {
return nil, mapErr(err)
}
out := make([]Note, len(ns))
for i, note := range ns {
out[i] = toNote(note)
}
return out, nil
return mapRows(ns, err, toNote)
}
func (a *storeAPI) ProposeTool(ctx context.Context, name, utterance, scope string, ts time.Time) (bool, error) {
@@ -299,14 +247,7 @@ func (a *storeAPI) DayPlan(ctx context.Context) (DayPlan, error) {
func (a *storeAPI) ListTools(ctx context.Context, status string) ([]Tool, error) {
ts, err := a.s.ListTools(ctx, status)
if err != nil {
return nil, mapErr(err)
}
out := make([]Tool, len(ts))
for i, t := range ts {
out[i] = toTool(t)
}
return out, nil
return mapRows(ts, err, toTool)
}
func (a *storeAPI) DeleteTool(ctx context.Context, name string) error {
@@ -334,12 +275,8 @@ func (a *storeAPI) CaptureTask(ctx context.Context, req CaptureTaskReq) (Capture
func (a *storeAPI) ListTasks(ctx context.Context, status string) ([]Task, error) {
ts, err := a.s.ListTasks(ctx, status)
if err != nil {
return nil, mapErr(err)
}
out := make([]Task, len(ts))
for i, t := range ts {
out[i] = Task{
return mapRows(ts, err, func(t store.Task) Task {
return Task{
ID: t.ID,
CreatedTs: t.CreatedTs,
Text: t.Text,
@@ -354,8 +291,7 @@ func (a *storeAPI) ListTasks(ctx context.Context, status string) ([]Task, error)
DoneWhen: t.DoneWhen,
BlockedOn: t.BlockedOn,
}
}
return out, nil
})
}
func (a *storeAPI) SetTaskStatus(ctx context.Context, id int64, status string, ts time.Time, by string) error {
@@ -379,24 +315,17 @@ func (a *storeAPI) SetTaskFields(ctx context.Context, id int64, doneWhen, blocke
func (a *storeAPI) ListProposedRoutines(ctx context.Context) ([]ProposedRoutine, error) {
rs, err := a.s.ListProposedRoutines(ctx)
if err != nil {
return nil, mapErr(err)
}
out := make([]ProposedRoutine, len(rs))
for i, r := range rs {
out[i] = ProposedRoutine{
return mapRows(rs, err, func(r store.ProposedRoutine) ProposedRoutine {
return ProposedRoutine{
ID: r.ID,
Action: r.Action,
Object: r.Object,
IntervalDays: r.IntervalDays,
Status: string(r.Status),
CreatedTs: r.CreatedTs.UnixMilli(),
ReminderID: r.ReminderID,
}
if r.ReminderID != nil {
out[i].ReminderID = r.ReminderID
}
}
return out, nil
})
}
func (a *storeAPI) DismissProposedRoutine(ctx context.Context, id int64) error {