2026-02-14 19:55:04 +00:00
import "./reply.directive.directive-behavior.e2e-mocks.js" ;
2026-01-16 20:11:01 +00:00
import fs from "node:fs/promises" ;
2026-01-14 01:08:15 +00:00
import path from "node:path" ;
2026-02-14 19:55:04 +00:00
import { describe , expect , it , vi } from "vitest" ;
import {
installDirectiveBehaviorE2EHooks ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig ,
replyText ,
replyTexts ,
2026-02-14 19:55:04 +00:00
runEmbeddedPiAgent ,
2026-02-16 14:52:09 +00:00
sessionStorePath ,
2026-02-14 19:55:04 +00:00
withTempHome ,
} from "./reply.directive.directive-behavior.e2e-harness.js" ;
2026-01-14 01:08:15 +00:00
import { getReplyFromConfig } from "./reply.js" ;
2026-01-16 20:11:01 +00:00
async function writeSkill ( params : { workspaceDir : string ; name : string ; description : string } ) {
const { workspaceDir , name , description } = params ;
const skillDir = path . join ( workspaceDir , "skills" , name ) ;
await fs . mkdir ( skillDir , { recursive : true } ) ;
await fs . writeFile (
path . join ( skillDir , "SKILL.md" ) ,
` --- \ nname: ${ name } \ ndescription: ${ description } \ n--- \ n \ n# ${ name } \ n ` ,
"utf-8" ,
) ;
}
2026-02-16 14:52:09 +00:00
async function runThinkingDirective ( home : string , model : string ) {
const res = await getReplyFromConfig (
{
Body : "/thinking xhigh" ,
From : "+1004" ,
To : "+2000" ,
CommandAuthorized : true ,
} ,
{ } ,
makeWhatsAppDirectiveConfig ( home , { model } , { session : { store : sessionStorePath ( home ) } } ) ,
) ;
return replyTexts ( res ) ;
}
2026-01-14 01:08:15 +00:00
describe ( "directive behavior" , ( ) = > {
2026-02-14 19:55:04 +00:00
installDirectiveBehaviorE2EHooks ( ) ;
2026-01-14 01:08:15 +00:00
it ( "accepts /thinking xhigh for codex models" , async ( ) = > {
await withTempHome ( async ( home ) = > {
2026-02-16 14:52:09 +00:00
const texts = await runThinkingDirective ( home , "openai-codex/gpt-5.2-codex" ) ;
2026-01-14 01:08:15 +00:00
expect ( texts ) . toContain ( "Thinking level set to xhigh." ) ;
} ) ;
} ) ;
it ( "accepts /thinking xhigh for openai gpt-5.2" , async ( ) = > {
await withTempHome ( async ( home ) = > {
2026-02-16 14:52:09 +00:00
const texts = await runThinkingDirective ( home , "openai/gpt-5.2" ) ;
2026-01-14 01:08:15 +00:00
expect ( texts ) . toContain ( "Thinking level set to xhigh." ) ;
} ) ;
} ) ;
it ( "rejects /thinking xhigh for non-codex models" , async ( ) = > {
await withTempHome ( async ( home ) = > {
2026-02-16 14:52:09 +00:00
const texts = await runThinkingDirective ( home , "openai/gpt-4.1-mini" ) ;
2026-01-14 01:08:15 +00:00
expect ( texts ) . toContain (
2026-02-13 12:39:22 +01:00
'Thinking level "xhigh" is only supported for openai/gpt-5.2, openai-codex/gpt-5.3-codex, openai-codex/gpt-5.3-codex-spark, openai-codex/gpt-5.2-codex, openai-codex/gpt-5.1-codex, github-copilot/gpt-5.2-codex or github-copilot/gpt-5.2.' ,
2026-01-14 01:08:15 +00:00
) ;
} ) ;
} ) ;
it ( "keeps reserved command aliases from matching after trimming" , async ( ) = > {
await withTempHome ( async ( home ) = > {
const res = await getReplyFromConfig (
{
Body : "/help" ,
From : "+1222" ,
To : "+1222" ,
2026-01-17 08:27:52 +00:00
CommandAuthorized : true ,
2026-01-14 01:08:15 +00:00
} ,
{ } ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig (
home ,
{
model : "anthropic/claude-opus-4-5" ,
models : {
"anthropic/claude-opus-4-5" : { alias : " help " } ,
2026-01-14 01:08:15 +00:00
} ,
} ,
2026-02-16 14:52:09 +00:00
{ session : { store : sessionStorePath ( home ) } } ,
) ,
2026-01-14 01:08:15 +00:00
) ;
2026-02-16 14:52:09 +00:00
const text = replyText ( res ) ;
2026-01-14 01:08:15 +00:00
expect ( text ) . toContain ( "Help" ) ;
expect ( runEmbeddedPiAgent ) . not . toHaveBeenCalled ( ) ;
} ) ;
} ) ;
2026-01-16 20:11:01 +00:00
it ( "treats skill commands as reserved for model aliases" , async ( ) = > {
await withTempHome ( async ( home ) = > {
2026-01-30 03:15:10 +01:00
const workspace = path . join ( home , "openclaw" ) ;
2026-01-16 20:11:01 +00:00
await writeSkill ( {
workspaceDir : workspace ,
name : "demo-skill" ,
description : "Demo skill" ,
} ) ;
await getReplyFromConfig (
{
Body : "/demo_skill" ,
From : "+1222" ,
To : "+1222" ,
2026-01-17 08:27:52 +00:00
CommandAuthorized : true ,
2026-01-16 20:11:01 +00:00
} ,
{ } ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig (
home ,
{
model : "anthropic/claude-opus-4-5" ,
workspace ,
models : {
"anthropic/claude-opus-4-5" : { alias : "demo_skill" } ,
2026-01-16 20:11:01 +00:00
} ,
} ,
2026-02-16 14:52:09 +00:00
{ session : { store : sessionStorePath ( home ) } } ,
) ,
2026-01-16 20:11:01 +00:00
) ;
expect ( runEmbeddedPiAgent ) . toHaveBeenCalled ( ) ;
const prompt = vi . mocked ( runEmbeddedPiAgent ) . mock . calls [ 0 ] ? . [ 0 ] ? . prompt ? ? "" ;
expect ( prompt ) . toContain ( 'Use the "demo-skill" skill' ) ;
} ) ;
} ) ;
2026-01-14 01:08:15 +00:00
it ( "errors on invalid queue options" , async ( ) = > {
await withTempHome ( async ( home ) = > {
const res = await getReplyFromConfig (
{
Body : "/queue collect debounce:bogus cap:zero drop:maybe" ,
From : "+1222" ,
To : "+1222" ,
2026-01-17 08:27:52 +00:00
CommandAuthorized : true ,
2026-01-14 01:08:15 +00:00
} ,
{ } ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig (
home ,
{ model : "anthropic/claude-opus-4-5" } ,
{
session : { store : sessionStorePath ( home ) } ,
2026-01-14 01:08:15 +00:00
} ,
2026-02-16 14:52:09 +00:00
) ,
2026-01-14 01:08:15 +00:00
) ;
2026-02-16 14:52:09 +00:00
const text = replyText ( res ) ;
2026-01-14 01:08:15 +00:00
expect ( text ) . toContain ( "Invalid debounce" ) ;
expect ( text ) . toContain ( "Invalid cap" ) ;
expect ( text ) . toContain ( "Invalid drop policy" ) ;
expect ( runEmbeddedPiAgent ) . not . toHaveBeenCalled ( ) ;
} ) ;
} ) ;
it ( "shows current queue settings when /queue has no arguments" , async ( ) = > {
await withTempHome ( async ( home ) = > {
const res = await getReplyFromConfig (
{
Body : "/queue" ,
From : "+1222" ,
To : "+1222" ,
Provider : "whatsapp" ,
2026-01-17 08:27:52 +00:00
CommandAuthorized : true ,
2026-01-14 01:08:15 +00:00
} ,
{ } ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig (
home ,
{ model : "anthropic/claude-opus-4-5" } ,
{
messages : {
queue : {
mode : "collect" ,
debounceMs : 1500 ,
cap : 9 ,
drop : "summarize" ,
} ,
2026-01-14 01:08:15 +00:00
} ,
2026-02-16 14:52:09 +00:00
session : { store : sessionStorePath ( home ) } ,
2026-01-14 01:08:15 +00:00
} ,
2026-02-16 14:52:09 +00:00
) ,
2026-01-14 01:08:15 +00:00
) ;
2026-02-16 14:52:09 +00:00
const text = replyText ( res ) ;
2026-01-14 01:08:15 +00:00
expect ( text ) . toContain (
"Current queue settings: mode=collect, debounce=1500ms, cap=9, drop=summarize." ,
) ;
expect ( text ) . toContain (
"Options: modes steer, followup, collect, steer+backlog, interrupt; debounce:<ms|s|m>, cap:<n>, drop:old|new|summarize." ,
) ;
expect ( runEmbeddedPiAgent ) . not . toHaveBeenCalled ( ) ;
} ) ;
} ) ;
it ( "shows current think level when /think has no argument" , async ( ) = > {
await withTempHome ( async ( home ) = > {
const res = await getReplyFromConfig (
2026-01-17 08:27:52 +00:00
{ Body : "/think" , From : "+1222" , To : "+1222" , CommandAuthorized : true } ,
2026-01-14 01:08:15 +00:00
{ } ,
2026-02-16 14:52:09 +00:00
makeWhatsAppDirectiveConfig (
home ,
{ model : "anthropic/claude-opus-4-5" , thinkingDefault : "high" } ,
{ session : { store : sessionStorePath ( home ) } } ,
) ,
2026-01-14 01:08:15 +00:00
) ;
2026-02-16 14:52:09 +00:00
const text = replyText ( res ) ;
2026-01-14 01:08:15 +00:00
expect ( text ) . toContain ( "Current thinking level: high" ) ;
expect ( text ) . toContain ( "Options: off, minimal, low, medium, high." ) ;
expect ( runEmbeddedPiAgent ) . not . toHaveBeenCalled ( ) ;
} ) ;
} ) ;
} ) ;