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,122 +0,0 @@
1
- // ============================================================
2
- // Plan Mode Tool — enter/exit plan mode for safer exploration.
3
- // Reference: claude-code-haha/src/tools/EnterPlanModeTool/EnterPlanModeTool.ts
4
- // claude-code-haha/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts
5
- // Category: system (mode switch)
6
- // ============================================================
7
- export const PLAN_MODE_TOOL_NAME = "plan_mode";
8
- export const PLAN_MODE_TOOL_SCHEMA = {
9
- type: "object",
10
- properties: {
11
- action: {
12
- type: "string",
13
- enum: ["enter", "exit"],
14
- description: "enter: Switch to plan mode (only read/search/think tools available).\n" +
15
- "exit: Leave plan mode and submit plan for approval (restores full tool access).",
16
- },
17
- plan: {
18
- type: "string",
19
- description: "The finalized plan text to present for user approval (used with 'exit' action). " +
20
- "Write a clear, structured plan of what will be done.",
21
- },
22
- planFilePath: {
23
- type: "string",
24
- description: "Optional file path where the plan was saved for reference.",
25
- },
26
- },
27
- required: ["action"],
28
- };
29
- /** Tools allowed during plan mode (read-only + reasoning) */
30
- export const PLAN_MODE_ALLOWED_TOOLS = [
31
- "read",
32
- "search",
33
- "think",
34
- "lsp",
35
- "web_search",
36
- "web_fetch",
37
- "memory_query",
38
- "memory_search",
39
- "skill_list",
40
- "skill_view",
41
- "tool_search",
42
- "plan_mode",
43
- ];
44
- export function createPlanModeTool(deps) {
45
- return {
46
- name: PLAN_MODE_TOOL_NAME,
47
- label: "Plan Mode",
48
- description: "Switch between plan mode and execution mode. In plan mode, only " +
49
- "read-only tools (read, search, think, lsp) are available — no file writes or commands. " +
50
- "Use plan mode to safely explore a problem before committing to changes. " +
51
- "Exit plan mode with a finalized plan for user approval.",
52
- parameters: PLAN_MODE_TOOL_SCHEMA,
53
- execute: async (_toolCallId, params) => {
54
- // Plan mode not allowed in sub-agent context
55
- if (deps.isAgentContext?.()) {
56
- return {
57
- content: [{ type: "text", text: "Error: plan mode is not available in sub-agent context." }],
58
- details: { type: "plan_mode", error: "agent_context" },
59
- };
60
- }
61
- switch (params.action) {
62
- case "enter": {
63
- const state = deps.getState();
64
- if (state.active) {
65
- return {
66
- content: [{ type: "text", text: "Already in plan mode. Use action='exit' with a plan to leave." }],
67
- details: { type: "plan_mode", error: "already_active" },
68
- };
69
- }
70
- const result = await deps.enterPlanMode();
71
- if (!result.success) {
72
- return {
73
- content: [{ type: "text", text: `Error: ${result.error || "failed to enter plan mode"}` }],
74
- details: { type: "plan_mode", error: result.error },
75
- };
76
- }
77
- const lines = [
78
- "Entered plan mode.",
79
- "",
80
- "Available tools: " + PLAN_MODE_ALLOWED_TOOLS.join(", "),
81
- "",
82
- "All write/execute tools are disabled. Explore the problem, then exit with a plan.",
83
- 'Use action="exit" with a plan parameter when ready.',
84
- ];
85
- return {
86
- content: [{ type: "text", text: lines.join("\n") }],
87
- details: { type: "plan_mode", action: "enter", allowedTools: PLAN_MODE_ALLOWED_TOOLS },
88
- };
89
- }
90
- case "exit": {
91
- const state = deps.getState();
92
- if (!state.active) {
93
- return {
94
- content: [{ type: "text", text: "Not in plan mode. Nothing to exit." }],
95
- details: { type: "plan_mode", error: "not_active" },
96
- };
97
- }
98
- const result = await deps.exitPlanMode(params.plan, params.planFilePath);
99
- if (!result.success) {
100
- return {
101
- content: [{ type: "text", text: `Error: ${result.error || "failed to exit plan mode"}` }],
102
- details: { type: "plan_mode", error: result.error },
103
- };
104
- }
105
- const lines = ["Exited plan mode. Full tool access restored."];
106
- if (params.plan) {
107
- lines.push("", "Submitted plan for approval:", "", params.plan);
108
- }
109
- return {
110
- content: [{ type: "text", text: lines.join("\n") }],
111
- details: { type: "plan_mode", action: "exit", hasPlan: !!params.plan },
112
- };
113
- }
114
- default:
115
- return {
116
- content: [{ type: "text", text: `Error: unknown action "${params.action}". Use "enter" or "exit".` }],
117
- details: { type: "plan_mode", error: "unknown_action" },
118
- };
119
- }
120
- },
121
- };
122
- }
@@ -1,84 +0,0 @@
1
- // ============================================================
2
- // File Read Tool — read file contents with offset/limit.
3
- // Reference: claude-code-haha/src/tools/FileReadTool/FileReadTool.ts
4
- // Category: coding
5
- // ============================================================
6
- export const READ_TOOL_NAME = "read";
7
- export const READ_TOOL_SCHEMA = {
8
- type: "object",
9
- properties: {
10
- path: {
11
- type: "string",
12
- description: "Absolute path to the file to read.",
13
- },
14
- offset: {
15
- type: "number",
16
- description: "Line number to start reading from (1-indexed). Default: 1.",
17
- },
18
- limit: {
19
- type: "number",
20
- description: "Maximum number of lines to read. Default/max: 2000.",
21
- },
22
- },
23
- required: ["path"],
24
- };
25
- export function createReadTool(deps) {
26
- const MAX_LINES = 2000;
27
- const MAX_BYTES = 50_000;
28
- return {
29
- name: READ_TOOL_NAME,
30
- label: "Read File",
31
- description: "Read the contents of a file. Supports text files and images (jpg, png, gif, webp). " +
32
- "For text files, output is truncated to 2000 lines or 50KB. " +
33
- "Binary files are rejected with a hint. " +
34
- "Use offset/limit for pagination of large files.",
35
- parameters: READ_TOOL_SCHEMA,
36
- execute: async (_toolCallId, params) => {
37
- const resolved = deps.resolvePath(params.path);
38
- // Validate path access
39
- if (deps.validatePath) {
40
- const blocked = deps.validatePath(resolved);
41
- if (blocked) {
42
- return {
43
- content: [{ type: "text", text: `Access denied: ${blocked}` }],
44
- details: { type: "read", path: resolved, error: "access_denied" },
45
- };
46
- }
47
- }
48
- const result = await deps.readFile(resolved);
49
- // Image
50
- if (result.type === "image") {
51
- return {
52
- content: [{ type: "image", data: result.base64, mimeType: result.mimeType }],
53
- details: { type: "read", path: resolved, isImage: true },
54
- };
55
- }
56
- // Binary rejection
57
- if (result.type === "binary") {
58
- return {
59
- content: [{
60
- type: "text",
61
- text: `Cannot read binary file (${result.mimeType}). ` +
62
- "Use a specific tool for this file type (e.g. pdf tool for PDFs).",
63
- }],
64
- details: { type: "read", path: resolved, error: "binary_file", mimeType: result.mimeType },
65
- };
66
- }
67
- // Text file
68
- const lines = result.text.split("\n");
69
- const offset = Math.max(0, (params.offset ?? 1) - 1);
70
- const limit = Math.min(params.limit ?? MAX_LINES, MAX_LINES);
71
- const sliced = lines.slice(offset, offset + limit);
72
- let text = sliced.join("\n");
73
- if (text.length > MAX_BYTES)
74
- text = text.slice(0, MAX_BYTES) + "\n... (truncated)";
75
- const totalLines = lines.length;
76
- const endLine = offset + sliced.length;
77
- const hasMore = endLine < totalLines;
78
- return {
79
- content: [{ type: "text", text }],
80
- details: { type: "read", path: resolved, totalLines, startLine: offset + 1, endLine, hasMore },
81
- };
82
- },
83
- };
84
- }
@@ -1,69 +0,0 @@
1
- // ============================================================
2
- // REPL Tool — execute JavaScript in a persistent VM context
3
- // with injected tool primitives for batch operations.
4
- // Reference: claude-code-haha/src/tools/REPLTool/primitiveTools.ts
5
- // Category: system
6
- // ============================================================
7
- export const REPL_TOOL_NAME = "repl";
8
- export const REPL_TOOL_SCHEMA = {
9
- type: "object",
10
- properties: {
11
- code: {
12
- type: "string",
13
- description: "JavaScript code to execute. The VM has access to these built-in primitives:\n" +
14
- "- readFile(path): Promise<string> — read a file\n" +
15
- "- writeFile(path, content): Promise<void> — write a file\n" +
16
- "- editFile(path, edits): Promise<string> — apply edits [{oldText, newText}]\n" +
17
- "- exec(command): Promise<{stdout, stderr, exitCode}> — run shell command\n" +
18
- "- glob(pattern): Promise<string[]> — find files by glob\n" +
19
- "- grep(pattern, path?): Promise<{file,line,text}[]> — search files\n" +
20
- "Use this for batch operations (rename many files, transform data, etc) " +
21
- "to reduce tool call round-trips.",
22
- },
23
- },
24
- required: ["code"],
25
- };
26
- /** Tool names that should be hidden from direct LLM access when REPL is active. */
27
- export const REPL_HIDES_TOOLS = ["read", "write", "edit", "exec", "search"];
28
- const MAX_CODE_LENGTH = 100_000;
29
- const MAX_OUTPUT_LENGTH = 50_000;
30
- export function createReplTool(deps) {
31
- return {
32
- name: REPL_TOOL_NAME,
33
- label: "REPL",
34
- description: "Execute JavaScript in a persistent VM with built-in file/shell primitives. " +
35
- "Use for batch operations that would otherwise require many individual tool calls. " +
36
- "The VM persists variables between calls within the same session. " +
37
- "Each primitive (readFile, writeFile, exec, etc.) still goes through permission checks.",
38
- parameters: REPL_TOOL_SCHEMA,
39
- execute: async (_toolCallId, params) => {
40
- if (!params.code || params.code.trim().length === 0) {
41
- return {
42
- content: [{ type: "text", text: "Error: code is required." }],
43
- details: { type: "repl", error: "empty_code" },
44
- };
45
- }
46
- if (params.code.length > MAX_CODE_LENGTH) {
47
- return {
48
- content: [{ type: "text", text: `Error: code too large (${params.code.length} chars, max ${MAX_CODE_LENGTH}).` }],
49
- details: { type: "repl", error: "code_too_large" },
50
- };
51
- }
52
- const result = await deps.executeInVm(params.code);
53
- let output = result.output || "";
54
- if (output.length > MAX_OUTPUT_LENGTH) {
55
- output = output.slice(0, MAX_OUTPUT_LENGTH) + "\n... (truncated)";
56
- }
57
- if (result.error) {
58
- return {
59
- content: [{ type: "text", text: `Error: ${result.error}\n\nOutput:\n${output}` }],
60
- details: { type: "repl", error: result.error, duration: result.duration },
61
- };
62
- }
63
- return {
64
- content: [{ type: "text", text: output || "(no output)" }],
65
- details: { type: "repl", duration: result.duration, outputLength: output.length },
66
- };
67
- },
68
- };
69
- }
@@ -1,225 +0,0 @@
1
- // ============================================================
2
- // Search Tool — unified file name (glob) + content (grep) search.
3
- // Fuses CC GlobTool + GrepTool into single PortableTool.
4
- // Reference: claude-code-haha/src/tools/GlobTool/GlobTool.ts
5
- // claude-code-haha/src/tools/GrepTool/GrepTool.ts
6
- // Category: search
7
- // ============================================================
8
- export const SEARCH_TOOL_NAME = "search";
9
- export const SEARCH_TOOL_SCHEMA = {
10
- type: "object",
11
- properties: {
12
- mode: {
13
- type: "string",
14
- enum: ["filename", "content", "both"],
15
- description: 'Search mode: "filename" to find files by name pattern (glob), ' +
16
- '"content" to search within file contents (regex), ' +
17
- '"both" to match both filename patterns and content simultaneously.',
18
- },
19
- pattern: {
20
- type: "string",
21
- description: "The pattern to search for. In filename mode this is a glob pattern " +
22
- "(e.g. **/*.ts). In content mode this is a regular expression. " +
23
- "In both mode this is treated as a regex for content, and fileGlob " +
24
- "filters the filename set.",
25
- },
26
- path: {
27
- type: "string",
28
- description: "Directory to search in. Defaults to workdir/cwd if omitted.",
29
- },
30
- fileGlob: {
31
- type: "string",
32
- description: 'Glob pattern to filter files (e.g. "*.ts", "*.{js,tsx}"). ' +
33
- "In content/both modes, only files matching this glob are searched.",
34
- },
35
- contextLines: {
36
- type: "number",
37
- description: "Number of context lines to show before and after each match " +
38
- "(content/both modes only). Default: 0.",
39
- },
40
- caseInsensitive: {
41
- type: "boolean",
42
- description: "Case insensitive search (content/both modes). Default: false.",
43
- },
44
- headLimit: {
45
- type: "number",
46
- description: "Maximum number of result entries to return. Default 100 for filename, " +
47
- "250 for content. Pass 0 for unlimited (use sparingly).",
48
- },
49
- offset: {
50
- type: "number",
51
- description: "Skip first N results before applying headLimit. Default: 0.",
52
- },
53
- },
54
- required: ["mode", "pattern"],
55
- };
56
- // ── Constants ───────────────────────────────────────────────
57
- const DEFAULT_FILENAME_LIMIT = 100;
58
- const DEFAULT_CONTENT_LIMIT = 250;
59
- const MAX_RESULT_CHARS = 100_000;
60
- // ── Factory ─────────────────────────────────────────────────
61
- export function createSearchTool(deps) {
62
- return {
63
- name: SEARCH_TOOL_NAME,
64
- label: "Search",
65
- description: "Search for files by name, search within file contents by regex, or both. " +
66
- "In filename mode, pattern is a glob. In content mode, pattern is a regex. " +
67
- "Results are paginated via headLimit + offset.",
68
- parameters: SEARCH_TOOL_SCHEMA,
69
- execute: async (_toolCallId, params) => {
70
- const cwd = params.path
71
- ? (deps.resolvePath ? deps.resolvePath(params.path) : params.path)
72
- : "";
73
- const mode = params.mode;
74
- if (mode === "filename") {
75
- return executeFilenameSearch(deps, params, cwd);
76
- }
77
- else if (mode === "content") {
78
- return executeContentSearch(deps, params, cwd);
79
- }
80
- else {
81
- // "both" — run filename glob + content grep, merge results
82
- return executeBothSearch(deps, params, cwd);
83
- }
84
- },
85
- };
86
- }
87
- // ── Filename search ─────────────────────────────────────────
88
- async function executeFilenameSearch(deps, params, cwd) {
89
- const limit = params.headLimit ?? DEFAULT_FILENAME_LIMIT;
90
- const { files, truncated } = await deps.glob(params.pattern, {
91
- cwd,
92
- limit: limit === 0 ? 10000 : limit,
93
- });
94
- const offset = params.offset ?? 0;
95
- const sliced = offset > 0 ? files.slice(offset) : files;
96
- const effectiveLimit = limit === 0 ? sliced.length : limit;
97
- const finalFiles = sliced.slice(0, effectiveLimit);
98
- const wasTruncated = truncated || sliced.length > effectiveLimit;
99
- if (finalFiles.length === 0) {
100
- return {
101
- content: [{ type: "text", text: "No files found matching pattern." }],
102
- details: { mode: "filename", totalMatches: 0, truncated: false },
103
- };
104
- }
105
- let text = finalFiles.join("\n");
106
- if (wasTruncated) {
107
- text += `\n\n(Results truncated. ${finalFiles.length} shown. Use a more specific pattern or increase headLimit.)`;
108
- }
109
- text = truncateText(text, MAX_RESULT_CHARS);
110
- return {
111
- content: [{ type: "text", text }],
112
- details: {
113
- mode: "filename",
114
- totalMatches: finalFiles.length,
115
- truncated: wasTruncated,
116
- },
117
- };
118
- }
119
- // ── Content search ──────────────────────────────────────────
120
- async function executeContentSearch(deps, params, cwd) {
121
- const headLimit = params.headLimit ?? DEFAULT_CONTENT_LIMIT;
122
- const { matches, truncated } = await deps.grep(params.pattern, {
123
- cwd,
124
- fileGlob: params.fileGlob,
125
- caseInsensitive: params.caseInsensitive,
126
- contextLines: params.contextLines,
127
- headLimit: headLimit === 0 ? undefined : headLimit,
128
- offset: params.offset,
129
- });
130
- if (matches.length === 0) {
131
- return {
132
- content: [{ type: "text", text: "No matches found." }],
133
- details: { mode: "content", totalMatches: 0, truncated: false },
134
- };
135
- }
136
- const lines = [];
137
- for (const m of matches) {
138
- if (m.contextBefore && m.contextBefore.length > 0) {
139
- for (const ctx of m.contextBefore) {
140
- lines.push(` ${ctx}`);
141
- }
142
- }
143
- lines.push(`${m.path}:${m.line}: ${m.text}`);
144
- if (m.contextAfter && m.contextAfter.length > 0) {
145
- for (const ctx of m.contextAfter) {
146
- lines.push(` ${ctx}`);
147
- }
148
- }
149
- // Separator between match groups when context is present
150
- if (params.contextLines && params.contextLines > 0) {
151
- lines.push("--");
152
- }
153
- }
154
- let text = lines.join("\n");
155
- if (truncated) {
156
- text += `\n\n(Results truncated at ${matches.length} matches. Use offset/headLimit for pagination.)`;
157
- }
158
- text = truncateText(text, MAX_RESULT_CHARS);
159
- return {
160
- content: [{ type: "text", text }],
161
- details: {
162
- mode: "content",
163
- totalMatches: matches.length,
164
- truncated,
165
- },
166
- };
167
- }
168
- // ── Both mode ───────────────────────────────────────────────
169
- async function executeBothSearch(deps, params, cwd) {
170
- // Run both in parallel
171
- const [globResult, grepResult] = await Promise.all([
172
- params.fileGlob
173
- ? deps.glob(params.fileGlob, { cwd, limit: DEFAULT_FILENAME_LIMIT })
174
- : Promise.resolve({ files: [], truncated: false }),
175
- deps.grep(params.pattern, {
176
- cwd,
177
- fileGlob: params.fileGlob,
178
- caseInsensitive: params.caseInsensitive,
179
- contextLines: params.contextLines,
180
- headLimit: params.headLimit ?? DEFAULT_CONTENT_LIMIT,
181
- offset: params.offset,
182
- }),
183
- ]);
184
- // Deduplicate: files that appear in both glob and grep results
185
- const contentFiles = new Set(grepResult.matches.map((m) => m.path));
186
- const uniqueGlobFiles = globResult.files.filter((f) => !contentFiles.has(f));
187
- const sections = [];
188
- if (uniqueGlobFiles.length > 0) {
189
- sections.push(`## Files matching glob (${uniqueGlobFiles.length}):\n${uniqueGlobFiles.join("\n")}`);
190
- }
191
- if (grepResult.matches.length > 0) {
192
- const lines = [];
193
- for (const m of grepResult.matches) {
194
- lines.push(`${m.path}:${m.line}: ${m.text}`);
195
- }
196
- sections.push(`## Content matches (${grepResult.matches.length}):\n${lines.join("\n")}`);
197
- }
198
- if (sections.length === 0) {
199
- return {
200
- content: [{ type: "text", text: "No matches found in either filename or content." }],
201
- details: { mode: "both", totalMatches: 0, truncated: false },
202
- };
203
- }
204
- const truncated = globResult.truncated || grepResult.truncated;
205
- let text = sections.join("\n\n");
206
- if (truncated) {
207
- text += "\n\n(Some results truncated. Use more specific patterns.)";
208
- }
209
- text = truncateText(text, MAX_RESULT_CHARS);
210
- return {
211
- content: [{ type: "text", text }],
212
- details: {
213
- mode: "both",
214
- totalMatches: uniqueGlobFiles.length + grepResult.matches.length,
215
- truncated,
216
- },
217
- };
218
- }
219
- // ── Util ────────────────────────────────────────────────────
220
- function truncateText(text, limit) {
221
- if (text.length <= limit)
222
- return text;
223
- const half = Math.floor(limit / 2) - 50;
224
- return `${text.slice(0, half)}\n\n... [truncated ${text.length - limit} chars] ...\n\n${text.slice(-half)}`;
225
- }
@@ -1,76 +0,0 @@
1
- // ============================================================
2
- // Send Message Tool — agent-to-agent IPC within a team/swarm.
3
- // Reference: claude-code-haha/src/tools/SendMessageTool/SendMessageTool.ts
4
- // hermes-agent-main/tools/send_message_tool.py
5
- // Category: system
6
- // ============================================================
7
- export const SEND_MESSAGE_TOOL_NAME = "send_message";
8
- export const SEND_MESSAGE_TOOL_SCHEMA = {
9
- type: "object",
10
- properties: {
11
- to: {
12
- type: "string",
13
- description: "Target agent name or '*' for broadcast to all team members. " +
14
- "Must be a valid agent name within the current team.",
15
- },
16
- message: {
17
- type: "string",
18
- description: "Message content to send to the target agent.",
19
- },
20
- summary: {
21
- type: "string",
22
- description: "Optional short summary (for logging/routing).",
23
- },
24
- },
25
- required: ["to", "message"],
26
- };
27
- export function createSendMessageTool(deps) {
28
- return {
29
- name: SEND_MESSAGE_TOOL_NAME,
30
- label: "Send Message",
31
- description: "Send a message to another agent in your team. Use '*' to broadcast to all teammates. " +
32
- "Messages are delivered asynchronously. Use for coordination, delegation, and status updates.",
33
- parameters: SEND_MESSAGE_TOOL_SCHEMA,
34
- execute: async (_toolCallId, params) => {
35
- if (!params.to || params.to.trim().length === 0) {
36
- return {
37
- content: [{ type: "text", text: "Error: 'to' is required (agent name or '*')." }],
38
- details: { type: "send_message", error: "missing_target" },
39
- };
40
- }
41
- if (!params.message || params.message.trim().length === 0) {
42
- return {
43
- content: [{ type: "text", text: "Error: message is required." }],
44
- details: { type: "send_message", error: "empty_message" },
45
- };
46
- }
47
- // Validate target exists (unless broadcast)
48
- if (params.to !== "*" && deps.listTeammates) {
49
- const teammates = deps.listTeammates();
50
- if (!teammates.includes(params.to)) {
51
- return {
52
- content: [{ type: "text", text: `Error: agent "${params.to}" not found in team. Available: ${teammates.join(", ")}` }],
53
- details: { type: "send_message", error: "target_not_found", available: teammates },
54
- };
55
- }
56
- }
57
- const result = await deps.sendMessage({
58
- to: params.to.trim(),
59
- message: params.message.trim(),
60
- summary: params.summary,
61
- senderId: deps.getSenderId(),
62
- });
63
- if (!result.success) {
64
- return {
65
- content: [{ type: "text", text: `Message delivery failed: ${result.error || "unknown error"}` }],
66
- details: { type: "send_message", success: false, error: result.error },
67
- };
68
- }
69
- const target = params.to === "*" ? `broadcast (${result.recipients?.length || 0} recipients)` : params.to;
70
- return {
71
- content: [{ type: "text", text: `Message sent to ${target}.` }],
72
- details: { type: "send_message", success: true, to: params.to, recipients: result.recipients },
73
- };
74
- },
75
- };
76
- }
@@ -1,54 +0,0 @@
1
- // ============================================================
2
- // Skill List Tool — discover available skills.
3
- // Reference: hermes-agent-2026.4.30/tools/skills_tool.py (skills_list)
4
- // Category: skill
5
- // ============================================================
6
- export const SKILL_LIST_TOOL_NAME = "skill_list";
7
- export const SKILL_LIST_TOOL_SCHEMA = {
8
- type: "object",
9
- properties: {
10
- category: {
11
- type: "string",
12
- description: "Filter skills by category (e.g. 'devops', 'mlops'). Omit to list all.",
13
- },
14
- },
15
- required: [],
16
- };
17
- export function createSkillListTool(deps) {
18
- return {
19
- name: SKILL_LIST_TOOL_NAME,
20
- label: "List Skills",
21
- description: "List all available skills (reusable workflows/knowledge packages). " +
22
- "Returns skill names, descriptions, and categories. " +
23
- "Use skill_view to see full skill content.",
24
- parameters: SKILL_LIST_TOOL_SCHEMA,
25
- execute: async (_toolCallId, params) => {
26
- const output = await deps.listSkills(params.category);
27
- if (output.skills.length === 0) {
28
- const msg = params.category
29
- ? `No skills found in category "${params.category}".`
30
- : "No skills available.";
31
- return {
32
- content: [{ type: "text", text: msg }],
33
- details: { type: "skill_list", count: 0 },
34
- };
35
- }
36
- const lines = [`Available skills (${output.skills.length}):`];
37
- if (output.categories.length > 0) {
38
- lines.push(`Categories: ${output.categories.join(", ")}`);
39
- }
40
- lines.push("");
41
- for (const s of output.skills) {
42
- const cat = s.category ? ` [${s.category}]` : "";
43
- const ver = s.version ? ` (v${s.version})` : "";
44
- lines.push(`- **${s.name}**${ver}${cat}: ${s.description}`);
45
- }
46
- lines.push("");
47
- lines.push("Use skill_view(name) to see full skill content.");
48
- return {
49
- content: [{ type: "text", text: lines.join("\n") }],
50
- details: { type: "skill_list", count: output.skills.length, categories: output.categories },
51
- };
52
- },
53
- };
54
- }