22import { describe , expect , it } from "vitest" ;
33import type { OpenClawConfig } from "../../config/types.openclaw.js" ;
44import { DEFAULT_LEARN_REQUEST } from "../../skills/workshop/learn-prompt.js" ;
5+ import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js" ;
56import { handleLearnCommand } from "./commands-learn.js" ;
67import type { HandleCommandsParams } from "./commands-types.js" ;
78
@@ -32,8 +33,8 @@ function buildLearnParams(
3233 return {
3334 cfg : { ...cfg , models : cfg . models ?? DEFAULT_TEST_MODELS } ,
3435 ctx : {
35- Provider : "web" ,
36- Surface : "web" ,
36+ Provider : INTERNAL_MESSAGE_CHANNEL ,
37+ Surface : INTERNAL_MESSAGE_CHANNEL ,
3738 CommandSource : "text" ,
3839 Body : commandBodyNormalized ,
3940 RawBody : commandBodyNormalized ,
@@ -47,15 +48,15 @@ function buildLearnParams(
4748 isAuthorizedSender : true ,
4849 senderIsOwner : true ,
4950 senderId : "tester" ,
50- channel : "web" ,
51- channelId : "web" ,
52- surface : "web" ,
51+ channel : INTERNAL_MESSAGE_CHANNEL ,
52+ channelId : INTERNAL_MESSAGE_CHANNEL ,
53+ surface : INTERNAL_MESSAGE_CHANNEL ,
5354 ownerList : [ ] ,
5455 rawBodyNormalized : commandBodyNormalized ,
5556 } ,
5657 directives : { } ,
5758 elevated : { enabled : true , allowed : true , failures : [ ] } ,
58- sessionKey : "agent:main:web :test" ,
59+ sessionKey : "agent:main:webchat :test" ,
5960 workspaceDir : "/tmp" ,
6061 provider : "openai" ,
6162 model : "gpt-5.5" ,
@@ -124,6 +125,28 @@ describe("learn command", () => {
124125 expect ( result ?. reply ?. text ) . toContain ( "Skill workshop is not available on this agent" ) ;
125126 } ) ;
126127
128+ it ( "keeps the workshop available for owner WebChat under a wildcard sender policy" , async ( ) => {
129+ const params = buildLearnParams ( "/learn" , {
130+ tools : { toolsBySender : { "*" : { deny : [ "skill_workshop" ] } } } ,
131+ } ) ;
132+
133+ const result = await handleLearnCommand ( params , true ) ;
134+
135+ expect ( result ?. shouldContinue ) . toBe ( true ) ;
136+ } ) ;
137+
138+ it ( "keeps the wildcard sender policy for non-owner WebChat" , async ( ) => {
139+ const params = buildLearnParams ( "/learn" , {
140+ tools : { toolsBySender : { "*" : { deny : [ "skill_workshop" ] } } } ,
141+ } ) ;
142+ params . command . senderIsOwner = false ;
143+
144+ const result = await handleLearnCommand ( params , true ) ;
145+
146+ expect ( result ?. shouldContinue ) . toBe ( false ) ;
147+ expect ( result ?. reply ?. text ) . toContain ( "Skill workshop is not available on this agent" ) ;
148+ } ) ;
149+
127150 it ( "replies without continuing when the runtime tool allowlist is empty" , async ( ) => {
128151 const params = buildLearnParams ( "/learn" ) ;
129152 params . opts = { toolsAllow : [ ] } ;
0 commit comments