feat(guild): announce channel type + agent-presence + busy-discard
Phase 1 of DIALECTIC-V2 — adds Fabric infrastructure for system-broadcast channels with HF-status-aware delivery filtering. New channel x_type 'announce': - channels.entity.ts + channels.service.ts + realtime.gateway.ts enum + union extended. - computeDelivery() adds an 'announce' case: recipient with presence='busy' → 'skip' (discarded silently); other presences → 'observer' (delivered, no wake). System-broadcast semantics — agents proactively check their announce inbox when they're ready, not interrupted out of band. - messaging.controller POST guard: announce-type channels reject posts that don't present x-fabric-system-key header matching FABRIC_BACKEND_GUILD_SYSTEM_API_KEY env. Empty env = no system caller is valid (closed-by-default). New entity + module agent_presences: - agent-presence.entity.ts: per-user (userId PK) status enum (idle/on_call/busy/exhausted/offline/unknown), source tag, updatedAt - agent-presence.service.ts: getStatus/getStatusMap (bulk for delivery-time fanout) + setStatus (upsert) - agent-presence.controller.ts: GET + PUT /agents/:userId/presence - agent-presence.module.ts: TypeORM forFeature + wired into AppModule - buildTypeOrmConfig() entities list extended RealtimeGateway wiring: - New optional field on the gateway (typed loosely to avoid circular import). RealtimeModule.onModuleInit() assigns from the injected AgentPresenceService — degrades gracefully (no busy-discard, treat all as 'unknown') if presence wiring is ever removed. - emitMessageCreated pre-loads presence per fanout only when xType is 'announce' (other xTypes bypass the lookup entirely). Note: actual presence data writes come from Fabric.OpenclawPlugin's presence-sync loop (separate commit on that submodule); without it, all rows are 'unknown' and announce delivery falls through to the default observer behavior (no busy filtering). System-only POST gate is independent and works immediately. See /home/hzhang/arch/DIALECTIC-V2-DESIGN.md sections 7 + 10 Phase 1.
This commit is contained in:
@@ -16,9 +16,9 @@ export class Channel {
|
||||
@Column({
|
||||
name: 'x_type',
|
||||
type: 'enum',
|
||||
enum: ['general', 'work', 'report', 'discuss', 'triage', 'custom', 'dm'],
|
||||
enum: ['general', 'work', 'report', 'discuss', 'triage', 'custom', 'dm', 'announce'],
|
||||
})
|
||||
xType!: 'general' | 'work' | 'report' | 'discuss' | 'triage' | 'custom' | 'dm';
|
||||
xType!: 'general' | 'work' | 'report' | 'discuss' | 'triage' | 'custom' | 'dm' | 'announce';
|
||||
|
||||
@Column({ type: 'varchar', length: 16, default: 'text' })
|
||||
kind!: 'text' | 'announcement';
|
||||
|
||||
Reference in New Issue
Block a user