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"`
|
ChannelID string `json:"channel_id"`
|
||||||
RootID string `json:"root_id,omitempty"`
|
RootID string `json:"root_id,omitempty"`
|
||||||
AgentID string `json:"agent_id"`
|
AgentID string `json:"agent_id"`
|
||||||
|
BotUserID string `json:"bot_user_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleCreateSession creates a new custom_livestatus post and starts tracking.
|
// 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
|
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{
|
post := &model.Post{
|
||||||
|
UserId: userID,
|
||||||
ChannelId: req.ChannelID,
|
ChannelId: req.ChannelID,
|
||||||
RootId: req.RootID,
|
RootId: req.RootID,
|
||||||
Type: "custom_livestatus",
|
Type: "custom_livestatus",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
"github.com/mattermost/mattermost/server/public/plugin"
|
"github.com/mattermost/mattermost/server/public/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,16 +19,37 @@ type Plugin struct {
|
|||||||
|
|
||||||
// store wraps KV store operations for session persistence.
|
// store wraps KV store operations for session persistence.
|
||||||
store *Store
|
store *Store
|
||||||
|
|
||||||
|
// botUserID is the plugin's bot user ID (created on activation).
|
||||||
|
botUserID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnActivate is called when the plugin is activated.
|
// OnActivate is called when the plugin is activated.
|
||||||
func (p *Plugin) OnActivate() error {
|
func (p *Plugin) OnActivate() error {
|
||||||
p.store = NewStore(p.API)
|
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")
|
p.API.LogInfo("OpenClaw Live Status plugin activated")
|
||||||
return nil
|
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.
|
// OnDeactivate is called when the plugin is deactivated.
|
||||||
func (p *Plugin) OnDeactivate() error {
|
func (p *Plugin) OnDeactivate() error {
|
||||||
// Mark all active sessions as interrupted
|
// Mark all active sessions as interrupted
|
||||||
|
|||||||
@@ -60,13 +60,24 @@ PluginClient.prototype.isHealthy = function () {
|
|||||||
* @param {string} agentId
|
* @param {string} agentId
|
||||||
* @returns {Promise<string>} post_id
|
* @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) {
|
PluginClient.prototype.createSession = function (sessionKey, channelId, rootId, agentId) {
|
||||||
return this._request('POST', '/api/v1/sessions', {
|
var body = {
|
||||||
session_key: sessionKey,
|
session_key: sessionKey,
|
||||||
channel_id: channelId,
|
channel_id: channelId,
|
||||||
root_id: rootId || '',
|
root_id: rootId || '',
|
||||||
agent_id: agentId,
|
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;
|
return data.post_id;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -171,13 +171,17 @@ async function startDaemon() {
|
|||||||
logger: logger.child({ module: 'plugin-client' }),
|
logger: logger.child({ module: 'plugin-client' }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initial plugin detection
|
// Initial plugin detection (awaited before monitor starts — see below)
|
||||||
pluginClient.isHealthy().then(function (healthy) {
|
try {
|
||||||
|
var healthy = await pluginClient.isHealthy();
|
||||||
usePlugin = healthy;
|
usePlugin = healthy;
|
||||||
logger.info({ usePlugin, url: config.plugin.url }, healthy
|
logger.info({ usePlugin, url: config.plugin.url }, healthy
|
||||||
? 'Plugin detected — using WebSocket rendering mode'
|
? 'Plugin detected — using WebSocket rendering mode'
|
||||||
: 'Plugin not available — using REST API fallback');
|
: 'Plugin not available — using REST API fallback');
|
||||||
});
|
} catch (_detectErr) {
|
||||||
|
usePlugin = false;
|
||||||
|
logger.warn('Plugin detection failed — using REST API fallback');
|
||||||
|
}
|
||||||
|
|
||||||
// Periodic re-detection
|
// Periodic re-detection
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user