qlogicagent 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/agent.js +1 -0
  2. package/dist/cli.js +9 -0
  3. package/dist/contracts.js +1 -0
  4. package/dist/index.js +5 -15
  5. package/dist/orchestration.js +118 -0
  6. package/package.json +56 -42
  7. package/dist/agent/agent.js +0 -113
  8. package/dist/agent/tool-loop.js +0 -575
  9. package/dist/agent/types.js +0 -14
  10. package/dist/cli/main.js +0 -23
  11. package/dist/cli/stdio-server.js +0 -463
  12. package/dist/config/config.js +0 -21
  13. package/dist/contracts/hooks.js +0 -7
  14. package/dist/contracts/index.js +0 -10
  15. package/dist/contracts/planner.js +0 -2
  16. package/dist/contracts/skill-candidate.js +0 -195
  17. package/dist/contracts/todo.js +0 -9
  18. package/dist/llm/builtin-providers.js +0 -531
  19. package/dist/llm/index.js +0 -14
  20. package/dist/llm/llm-client.js +0 -67
  21. package/dist/llm/model-catalog.js +0 -191
  22. package/dist/llm/provider-def.js +0 -12
  23. package/dist/llm/provider-registry.js +0 -147
  24. package/dist/llm/transport.js +0 -27
  25. package/dist/llm/transports/anthropic-messages.js +0 -293
  26. package/dist/llm/transports/openai-chat.js +0 -165
  27. package/dist/orchestration/agent-registry.js +0 -116
  28. package/dist/orchestration/approval-aware-tool-plan.js +0 -87
  29. package/dist/orchestration/context-compression.js +0 -583
  30. package/dist/orchestration/conversation-repair.js +0 -429
  31. package/dist/orchestration/curator-scheduler.js +0 -135
  32. package/dist/orchestration/embedded-failover-policy.js +0 -168
  33. package/dist/orchestration/error-classification.js +0 -77
  34. package/dist/orchestration/failover-classification.js +0 -381
  35. package/dist/orchestration/failover-error.js +0 -198
  36. package/dist/orchestration/fork-subagent.js +0 -98
  37. package/dist/orchestration/index.js +0 -267
  38. package/dist/orchestration/memory-flush-policy.js +0 -85
  39. package/dist/orchestration/memory-provider.js +0 -2
  40. package/dist/orchestration/parallel-tool-calls.js +0 -59
  41. package/dist/orchestration/prompt-cache-strategy.js +0 -228
  42. package/dist/orchestration/reactive-compact.js +0 -78
  43. package/dist/orchestration/retry-loop.js +0 -24
  44. package/dist/orchestration/skill-candidate.js +0 -141
  45. package/dist/orchestration/skill-consolidation.js +0 -220
  46. package/dist/orchestration/skill-improvement.js +0 -66
  47. package/dist/orchestration/skill-similarity.js +0 -131
  48. package/dist/orchestration/streaming-tool-executor.js +0 -96
  49. package/dist/orchestration/team-orchestration.js +0 -369
  50. package/dist/orchestration/team-tool-loop-wiring.js +0 -147
  51. package/dist/orchestration/tool-choice-policy.js +0 -164
  52. package/dist/orchestration/tool-loop-state.js +0 -133
  53. package/dist/orchestration/tool-schema.js +0 -297
  54. package/dist/orchestration/transcript-repair.js +0 -426
  55. package/dist/orchestration/turn-loop-guard.js +0 -92
  56. package/dist/orchestration/web-browser-policy.js +0 -39
  57. package/dist/runtime/context-compression.js +0 -274
  58. package/dist/runtime/hook-registry.js +0 -53
  59. package/dist/runtime/memory-hooks.js +0 -65
  60. package/dist/runtime/tool-eligibility.js +0 -111
  61. package/dist/skills/index.js +0 -82
  62. package/dist/skills/memory-extractor.js +0 -173
  63. package/dist/skills/memory-query-tool.js +0 -127
  64. package/dist/skills/memory-store.js +0 -228
  65. package/dist/skills/memory-tool.js +0 -192
  66. package/dist/skills/portable-tool.js +0 -14
  67. package/dist/skills/qmemory-adapter.js +0 -165
  68. package/dist/skills/skill-frontmatter.js +0 -344
  69. package/dist/skills/skill-guard.js +0 -229
  70. package/dist/skills/skill-loader.js +0 -303
  71. package/dist/skills/skill-source.js +0 -126
  72. package/dist/skills/skill-types.js +0 -6
  73. package/dist/skills/think-tool.js +0 -59
  74. package/dist/skills/todo-tool.js +0 -114
  75. package/dist/skills/tools/agent-tool.js +0 -142
  76. package/dist/skills/tools/apply-patch-tool.js +0 -184
  77. package/dist/skills/tools/ask-user-tool.js +0 -121
  78. package/dist/skills/tools/brief-tool.js +0 -95
  79. package/dist/skills/tools/browser-tool.js +0 -155
  80. package/dist/skills/tools/checkpoint-tool.js +0 -102
  81. package/dist/skills/tools/config-tool.js +0 -143
  82. package/dist/skills/tools/cron-tool.js +0 -175
  83. package/dist/skills/tools/edit-tool.js +0 -70
  84. package/dist/skills/tools/exec-tool.js +0 -133
  85. package/dist/skills/tools/image-generate-tool.js +0 -67
  86. package/dist/skills/tools/instructions-tool.js +0 -187
  87. package/dist/skills/tools/lsp-tool.js +0 -227
  88. package/dist/skills/tools/mcp-client-types.js +0 -53
  89. package/dist/skills/tools/mcp-tool.js +0 -503
  90. package/dist/skills/tools/memory-tool.js +0 -88
  91. package/dist/skills/tools/monitor-tool.js +0 -131
  92. package/dist/skills/tools/music-generate-tool.js +0 -62
  93. package/dist/skills/tools/notify-tool.js +0 -62
  94. package/dist/skills/tools/patch-tool.js +0 -505
  95. package/dist/skills/tools/pdf-tool.js +0 -88
  96. package/dist/skills/tools/plan-mode-tool.js +0 -122
  97. package/dist/skills/tools/read-tool.js +0 -84
  98. package/dist/skills/tools/repl-tool.js +0 -69
  99. package/dist/skills/tools/search-tool.js +0 -225
  100. package/dist/skills/tools/send-message-tool.js +0 -76
  101. package/dist/skills/tools/skill-list-tool.js +0 -54
  102. package/dist/skills/tools/skill-manage-tool.js +0 -153
  103. package/dist/skills/tools/skill-view-tool.js +0 -72
  104. package/dist/skills/tools/sleep-tool.js +0 -81
  105. package/dist/skills/tools/structured-output-tool.js +0 -176
  106. package/dist/skills/tools/task-tool.js +0 -161
  107. package/dist/skills/tools/team-tool.js +0 -105
  108. package/dist/skills/tools/tool-search-tool.js +0 -110
  109. package/dist/skills/tools/tts-tool.js +0 -45
  110. package/dist/skills/tools/video-edit-tool.js +0 -74
  111. package/dist/skills/tools/video-generate-tool.js +0 -66
  112. package/dist/skills/tools/video-merge-tool.js +0 -92
  113. package/dist/skills/tools/video-upscale-tool.js +0 -52
  114. package/dist/skills/tools/web-fetch-tool.js +0 -92
  115. package/dist/skills/tools/web-search-tool.js +0 -86
  116. package/dist/skills/tools/worktree-tool.js +0 -147
  117. package/dist/skills/tools/write-tool.js +0 -81
  118. /package/dist/{agent → types/agent}/agent.d.ts +0 -0
  119. /package/dist/{agent → types/agent}/tool-loop.d.ts +0 -0
  120. /package/dist/{agent → types/agent}/types.d.ts +0 -0
  121. /package/dist/{cli → types/cli}/main.d.ts +0 -0
  122. /package/dist/{cli → types/cli}/stdio-server.d.ts +0 -0
  123. /package/dist/{config → types/config}/config.d.ts +0 -0
  124. /package/dist/{contracts → types/contracts}/hooks.d.ts +0 -0
  125. /package/dist/{contracts → types/contracts}/index.d.ts +0 -0
  126. /package/dist/{contracts → types/contracts}/planner.d.ts +0 -0
  127. /package/dist/{contracts → types/contracts}/skill-candidate.d.ts +0 -0
  128. /package/dist/{contracts → types/contracts}/todo.d.ts +0 -0
  129. /package/dist/{index.d.ts → types/index.d.ts} +0 -0
  130. /package/dist/{llm → types/llm}/builtin-providers.d.ts +0 -0
  131. /package/dist/{llm → types/llm}/index.d.ts +0 -0
  132. /package/dist/{llm → types/llm}/llm-client.d.ts +0 -0
  133. /package/dist/{llm → types/llm}/model-catalog.d.ts +0 -0
  134. /package/dist/{llm → types/llm}/provider-def.d.ts +0 -0
  135. /package/dist/{llm → types/llm}/provider-registry.d.ts +0 -0
  136. /package/dist/{llm → types/llm}/transport.d.ts +0 -0
  137. /package/dist/{llm → types/llm}/transports/anthropic-messages.d.ts +0 -0
  138. /package/dist/{llm → types/llm}/transports/openai-chat.d.ts +0 -0
  139. /package/dist/{orchestration → types/orchestration}/agent-registry.d.ts +0 -0
  140. /package/dist/{orchestration → types/orchestration}/approval-aware-tool-plan.d.ts +0 -0
  141. /package/dist/{orchestration → types/orchestration}/context-compression.d.ts +0 -0
  142. /package/dist/{orchestration → types/orchestration}/conversation-repair.d.ts +0 -0
  143. /package/dist/{orchestration → types/orchestration}/curator-scheduler.d.ts +0 -0
  144. /package/dist/{orchestration → types/orchestration}/embedded-failover-policy.d.ts +0 -0
  145. /package/dist/{orchestration → types/orchestration}/error-classification.d.ts +0 -0
  146. /package/dist/{orchestration → types/orchestration}/failover-classification.d.ts +0 -0
  147. /package/dist/{orchestration → types/orchestration}/failover-error.d.ts +0 -0
  148. /package/dist/{orchestration → types/orchestration}/fork-subagent.d.ts +0 -0
  149. /package/dist/{orchestration → types/orchestration}/index.d.ts +0 -0
  150. /package/dist/{orchestration → types/orchestration}/memory-flush-policy.d.ts +0 -0
  151. /package/dist/{orchestration → types/orchestration}/memory-provider.d.ts +0 -0
  152. /package/dist/{orchestration → types/orchestration}/parallel-tool-calls.d.ts +0 -0
  153. /package/dist/{orchestration → types/orchestration}/prompt-cache-strategy.d.ts +0 -0
  154. /package/dist/{orchestration → types/orchestration}/reactive-compact.d.ts +0 -0
  155. /package/dist/{orchestration → types/orchestration}/retry-loop.d.ts +0 -0
  156. /package/dist/{orchestration → types/orchestration}/skill-candidate.d.ts +0 -0
  157. /package/dist/{orchestration → types/orchestration}/skill-consolidation.d.ts +0 -0
  158. /package/dist/{orchestration → types/orchestration}/skill-improvement.d.ts +0 -0
  159. /package/dist/{orchestration → types/orchestration}/skill-similarity.d.ts +0 -0
  160. /package/dist/{orchestration → types/orchestration}/streaming-tool-executor.d.ts +0 -0
  161. /package/dist/{orchestration → types/orchestration}/team-orchestration.d.ts +0 -0
  162. /package/dist/{orchestration → types/orchestration}/team-tool-loop-wiring.d.ts +0 -0
  163. /package/dist/{orchestration → types/orchestration}/tool-choice-policy.d.ts +0 -0
  164. /package/dist/{orchestration → types/orchestration}/tool-loop-state.d.ts +0 -0
  165. /package/dist/{orchestration → types/orchestration}/tool-schema.d.ts +0 -0
  166. /package/dist/{orchestration → types/orchestration}/transcript-repair.d.ts +0 -0
  167. /package/dist/{orchestration → types/orchestration}/turn-loop-guard.d.ts +0 -0
  168. /package/dist/{orchestration → types/orchestration}/web-browser-policy.d.ts +0 -0
  169. /package/dist/{runtime → types/runtime}/context-compression.d.ts +0 -0
  170. /package/dist/{runtime → types/runtime}/hook-registry.d.ts +0 -0
  171. /package/dist/{runtime → types/runtime}/memory-hooks.d.ts +0 -0
  172. /package/dist/{runtime → types/runtime}/tool-eligibility.d.ts +0 -0
  173. /package/dist/{skills → types/skills}/index.d.ts +0 -0
  174. /package/dist/{skills → types/skills}/memory-extractor.d.ts +0 -0
  175. /package/dist/{skills → types/skills}/memory-query-tool.d.ts +0 -0
  176. /package/dist/{skills → types/skills}/memory-store.d.ts +0 -0
  177. /package/dist/{skills → types/skills}/memory-tool.d.ts +0 -0
  178. /package/dist/{skills → types/skills}/portable-tool.d.ts +0 -0
  179. /package/dist/{skills → types/skills}/qmemory-adapter.d.ts +0 -0
  180. /package/dist/{skills → types/skills}/skill-frontmatter.d.ts +0 -0
  181. /package/dist/{skills → types/skills}/skill-guard.d.ts +0 -0
  182. /package/dist/{skills → types/skills}/skill-loader.d.ts +0 -0
  183. /package/dist/{skills → types/skills}/skill-source.d.ts +0 -0
  184. /package/dist/{skills → types/skills}/skill-types.d.ts +0 -0
  185. /package/dist/{skills → types/skills}/think-tool.d.ts +0 -0
  186. /package/dist/{skills → types/skills}/todo-tool.d.ts +0 -0
  187. /package/dist/{skills → types/skills}/tools/agent-tool.d.ts +0 -0
  188. /package/dist/{skills → types/skills}/tools/apply-patch-tool.d.ts +0 -0
  189. /package/dist/{skills → types/skills}/tools/ask-user-tool.d.ts +0 -0
  190. /package/dist/{skills → types/skills}/tools/brief-tool.d.ts +0 -0
  191. /package/dist/{skills → types/skills}/tools/browser-tool.d.ts +0 -0
  192. /package/dist/{skills → types/skills}/tools/checkpoint-tool.d.ts +0 -0
  193. /package/dist/{skills → types/skills}/tools/config-tool.d.ts +0 -0
  194. /package/dist/{skills → types/skills}/tools/cron-tool.d.ts +0 -0
  195. /package/dist/{skills → types/skills}/tools/edit-tool.d.ts +0 -0
  196. /package/dist/{skills → types/skills}/tools/exec-tool.d.ts +0 -0
  197. /package/dist/{skills → types/skills}/tools/image-generate-tool.d.ts +0 -0
  198. /package/dist/{skills → types/skills}/tools/instructions-tool.d.ts +0 -0
  199. /package/dist/{skills → types/skills}/tools/lsp-tool.d.ts +0 -0
  200. /package/dist/{skills → types/skills}/tools/mcp-client-types.d.ts +0 -0
  201. /package/dist/{skills → types/skills}/tools/mcp-tool.d.ts +0 -0
  202. /package/dist/{skills → types/skills}/tools/memory-tool.d.ts +0 -0
  203. /package/dist/{skills → types/skills}/tools/monitor-tool.d.ts +0 -0
  204. /package/dist/{skills → types/skills}/tools/music-generate-tool.d.ts +0 -0
  205. /package/dist/{skills → types/skills}/tools/notify-tool.d.ts +0 -0
  206. /package/dist/{skills → types/skills}/tools/patch-tool.d.ts +0 -0
  207. /package/dist/{skills → types/skills}/tools/pdf-tool.d.ts +0 -0
  208. /package/dist/{skills → types/skills}/tools/plan-mode-tool.d.ts +0 -0
  209. /package/dist/{skills → types/skills}/tools/read-tool.d.ts +0 -0
  210. /package/dist/{skills → types/skills}/tools/repl-tool.d.ts +0 -0
  211. /package/dist/{skills → types/skills}/tools/search-tool.d.ts +0 -0
  212. /package/dist/{skills → types/skills}/tools/send-message-tool.d.ts +0 -0
  213. /package/dist/{skills → types/skills}/tools/skill-list-tool.d.ts +0 -0
  214. /package/dist/{skills → types/skills}/tools/skill-manage-tool.d.ts +0 -0
  215. /package/dist/{skills → types/skills}/tools/skill-view-tool.d.ts +0 -0
  216. /package/dist/{skills → types/skills}/tools/sleep-tool.d.ts +0 -0
  217. /package/dist/{skills → types/skills}/tools/structured-output-tool.d.ts +0 -0
  218. /package/dist/{skills → types/skills}/tools/task-tool.d.ts +0 -0
  219. /package/dist/{skills → types/skills}/tools/team-tool.d.ts +0 -0
  220. /package/dist/{skills → types/skills}/tools/tool-search-tool.d.ts +0 -0
  221. /package/dist/{skills → types/skills}/tools/tts-tool.d.ts +0 -0
  222. /package/dist/{skills → types/skills}/tools/video-edit-tool.d.ts +0 -0
  223. /package/dist/{skills → types/skills}/tools/video-generate-tool.d.ts +0 -0
  224. /package/dist/{skills → types/skills}/tools/video-merge-tool.d.ts +0 -0
  225. /package/dist/{skills → types/skills}/tools/video-upscale-tool.d.ts +0 -0
  226. /package/dist/{skills → types/skills}/tools/web-fetch-tool.d.ts +0 -0
  227. /package/dist/{skills → types/skills}/tools/web-search-tool.d.ts +0 -0
  228. /package/dist/{skills → types/skills}/tools/worktree-tool.d.ts +0 -0
  229. /package/dist/{skills → types/skills}/tools/write-tool.d.ts +0 -0
@@ -1,303 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Skill discovery & loading — portable, DI-based.
3
- // Mirrors openclaw/src/agents/skills/workspace.ts logic but decoupled from
4
- // Node.js fs/path via SkillLoaderDeps.
5
- // ---------------------------------------------------------------------------
6
- import { parseFrontmatter, resolveSkillMetadata, resolveSkillInvocationPolicy } from "./skill-frontmatter.js";
7
- // ---------------------------------------------------------------------------
8
- // Default limits (match openclaw upstream)
9
- // ---------------------------------------------------------------------------
10
- const DEFAULT_LIMITS = {
11
- maxCandidatesPerRoot: 300,
12
- maxSkillsLoadedPerSource: 200,
13
- maxSkillsInPrompt: 150,
14
- maxSkillsPromptChars: 30_000,
15
- maxSkillFileBytes: 256_000,
16
- };
17
- function resolveLimits(input) {
18
- return {
19
- maxCandidatesPerRoot: input?.maxCandidatesPerRoot ?? DEFAULT_LIMITS.maxCandidatesPerRoot,
20
- maxSkillsLoadedPerSource: input?.maxSkillsLoadedPerSource ?? DEFAULT_LIMITS.maxSkillsLoadedPerSource,
21
- maxSkillsInPrompt: input?.maxSkillsInPrompt ?? DEFAULT_LIMITS.maxSkillsInPrompt,
22
- maxSkillsPromptChars: input?.maxSkillsPromptChars ?? DEFAULT_LIMITS.maxSkillsPromptChars,
23
- maxSkillFileBytes: input?.maxSkillFileBytes ?? DEFAULT_LIMITS.maxSkillFileBytes,
24
- };
25
- }
26
- // ---------------------------------------------------------------------------
27
- // Path containment guard
28
- // ---------------------------------------------------------------------------
29
- function isPathInside(parentRealPath, childRealPath, sep) {
30
- const normalizedParent = parentRealPath.endsWith(sep) ? parentRealPath : parentRealPath + sep;
31
- return childRealPath === parentRealPath || childRealPath.startsWith(normalizedParent);
32
- }
33
- function resolveContainedPath(deps, rootRealPath, candidatePath) {
34
- try {
35
- const real = deps.fs.realpathSync(candidatePath);
36
- return isPathInside(rootRealPath, real, deps.path.sep) ? real : null;
37
- }
38
- catch {
39
- return null;
40
- }
41
- }
42
- // ---------------------------------------------------------------------------
43
- // Directory listing helpers
44
- // ---------------------------------------------------------------------------
45
- function listChildDirectories(deps, dir) {
46
- try {
47
- const entries = deps.fs.readdirSync(dir, { withFileTypes: true });
48
- const dirs = [];
49
- for (const entry of entries) {
50
- if (entry.name.startsWith(".") || entry.name === "node_modules")
51
- continue;
52
- if (entry.isDirectory()) {
53
- dirs.push(entry.name);
54
- continue;
55
- }
56
- if (entry.isSymbolicLink()) {
57
- try {
58
- const fullPath = deps.path.join(dir, entry.name);
59
- if (deps.fs.statSync(fullPath).isDirectory()) {
60
- dirs.push(entry.name);
61
- }
62
- }
63
- catch {
64
- // broken symlink — skip
65
- }
66
- }
67
- }
68
- return dirs;
69
- }
70
- catch {
71
- return [];
72
- }
73
- }
74
- /**
75
- * Detect nested `skills/` subfolder. If `dir/skills/<x>/SKILL.md` exists,
76
- * treat `dir/skills/` as the real root.
77
- */
78
- function resolveNestedSkillsRoot(deps, dir, maxEntriesToScan) {
79
- const nested = deps.path.join(dir, "skills");
80
- try {
81
- if (!deps.fs.existsSync(nested) || !deps.fs.statSync(nested).isDirectory()) {
82
- return dir;
83
- }
84
- }
85
- catch {
86
- return dir;
87
- }
88
- const nestedDirs = listChildDirectories(deps, nested);
89
- const toScan = nestedDirs.slice(0, Math.min(nestedDirs.length, maxEntriesToScan));
90
- for (const name of toScan) {
91
- const skillMd = deps.path.join(nested, name, "SKILL.md");
92
- if (deps.fs.existsSync(skillMd)) {
93
- return nested;
94
- }
95
- }
96
- return dir;
97
- }
98
- // ---------------------------------------------------------------------------
99
- // Single-source skill loading
100
- // ---------------------------------------------------------------------------
101
- function loadSkillsFromSourceDir(deps, dir, source, limits) {
102
- const rootDir = deps.path.resolve(dir);
103
- let rootRealPath;
104
- try {
105
- rootRealPath = deps.fs.realpathSync(rootDir);
106
- }
107
- catch {
108
- return [];
109
- }
110
- const baseDir = resolveNestedSkillsRoot(deps, rootDir, limits.maxCandidatesPerRoot);
111
- const baseDirRealPath = resolveContainedPath(deps, rootRealPath, baseDir);
112
- if (!baseDirRealPath)
113
- return [];
114
- // Case 1: root itself is a single skill
115
- const rootSkillMd = deps.path.join(baseDir, "SKILL.md");
116
- if (deps.fs.existsSync(rootSkillMd)) {
117
- if (!resolveContainedPath(deps, baseDirRealPath, rootSkillMd))
118
- return [];
119
- try {
120
- const size = deps.fs.statSync(rootSkillMd).size;
121
- if (size > limits.maxSkillFileBytes)
122
- return [];
123
- }
124
- catch {
125
- return [];
126
- }
127
- return [buildWorkspaceSkill(deps, rootSkillMd, baseDir, source)].filter((s) => s !== null);
128
- }
129
- // Case 2: enumerate child directories for `<child>/SKILL.md`
130
- const childDirs = listChildDirectories(deps, baseDir);
131
- const maxCandidates = Math.max(0, limits.maxSkillsLoadedPerSource);
132
- const limitedChildren = childDirs.slice().sort().slice(0, maxCandidates);
133
- const skills = [];
134
- for (const name of limitedChildren) {
135
- const skillDir = deps.path.join(baseDir, name);
136
- if (!resolveContainedPath(deps, baseDirRealPath, skillDir))
137
- continue;
138
- const skillMd = deps.path.join(skillDir, "SKILL.md");
139
- if (!deps.fs.existsSync(skillMd))
140
- continue;
141
- if (!resolveContainedPath(deps, baseDirRealPath, skillMd))
142
- continue;
143
- try {
144
- const size = deps.fs.statSync(skillMd).size;
145
- if (size > limits.maxSkillFileBytes)
146
- continue;
147
- }
148
- catch {
149
- continue;
150
- }
151
- const skill = buildWorkspaceSkill(deps, skillMd, skillDir, source);
152
- if (skill)
153
- skills.push(skill);
154
- if (skills.length >= limits.maxSkillsLoadedPerSource)
155
- break;
156
- }
157
- return skills;
158
- }
159
- function buildWorkspaceSkill(deps, filePath, baseDir, source) {
160
- try {
161
- const content = deps.fs.readFileSync(filePath, "utf-8");
162
- const fm = parseFrontmatter(content);
163
- const name = fm["name"] ?? deps.path.resolve(baseDir).split(deps.path.sep).pop() ?? "unknown";
164
- return {
165
- name,
166
- description: fm["description"],
167
- source,
168
- filePath: deps.path.resolve(filePath),
169
- baseDir: deps.path.resolve(baseDir),
170
- primaryEnv: fm["primaryEnv"] ?? fm["primary-env"],
171
- requiredEnv: fm["required-env"]?.split(",").map((s) => s.trim()).filter(Boolean),
172
- };
173
- }
174
- catch {
175
- return null;
176
- }
177
- }
178
- // ---------------------------------------------------------------------------
179
- // Public API
180
- // ---------------------------------------------------------------------------
181
- /**
182
- * Discover all skills from configured search paths, applying precedence merge
183
- * and size/count limits. Returns fully parsed `SkillEntry` objects.
184
- */
185
- export function loadSkillEntries(deps) {
186
- const limits = resolveLimits(deps.limits);
187
- const { searchPaths } = deps;
188
- const sources = [];
189
- // Order: extra < bundled < managed < personalAgents < projectAgents < workspace
190
- if (searchPaths.extra) {
191
- for (const dir of searchPaths.extra) {
192
- sources.push({ dir, source: "extra" });
193
- }
194
- }
195
- if (searchPaths.bundled) {
196
- sources.push({ dir: searchPaths.bundled, source: "bundled" });
197
- }
198
- if (searchPaths.managed) {
199
- sources.push({ dir: searchPaths.managed, source: "managed" });
200
- }
201
- if (searchPaths.personalAgents) {
202
- sources.push({ dir: searchPaths.personalAgents, source: "agents-personal" });
203
- }
204
- if (searchPaths.projectAgents) {
205
- sources.push({ dir: searchPaths.projectAgents, source: "agents-project" });
206
- }
207
- if (searchPaths.workspace) {
208
- sources.push({ dir: searchPaths.workspace, source: "workspace" });
209
- }
210
- // Merge with later sources overriding earlier ones (by name)
211
- const merged = new Map();
212
- for (const src of sources) {
213
- const skills = loadSkillsFromSourceDir(deps, src.dir, src.source, limits);
214
- for (const skill of skills) {
215
- merged.set(skill.name, skill);
216
- }
217
- }
218
- // Build entries with parsed metadata
219
- const entries = [];
220
- for (const skill of merged.values()) {
221
- let frontmatter = parseFrontmatter("");
222
- try {
223
- const raw = deps.fs.readFileSync(skill.filePath, "utf-8");
224
- frontmatter = parseFrontmatter(raw);
225
- }
226
- catch {
227
- // ignore malformed
228
- }
229
- entries.push({
230
- skill,
231
- frontmatter,
232
- metadata: resolveSkillMetadata(frontmatter),
233
- invocation: resolveSkillInvocationPolicy(frontmatter),
234
- });
235
- }
236
- return entries;
237
- }
238
- /**
239
- * Filter skill entries by a name-based filter list.
240
- * If filter is undefined or empty, returns all entries.
241
- */
242
- export function filterSkillEntries(entries, skillFilter) {
243
- if (!skillFilter || skillFilter.length === 0)
244
- return entries;
245
- const normalized = new Set(skillFilter.map((s) => s.trim().toLowerCase()).filter(Boolean));
246
- if (normalized.size === 0)
247
- return [];
248
- return entries.filter((e) => normalized.has(e.skill.name.toLowerCase()));
249
- }
250
- /**
251
- * Build a system-prompt-embeddable skill snapshot.
252
- * Applies count and character limits from the provided config.
253
- */
254
- export function buildSkillSnapshot(entries, limits, skillFilter) {
255
- const resolved = resolveLimits(limits);
256
- const filtered = filterSkillEntries(entries, skillFilter);
257
- // Truncate by count first
258
- let promptSkills = filtered.slice(0, Math.max(0, resolved.maxSkillsInPrompt));
259
- // Format function for prompt
260
- const formatForPrompt = (skills) => {
261
- if (skills.length === 0)
262
- return "";
263
- const lines = [];
264
- for (const entry of skills) {
265
- const s = entry.skill;
266
- const meta = entry.metadata;
267
- const desc = s.description ? ` — ${s.description}` : "";
268
- const env = s.primaryEnv ? ` [${s.primaryEnv}]` : "";
269
- const emoji = meta?.emoji ? `${meta.emoji} ` : "";
270
- lines.push(`- ${emoji}**${s.name}**${env}${desc}`);
271
- // Compact path with ~ prefix
272
- lines.push(` File: ${s.filePath}`);
273
- }
274
- return lines.join("\n");
275
- };
276
- // Truncate by character budget via binary search
277
- let prompt = formatForPrompt(promptSkills);
278
- if (prompt.length > resolved.maxSkillsPromptChars) {
279
- let lo = 0;
280
- let hi = promptSkills.length;
281
- while (lo < hi) {
282
- const mid = Math.ceil((lo + hi) / 2);
283
- const candidate = formatForPrompt(promptSkills.slice(0, mid));
284
- if (candidate.length <= resolved.maxSkillsPromptChars) {
285
- lo = mid;
286
- }
287
- else {
288
- hi = mid - 1;
289
- }
290
- }
291
- promptSkills = promptSkills.slice(0, lo);
292
- prompt = formatForPrompt(promptSkills);
293
- }
294
- return {
295
- prompt,
296
- skills: promptSkills.map((e) => ({
297
- name: e.skill.name,
298
- primaryEnv: e.skill.primaryEnv,
299
- requiredEnv: e.skill.requiredEnv,
300
- })),
301
- skillFilter,
302
- };
303
- }
@@ -1,126 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Skill source abstraction — defines where skills come from and how they
3
- // are fetched/installed. Consumers implement specific source adapters.
4
- // ---------------------------------------------------------------------------
5
- /**
6
- * Orchestrate the full install pipeline:
7
- * Fetch → Quarantine → Scan → Validate → Move → Lock
8
- *
9
- * This function is pure orchestration — actual I/O is delegated to deps.
10
- */
11
- export async function installSkill(params) {
12
- const { source, fetchDeps, storageDeps, scanSkillDir, quarantineDir } = params;
13
- // Step 1: Fetch to quarantine
14
- let fetchResult;
15
- try {
16
- fetchResult = await fetchDeps.fetch(source, quarantineDir);
17
- }
18
- catch (err) {
19
- return {
20
- success: false,
21
- name: source.identifier,
22
- verdict: "reject",
23
- error: `Fetch failed: ${err instanceof Error ? err.message : String(err)}`,
24
- };
25
- }
26
- const skillName = fetchResult.name ?? source.identifier.split("/").pop() ?? "unknown";
27
- // Step 2: Security scan
28
- let scanSummary;
29
- try {
30
- scanSummary = await scanSkillDir(fetchResult.quarantineDir);
31
- }
32
- catch (err) {
33
- return {
34
- success: false,
35
- name: skillName,
36
- verdict: "reject",
37
- error: `Scan failed: ${err instanceof Error ? err.message : String(err)}`,
38
- };
39
- }
40
- // Step 3: Verdict
41
- let verdict;
42
- if (scanSummary.critical > 0) {
43
- verdict = source.trust === "builtin" ? "quarantine" : "reject";
44
- }
45
- else if (scanSummary.warn > 0) {
46
- verdict = "quarantine";
47
- }
48
- else {
49
- verdict = "pass";
50
- }
51
- if (verdict === "reject") {
52
- return {
53
- success: false,
54
- name: skillName,
55
- verdict,
56
- scanSummary,
57
- error: `Security scan rejected: ${scanSummary.critical} critical finding(s)`,
58
- };
59
- }
60
- // Step 4: Move to install location
61
- let installDir;
62
- try {
63
- installDir = await storageDeps.moveToInstallDir(fetchResult.quarantineDir, skillName);
64
- }
65
- catch (err) {
66
- return {
67
- success: false,
68
- name: skillName,
69
- verdict,
70
- scanSummary,
71
- error: `Install move failed: ${err instanceof Error ? err.message : String(err)}`,
72
- };
73
- }
74
- // Step 5: Update lockfile
75
- try {
76
- const lockfile = await storageDeps.readLockfile();
77
- lockfile.entries[skillName] = {
78
- name: skillName,
79
- source,
80
- installedAt: new Date().toISOString(),
81
- scanVerdict: verdict,
82
- scanSummary,
83
- };
84
- await storageDeps.writeLockfile(lockfile);
85
- }
86
- catch {
87
- // Non-fatal: skill is installed but lock may be stale
88
- }
89
- return {
90
- success: true,
91
- name: skillName,
92
- installDir,
93
- verdict,
94
- scanSummary,
95
- };
96
- }
97
- /**
98
- * Uninstall a skill: remove from disk + update lockfile.
99
- */
100
- export async function uninstallSkill(params) {
101
- const { skillName, storageDeps } = params;
102
- try {
103
- await storageDeps.removeSkill(skillName);
104
- }
105
- catch (err) {
106
- return {
107
- success: false,
108
- error: `Remove failed: ${err instanceof Error ? err.message : String(err)}`,
109
- };
110
- }
111
- try {
112
- const lockfile = await storageDeps.readLockfile();
113
- delete lockfile.entries[skillName];
114
- await storageDeps.writeLockfile(lockfile);
115
- }
116
- catch {
117
- // Non-fatal
118
- }
119
- return { success: true };
120
- }
121
- /**
122
- * Create an empty lockfile.
123
- */
124
- export function createEmptyLockfile() {
125
- return { version: 1, entries: {} };
126
- }
@@ -1,6 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Skill system type definitions — portable, runtime-agnostic.
3
- // Mirrors openclaw/src/agents/skills/types.ts + security/skill-scanner.ts
4
- // but decoupled from framework internals.
5
- // ---------------------------------------------------------------------------
6
- export {};
@@ -1,59 +0,0 @@
1
- // ============================================================
2
- // Think Tool — explicit reasoning before complex decisions.
3
- //
4
- // The Agent calls `think` to reason step-by-step before deciding
5
- // which tools to use. The thought is never shown to the user.
6
- // Pure no-op: zero side effects, zero dependencies.
7
- // ============================================================
8
- export const THINK_TOOL_NAME = "think";
9
- export const THINK_TOOL_SCHEMA = {
10
- type: "object",
11
- properties: {
12
- thought: {
13
- type: "string",
14
- description: [
15
- "Your internal reasoning about the current situation.",
16
- "Use this to:",
17
- "• Analyze what the user really wants (disambiguate vague requests)",
18
- "• Plan multi-step approaches before executing",
19
- "• Evaluate which tool(s) to use and why",
20
- "• Consider edge cases or potential issues",
21
- "• Reflect on conversation context and user preferences",
22
- "This content is never shown to the user.",
23
- ].join("\n"),
24
- },
25
- },
26
- required: ["thought"],
27
- };
28
- export function createThinkTool() {
29
- return {
30
- name: THINK_TOOL_NAME,
31
- label: "Think",
32
- shouldDefer: true,
33
- description: [
34
- "Use this tool to think and reason about the current situation BEFORE taking action.",
35
- "Call this tool when you need to:",
36
- "- Analyze an ambiguous or complex user request before deciding what to do",
37
- "- Plan a multi-step approach (what tools to call and in what order)",
38
- "- Identify which steps can run in parallel vs. which must be sequential",
39
- "- Evaluate tradeoffs between different approaches",
40
- "- Reflect on user preferences from conversation history",
41
- "- Process new information that changes your understanding",
42
- "",
43
- "This tool has NO side effects — it simply records your reasoning process.",
44
- "Your thought is NOT shown to the user; it only improves YOUR decision quality.",
45
- "After thinking, proceed to take the appropriate action.",
46
- "",
47
- "When planning multi-step work, be explicit about parallelism:",
48
- '- Say "这些可以并行生成" or "these can run in parallel" for independent tasks.',
49
- '- Say "先…然后…" or "step 1 first, then step 2" for sequential dependencies.',
50
- ].join("\n"),
51
- parameters: THINK_TOOL_SCHEMA,
52
- execute: async (_toolCallId, _params) => {
53
- return {
54
- content: [{ type: "text", text: "Thought recorded. Now proceed with the best action based on your reasoning." }],
55
- details: { type: "think" },
56
- };
57
- },
58
- };
59
- }
@@ -1,114 +0,0 @@
1
- // ============================================================
2
- // Todo Tool — session-level structured task management.
3
- //
4
- // Allows the agent to create, update, and track multi-step task
5
- // lists during complex conversations. Each tool invocation
6
- // replaces the full todo list (same pattern as Copilot's
7
- // manage_todo_list).
8
- //
9
- // Aligned with Claude Code TodoWriteTool:
10
- // - activeForm field (present-tense text for UI spinners)
11
- // - oldTodos snapshot returned for diffing
12
- // - Auto-clear when all items completed
13
- // - verificationNudgeNeeded signal
14
- // - Per-agent isolation via agentId option
15
- //
16
- // Reference: claude-code-haha/src/tools/TodoWriteTool/TodoWriteTool.ts
17
- // ============================================================
18
- import { summarizeTodoList } from "../contracts/todo.js";
19
- export const TODO_TOOL_NAME = "todo";
20
- export const TODO_TOOL_SCHEMA = {
21
- type: "object",
22
- properties: {
23
- todoList: {
24
- type: "array",
25
- description: "Complete array of ALL todo items. Must include both existing and new items. " +
26
- "Only one item may be in-progress at a time. Mark todos completed " +
27
- "IMMEDIATELY after finishing — do not batch completions.",
28
- items: {
29
- type: "object",
30
- properties: {
31
- id: { type: "number", description: "Unique numeric id (sequential from 1)." },
32
- title: { type: "string", description: "Concise action-oriented label (3-7 words). Displayed in UI." },
33
- status: {
34
- type: "string",
35
- enum: ["not-started", "in-progress", "completed"],
36
- description: "not-started | in-progress (max 1) | completed",
37
- },
38
- },
39
- required: ["id", "title", "status"],
40
- },
41
- },
42
- },
43
- required: ["todoList"],
44
- };
45
- /**
46
- * Create a stateful todo tool instance.
47
- *
48
- * Each call returns a tool with its own session-local list.
49
- * Multiple instances can exist for different sessions/agents.
50
- */
51
- export function createTodoTool(options) {
52
- let currentList = [];
53
- const opts = options ?? {};
54
- return {
55
- name: TODO_TOOL_NAME,
56
- label: "Todo",
57
- description: "Manage a structured todo list to track progress on multi-step tasks. " +
58
- "Each call replaces the full list. Use frequently during complex work " +
59
- "to plan steps and show progress. Mark items in-progress before starting, " +
60
- "completed immediately after finishing.",
61
- parameters: TODO_TOOL_SCHEMA,
62
- searchHint: "manage session task checklist progress tracking",
63
- maxResultSizeChars: 100_000,
64
- execute: async (_toolCallId, params) => {
65
- const items = params.todoList;
66
- // Validate: at most 1 in-progress
67
- const inProgress = items.filter((t) => t.status === "in-progress");
68
- if (inProgress.length > 1) {
69
- return {
70
- content: [{ type: "text", text: JSON.stringify({
71
- warning: `Only 1 item may be in-progress at a time (found ${inProgress.length}).`,
72
- todoList: currentList,
73
- }) }],
74
- details: { type: "todo", warning: "multiple_in_progress" },
75
- };
76
- }
77
- // Capture old state for diff (CC-aligned: returns oldTodos)
78
- const oldTodos = [...currentList];
79
- // Check if all items are completed
80
- const allDone = items.length > 0 && items.every((t) => t.status === "completed");
81
- // Auto-clear when all completed (CC behavior)
82
- if (allDone && opts.autoClearOnComplete) {
83
- currentList = [];
84
- }
85
- else {
86
- currentList = items;
87
- }
88
- const summary = summarizeTodoList(items);
89
- // Verification nudge: ≥3 items, all done, none matching /verif/i
90
- let verificationNudgeNeeded = false;
91
- if (opts.enableVerificationNudge &&
92
- allDone &&
93
- items.length >= 3 &&
94
- !items.some((t) => /verif/i.test(t.title))) {
95
- verificationNudgeNeeded = true;
96
- }
97
- const result = {
98
- total: summary.total,
99
- completed: summary.completed,
100
- inProgress: summary.inProgress,
101
- notStarted: summary.notStarted,
102
- todoList: currentList,
103
- oldTodos,
104
- };
105
- if (verificationNudgeNeeded) {
106
- result.verificationNudgeNeeded = true;
107
- }
108
- return {
109
- content: [{ type: "text", text: JSON.stringify(result) }],
110
- details: { type: "todo", ...summary, verificationNudgeNeeded, agentId: opts.agentId },
111
- };
112
- },
113
- };
114
- }