fix: plugin bot user + await plugin detection before session scan
- Add EnsureBotUser on plugin activate (fixes 'Unable to find user' error) - Accept bot_user_id in create session request - Await plugin health check before starting session monitor (prevents race where sessions detect before plugin flag is set) - Plugin now creates custom_livestatus posts with proper bot user
This commit is contained in:
@@ -75,6 +75,7 @@ type CreateSessionRequest struct {
|
||||
ChannelID string `json:"channel_id"`
|
||||
RootID string `json:"root_id,omitempty"`
|
||||
AgentID string `json:"agent_id"`
|
||||
BotUserID string `json:"bot_user_id,omitempty"`
|
||||
}
|
||||
|
||||
// handleCreateSession creates a new custom_livestatus post and starts tracking.
|
||||
@@ -98,8 +99,20 @@ func (p *Plugin) handleCreateSession(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create the custom post
|
||||
// Create the custom post — UserId is required
|
||||
// Use the bot user ID passed in the request, or fall back to plugin bot
|
||||
userID := req.BotUserID
|
||||
if userID == "" {
|
||||
// Try to get plugin's own bot
|
||||
userID = p.getBotUserID()
|
||||
}
|
||||
if userID == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "bot_user_id required (no plugin bot available)"})
|
||||
return
|
||||
}
|
||||
|
||||
post := &model.Post{
|
||||
UserId: userID,
|
||||
ChannelId: req.ChannelID,
|
||||
RootId: req.RootID,
|
||||
Type: "custom_livestatus",
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/plugin"
|
||||
)
|
||||
|
||||
@@ -18,16 +19,37 @@ type Plugin struct {
|
||||
|
||||
// store wraps KV store operations for session persistence.
|
||||
store *Store
|
||||
|
||||
// botUserID is the plugin's bot user ID (created on activation).
|
||||
botUserID string
|
||||
}
|
||||
|
||||
// OnActivate is called when the plugin is activated.
|
||||
func (p *Plugin) OnActivate() error {
|
||||
p.store = NewStore(p.API)
|
||||
|
||||
// Ensure plugin bot user exists
|
||||
botID, appErr := p.API.EnsureBotUser(&model.Bot{
|
||||
Username: "livestatus",
|
||||
DisplayName: "Live Status",
|
||||
Description: "OpenClaw Live Status plugin bot",
|
||||
})
|
||||
if appErr != nil {
|
||||
p.API.LogWarn("Failed to ensure bot user", "error", appErr.Error())
|
||||
} else {
|
||||
p.botUserID = botID
|
||||
p.API.LogInfo("Plugin bot user ensured", "botUserID", botID)
|
||||
}
|
||||
|
||||
p.API.LogInfo("OpenClaw Live Status plugin activated")
|
||||
return nil
|
||||
}
|
||||
|
||||
// getBotUserID returns the plugin's bot user ID.
|
||||
func (p *Plugin) getBotUserID() string {
|
||||
return p.botUserID
|
||||
}
|
||||
|
||||
// OnDeactivate is called when the plugin is deactivated.
|
||||
func (p *Plugin) OnDeactivate() error {
|
||||
// Mark all active sessions as interrupted
|
||||
|
||||
@@ -60,13 +60,24 @@ PluginClient.prototype.isHealthy = function () {
|
||||
* @param {string} agentId
|
||||
* @returns {Promise<string>} post_id
|
||||
*/
|
||||
/**
|
||||
* @param {string} botUserId - Mattermost bot user ID to author the post
|
||||
*/
|
||||
PluginClient.prototype.setBotUserId = function (botUserId) {
|
||||
this.botUserId = botUserId;
|
||||
};
|
||||
|
||||
PluginClient.prototype.createSession = function (sessionKey, channelId, rootId, agentId) {
|
||||
return this._request('POST', '/api/v1/sessions', {
|
||||
var body = {
|
||||
session_key: sessionKey,
|
||||
channel_id: channelId,
|
||||
root_id: rootId || '',
|
||||
agent_id: agentId,
|
||||
}).then(function (data) {
|
||||
};
|
||||
if (this.botUserId) {
|
||||
body.bot_user_id = this.botUserId;
|
||||
}
|
||||
return this._request('POST', '/api/v1/sessions', body).then(function (data) {
|
||||
return data.post_id;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -171,13 +171,17 @@ async function startDaemon() {
|
||||
logger: logger.child({ module: 'plugin-client' }),
|
||||
});
|
||||
|
||||
// Initial plugin detection
|
||||
pluginClient.isHealthy().then(function (healthy) {
|
||||
// Initial plugin detection (awaited before monitor starts — see below)
|
||||
try {
|
||||
var healthy = await pluginClient.isHealthy();
|
||||
usePlugin = healthy;
|
||||
logger.info({ usePlugin, url: config.plugin.url }, healthy
|
||||
? 'Plugin detected — using WebSocket rendering mode'
|
||||
: 'Plugin not available — using REST API fallback');
|
||||
});
|
||||
} catch (_detectErr) {
|
||||
usePlugin = false;
|
||||
logger.warn('Plugin detection failed — using REST API fallback');
|
||||
}
|
||||
|
||||
// Periodic re-detection
|
||||
setInterval(function () {
|
||||
|
||||
Reference in New Issue
Block a user