-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathskill_commands.cpp
More file actions
130 lines (113 loc) · 4.72 KB
/
Copy pathskill_commands.cpp
File metadata and controls
130 lines (113 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "skill_commands.hpp"
#include "skill_activation.hpp"
#include "skill_registry.hpp"
#include "../agent_loop.hpp"
#include "../commands/command_registry.hpp"
#include "../tui_state.hpp"
#include "../utils/logger.hpp"
#include <mutex>
namespace acecode {
namespace {
std::string truncate_description(const std::string& desc, size_t max_len = 80) {
if (desc.size() <= max_len) return desc;
if (max_len <= 3) return desc.substr(0, max_len);
size_t cut = max_len - 3;
// Walk back until we land on a UTF-8 lead byte (not a continuation byte 10xxxxxx).
while (cut > 0 && (static_cast<unsigned char>(desc[cut]) & 0xC0) == 0x80)
--cut;
return desc.substr(0, cut) + "...";
}
} // namespace
std::vector<std::string> register_skill_commands(CommandRegistry& cmd_registry,
SkillRegistry& skill_registry) {
std::vector<std::string> registered;
auto skills = skill_registry.list();
for (const auto& meta : skills) {
const std::string& key = meta.command_key;
if (key.empty()) continue;
if (cmd_registry.has_command(key)) {
LOG_WARN("[skills] command /" + key +
" collides with existing built-in; skill '" + meta.name + "' not registered as slash command");
continue;
}
SlashCommand cmd;
cmd.name = key;
cmd.description = truncate_description(meta.description);
std::string skill_name = meta.name;
cmd.execute = [&skill_registry, skill_name](CommandContext& ctx, const std::string& args) {
auto found = skill_registry.find(skill_name);
if (!found) {
std::lock_guard<std::mutex> lk(ctx.state.mu);
ctx.state.conversation.push_back({"system",
"Skill '" + skill_name + "' is no longer available (registry may have been reloaded).",
false});
ctx.state.chat_follow_tail = true;
return;
}
// Map slash selection to Codex's linked Skill mention. AgentLoop
// resolves that mention and injects the complete SKILL.md through
// the same path used by Web and subagent input.
std::string message = build_skill_invocation_hint(*found, args);
std::string display = "/" + found->command_key;
if (!args.empty()) display += " " + args;
{
std::lock_guard<std::mutex> lk(ctx.state.mu);
ctx.state.conversation.push_back({"system",
"[Invoking skill: " + skill_name + "]", false});
ctx.state.chat_follow_tail = true;
if (ctx.state.is_waiting) {
ctx.state.pending_queue.push_back(message);
return;
}
// 新一轮等待:提前把计时/计数字段重置,否则 on_busy_changed 会因为
// is_waiting 已为 true 跳过它的重置块,thinking_start_time 停在 0
// 会让底部 chip 秒数巨大。
ctx.state.thinking_start_time = std::chrono::steady_clock::now();
ctx.state.streaming_output_chars = 0;
ctx.state.turn_completion_tokens_confirmed = 0;
ctx.state.is_waiting = true;
}
ctx.agent_loop.submit(message, display);
};
cmd_registry.register_command(cmd);
registered.push_back(key);
}
return registered;
}
void unregister_skill_commands(CommandRegistry& cmd_registry,
const std::vector<std::string>& command_keys) {
for (const auto& k : command_keys) {
cmd_registry.unregister_command(k);
}
}
namespace {
std::mutex g_tracked_mu;
std::vector<std::string> g_tracked_keys;
}
std::vector<std::string> register_skill_commands_tracked(CommandRegistry& cmd_registry,
SkillRegistry& skill_registry) {
auto keys = register_skill_commands(cmd_registry, skill_registry);
{
std::lock_guard<std::mutex> lk(g_tracked_mu);
g_tracked_keys = keys;
}
return keys;
}
size_t reload_skill_commands(CommandRegistry& cmd_registry,
SkillRegistry& skill_registry) {
std::vector<std::string> old_keys;
{
std::lock_guard<std::mutex> lk(g_tracked_mu);
old_keys = g_tracked_keys;
g_tracked_keys.clear();
}
unregister_skill_commands(cmd_registry, old_keys);
skill_registry.reload();
auto new_keys = register_skill_commands(cmd_registry, skill_registry);
{
std::lock_guard<std::mutex> lk(g_tracked_mu);
g_tracked_keys = new_keys;
}
return new_keys.size();
}
} // namespace acecode