3 Commits

Author SHA1 Message Date
Claude Code
38d1d56cc6 Restore config layout with 0.1.7 default
Some checks failed
WHOOSH CI / speclint (push) Has been cancelled
WHOOSH CI / contracts (push) Has been cancelled
2025-10-17 09:28:28 +11:00
Claude Code
f5a141f97b Bump WHOOSH release to 0.1.7 2025-10-17 09:26:02 +11:00
Claude Code
e2847a64ba Refine discovery to trust mesh multiaddrs 2025-10-17 09:13:54 +11:00
6 changed files with 72 additions and 24 deletions

View File

@@ -1,4 +1,6 @@
FROM golang:1.22-alpine AS builder
# syntax=docker/dockerfile:1.4
FROM golang:1.24-alpine AS builder
# Install build dependencies
RUN apk add --no-cache git ca-certificates tzdata
@@ -6,15 +8,15 @@ RUN apk add --no-cache git ca-certificates tzdata
# Set working directory
WORKDIR /app
# Provide CHORUS module for local replace directive
COPY --from=chorus / /CHORUS/
# Copy BACKBEAT dependency first
COPY BACKBEAT-prototype ./BACKBEAT-prototype/
# Copy go mod files first for better caching
COPY go.mod go.sum ./
# Download and verify dependencies
RUN go mod download && go mod verify
# Copy source code
COPY . .
@@ -24,7 +26,7 @@ RUN cp /etc/group /tmp/group && \
echo "docker:x:998:65534" >> /tmp/group
# Build with optimizations and version info
ARG VERSION=v0.1.0-mvp
ARG VERSION=v0.1.7
ARG COMMIT_HASH
ARG BUILD_DATE
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \

5
TODO.md Normal file
View File

@@ -0,0 +1,5 @@
# TODO
1. Disable or refactor `SwarmDiscovery` so it consumes libp2p metadata rather than Docker task attachments (`DISCOVERY_METHOD=dns` fallback until parity is reached).
2. Shift council opportunity delivery to prefer mesh/NATS using the freshly stored `Agent.P2PAddr`, leaving HTTP as a compatibility fallback.
3. Emit telemetry/alerts whenever an agent reports zero `multiaddrs` so operations can catch misconfigured peers before discovery regresses.

View File

@@ -26,7 +26,7 @@ const (
var (
// Build-time variables (set via ldflags)
version = "0.1.5"
version = "0.1.7"
commitHash = "unknown"
buildDate = "unknown"
)

View File

@@ -93,7 +93,7 @@ type N8NConfig struct {
type OpenTelemetryConfig struct {
Enabled bool `envconfig:"ENABLED" default:"true"`
ServiceName string `envconfig:"SERVICE_NAME" default:"whoosh"`
ServiceVersion string `envconfig:"SERVICE_VERSION" default:"1.0.0"`
ServiceVersion string `envconfig:"SERVICE_VERSION" default:"0.1.7"`
Environment string `envconfig:"ENVIRONMENT" default:"production"`
JaegerEndpoint string `envconfig:"JAEGER_ENDPOINT" default:"http://localhost:14268/api/traces"`
SampleRate float64 `envconfig:"SAMPLE_RATE" default:"1.0"`

View File

@@ -12,6 +12,7 @@ import (
"sync"
"time"
"github.com/multiformats/go-multiaddr"
"github.com/rs/zerolog/log"
)
@@ -485,6 +486,7 @@ func (d *Discovery) processServiceResponse(endpoint string, resp *http.Response)
Model string `json:"model"`
PeerID string `json:"peer_id"`
Metadata map[string]interface{} `json:"metadata"`
Multiaddrs []string `json:"multiaddrs"`
}
if err := json.NewDecoder(resp.Body).Decode(&agentInfo); err != nil {
@@ -494,14 +496,52 @@ func (d *Discovery) processServiceResponse(endpoint string, resp *http.Response)
}
apiEndpoint, host := normalizeAPIEndpoint(endpoint)
resolvedHTTPHost := ""
resolvedP2PAddr := ""
for _, addr := range agentInfo.Multiaddrs {
ma, err := multiaddr.NewMultiaddr(addr)
if err != nil {
log.Debug().Str("multiaddr", addr).Err(err).Msg("Skipping invalid multiaddr from agent health response")
continue
}
if resolvedP2PAddr == "" {
resolvedP2PAddr = addr
}
if resolvedHTTPHost != "" {
continue
}
if ipV4, err := ma.ValueForProtocol(multiaddr.P_IP4); err == nil && ipV4 != "" {
resolvedHTTPHost = ipV4
continue
}
if ipV6, err := ma.ValueForProtocol(multiaddr.P_IP6); err == nil && ipV6 != "" {
resolvedHTTPHost = fmt.Sprintf("[%s]", ipV6)
}
}
if resolvedHTTPHost == "" {
resolvedHTTPHost = host
}
p2pAddr := endpoint
if host != "" {
if resolvedP2PAddr != "" {
p2pAddr = resolvedP2PAddr
} else if agentInfo.PeerID != "" && resolvedHTTPHost != "" {
// Fall back to synthesised multiaddr using discovered host + known p2p port
p2pAddr = fmt.Sprintf("/ip4/%s/tcp/9000/p2p/%s", strings.Trim(resolvedHTTPHost, "[]"), agentInfo.PeerID)
} else if host != "" {
p2pAddr = fmt.Sprintf("%s:%d", host, 9000)
}
// Build multiaddr from peer_id if available
if agentInfo.PeerID != "" && host != "" {
p2pAddr = fmt.Sprintf("/ip4/%s/tcp/9000/p2p/%s", host, agentInfo.PeerID)
// Prefer resolved IP for HTTP endpoint when available to avoid Swarm VIP routing issues
if resolvedHTTPHost != "" {
apiEndpoint = fmt.Sprintf("http://%s:%d", resolvedHTTPHost, d.config.AgentPort)
}
// Create detailed agent from parsed info
@@ -546,7 +586,8 @@ func (d *Discovery) processServiceResponse(endpoint string, resp *http.Response)
log.Info().
Str("agent_id", agent.ID).
Str("peer_id", agent.PeerID).
Str("endpoint", endpoint).
Str("endpoint", apiEndpoint).
Str("p2p_addr", p2pAddr).
Msg("🤖 Discovered CHORUS agent with metadata")
}

View File

@@ -4,7 +4,7 @@ set -e
# WHOOSH Docker Swarm Deployment Script
# Following CHORUS deployment patterns with SHHH secret management
VERSION=${1:-v0.1.0-mvp}
VERSION=${1:-v0.1.7}
REGISTRY_HOST=registry.home.deepblack.cloud
echo "🎭 WHOOSH Swarm Deployment - Version: $VERSION"