fix(commands): inject forced skill content for /use (#4044)
This commit is contained in:
@@ -949,8 +949,11 @@ async function cmdUse(args){
|
||||
}
|
||||
return;
|
||||
}
|
||||
const detail = await api(`/api/skills/content?name=${encodeURIComponent(match.name)}`);
|
||||
const skillContent = detail&&typeof detail.content==='string' ? detail.content.trim() : '';
|
||||
if(!skillContent) throw new Error(`Skill \`${match.name}\` has no readable content.`);
|
||||
const directive = `[USER OVERRIDE] You MUST consult skill '${match.name}' via skill_view before responding to the next message.`;
|
||||
resolve(directive);
|
||||
resolve({name:match.name,directive,content:skillContent});
|
||||
if(isCurrentSession()){
|
||||
S.messages.push({role:'assistant', content:`Next turn: skill \`${match.name}\` will be forced.`});
|
||||
renderMessages();
|
||||
|
||||
@@ -1063,10 +1063,22 @@ async function send(){
|
||||
if(_forcedSkillDirectivePending){
|
||||
const _pending=_forcedSkillDirectivePending;
|
||||
if(!_pending.sessionId||_pending.sessionId===activeSid){
|
||||
const _directive = await _pending.promise;
|
||||
const _directivePayload = await _pending.promise;
|
||||
if(_forcedSkillDirectivePending===_pending)_forcedSkillDirectivePending = null;
|
||||
if(typeof _directive==='string'&&_directive){
|
||||
msgText=`${_directive}\n\n${msgText||''}`.trim();
|
||||
if(_directivePayload){
|
||||
const _directive = typeof _directivePayload==='string'
|
||||
? _directivePayload
|
||||
: String(_directivePayload.directive||'').trim();
|
||||
const _forcedSkillName = typeof _directivePayload==='string'
|
||||
? ''
|
||||
: String(_directivePayload.name||'').trim();
|
||||
const _forcedSkillContent = typeof _directivePayload==='string'
|
||||
? ''
|
||||
: String(_directivePayload.content||'').trim();
|
||||
const _forcedSkillBlock = _forcedSkillName&&_forcedSkillContent
|
||||
? `[FORCED SKILL CONTEXT: ${_forcedSkillName}]\n${_forcedSkillContent}\n[/FORCED SKILL CONTEXT]`
|
||||
: '';
|
||||
msgText=`${_directive}${_forcedSkillBlock?`\n\n${_forcedSkillBlock}`:''}\n\n${msgText||''}`.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ def test_forced_skill_directive_set_in_cmdUse():
|
||||
src = read("static/commands.js")
|
||||
assert "pending.promise = new Promise" in src, "cmdUse must create a pending Promise"
|
||||
assert "_forcedSkillDirectivePending = pending;" in src, "cmdUse must publish the pending directive before awaiting"
|
||||
assert "resolve({name:match.name,directive,content:skillContent});" in src, \
|
||||
"cmdUse must resolve the pending payload with skill name, directive, and fetched content"
|
||||
|
||||
|
||||
def test_use_entry_has_noEcho():
|
||||
@@ -59,7 +61,7 @@ def test_directive_consumed_at_injection_site():
|
||||
finally_part = src.split("finally")[1] if "finally" in src else ""
|
||||
assert "_forcedSkillDirectivePending = null;" not in finally_part, \
|
||||
"_forcedSkillDirectivePending must NOT be cleared in the finally block"
|
||||
assert "const _directive = await _pending.promise;" in src, \
|
||||
assert "const _directivePayload = await _pending.promise;" in src, \
|
||||
"consume site must await the pending promise"
|
||||
assert "_forcedSkillDirectivePending = null;" in src, \
|
||||
"_forcedSkillDirectivePending must be cleared somewhere in messages.js"
|
||||
@@ -78,6 +80,14 @@ def test_directive_text_uses_match_name():
|
||||
assert "[USER OVERRIDE] You MUST consult skill '" in src, "directive text must match the specified format"
|
||||
|
||||
|
||||
def test_use_fetches_canonical_skill_content():
|
||||
src = read("static/commands.js")
|
||||
assert "api(`/api/skills/content?name=${encodeURIComponent(match.name)}`)" in src, \
|
||||
"cmdUse must fetch the canonical skill content after resolving the canonical skill name"
|
||||
assert "typeof detail.content==='string' ? detail.content.trim() : ''" in src, \
|
||||
"cmdUse must reject missing or non-string skill content"
|
||||
|
||||
|
||||
def test_pending_promise_set_synchronously():
|
||||
"""_forcedSkillDirectivePending must be set before the first await in cmdUse."""
|
||||
src = read("static/commands.js")
|
||||
@@ -114,3 +124,5 @@ def test_directive_only_consumed_by_matching_session():
|
||||
"send() must only consume /use directives issued for the active session"
|
||||
assert "if(_forcedSkillDirectivePending===_pending)_forcedSkillDirectivePending = null;" in src, \
|
||||
"send() must not clear a newer pending directive created while awaiting"
|
||||
assert "[FORCED SKILL CONTEXT: ${_forcedSkillName}]" in src, \
|
||||
"send() must prepend deterministic forced-skill content before the user message"
|
||||
|
||||
Reference in New Issue
Block a user