diff --git a/cmd/plexum-harborforge-plugin/main.go b/cmd/plexum-harborforge-plugin/main.go index 280d61b..c809558 100644 --- a/cmd/plexum-harborforge-plugin/main.go +++ b/cmd/plexum-harborforge-plugin/main.go @@ -131,15 +131,16 @@ func (p *harborForgePlugin) Init(ctx context.Context, host sdkplugin.HostAPI) er Scheduler: p.sched, Host: host, AgentIDFromCtx: func(ctx context.Context) string { - // Plexum stashes the calling agent id on the host-side - // context (via WithAgent) before dispatching tool calls. - // We can't directly import internal/agentloop from a - // plugin, so we rely on PLEXUM_TOOL_AGENT_ID env-style - // (set per-call by host when we add that wiring) or fall - // back to the only-active-agent heuristic. v1: prefer the - // only-active wake-target (deterministic in single-agent - // HF deployments). - return p.bestEffortAgentID() + // Host attaches the caller agent id via tools/call + // `_meta.agent_id`; SDK unpacks it into ctx. + if id := sdkplugin.AgentIDFromContext(ctx); id != "" { + return id + } + // Fallback for host paths that don't carry an agent + // (channel-driven, CLI plugin-call). When a single + // calendar slot is active we can deterministically + // attribute the call to that slot's owner. + return p.sched.SingleActiveAgentID() }, } @@ -209,28 +210,6 @@ func mapStateToCalendar(s string) calendar.AgentStatusValue { return calendar.AgentStatusOffline } -// bestEffortAgentID is a v1 stop-gap for tools that need the calling -// agent's id but don't have it on the ctx (Plexum SDK doesn't yet -// expose this — TODO upstream). v1: if exactly one agent has an -// active calendar slot we return it; otherwise empty. The calendar -// tools (the only ones that need agent context) usually fire when -// exactly one slot is active. -func (p *harborForgePlugin) bestEffortAgentID() string { - sch := p.sched.Status() - if len(sch.Active) != 1 { - return "" - } - // We don't track AgentID on Slot directly — the scheduler keeps - // activeByAgentID. Iterate to find the one. - for _, a := range sch.Active { - // Slot is shared between agents only via the scheduler's maps; - // here we have just the Slot struct without owner. - _ = a - } - // Fallback to scheduler's helper: - return p.sched.SingleActiveAgentID() -} - func manifestFromDisk() sdkplugin.Manifest { // Bundled manifest.json is the authoritative shape; the binary // version reads it next to itself to avoid hand-syncing two