claude-flow 3.5.70 → 3.5.71

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 (87) hide show
  1. package/package.json +1 -1
  2. package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-tools.js +35 -1
  3. package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +81 -0
  4. package/v3/@claude-flow/cli/dist/src/mcp-tools/analyze-tools.js +29 -0
  5. package/v3/@claude-flow/cli/dist/src/mcp-tools/autopilot-tools.js +4 -0
  6. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +146 -0
  7. package/v3/@claude-flow/cli/dist/src/mcp-tools/claims-tools.js +116 -0
  8. package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js +31 -0
  9. package/v3/@claude-flow/cli/dist/src/mcp-tools/daa-tools.js +61 -0
  10. package/v3/@claude-flow/cli/dist/src/mcp-tools/embeddings-tools.js +26 -0
  11. package/v3/@claude-flow/cli/dist/src/mcp-tools/github-tools.js +96 -0
  12. package/v3/@claude-flow/cli/dist/src/mcp-tools/guidance-tools.js +21 -0
  13. package/v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.js +56 -0
  14. package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +176 -0
  15. package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +18 -2
  16. package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +51 -0
  17. package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +11 -0
  18. package/v3/@claude-flow/cli/dist/src/mcp-tools/ruvllm-tools.js +31 -0
  19. package/v3/@claude-flow/cli/dist/src/mcp-tools/security-tools.js +36 -0
  20. package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +6 -0
  21. package/v3/@claude-flow/cli/dist/src/mcp-tools/transfer-tools.js +51 -0
  22. package/v3/@claude-flow/cli/dist/src/mcp-tools/wasm-agent-tools.js +61 -0
  23. package/v3/@claude-flow/cli/package.json +1 -1
  24. package/v3/@claude-flow/guidance/dist/adversarial.d.ts +284 -0
  25. package/v3/@claude-flow/guidance/dist/adversarial.js +572 -0
  26. package/v3/@claude-flow/guidance/dist/analyzer.d.ts +530 -0
  27. package/v3/@claude-flow/guidance/dist/analyzer.js +2518 -0
  28. package/v3/@claude-flow/guidance/dist/artifacts.d.ts +283 -0
  29. package/v3/@claude-flow/guidance/dist/artifacts.js +356 -0
  30. package/v3/@claude-flow/guidance/dist/authority.d.ts +290 -0
  31. package/v3/@claude-flow/guidance/dist/authority.js +558 -0
  32. package/v3/@claude-flow/guidance/dist/capabilities.d.ts +209 -0
  33. package/v3/@claude-flow/guidance/dist/capabilities.js +485 -0
  34. package/v3/@claude-flow/guidance/dist/coherence.d.ts +233 -0
  35. package/v3/@claude-flow/guidance/dist/coherence.js +372 -0
  36. package/v3/@claude-flow/guidance/dist/compiler.d.ts +87 -0
  37. package/v3/@claude-flow/guidance/dist/compiler.js +419 -0
  38. package/v3/@claude-flow/guidance/dist/conformance-kit.d.ts +225 -0
  39. package/v3/@claude-flow/guidance/dist/conformance-kit.js +629 -0
  40. package/v3/@claude-flow/guidance/dist/continue-gate.d.ts +214 -0
  41. package/v3/@claude-flow/guidance/dist/continue-gate.js +353 -0
  42. package/v3/@claude-flow/guidance/dist/crypto-utils.d.ts +17 -0
  43. package/v3/@claude-flow/guidance/dist/crypto-utils.js +24 -0
  44. package/v3/@claude-flow/guidance/dist/evolution.d.ts +282 -0
  45. package/v3/@claude-flow/guidance/dist/evolution.js +500 -0
  46. package/v3/@claude-flow/guidance/dist/gates.d.ts +79 -0
  47. package/v3/@claude-flow/guidance/dist/gates.js +302 -0
  48. package/v3/@claude-flow/guidance/dist/gateway.d.ts +206 -0
  49. package/v3/@claude-flow/guidance/dist/gateway.js +452 -0
  50. package/v3/@claude-flow/guidance/dist/generators.d.ts +153 -0
  51. package/v3/@claude-flow/guidance/dist/generators.js +682 -0
  52. package/v3/@claude-flow/guidance/dist/headless.d.ts +177 -0
  53. package/v3/@claude-flow/guidance/dist/headless.js +342 -0
  54. package/v3/@claude-flow/guidance/dist/hooks.d.ts +109 -0
  55. package/v3/@claude-flow/guidance/dist/hooks.js +347 -0
  56. package/v3/@claude-flow/guidance/dist/index.d.ts +205 -0
  57. package/v3/@claude-flow/guidance/dist/index.js +321 -0
  58. package/v3/@claude-flow/guidance/dist/ledger.d.ts +162 -0
  59. package/v3/@claude-flow/guidance/dist/ledger.js +375 -0
  60. package/v3/@claude-flow/guidance/dist/manifest-validator.d.ts +289 -0
  61. package/v3/@claude-flow/guidance/dist/manifest-validator.js +838 -0
  62. package/v3/@claude-flow/guidance/dist/memory-gate.d.ts +222 -0
  63. package/v3/@claude-flow/guidance/dist/memory-gate.js +382 -0
  64. package/v3/@claude-flow/guidance/dist/meta-governance.d.ts +265 -0
  65. package/v3/@claude-flow/guidance/dist/meta-governance.js +348 -0
  66. package/v3/@claude-flow/guidance/dist/optimizer.d.ts +104 -0
  67. package/v3/@claude-flow/guidance/dist/optimizer.js +329 -0
  68. package/v3/@claude-flow/guidance/dist/persistence.d.ts +189 -0
  69. package/v3/@claude-flow/guidance/dist/persistence.js +464 -0
  70. package/v3/@claude-flow/guidance/dist/proof.d.ts +185 -0
  71. package/v3/@claude-flow/guidance/dist/proof.js +238 -0
  72. package/v3/@claude-flow/guidance/dist/retriever.d.ts +116 -0
  73. package/v3/@claude-flow/guidance/dist/retriever.js +394 -0
  74. package/v3/@claude-flow/guidance/dist/ruvbot-integration.d.ts +370 -0
  75. package/v3/@claude-flow/guidance/dist/ruvbot-integration.js +738 -0
  76. package/v3/@claude-flow/guidance/dist/temporal.d.ts +426 -0
  77. package/v3/@claude-flow/guidance/dist/temporal.js +658 -0
  78. package/v3/@claude-flow/guidance/dist/trust.d.ts +283 -0
  79. package/v3/@claude-flow/guidance/dist/trust.js +473 -0
  80. package/v3/@claude-flow/guidance/dist/truth-anchors.d.ts +276 -0
  81. package/v3/@claude-flow/guidance/dist/truth-anchors.js +488 -0
  82. package/v3/@claude-flow/guidance/dist/types.d.ts +378 -0
  83. package/v3/@claude-flow/guidance/dist/types.js +10 -0
  84. package/v3/@claude-flow/guidance/dist/uncertainty.d.ts +372 -0
  85. package/v3/@claude-flow/guidance/dist/uncertainty.js +619 -0
  86. package/v3/@claude-flow/guidance/dist/wasm-kernel.d.ts +48 -0
  87. package/v3/@claude-flow/guidance/dist/wasm-kernel.js +158 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.5.70",
3
+ "version": "3.5.71",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -7,7 +7,7 @@
7
7
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
8
8
  import { join } from 'node:path';
9
9
  import { getProjectCwd } from './types.js';
10
- import { validateAgentSpawn } from './validate-input.js';
10
+ import { validateIdentifier, validateAgentSpawn } from './validate-input.js';
11
11
  // Storage paths
12
12
  const STORAGE_DIR = '.claude-flow';
13
13
  const AGENT_DIR = 'agents';
@@ -221,6 +221,9 @@ export const agentTools = [
221
221
  required: ['agentId'],
222
222
  },
223
223
  handler: async (input) => {
224
+ const v = validateIdentifier(input.agentId, 'agentId');
225
+ if (!v.valid)
226
+ return { success: false, error: `Input validation failed: ${v.error}` };
224
227
  const store = loadAgentStore();
225
228
  const agentId = input.agentId;
226
229
  if (store.agents[agentId]) {
@@ -252,6 +255,9 @@ export const agentTools = [
252
255
  required: ['agentId'],
253
256
  },
254
257
  handler: async (input) => {
258
+ const v = validateIdentifier(input.agentId, 'agentId');
259
+ if (!v.valid)
260
+ return { agentId: input.agentId, status: 'not_found', error: `Input validation failed: ${v.error}` };
255
261
  const store = loadAgentStore();
256
262
  const agentId = input.agentId;
257
263
  const agent = store.agents[agentId];
@@ -287,6 +293,16 @@ export const agentTools = [
287
293
  },
288
294
  },
289
295
  handler: async (input) => {
296
+ if (input.status) {
297
+ const v = validateIdentifier(input.status, 'status');
298
+ if (!v.valid)
299
+ return { agents: [], total: 0, error: `Input validation failed: ${v.error}` };
300
+ }
301
+ if (input.domain) {
302
+ const v = validateIdentifier(input.domain, 'domain');
303
+ if (!v.valid)
304
+ return { agents: [], total: 0, error: `Input validation failed: ${v.error}` };
305
+ }
290
306
  const store = loadAgentStore();
291
307
  let agents = Object.values(store.agents);
292
308
  // Filter by status
@@ -333,6 +349,11 @@ export const agentTools = [
333
349
  required: ['action'],
334
350
  },
335
351
  handler: async (input) => {
352
+ if (input.agentType) {
353
+ const v = validateIdentifier(input.agentType, 'agentType');
354
+ if (!v.valid)
355
+ return { action: input.action, error: `Input validation failed: ${v.error}` };
356
+ }
336
357
  const store = loadAgentStore();
337
358
  const agents = Object.values(store.agents).filter(a => a.status !== 'terminated');
338
359
  const action = input.action || 'status'; // Default to status
@@ -443,6 +464,11 @@ export const agentTools = [
443
464
  },
444
465
  },
445
466
  handler: async (input) => {
467
+ if (input.agentId) {
468
+ const v = validateIdentifier(input.agentId, 'agentId');
469
+ if (!v.valid)
470
+ return { agentId: input.agentId, error: `Input validation failed: ${v.error}` };
471
+ }
446
472
  const store = loadAgentStore();
447
473
  const agents = Object.values(store.agents).filter(a => a.status !== 'terminated');
448
474
  const threshold = input.threshold || 0.5;
@@ -517,6 +543,14 @@ export const agentTools = [
517
543
  required: ['agentId'],
518
544
  },
519
545
  handler: async (input) => {
546
+ const v = validateIdentifier(input.agentId, 'agentId');
547
+ if (!v.valid)
548
+ return { success: false, agentId: input.agentId, error: `Input validation failed: ${v.error}` };
549
+ if (input.status) {
550
+ const vs = validateIdentifier(input.status, 'status');
551
+ if (!vs.valid)
552
+ return { success: false, agentId: input.agentId, error: `Input validation failed: ${vs.error}` };
553
+ }
520
554
  const store = loadAgentStore();
521
555
  const agentId = input.agentId;
522
556
  const agent = store.agents[agentId];
@@ -10,6 +10,7 @@
10
10
  *
11
11
  * @module v3/cli/mcp-tools/agentdb-tools
12
12
  */
13
+ import { validateIdentifier, validateText } from './validate-input.js';
13
14
  // ===== Shared validation helpers =====
14
15
  const MAX_STRING_LENGTH = 100_000; // 100KB max for any string input
15
16
  const MAX_BATCH_SIZE = 500; // Max entries per batch operation
@@ -109,6 +110,14 @@ export const agentdbPatternStore = {
109
110
  },
110
111
  handler: async (params) => {
111
112
  try {
113
+ const vPattern = validateText(params.pattern, 'pattern', 100_000);
114
+ if (!vPattern.valid)
115
+ return { success: false, error: vPattern.error };
116
+ if (params.type) {
117
+ const vType = validateIdentifier(params.type, 'type');
118
+ if (!vType.valid)
119
+ return { success: false, error: vType.error };
120
+ }
112
121
  const pattern = validateString(params.pattern, 'pattern');
113
122
  if (!pattern)
114
123
  return { success: false, error: 'pattern is required (non-empty string, max 100KB)' };
@@ -140,6 +149,9 @@ export const agentdbPatternSearch = {
140
149
  },
141
150
  handler: async (params) => {
142
151
  try {
152
+ const vQuery = validateText(params.query, 'query', 10_000);
153
+ if (!vQuery.valid)
154
+ return { results: [], error: vQuery.error };
143
155
  const query = validateString(params.query, 'query', 10_000);
144
156
  if (!query)
145
157
  return { results: [], error: 'query is required (non-empty string, max 10KB)' };
@@ -172,6 +184,14 @@ export const agentdbFeedback = {
172
184
  },
173
185
  handler: async (params) => {
174
186
  try {
187
+ const vTaskId = validateIdentifier(params.taskId, 'taskId');
188
+ if (!vTaskId.valid)
189
+ return { success: false, error: vTaskId.error };
190
+ if (params.agent) {
191
+ const vAgent = validateIdentifier(params.agent, 'agent');
192
+ if (!vAgent.valid)
193
+ return { success: false, error: vAgent.error };
194
+ }
175
195
  const taskId = validateString(params.taskId, 'taskId', 500);
176
196
  if (!taskId)
177
197
  return { success: false, error: 'taskId is required (non-empty string, max 500 chars)' };
@@ -205,6 +225,15 @@ export const agentdbCausalEdge = {
205
225
  },
206
226
  handler: async (params) => {
207
227
  try {
228
+ const vSourceId = validateIdentifier(params.sourceId, 'sourceId');
229
+ if (!vSourceId.valid)
230
+ return { success: false, error: vSourceId.error };
231
+ const vTargetId = validateIdentifier(params.targetId, 'targetId');
232
+ if (!vTargetId.valid)
233
+ return { success: false, error: vTargetId.error };
234
+ const vRelation = validateIdentifier(params.relation, 'relation');
235
+ if (!vRelation.valid)
236
+ return { success: false, error: vRelation.error };
208
237
  const sourceId = validateString(params.sourceId, 'sourceId', 500);
209
238
  const targetId = validateString(params.targetId, 'targetId', 500);
210
239
  const relation = validateString(params.relation, 'relation', 200);
@@ -242,6 +271,14 @@ export const agentdbRoute = {
242
271
  },
243
272
  handler: async (params) => {
244
273
  try {
274
+ const vTask = validateText(params.task, 'task', 10_000);
275
+ if (!vTask.valid)
276
+ return { route: 'general', confidence: 0.5, agents: ['coder'], controller: 'error', error: vTask.error };
277
+ if (params.context) {
278
+ const vCtx = validateText(params.context, 'context', 10_000);
279
+ if (!vCtx.valid)
280
+ return { route: 'general', confidence: 0.5, agents: ['coder'], controller: 'error', error: vCtx.error };
281
+ }
245
282
  const task = validateString(params.task, 'task', 10_000);
246
283
  if (!task)
247
284
  return { route: 'general', confidence: 0.5, agents: ['coder'], controller: 'error', error: 'task is required (non-empty string)' };
@@ -271,6 +308,14 @@ export const agentdbSessionStart = {
271
308
  },
272
309
  handler: async (params) => {
273
310
  try {
311
+ const vSessionId = validateIdentifier(params.sessionId, 'sessionId');
312
+ if (!vSessionId.valid)
313
+ return { success: false, error: vSessionId.error };
314
+ if (params.context) {
315
+ const vCtx = validateText(params.context, 'context', 10_000);
316
+ if (!vCtx.valid)
317
+ return { success: false, error: vCtx.error };
318
+ }
274
319
  const sessionId = validateString(params.sessionId, 'sessionId', 500);
275
320
  if (!sessionId)
276
321
  return { success: false, error: 'sessionId is required (non-empty string)' };
@@ -301,6 +346,14 @@ export const agentdbSessionEnd = {
301
346
  },
302
347
  handler: async (params) => {
303
348
  try {
349
+ const vSessionId = validateIdentifier(params.sessionId, 'sessionId');
350
+ if (!vSessionId.valid)
351
+ return { success: false, error: vSessionId.error };
352
+ if (params.summary) {
353
+ const vSummary = validateText(params.summary, 'summary', 50_000);
354
+ if (!vSummary.valid)
355
+ return { success: false, error: vSummary.error };
356
+ }
304
357
  const sessionId = validateString(params.sessionId, 'sessionId', 500);
305
358
  if (!sessionId)
306
359
  return { success: false, error: 'sessionId is required (non-empty string)' };
@@ -337,6 +390,17 @@ export const agentdbHierarchicalStore = {
337
390
  },
338
391
  handler: async (params) => {
339
392
  try {
393
+ const vKey = validateIdentifier(params.key, 'key');
394
+ if (!vKey.valid)
395
+ return { success: false, error: vKey.error };
396
+ const vValue = validateText(params.value, 'value');
397
+ if (!vValue.valid)
398
+ return { success: false, error: vValue.error };
399
+ if (params.tier) {
400
+ const vTier = validateIdentifier(params.tier, 'tier');
401
+ if (!vTier.valid)
402
+ return { success: false, error: vTier.error };
403
+ }
340
404
  const key = validateString(params.key, 'key', 1000);
341
405
  const value = validateString(params.value, 'value');
342
406
  if (!key)
@@ -371,6 +435,14 @@ export const agentdbHierarchicalRecall = {
371
435
  },
372
436
  handler: async (params) => {
373
437
  try {
438
+ const vQuery = validateText(params.query, 'query', 10_000);
439
+ if (!vQuery.valid)
440
+ return { results: [], error: vQuery.error };
441
+ if (params.tier) {
442
+ const vTier = validateIdentifier(params.tier, 'tier');
443
+ if (!vTier.valid)
444
+ return { results: [], error: vTier.error };
445
+ }
374
446
  const query = validateString(params.query, 'query', 10_000);
375
447
  if (!query)
376
448
  return { results: [], error: 'query is required (non-empty string, max 10KB)' };
@@ -445,6 +517,9 @@ export const agentdbBatch = {
445
517
  },
446
518
  handler: async (params) => {
447
519
  try {
520
+ const vOp = validateIdentifier(params.operation, 'operation');
521
+ if (!vOp.valid)
522
+ return { success: false, error: vOp.error };
448
523
  const operation = validateString(params.operation, 'operation', 20);
449
524
  if (!operation)
450
525
  return { success: false, error: 'operation is required (string)' };
@@ -496,6 +571,9 @@ export const agentdbContextSynthesize = {
496
571
  },
497
572
  handler: async (params) => {
498
573
  try {
574
+ const vQuery = validateText(params.query, 'query', 10_000);
575
+ if (!vQuery.valid)
576
+ return { success: false, error: vQuery.error };
499
577
  const query = validateString(params.query, 'query', 10_000);
500
578
  if (!query)
501
579
  return { success: false, error: 'query is required (non-empty string, max 10KB)' };
@@ -524,6 +602,9 @@ export const agentdbSemanticRoute = {
524
602
  },
525
603
  handler: async (params) => {
526
604
  try {
605
+ const vInput = validateText(params.input, 'input', 10_000);
606
+ if (!vInput.valid)
607
+ return { route: null, error: vInput.error };
527
608
  const input = validateString(params.input, 'input', 10_000);
528
609
  if (!input)
529
610
  return { route: null, error: 'input is required (non-empty string, max 10KB)' };
@@ -2,6 +2,7 @@
2
2
  * Analyze MCP Tools
3
3
  * Provides diff analysis and classification via MCP protocol
4
4
  */
5
+ import { validateIdentifier, validatePath } from './validate-input.js';
5
6
  import { analyzeDiff, assessFileRisk, assessOverallRisk, classifyDiff, suggestReviewers, getGitDiffNumstat, } from '../ruvector/diff-classifier.js';
6
7
  /**
7
8
  * Diff Analysis Tool
@@ -38,6 +39,11 @@ export const analyzeDiffTool = {
38
39
  },
39
40
  },
40
41
  handler: async (params) => {
42
+ if (params.ref) {
43
+ const vRef = validateIdentifier(params.ref, 'ref');
44
+ if (!vRef.valid)
45
+ return { error: true, message: vRef.error, ref: params.ref };
46
+ }
41
47
  const ref = params.ref || 'HEAD';
42
48
  const includeFileRisks = params.includeFileRisks !== false;
43
49
  const includeReviewers = params.includeReviewers !== false;
@@ -93,6 +99,11 @@ export const diffRiskTool = {
93
99
  },
94
100
  },
95
101
  handler: async (params) => {
102
+ if (params.ref) {
103
+ const vRef = validateIdentifier(params.ref, 'ref');
104
+ if (!vRef.valid)
105
+ return { error: true, message: vRef.error, ref: params.ref };
106
+ }
96
107
  const ref = params.ref || 'HEAD';
97
108
  try {
98
109
  const files = getGitDiffNumstat(ref);
@@ -133,6 +144,11 @@ export const diffClassifyTool = {
133
144
  },
134
145
  },
135
146
  handler: async (params) => {
147
+ if (params.ref) {
148
+ const vRef = validateIdentifier(params.ref, 'ref');
149
+ if (!vRef.valid)
150
+ return { error: true, message: vRef.error, ref: params.ref };
151
+ }
136
152
  const ref = params.ref || 'HEAD';
137
153
  try {
138
154
  const files = getGitDiffNumstat(ref);
@@ -177,6 +193,11 @@ export const diffReviewersTool = {
177
193
  },
178
194
  },
179
195
  handler: async (params) => {
196
+ if (params.ref) {
197
+ const vRef = validateIdentifier(params.ref, 'ref');
198
+ if (!vRef.valid)
199
+ return { error: true, message: vRef.error, ref: params.ref };
200
+ }
180
201
  const ref = params.ref || 'HEAD';
181
202
  const limit = params.limit || 5;
182
203
  try {
@@ -233,6 +254,9 @@ export const fileRiskTool = {
233
254
  required: ['path'],
234
255
  },
235
256
  handler: async (params) => {
257
+ const vPath = validatePath(params.path, 'path');
258
+ if (!vPath.valid)
259
+ return { file: params.path, risk: 'unknown', score: 0, reasons: [vPath.error] };
236
260
  const file = {
237
261
  path: params.path,
238
262
  status: params.status || 'modified',
@@ -270,6 +294,11 @@ export const diffStatsTool = {
270
294
  },
271
295
  },
272
296
  handler: async (params) => {
297
+ if (params.ref) {
298
+ const vRef = validateIdentifier(params.ref, 'ref');
299
+ if (!vRef.valid)
300
+ return { error: true, message: vRef.error, ref: params.ref };
301
+ }
273
302
  const ref = params.ref || 'HEAD';
274
303
  try {
275
304
  const files = getGitDiffNumstat(ref);
@@ -7,6 +7,7 @@
7
7
  * ADR-072: Autopilot Integration
8
8
  * @module @claude-flow/cli/mcp-tools/autopilot
9
9
  */
10
+ import { validateText } from './validate-input.js';
10
11
  import { loadState, saveState, appendLog, loadLog, discoverTasks, isTerminal, tryLoadLearning, validateNumber, validateTaskSources, VALID_TASK_SOURCES, } from '../autopilot-state.js';
11
12
  function ok(data) {
12
13
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
@@ -175,6 +176,9 @@ const autopilotHistory = {
175
176
  required: ['query'],
176
177
  },
177
178
  handler: async (params) => {
179
+ const vQuery = validateText(params.query, 'query');
180
+ if (!vQuery.valid)
181
+ return ok({ query: '', results: [], error: vQuery.error });
178
182
  const query = String(params.query || '');
179
183
  const limit = validateNumber(params.limit, 1, 100, 10);
180
184
  const learning = await tryLoadLearning();
@@ -4,6 +4,7 @@
4
4
  * CLI integration for @claude-flow/browser package.
5
5
  * Provides browser automation tools for web navigation, interaction, and data extraction.
6
6
  */
7
+ import { validateIdentifier, validateText } from './validate-input.js';
7
8
  // Session registry for multi-session support
8
9
  const browserSessions = new Map();
9
10
  /**
@@ -75,6 +76,14 @@ export const browserTools = [
75
76
  required: ['url'],
76
77
  },
77
78
  handler: async (input) => {
79
+ const vUrl = validateText(input.url, 'url');
80
+ if (!vUrl.valid)
81
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vUrl.error }) }], isError: true };
82
+ if (input.session) {
83
+ const vS = validateIdentifier(input.session, 'session');
84
+ if (!vS.valid)
85
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
86
+ }
78
87
  const { url, session, waitUntil } = input;
79
88
  const args = ['open', url];
80
89
  if (waitUntil)
@@ -176,6 +185,16 @@ export const browserTools = [
176
185
  },
177
186
  },
178
187
  handler: async (input) => {
188
+ if (input.selector) {
189
+ const vSel = validateText(input.selector, 'selector');
190
+ if (!vSel.valid)
191
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vSel.error }) }], isError: true };
192
+ }
193
+ if (input.session) {
194
+ const vS = validateIdentifier(input.session, 'session');
195
+ if (!vS.valid)
196
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
197
+ }
179
198
  const { session, interactive, compact, depth, selector } = input;
180
199
  const args = ['snapshot'];
181
200
  if (interactive)
@@ -203,6 +222,16 @@ export const browserTools = [
203
222
  },
204
223
  },
205
224
  handler: async (input) => {
225
+ if (input.path) {
226
+ const vP = validateText(input.path, 'path');
227
+ if (!vP.valid)
228
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vP.error }) }], isError: true };
229
+ }
230
+ if (input.session) {
231
+ const vS = validateIdentifier(input.session, 'session');
232
+ if (!vS.valid)
233
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
234
+ }
206
235
  const { session, path, fullPage } = input;
207
236
  const args = ['screenshot'];
208
237
  if (path)
@@ -231,6 +260,14 @@ export const browserTools = [
231
260
  required: ['target'],
232
261
  },
233
262
  handler: async (input) => {
263
+ const vTarget = validateText(input.target, 'target');
264
+ if (!vTarget.valid)
265
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
266
+ if (input.session) {
267
+ const vS = validateIdentifier(input.session, 'session');
268
+ if (!vS.valid)
269
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
270
+ }
234
271
  const { target, session, button, count } = input;
235
272
  const args = ['click', target];
236
273
  if (button)
@@ -255,6 +292,17 @@ export const browserTools = [
255
292
  required: ['target', 'value'],
256
293
  },
257
294
  handler: async (input) => {
295
+ const vTarget = validateText(input.target, 'target');
296
+ if (!vTarget.valid)
297
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
298
+ const vValue = validateText(input.value, 'value');
299
+ if (!vValue.valid)
300
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vValue.error }) }], isError: true };
301
+ if (input.session) {
302
+ const vS = validateIdentifier(input.session, 'session');
303
+ if (!vS.valid)
304
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
305
+ }
258
306
  const { target, value, session } = input;
259
307
  return execBrowserCommand(['fill', target, value], session);
260
308
  },
@@ -275,6 +323,17 @@ export const browserTools = [
275
323
  required: ['target', 'text'],
276
324
  },
277
325
  handler: async (input) => {
326
+ const vTarget = validateText(input.target, 'target');
327
+ if (!vTarget.valid)
328
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
329
+ const vText = validateText(input.text, 'text');
330
+ if (!vText.valid)
331
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vText.error }) }], isError: true };
332
+ if (input.session) {
333
+ const vS = validateIdentifier(input.session, 'session');
334
+ if (!vS.valid)
335
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
336
+ }
278
337
  const { target, text, session, delay } = input;
279
338
  const args = ['type', target, text];
280
339
  if (delay)
@@ -296,6 +355,14 @@ export const browserTools = [
296
355
  required: ['key'],
297
356
  },
298
357
  handler: async (input) => {
358
+ const vKey = validateText(input.key, 'key');
359
+ if (!vKey.valid)
360
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vKey.error }) }], isError: true };
361
+ if (input.session) {
362
+ const vS = validateIdentifier(input.session, 'session');
363
+ if (!vS.valid)
364
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
365
+ }
299
366
  const { key, session } = input;
300
367
  return execBrowserCommand(['press', key], session);
301
368
  },
@@ -314,6 +381,14 @@ export const browserTools = [
314
381
  required: ['target'],
315
382
  },
316
383
  handler: async (input) => {
384
+ const vTarget = validateText(input.target, 'target');
385
+ if (!vTarget.valid)
386
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
387
+ if (input.session) {
388
+ const vS = validateIdentifier(input.session, 'session');
389
+ if (!vS.valid)
390
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
391
+ }
317
392
  const { target, session } = input;
318
393
  return execBrowserCommand(['hover', target], session);
319
394
  },
@@ -333,6 +408,17 @@ export const browserTools = [
333
408
  required: ['target', 'value'],
334
409
  },
335
410
  handler: async (input) => {
411
+ const vTarget = validateText(input.target, 'target');
412
+ if (!vTarget.valid)
413
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
414
+ const vValue = validateText(input.value, 'value');
415
+ if (!vValue.valid)
416
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vValue.error }) }], isError: true };
417
+ if (input.session) {
418
+ const vS = validateIdentifier(input.session, 'session');
419
+ if (!vS.valid)
420
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
421
+ }
336
422
  const { target, value, session } = input;
337
423
  return execBrowserCommand(['select', target, value], session);
338
424
  },
@@ -351,6 +437,14 @@ export const browserTools = [
351
437
  required: ['target'],
352
438
  },
353
439
  handler: async (input) => {
440
+ const vTarget = validateText(input.target, 'target');
441
+ if (!vTarget.valid)
442
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
443
+ if (input.session) {
444
+ const vS = validateIdentifier(input.session, 'session');
445
+ if (!vS.valid)
446
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
447
+ }
354
448
  const { target, session } = input;
355
449
  return execBrowserCommand(['check', target], session);
356
450
  },
@@ -369,6 +463,14 @@ export const browserTools = [
369
463
  required: ['target'],
370
464
  },
371
465
  handler: async (input) => {
466
+ const vTarget = validateText(input.target, 'target');
467
+ if (!vTarget.valid)
468
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
469
+ if (input.session) {
470
+ const vS = validateIdentifier(input.session, 'session');
471
+ if (!vS.valid)
472
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
473
+ }
372
474
  const { target, session } = input;
373
475
  return execBrowserCommand(['uncheck', target], session);
374
476
  },
@@ -412,6 +514,14 @@ export const browserTools = [
412
514
  required: ['target'],
413
515
  },
414
516
  handler: async (input) => {
517
+ const vTarget = validateText(input.target, 'target');
518
+ if (!vTarget.valid)
519
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
520
+ if (input.session) {
521
+ const vS = validateIdentifier(input.session, 'session');
522
+ if (!vS.valid)
523
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
524
+ }
415
525
  const { target, session } = input;
416
526
  return execBrowserCommand(['get', 'text', target], session);
417
527
  },
@@ -430,6 +540,14 @@ export const browserTools = [
430
540
  required: ['target'],
431
541
  },
432
542
  handler: async (input) => {
543
+ const vTarget = validateText(input.target, 'target');
544
+ if (!vTarget.valid)
545
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vTarget.error }) }], isError: true };
546
+ if (input.session) {
547
+ const vS = validateIdentifier(input.session, 'session');
548
+ if (!vS.valid)
549
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
550
+ }
433
551
  const { target, session } = input;
434
552
  return execBrowserCommand(['get', 'value', target], session);
435
553
  },
@@ -485,6 +603,26 @@ export const browserTools = [
485
603
  },
486
604
  },
487
605
  handler: async (input) => {
606
+ if (input.selector) {
607
+ const vSel = validateText(input.selector, 'selector');
608
+ if (!vSel.valid)
609
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vSel.error }) }], isError: true };
610
+ }
611
+ if (input.text) {
612
+ const vT = validateText(input.text, 'text');
613
+ if (!vT.valid)
614
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vT.error }) }], isError: true };
615
+ }
616
+ if (input.url) {
617
+ const vU = validateText(input.url, 'url');
618
+ if (!vU.valid)
619
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vU.error }) }], isError: true };
620
+ }
621
+ if (input.session) {
622
+ const vS = validateIdentifier(input.session, 'session');
623
+ if (!vS.valid)
624
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
625
+ }
488
626
  const { selector, text, url, timeout, session } = input;
489
627
  const args = ['wait'];
490
628
  if (selector)
@@ -515,6 +653,14 @@ export const browserTools = [
515
653
  required: ['script'],
516
654
  },
517
655
  handler: async (input) => {
656
+ const vScript = validateText(input.script, 'script');
657
+ if (!vScript.valid)
658
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vScript.error }) }], isError: true };
659
+ if (input.session) {
660
+ const vS = validateIdentifier(input.session, 'session');
661
+ if (!vS.valid)
662
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
663
+ }
518
664
  const { script, session } = input;
519
665
  return execBrowserCommand(['eval', script], session);
520
666
  },