fix(mail): prevent message type failures (#960)
This commit is contained in:
@@ -11,9 +11,9 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/steveyegge/gastown/internal/beads"
|
"github.com/steveyegge/gastown/internal/beads"
|
||||||
"github.com/steveyegge/gastown/internal/constants"
|
|
||||||
"github.com/steveyegge/gastown/internal/claude"
|
"github.com/steveyegge/gastown/internal/claude"
|
||||||
"github.com/steveyegge/gastown/internal/config"
|
"github.com/steveyegge/gastown/internal/config"
|
||||||
|
"github.com/steveyegge/gastown/internal/constants"
|
||||||
"github.com/steveyegge/gastown/internal/deps"
|
"github.com/steveyegge/gastown/internal/deps"
|
||||||
"github.com/steveyegge/gastown/internal/formula"
|
"github.com/steveyegge/gastown/internal/formula"
|
||||||
"github.com/steveyegge/gastown/internal/shell"
|
"github.com/steveyegge/gastown/internal/shell"
|
||||||
@@ -408,11 +408,8 @@ func initTownBeads(townPath string) error {
|
|||||||
|
|
||||||
// Configure custom types for Gas Town (agent, role, rig, convoy, slot).
|
// Configure custom types for Gas Town (agent, role, rig, convoy, slot).
|
||||||
// These were extracted from beads core in v0.46.0 and now require explicit config.
|
// These were extracted from beads core in v0.46.0 and now require explicit config.
|
||||||
configCmd := exec.Command("bd", "config", "set", "types.custom", constants.BeadsCustomTypes)
|
if err := beads.EnsureCustomTypes(beadsDir); err != nil {
|
||||||
configCmd.Dir = townPath
|
return fmt.Errorf("ensuring custom types: %w", err)
|
||||||
if configOutput, configErr := configCmd.CombinedOutput(); configErr != nil {
|
|
||||||
// Non-fatal: older beads versions don't need this, newer ones do
|
|
||||||
fmt.Printf(" %s Could not set custom types: %s\n", style.Dim.Render("⚠"), strings.TrimSpace(string(configOutput)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure allowed_prefixes for convoy beads (hq-cv-* IDs).
|
// Configure allowed_prefixes for convoy beads (hq-cv-* IDs).
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ func (m *Mailbox) identityVariants() []string {
|
|||||||
|
|
||||||
// queryMessages runs a bd list query with the given filter flag and value.
|
// queryMessages runs a bd list query with the given filter flag and value.
|
||||||
func (m *Mailbox) queryMessages(beadsDir, filterFlag, filterValue, status string) ([]*Message, error) {
|
func (m *Mailbox) queryMessages(beadsDir, filterFlag, filterValue, status string) ([]*Message, error) {
|
||||||
|
if err := beads.EnsureCustomTypes(beadsDir); err != nil {
|
||||||
|
return nil, fmt.Errorf("ensuring custom types: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
args := []string{"list",
|
args := []string{"list",
|
||||||
"--type", "message",
|
"--type", "message",
|
||||||
filterFlag, filterValue,
|
filterFlag, filterValue,
|
||||||
@@ -829,8 +833,8 @@ func (m *Mailbox) rewriteLegacy(messages []*Message) error {
|
|||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
data, err := json.Marshal(msg)
|
data, err := json.Marshal(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = file.Close() // best-effort cleanup
|
_ = file.Close() // best-effort cleanup
|
||||||
_ = os.Remove(tmpPath) // best-effort cleanup
|
_ = os.Remove(tmpPath) // best-effort cleanup
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, _ = file.WriteString(string(data) + "\n") // non-fatal: partial write is acceptable
|
_, _ = file.WriteString(string(data) + "\n") // non-fatal: partial write is acceptable
|
||||||
|
|||||||
+26
-4
@@ -189,6 +189,13 @@ func (r *Router) resolveBeadsDir(_ string) string { // address unused: all mail
|
|||||||
return filepath.Join(r.townRoot, ".beads")
|
return filepath.Join(r.townRoot, ".beads")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) ensureCustomTypes(beadsDir string) error {
|
||||||
|
if err := beads.EnsureCustomTypes(beadsDir); err != nil {
|
||||||
|
return fmt.Errorf("ensuring custom types: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// isTownLevelAddress returns true if the address is for a town-level agent or the overseer.
|
// isTownLevelAddress returns true if the address is for a town-level agent or the overseer.
|
||||||
func isTownLevelAddress(address string) bool {
|
func isTownLevelAddress(address string) bool {
|
||||||
addr := strings.TrimSuffix(address, "/")
|
addr := strings.TrimSuffix(address, "/")
|
||||||
@@ -214,10 +221,10 @@ const (
|
|||||||
|
|
||||||
// ParsedGroup represents a parsed @group address.
|
// ParsedGroup represents a parsed @group address.
|
||||||
type ParsedGroup struct {
|
type ParsedGroup struct {
|
||||||
Type GroupType
|
Type GroupType
|
||||||
RoleType string // witness, crew, polecat, dog, etc.
|
RoleType string // witness, crew, polecat, dog, etc.
|
||||||
Rig string // rig name for rig-scoped groups
|
Rig string // rig name for rig-scoped groups
|
||||||
Original string // original @group string
|
Original string // original @group string
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseGroupAddress parses a @group address into its components.
|
// parseGroupAddress parses a @group address into its components.
|
||||||
@@ -697,6 +704,9 @@ func (r *Router) sendToSingle(msg *Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beadsDir := r.resolveBeadsDir(msg.To)
|
beadsDir := r.resolveBeadsDir(msg.To)
|
||||||
|
if err := r.ensureCustomTypes(beadsDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err := runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
_, err := runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sending message: %w", err)
|
return fmt.Errorf("sending message: %w", err)
|
||||||
@@ -807,6 +817,9 @@ func (r *Router) sendToQueue(msg *Message) error {
|
|||||||
|
|
||||||
// Queue messages go to town-level beads (shared location)
|
// Queue messages go to town-level beads (shared location)
|
||||||
beadsDir := r.resolveBeadsDir("")
|
beadsDir := r.resolveBeadsDir("")
|
||||||
|
if err := r.ensureCustomTypes(beadsDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sending to queue %s: %w", queueName, err)
|
return fmt.Errorf("sending to queue %s: %w", queueName, err)
|
||||||
@@ -878,6 +891,9 @@ func (r *Router) sendToAnnounce(msg *Message) error {
|
|||||||
|
|
||||||
// Announce messages go to town-level beads (shared location)
|
// Announce messages go to town-level beads (shared location)
|
||||||
beadsDir := r.resolveBeadsDir("")
|
beadsDir := r.resolveBeadsDir("")
|
||||||
|
if err := r.ensureCustomTypes(beadsDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sending to announce %s: %w", announceName, err)
|
return fmt.Errorf("sending to announce %s: %w", announceName, err)
|
||||||
@@ -951,6 +967,9 @@ func (r *Router) sendToChannel(msg *Message) error {
|
|||||||
|
|
||||||
// Channel messages go to town-level beads (shared location)
|
// Channel messages go to town-level beads (shared location)
|
||||||
beadsDir := r.resolveBeadsDir("")
|
beadsDir := r.resolveBeadsDir("")
|
||||||
|
if err := r.ensureCustomTypes(beadsDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
_, err = runBdCommand(args, filepath.Dir(beadsDir), beadsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sending to channel %s: %w", channelName, err)
|
return fmt.Errorf("sending to channel %s: %w", channelName, err)
|
||||||
@@ -988,6 +1007,9 @@ func (r *Router) pruneAnnounce(announceName string, retainCount int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beadsDir := r.resolveBeadsDir("")
|
beadsDir := r.resolveBeadsDir("")
|
||||||
|
if err := r.ensureCustomTypes(beadsDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Query existing messages in this announce channel
|
// Query existing messages in this announce channel
|
||||||
// Use bd list with labels filter to find messages with announce:<name> label
|
// Use bd list with labels filter to find messages with announce:<name> label
|
||||||
|
|||||||
Reference in New Issue
Block a user