@lumenflow/core 1.0.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.
- package/LICENSE +190 -0
- package/README.md +119 -0
- package/dist/active-wu-detector.d.ts +33 -0
- package/dist/active-wu-detector.js +106 -0
- package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
- package/dist/adapters/filesystem-metrics.adapter.js +519 -0
- package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
- package/dist/adapters/terminal-renderer.adapter.js +337 -0
- package/dist/arg-parser.d.ts +63 -0
- package/dist/arg-parser.js +560 -0
- package/dist/backlog-editor.d.ts +98 -0
- package/dist/backlog-editor.js +179 -0
- package/dist/backlog-generator.d.ts +111 -0
- package/dist/backlog-generator.js +381 -0
- package/dist/backlog-parser.d.ts +45 -0
- package/dist/backlog-parser.js +102 -0
- package/dist/backlog-sync-validator.d.ts +78 -0
- package/dist/backlog-sync-validator.js +294 -0
- package/dist/branch-drift.d.ts +34 -0
- package/dist/branch-drift.js +51 -0
- package/dist/cleanup-install-config.d.ts +33 -0
- package/dist/cleanup-install-config.js +37 -0
- package/dist/cleanup-lock.d.ts +139 -0
- package/dist/cleanup-lock.js +313 -0
- package/dist/code-path-validator.d.ts +146 -0
- package/dist/code-path-validator.js +537 -0
- package/dist/code-paths-overlap.d.ts +55 -0
- package/dist/code-paths-overlap.js +245 -0
- package/dist/commands-logger.d.ts +77 -0
- package/dist/commands-logger.js +254 -0
- package/dist/commit-message-utils.d.ts +25 -0
- package/dist/commit-message-utils.js +41 -0
- package/dist/compliance-parser.d.ts +150 -0
- package/dist/compliance-parser.js +507 -0
- package/dist/constants/backlog-patterns.d.ts +20 -0
- package/dist/constants/backlog-patterns.js +23 -0
- package/dist/constants/dora-constants.d.ts +49 -0
- package/dist/constants/dora-constants.js +53 -0
- package/dist/constants/gate-constants.d.ts +15 -0
- package/dist/constants/gate-constants.js +15 -0
- package/dist/constants/linter-constants.d.ts +16 -0
- package/dist/constants/linter-constants.js +16 -0
- package/dist/constants/tokenizer-constants.d.ts +15 -0
- package/dist/constants/tokenizer-constants.js +15 -0
- package/dist/core/scope-checker.d.ts +97 -0
- package/dist/core/scope-checker.js +163 -0
- package/dist/core/tool-runner.d.ts +161 -0
- package/dist/core/tool-runner.js +393 -0
- package/dist/core/tool.constants.d.ts +105 -0
- package/dist/core/tool.constants.js +101 -0
- package/dist/core/tool.schemas.d.ts +226 -0
- package/dist/core/tool.schemas.js +226 -0
- package/dist/core/worktree-guard.d.ts +130 -0
- package/dist/core/worktree-guard.js +242 -0
- package/dist/coverage-gate.d.ts +108 -0
- package/dist/coverage-gate.js +196 -0
- package/dist/date-utils.d.ts +75 -0
- package/dist/date-utils.js +140 -0
- package/dist/dependency-graph.d.ts +142 -0
- package/dist/dependency-graph.js +550 -0
- package/dist/dependency-guard.d.ts +54 -0
- package/dist/dependency-guard.js +142 -0
- package/dist/dependency-validator.d.ts +105 -0
- package/dist/dependency-validator.js +154 -0
- package/dist/docs-path-validator.d.ts +36 -0
- package/dist/docs-path-validator.js +95 -0
- package/dist/domain/orchestration.constants.d.ts +99 -0
- package/dist/domain/orchestration.constants.js +97 -0
- package/dist/domain/orchestration.schemas.d.ts +280 -0
- package/dist/domain/orchestration.schemas.js +211 -0
- package/dist/domain/orchestration.types.d.ts +133 -0
- package/dist/domain/orchestration.types.js +12 -0
- package/dist/error-handler.d.ts +116 -0
- package/dist/error-handler.js +136 -0
- package/dist/file-classifiers.d.ts +62 -0
- package/dist/file-classifiers.js +108 -0
- package/dist/gates-agent-mode.d.ts +81 -0
- package/dist/gates-agent-mode.js +94 -0
- package/dist/generate-traceability.d.ts +107 -0
- package/dist/generate-traceability.js +411 -0
- package/dist/git-adapter.d.ts +395 -0
- package/dist/git-adapter.js +649 -0
- package/dist/git-staged-validator.d.ts +32 -0
- package/dist/git-staged-validator.js +48 -0
- package/dist/hardcoded-strings.d.ts +61 -0
- package/dist/hardcoded-strings.js +270 -0
- package/dist/incremental-lint.d.ts +78 -0
- package/dist/incremental-lint.js +129 -0
- package/dist/incremental-test.d.ts +39 -0
- package/dist/incremental-test.js +61 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +61 -0
- package/dist/invariants/check-automated-tests.d.ts +50 -0
- package/dist/invariants/check-automated-tests.js +166 -0
- package/dist/invariants-runner.d.ts +103 -0
- package/dist/invariants-runner.js +527 -0
- package/dist/lane-checker.d.ts +50 -0
- package/dist/lane-checker.js +319 -0
- package/dist/lane-inference.d.ts +39 -0
- package/dist/lane-inference.js +195 -0
- package/dist/lane-lock.d.ts +211 -0
- package/dist/lane-lock.js +474 -0
- package/dist/lane-validator.d.ts +48 -0
- package/dist/lane-validator.js +114 -0
- package/dist/logs-lib.d.ts +104 -0
- package/dist/logs-lib.js +207 -0
- package/dist/lumenflow-config-schema.d.ts +272 -0
- package/dist/lumenflow-config-schema.js +207 -0
- package/dist/lumenflow-config.d.ts +95 -0
- package/dist/lumenflow-config.js +236 -0
- package/dist/manual-test-validator.d.ts +80 -0
- package/dist/manual-test-validator.js +200 -0
- package/dist/merge-lock.d.ts +115 -0
- package/dist/merge-lock.js +251 -0
- package/dist/micro-worktree.d.ts +159 -0
- package/dist/micro-worktree.js +427 -0
- package/dist/migration-deployer.d.ts +69 -0
- package/dist/migration-deployer.js +151 -0
- package/dist/orchestration-advisory-loader.d.ts +28 -0
- package/dist/orchestration-advisory-loader.js +87 -0
- package/dist/orchestration-advisory.d.ts +58 -0
- package/dist/orchestration-advisory.js +94 -0
- package/dist/orchestration-di.d.ts +48 -0
- package/dist/orchestration-di.js +57 -0
- package/dist/orchestration-rules.d.ts +57 -0
- package/dist/orchestration-rules.js +201 -0
- package/dist/orphan-detector.d.ts +131 -0
- package/dist/orphan-detector.js +226 -0
- package/dist/path-classifiers.d.ts +57 -0
- package/dist/path-classifiers.js +93 -0
- package/dist/piped-command-detector.d.ts +34 -0
- package/dist/piped-command-detector.js +64 -0
- package/dist/ports/dashboard-renderer.port.d.ts +112 -0
- package/dist/ports/dashboard-renderer.port.js +25 -0
- package/dist/ports/metrics-collector.port.d.ts +132 -0
- package/dist/ports/metrics-collector.port.js +26 -0
- package/dist/process-detector.d.ts +84 -0
- package/dist/process-detector.js +172 -0
- package/dist/prompt-linter.d.ts +72 -0
- package/dist/prompt-linter.js +312 -0
- package/dist/prompt-monitor.d.ts +15 -0
- package/dist/prompt-monitor.js +205 -0
- package/dist/rebase-artifact-cleanup.d.ts +145 -0
- package/dist/rebase-artifact-cleanup.js +433 -0
- package/dist/retry-strategy.d.ts +189 -0
- package/dist/retry-strategy.js +283 -0
- package/dist/risk-detector.d.ts +108 -0
- package/dist/risk-detector.js +252 -0
- package/dist/rollback-utils.d.ts +76 -0
- package/dist/rollback-utils.js +104 -0
- package/dist/section-headings.d.ts +43 -0
- package/dist/section-headings.js +49 -0
- package/dist/spawn-escalation.d.ts +90 -0
- package/dist/spawn-escalation.js +253 -0
- package/dist/spawn-monitor.d.ts +229 -0
- package/dist/spawn-monitor.js +672 -0
- package/dist/spawn-recovery.d.ts +82 -0
- package/dist/spawn-recovery.js +298 -0
- package/dist/spawn-registry-schema.d.ts +98 -0
- package/dist/spawn-registry-schema.js +108 -0
- package/dist/spawn-registry-store.d.ts +146 -0
- package/dist/spawn-registry-store.js +273 -0
- package/dist/spawn-tree.d.ts +121 -0
- package/dist/spawn-tree.js +285 -0
- package/dist/stamp-status-validator.d.ts +84 -0
- package/dist/stamp-status-validator.js +134 -0
- package/dist/stamp-utils.d.ts +100 -0
- package/dist/stamp-utils.js +229 -0
- package/dist/state-machine.d.ts +26 -0
- package/dist/state-machine.js +83 -0
- package/dist/system-map-validator.d.ts +80 -0
- package/dist/system-map-validator.js +272 -0
- package/dist/telemetry.d.ts +80 -0
- package/dist/telemetry.js +213 -0
- package/dist/token-counter.d.ts +51 -0
- package/dist/token-counter.js +145 -0
- package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
- package/dist/usecases/get-dashboard-data.usecase.js +61 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
- package/dist/usecases/get-suggestions.usecase.js +153 -0
- package/dist/user-normalizer.d.ts +41 -0
- package/dist/user-normalizer.js +141 -0
- package/dist/validators/phi-constants.d.ts +97 -0
- package/dist/validators/phi-constants.js +152 -0
- package/dist/validators/phi-scanner.d.ts +58 -0
- package/dist/validators/phi-scanner.js +215 -0
- package/dist/worktree-ownership.d.ts +50 -0
- package/dist/worktree-ownership.js +74 -0
- package/dist/worktree-scanner.d.ts +103 -0
- package/dist/worktree-scanner.js +168 -0
- package/dist/worktree-symlink.d.ts +99 -0
- package/dist/worktree-symlink.js +359 -0
- package/dist/wu-backlog-updater.d.ts +17 -0
- package/dist/wu-backlog-updater.js +37 -0
- package/dist/wu-checkpoint.d.ts +124 -0
- package/dist/wu-checkpoint.js +233 -0
- package/dist/wu-claim-helpers.d.ts +26 -0
- package/dist/wu-claim-helpers.js +63 -0
- package/dist/wu-claim-resume.d.ts +106 -0
- package/dist/wu-claim-resume.js +276 -0
- package/dist/wu-consistency-checker.d.ts +95 -0
- package/dist/wu-consistency-checker.js +567 -0
- package/dist/wu-constants.d.ts +1275 -0
- package/dist/wu-constants.js +1382 -0
- package/dist/wu-create-validators.d.ts +42 -0
- package/dist/wu-create-validators.js +93 -0
- package/dist/wu-done-branch-only.d.ts +63 -0
- package/dist/wu-done-branch-only.js +191 -0
- package/dist/wu-done-messages.d.ts +119 -0
- package/dist/wu-done-messages.js +185 -0
- package/dist/wu-done-pr.d.ts +72 -0
- package/dist/wu-done-pr.js +174 -0
- package/dist/wu-done-retry-helpers.d.ts +85 -0
- package/dist/wu-done-retry-helpers.js +172 -0
- package/dist/wu-done-ui.d.ts +37 -0
- package/dist/wu-done-ui.js +69 -0
- package/dist/wu-done-validators.d.ts +411 -0
- package/dist/wu-done-validators.js +1229 -0
- package/dist/wu-done-worktree.d.ts +182 -0
- package/dist/wu-done-worktree.js +1097 -0
- package/dist/wu-helpers.d.ts +128 -0
- package/dist/wu-helpers.js +248 -0
- package/dist/wu-lint.d.ts +70 -0
- package/dist/wu-lint.js +234 -0
- package/dist/wu-paths.d.ts +171 -0
- package/dist/wu-paths.js +178 -0
- package/dist/wu-preflight-validators.d.ts +86 -0
- package/dist/wu-preflight-validators.js +251 -0
- package/dist/wu-recovery.d.ts +138 -0
- package/dist/wu-recovery.js +341 -0
- package/dist/wu-repair-core.d.ts +131 -0
- package/dist/wu-repair-core.js +669 -0
- package/dist/wu-schema-normalization.d.ts +17 -0
- package/dist/wu-schema-normalization.js +82 -0
- package/dist/wu-schema.d.ts +793 -0
- package/dist/wu-schema.js +881 -0
- package/dist/wu-spawn-helpers.d.ts +121 -0
- package/dist/wu-spawn-helpers.js +271 -0
- package/dist/wu-spawn.d.ts +158 -0
- package/dist/wu-spawn.js +1306 -0
- package/dist/wu-state-schema.d.ts +213 -0
- package/dist/wu-state-schema.js +156 -0
- package/dist/wu-state-store.d.ts +264 -0
- package/dist/wu-state-store.js +691 -0
- package/dist/wu-status-transition.d.ts +63 -0
- package/dist/wu-status-transition.js +382 -0
- package/dist/wu-status-updater.d.ts +25 -0
- package/dist/wu-status-updater.js +116 -0
- package/dist/wu-transaction-collectors.d.ts +116 -0
- package/dist/wu-transaction-collectors.js +272 -0
- package/dist/wu-transaction.d.ts +170 -0
- package/dist/wu-transaction.js +273 -0
- package/dist/wu-validation-constants.d.ts +60 -0
- package/dist/wu-validation-constants.js +66 -0
- package/dist/wu-validation.d.ts +118 -0
- package/dist/wu-validation.js +243 -0
- package/dist/wu-validator.d.ts +62 -0
- package/dist/wu-validator.js +325 -0
- package/dist/wu-yaml-fixer.d.ts +97 -0
- package/dist/wu-yaml-fixer.js +264 -0
- package/dist/wu-yaml.d.ts +86 -0
- package/dist/wu-yaml.js +222 -0
- package/package.json +114 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tool-runner.mjs
|
|
3
|
+
* @description Unified tool execution layer integrating all core components (WU-1398)
|
|
4
|
+
*
|
|
5
|
+
* This module provides a higher-order function pattern for executing tools with:
|
|
6
|
+
* - Input validation via Zod schemas (tool.schemas.ts)
|
|
7
|
+
* - Worktree context detection (worktree-guard.mjs)
|
|
8
|
+
* - Scope validation against code_paths (scope-checker.mjs)
|
|
9
|
+
* - Audit logging for telemetry (.beacon/telemetry/tools.ndjson)
|
|
10
|
+
* - Consistent error handling with agent-friendly messages
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { runTool, ToolRunner, createToolConfig } from './tool-runner.js';
|
|
14
|
+
*
|
|
15
|
+
* // Direct invocation
|
|
16
|
+
* const result = await runTool(toolDefinition, { arg: 'value' });
|
|
17
|
+
*
|
|
18
|
+
* // Registry-based invocation
|
|
19
|
+
* const runner = new ToolRunner();
|
|
20
|
+
* runner.register(myTool);
|
|
21
|
+
* const result = await runner.run('tool:name', { arg: 'value' });
|
|
22
|
+
*
|
|
23
|
+
* @see tools/lib/core/tool.schemas.ts - Zod schemas for tool I/O
|
|
24
|
+
* @see tools/lib/core/worktree-guard.mjs - WU context detection
|
|
25
|
+
* @see tools/lib/core/scope-checker.mjs - Code path validation
|
|
26
|
+
*/
|
|
27
|
+
import { TOOL_ERROR_CODES, PERMISSION_LEVELS, TOOL_STATUS, DEFAULT_TOOL_TIMEOUT_MS, } from './tool.constants.js';
|
|
28
|
+
import { validateToolInput, createErrorOutput } from './tool.schemas.js';
|
|
29
|
+
import { getWUContext, assertWorktreeRequired } from './worktree-guard.js';
|
|
30
|
+
import { getActiveScope, isPathInScope } from './scope-checker.js';
|
|
31
|
+
/**
|
|
32
|
+
* Default configuration values for tool runner
|
|
33
|
+
*/
|
|
34
|
+
export const RUNNER_DEFAULTS = {
|
|
35
|
+
/** Default timeout for tool execution in milliseconds */
|
|
36
|
+
TIMEOUT_MS: DEFAULT_TOOL_TIMEOUT_MS,
|
|
37
|
+
/** Enable audit logging by default */
|
|
38
|
+
ENABLE_AUDIT_LOG: true,
|
|
39
|
+
/** Default: read tools don't require worktree */
|
|
40
|
+
REQUIRES_WORKTREE: false,
|
|
41
|
+
/** Default: read tools don't require scope check */
|
|
42
|
+
REQUIRES_SCOPE: false,
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Create tool configuration with sensible defaults
|
|
46
|
+
*
|
|
47
|
+
* @param {object} tool - Tool definition
|
|
48
|
+
* @param {object} options - Configuration overrides
|
|
49
|
+
* @returns {object} Merged configuration
|
|
50
|
+
*/
|
|
51
|
+
export function createToolConfig(tool, options = {}) {
|
|
52
|
+
const isWriteOperation = tool.metadata.permission === PERMISSION_LEVELS.WRITE ||
|
|
53
|
+
tool.metadata.permission === PERMISSION_LEVELS.ADMIN;
|
|
54
|
+
return {
|
|
55
|
+
requiresWorktree: options.requiresWorktree ?? isWriteOperation,
|
|
56
|
+
requiresScope: options.requiresScope ?? isWriteOperation,
|
|
57
|
+
enableAuditLog: options.enableAuditLog ?? RUNNER_DEFAULTS.ENABLE_AUDIT_LOG,
|
|
58
|
+
timeoutMs: options.timeoutMs ?? RUNNER_DEFAULTS.TIMEOUT_MS,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extract file path from tool input if present
|
|
63
|
+
*
|
|
64
|
+
* @param {object} input - Tool input
|
|
65
|
+
* @returns {string|null} File path or null
|
|
66
|
+
*/
|
|
67
|
+
function extractFilePath(input) {
|
|
68
|
+
// Common field names for file paths
|
|
69
|
+
const pathFields = ['path', 'filePath', 'file', 'targetPath'];
|
|
70
|
+
for (const field of pathFields) {
|
|
71
|
+
if (typeof input[field] === 'string') {
|
|
72
|
+
return input[field];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create default dependencies using real implementations
|
|
79
|
+
*
|
|
80
|
+
* @returns {object} Default dependency implementations
|
|
81
|
+
*/
|
|
82
|
+
function createDefaultDependencies() {
|
|
83
|
+
return {
|
|
84
|
+
getWUContext,
|
|
85
|
+
getActiveScope,
|
|
86
|
+
isPathInScope,
|
|
87
|
+
assertWorktreeRequired,
|
|
88
|
+
logAudit: createAuditLogger(),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create audit logger function
|
|
93
|
+
*
|
|
94
|
+
* @returns {Function} Audit logging function
|
|
95
|
+
*/
|
|
96
|
+
function createAuditLogger() {
|
|
97
|
+
return (entry) => {
|
|
98
|
+
// Write to NDJSON telemetry file
|
|
99
|
+
// Implementation deferred - currently no-op for testing
|
|
100
|
+
// Will integrate with .beacon/telemetry/tools.ndjson in future WU
|
|
101
|
+
void entry;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Generate helpful suggestions for validation errors
|
|
106
|
+
*
|
|
107
|
+
* @param {object} tool - Tool definition
|
|
108
|
+
* @param {object} zodError - Zod validation error
|
|
109
|
+
* @returns {string[]} Array of suggestions
|
|
110
|
+
*/
|
|
111
|
+
function generateValidationHints(tool, zodError) {
|
|
112
|
+
const hints = [];
|
|
113
|
+
// Add field-specific hints
|
|
114
|
+
for (const issue of zodError.issues) {
|
|
115
|
+
const path = issue.path.join('.');
|
|
116
|
+
hints.push(`Field '${path}': ${issue.message}`);
|
|
117
|
+
}
|
|
118
|
+
// Add general help hint
|
|
119
|
+
hints.push(`Run with --help to see valid arguments for ${tool.metadata.name}`);
|
|
120
|
+
return hints;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Run a tool with full validation and guards
|
|
124
|
+
*
|
|
125
|
+
* @param {object} tool - Tool definition (metadata, inputSchema, execute)
|
|
126
|
+
* @param {object} input - Tool input arguments
|
|
127
|
+
* @param {object} options - Execution options
|
|
128
|
+
* @param {object} options.dependencies - Injected dependencies (for testing)
|
|
129
|
+
* @param {object} options.config - Configuration overrides
|
|
130
|
+
* @param {object} options.context - Execution context (sessionId, etc.)
|
|
131
|
+
* @returns {Promise<object>} Tool output (success/failure with data/error)
|
|
132
|
+
*/
|
|
133
|
+
export async function runTool(tool, input, options = {}) {
|
|
134
|
+
const startTime = Date.now();
|
|
135
|
+
const startedAt = new Date().toISOString();
|
|
136
|
+
// Merge dependencies with defaults
|
|
137
|
+
const deps = {
|
|
138
|
+
...createDefaultDependencies(),
|
|
139
|
+
...options.dependencies,
|
|
140
|
+
};
|
|
141
|
+
// Create configuration
|
|
142
|
+
const config = createToolConfig(tool, options.config);
|
|
143
|
+
// Get WU context for audit logging
|
|
144
|
+
let wuContext = null;
|
|
145
|
+
try {
|
|
146
|
+
wuContext = await deps.getWUContext();
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Context retrieval failure is non-fatal
|
|
150
|
+
wuContext = null;
|
|
151
|
+
}
|
|
152
|
+
// Build execution metadata
|
|
153
|
+
const metadata = {
|
|
154
|
+
startedAt,
|
|
155
|
+
durationMs: 0,
|
|
156
|
+
};
|
|
157
|
+
// Helper to create audit log entry
|
|
158
|
+
const createAuditEntry = (status, output, error) => ({
|
|
159
|
+
tool: tool.metadata.name,
|
|
160
|
+
status,
|
|
161
|
+
startedAt,
|
|
162
|
+
completedAt: new Date().toISOString(),
|
|
163
|
+
durationMs: Date.now() - startTime,
|
|
164
|
+
input,
|
|
165
|
+
output,
|
|
166
|
+
error,
|
|
167
|
+
context: wuContext
|
|
168
|
+
? {
|
|
169
|
+
wuId: wuContext.wuId,
|
|
170
|
+
lane: wuContext.lane,
|
|
171
|
+
worktreePath: wuContext.worktreePath,
|
|
172
|
+
}
|
|
173
|
+
: {},
|
|
174
|
+
});
|
|
175
|
+
try {
|
|
176
|
+
// Step 1: Validate input schema
|
|
177
|
+
const validation = validateToolInput(input, tool.inputSchema);
|
|
178
|
+
if (!validation.success) {
|
|
179
|
+
const validationError = validation;
|
|
180
|
+
const errorOutput = createErrorOutput({
|
|
181
|
+
code: TOOL_ERROR_CODES.SCHEMA_VALIDATION_FAILED,
|
|
182
|
+
message: `Input validation failed for ${tool.metadata.name}`,
|
|
183
|
+
details: { issues: validationError.error.issues },
|
|
184
|
+
tryNext: generateValidationHints(tool, validationError.error),
|
|
185
|
+
}, metadata);
|
|
186
|
+
if (config.enableAuditLog) {
|
|
187
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.FAILED, null, errorOutput.error));
|
|
188
|
+
}
|
|
189
|
+
return errorOutput;
|
|
190
|
+
}
|
|
191
|
+
// Narrow validation to success case
|
|
192
|
+
const validatedInput = validation;
|
|
193
|
+
// Step 2: Check worktree requirement
|
|
194
|
+
if (config.requiresWorktree) {
|
|
195
|
+
try {
|
|
196
|
+
await deps.assertWorktreeRequired({
|
|
197
|
+
operation: tool.metadata.name,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
202
|
+
const errorOutput = createErrorOutput({
|
|
203
|
+
code: TOOL_ERROR_CODES.PERMISSION_DENIED,
|
|
204
|
+
message: errMessage,
|
|
205
|
+
tryNext: [
|
|
206
|
+
'Claim a WU first: pnpm wu:claim --id WU-XXX --lane "Your Lane"',
|
|
207
|
+
'Then change to the worktree directory',
|
|
208
|
+
],
|
|
209
|
+
}, metadata);
|
|
210
|
+
if (config.enableAuditLog) {
|
|
211
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.FAILED, null, errorOutput.error));
|
|
212
|
+
}
|
|
213
|
+
return errorOutput;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Step 3: Check scope for write operations with file paths
|
|
217
|
+
if (config.requiresScope) {
|
|
218
|
+
const filePath = extractFilePath(validatedInput.data);
|
|
219
|
+
if (filePath) {
|
|
220
|
+
const scope = await deps.getActiveScope();
|
|
221
|
+
// If we have a scope, validate the path
|
|
222
|
+
if (scope &&
|
|
223
|
+
!deps.isPathInScope(filePath, scope)) {
|
|
224
|
+
const errorOutput = createErrorOutput({
|
|
225
|
+
code: TOOL_ERROR_CODES.PERMISSION_DENIED,
|
|
226
|
+
message: `Path '${filePath}' is outside WU scope for ${scope.wuId}`,
|
|
227
|
+
details: {
|
|
228
|
+
path: filePath,
|
|
229
|
+
allowedPaths: scope.code_paths,
|
|
230
|
+
},
|
|
231
|
+
tryNext: [
|
|
232
|
+
`Only modify files matching: ${scope.code_paths.join(', ')}`,
|
|
233
|
+
'Update WU code_paths if this file should be in scope',
|
|
234
|
+
],
|
|
235
|
+
}, metadata);
|
|
236
|
+
if (config.enableAuditLog) {
|
|
237
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.FAILED, null, errorOutput.error));
|
|
238
|
+
}
|
|
239
|
+
return errorOutput;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Step 4: Execute the tool
|
|
244
|
+
const result = (await tool.execute(validatedInput.data, options.context));
|
|
245
|
+
// Step 5: Validate output if schema defined
|
|
246
|
+
if (tool.outputSchema && result.success && result.data) {
|
|
247
|
+
const outputValidation = validateToolInput(result.data, tool.outputSchema);
|
|
248
|
+
if (!outputValidation.success) {
|
|
249
|
+
const outputValidationError = outputValidation;
|
|
250
|
+
const errorOutput = createErrorOutput({
|
|
251
|
+
code: TOOL_ERROR_CODES.INVALID_OUTPUT,
|
|
252
|
+
message: `Tool ${tool.metadata.name} produced invalid output`,
|
|
253
|
+
details: { issues: outputValidationError.error.issues },
|
|
254
|
+
}, { ...metadata, durationMs: Date.now() - startTime });
|
|
255
|
+
if (config.enableAuditLog) {
|
|
256
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.FAILED, null, errorOutput.error));
|
|
257
|
+
}
|
|
258
|
+
return errorOutput;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Add metadata to result
|
|
262
|
+
const resultMetadata = result.metadata || {};
|
|
263
|
+
const finalResult = {
|
|
264
|
+
...result,
|
|
265
|
+
metadata: {
|
|
266
|
+
...resultMetadata,
|
|
267
|
+
...metadata,
|
|
268
|
+
durationMs: Date.now() - startTime,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
// Log successful execution
|
|
272
|
+
if (config.enableAuditLog) {
|
|
273
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.SUCCESS, finalResult, null));
|
|
274
|
+
}
|
|
275
|
+
return finalResult;
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
// Handle unexpected execution errors
|
|
279
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
280
|
+
const errorStack = err instanceof Error ? err.stack : undefined;
|
|
281
|
+
const errorOutput = createErrorOutput({
|
|
282
|
+
code: TOOL_ERROR_CODES.EXECUTION_FAILED,
|
|
283
|
+
message: errorMessage,
|
|
284
|
+
stack: errorStack,
|
|
285
|
+
tryNext: ['Check tool input and try again', 'Report issue if problem persists'],
|
|
286
|
+
}, { ...metadata, durationMs: Date.now() - startTime });
|
|
287
|
+
if (config.enableAuditLog) {
|
|
288
|
+
deps.logAudit(createAuditEntry(TOOL_STATUS.FAILED, null, errorOutput.error));
|
|
289
|
+
}
|
|
290
|
+
return errorOutput;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Tool registry and runner class
|
|
295
|
+
*
|
|
296
|
+
* Provides a registry for tool definitions and a unified execution interface.
|
|
297
|
+
*/
|
|
298
|
+
export class ToolRunner {
|
|
299
|
+
#tools = new Map();
|
|
300
|
+
#config;
|
|
301
|
+
#dependencies;
|
|
302
|
+
/**
|
|
303
|
+
* Create a new ToolRunner instance
|
|
304
|
+
*
|
|
305
|
+
* @param {object} options - Runner options
|
|
306
|
+
* @param {boolean} options.enableAuditLog - Enable audit logging
|
|
307
|
+
* @param {number} options.timeoutMs - Default timeout
|
|
308
|
+
* @param {object} options.dependencies - Injected dependencies
|
|
309
|
+
*/
|
|
310
|
+
constructor(options = {}) {
|
|
311
|
+
this.#config = {
|
|
312
|
+
enableAuditLog: options.enableAuditLog ?? RUNNER_DEFAULTS.ENABLE_AUDIT_LOG,
|
|
313
|
+
timeoutMs: options.timeoutMs ?? RUNNER_DEFAULTS.TIMEOUT_MS,
|
|
314
|
+
};
|
|
315
|
+
this.#dependencies = options.dependencies || createDefaultDependencies();
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Register a tool definition
|
|
319
|
+
*
|
|
320
|
+
* @param {object} tool - Tool definition
|
|
321
|
+
* @throws {Error} If tool with same name already registered
|
|
322
|
+
*/
|
|
323
|
+
register(tool) {
|
|
324
|
+
const name = tool.metadata.name;
|
|
325
|
+
if (this.#tools.has(name)) {
|
|
326
|
+
throw new Error(`Tool '${name}' is already registered`);
|
|
327
|
+
}
|
|
328
|
+
this.#tools.set(name, tool);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Check if a tool is registered
|
|
332
|
+
*
|
|
333
|
+
* @param {string} name - Tool name
|
|
334
|
+
* @returns {boolean} True if tool exists
|
|
335
|
+
*/
|
|
336
|
+
hasTool(name) {
|
|
337
|
+
return this.#tools.has(name);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Run a registered tool by name
|
|
341
|
+
*
|
|
342
|
+
* @param {string} name - Tool name
|
|
343
|
+
* @param {object} input - Tool input
|
|
344
|
+
* @param {object} options - Execution options
|
|
345
|
+
* @returns {Promise<object>} Tool output
|
|
346
|
+
*/
|
|
347
|
+
async run(name, input, options = {}) {
|
|
348
|
+
const tool = this.#tools.get(name);
|
|
349
|
+
if (!tool) {
|
|
350
|
+
return createErrorOutput({
|
|
351
|
+
code: TOOL_ERROR_CODES.TOOL_NOT_FOUND,
|
|
352
|
+
message: `Tool '${name}' not found in registry`,
|
|
353
|
+
tryNext: ['Check tool name spelling', 'Use runner.listTools() to see available tools'],
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
return runTool(tool, input, {
|
|
357
|
+
...options,
|
|
358
|
+
dependencies: this.#dependencies,
|
|
359
|
+
config: { ...this.#config, ...options.config },
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get runner configuration
|
|
364
|
+
*
|
|
365
|
+
* @returns {object} Current configuration
|
|
366
|
+
*/
|
|
367
|
+
getConfig() {
|
|
368
|
+
return { ...this.#config };
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* List all registered tools
|
|
372
|
+
*
|
|
373
|
+
* @param {object} options - Filter options
|
|
374
|
+
* @param {string} options.domain - Filter by domain
|
|
375
|
+
* @returns {object[]} Array of tool metadata
|
|
376
|
+
*/
|
|
377
|
+
listTools(options = {}) {
|
|
378
|
+
const tools = [];
|
|
379
|
+
for (const tool of this.#tools.values()) {
|
|
380
|
+
if (options.domain && tool.metadata.domain !== options.domain) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
tools.push({
|
|
384
|
+
name: tool.metadata.name,
|
|
385
|
+
description: tool.metadata.description,
|
|
386
|
+
domain: tool.metadata.domain,
|
|
387
|
+
permission: tool.metadata.permission,
|
|
388
|
+
version: tool.metadata.version,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
return tools;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tool.constants.ts
|
|
3
|
+
* @description Shared constants for tool abstraction layer (WU-1394)
|
|
4
|
+
*
|
|
5
|
+
* Provides domain enums, error codes, and permission levels for unified
|
|
6
|
+
* tool system. Used by tool registry, audit logging, and provider adapters.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Tool domain categories for classification and routing
|
|
10
|
+
*/
|
|
11
|
+
export declare const TOOL_DOMAINS: {
|
|
12
|
+
/** Work Unit lifecycle operations (claim, done, block, etc.) */
|
|
13
|
+
readonly WU: "wu";
|
|
14
|
+
/** Git operations (commit, push, merge, etc.) */
|
|
15
|
+
readonly GIT: "git";
|
|
16
|
+
/** File system operations (read, write, delete, etc.) */
|
|
17
|
+
readonly FILE: "file";
|
|
18
|
+
/** Code exploration and search (grep, glob, find, etc.) */
|
|
19
|
+
readonly EXPLORE: "explore";
|
|
20
|
+
/** Testing operations (run tests, coverage, etc.) */
|
|
21
|
+
readonly TEST: "test";
|
|
22
|
+
/** Database operations (migrations, queries, etc.) */
|
|
23
|
+
readonly DB: "db";
|
|
24
|
+
/** Security operations (auth, permissions, audit, etc.) */
|
|
25
|
+
readonly SECURITY: "security";
|
|
26
|
+
/** Initiative management operations */
|
|
27
|
+
readonly INITIATIVE: "initiative";
|
|
28
|
+
/** Metrics and reporting operations */
|
|
29
|
+
readonly METRICS: "metrics";
|
|
30
|
+
/** Orchestration operations (status, suggest, etc.) */
|
|
31
|
+
readonly ORCHESTRATION: "orchestration";
|
|
32
|
+
/** Documentation operations (linting, validation, etc.) */
|
|
33
|
+
readonly DOCS: "docs";
|
|
34
|
+
/** General utility operations */
|
|
35
|
+
readonly UTIL: "util";
|
|
36
|
+
};
|
|
37
|
+
export type ToolDomain = (typeof TOOL_DOMAINS)[keyof typeof TOOL_DOMAINS];
|
|
38
|
+
/**
|
|
39
|
+
* Permission levels for access control
|
|
40
|
+
*/
|
|
41
|
+
export declare const PERMISSION_LEVELS: {
|
|
42
|
+
/** Read-only operations (no state changes) */
|
|
43
|
+
readonly READ: "read";
|
|
44
|
+
/** Write operations (modifies state) */
|
|
45
|
+
readonly WRITE: "write";
|
|
46
|
+
/** Administrative operations (destructive, requires elevated access) */
|
|
47
|
+
readonly ADMIN: "admin";
|
|
48
|
+
};
|
|
49
|
+
export type PermissionLevel = (typeof PERMISSION_LEVELS)[keyof typeof PERMISSION_LEVELS];
|
|
50
|
+
/**
|
|
51
|
+
* Tool error codes (extends existing ErrorCodes from error-handler.mjs)
|
|
52
|
+
*/
|
|
53
|
+
export declare const TOOL_ERROR_CODES: {
|
|
54
|
+
/** Tool not found in registry */
|
|
55
|
+
readonly TOOL_NOT_FOUND: "TOOL_NOT_FOUND";
|
|
56
|
+
/** Invalid tool input schema */
|
|
57
|
+
readonly INVALID_INPUT: "INVALID_INPUT";
|
|
58
|
+
/** Invalid tool output schema */
|
|
59
|
+
readonly INVALID_OUTPUT: "INVALID_OUTPUT";
|
|
60
|
+
/** Tool execution failed */
|
|
61
|
+
readonly EXECUTION_FAILED: "EXECUTION_FAILED";
|
|
62
|
+
/** Permission denied for tool operation */
|
|
63
|
+
readonly PERMISSION_DENIED: "PERMISSION_DENIED";
|
|
64
|
+
/** Tool timeout */
|
|
65
|
+
readonly TIMEOUT: "TIMEOUT";
|
|
66
|
+
/** Tool not available in current context */
|
|
67
|
+
readonly NOT_AVAILABLE: "NOT_AVAILABLE";
|
|
68
|
+
/** Schema validation failed */
|
|
69
|
+
readonly SCHEMA_VALIDATION_FAILED: "SCHEMA_VALIDATION_FAILED";
|
|
70
|
+
/** Missing required argument */
|
|
71
|
+
readonly MISSING_ARGUMENT: "MISSING_ARGUMENT";
|
|
72
|
+
/** Invalid argument type */
|
|
73
|
+
readonly INVALID_ARGUMENT_TYPE: "INVALID_ARGUMENT_TYPE";
|
|
74
|
+
/** Tool already registered */
|
|
75
|
+
readonly DUPLICATE_TOOL: "DUPLICATE_TOOL";
|
|
76
|
+
/** Provider adapter error */
|
|
77
|
+
readonly PROVIDER_ERROR: "PROVIDER_ERROR";
|
|
78
|
+
};
|
|
79
|
+
export type ToolErrorCode = (typeof TOOL_ERROR_CODES)[keyof typeof TOOL_ERROR_CODES];
|
|
80
|
+
/**
|
|
81
|
+
* Tool execution status values
|
|
82
|
+
*/
|
|
83
|
+
export declare const TOOL_STATUS: {
|
|
84
|
+
/** Tool execution pending */
|
|
85
|
+
readonly PENDING: "pending";
|
|
86
|
+
/** Tool currently executing */
|
|
87
|
+
readonly RUNNING: "running";
|
|
88
|
+
/** Tool execution completed successfully */
|
|
89
|
+
readonly SUCCESS: "success";
|
|
90
|
+
/** Tool execution failed */
|
|
91
|
+
readonly FAILED: "failed";
|
|
92
|
+
/** Tool execution timed out */
|
|
93
|
+
readonly TIMEOUT: "timeout";
|
|
94
|
+
/** Tool execution cancelled */
|
|
95
|
+
readonly CANCELLED: "cancelled";
|
|
96
|
+
};
|
|
97
|
+
export type ToolStatus = (typeof TOOL_STATUS)[keyof typeof TOOL_STATUS];
|
|
98
|
+
/**
|
|
99
|
+
* Default timeout for tool execution (milliseconds)
|
|
100
|
+
*/
|
|
101
|
+
export declare const DEFAULT_TOOL_TIMEOUT_MS = 30000;
|
|
102
|
+
/**
|
|
103
|
+
* Maximum number of retries for transient failures
|
|
104
|
+
*/
|
|
105
|
+
export declare const MAX_TOOL_RETRIES = 3;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tool.constants.ts
|
|
3
|
+
* @description Shared constants for tool abstraction layer (WU-1394)
|
|
4
|
+
*
|
|
5
|
+
* Provides domain enums, error codes, and permission levels for unified
|
|
6
|
+
* tool system. Used by tool registry, audit logging, and provider adapters.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Tool domain categories for classification and routing
|
|
10
|
+
*/
|
|
11
|
+
export const TOOL_DOMAINS = {
|
|
12
|
+
/** Work Unit lifecycle operations (claim, done, block, etc.) */
|
|
13
|
+
WU: 'wu',
|
|
14
|
+
/** Git operations (commit, push, merge, etc.) */
|
|
15
|
+
GIT: 'git',
|
|
16
|
+
/** File system operations (read, write, delete, etc.) */
|
|
17
|
+
FILE: 'file',
|
|
18
|
+
/** Code exploration and search (grep, glob, find, etc.) */
|
|
19
|
+
EXPLORE: 'explore',
|
|
20
|
+
/** Testing operations (run tests, coverage, etc.) */
|
|
21
|
+
TEST: 'test',
|
|
22
|
+
/** Database operations (migrations, queries, etc.) */
|
|
23
|
+
DB: 'db',
|
|
24
|
+
/** Security operations (auth, permissions, audit, etc.) */
|
|
25
|
+
SECURITY: 'security',
|
|
26
|
+
/** Initiative management operations */
|
|
27
|
+
INITIATIVE: 'initiative',
|
|
28
|
+
/** Metrics and reporting operations */
|
|
29
|
+
METRICS: 'metrics',
|
|
30
|
+
/** Orchestration operations (status, suggest, etc.) */
|
|
31
|
+
ORCHESTRATION: 'orchestration',
|
|
32
|
+
/** Documentation operations (linting, validation, etc.) */
|
|
33
|
+
DOCS: 'docs',
|
|
34
|
+
/** General utility operations */
|
|
35
|
+
UTIL: 'util',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Permission levels for access control
|
|
39
|
+
*/
|
|
40
|
+
export const PERMISSION_LEVELS = {
|
|
41
|
+
/** Read-only operations (no state changes) */
|
|
42
|
+
READ: 'read',
|
|
43
|
+
/** Write operations (modifies state) */
|
|
44
|
+
WRITE: 'write',
|
|
45
|
+
/** Administrative operations (destructive, requires elevated access) */
|
|
46
|
+
ADMIN: 'admin',
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Tool error codes (extends existing ErrorCodes from error-handler.mjs)
|
|
50
|
+
*/
|
|
51
|
+
export const TOOL_ERROR_CODES = {
|
|
52
|
+
/** Tool not found in registry */
|
|
53
|
+
TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',
|
|
54
|
+
/** Invalid tool input schema */
|
|
55
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
56
|
+
/** Invalid tool output schema */
|
|
57
|
+
INVALID_OUTPUT: 'INVALID_OUTPUT',
|
|
58
|
+
/** Tool execution failed */
|
|
59
|
+
EXECUTION_FAILED: 'EXECUTION_FAILED',
|
|
60
|
+
/** Permission denied for tool operation */
|
|
61
|
+
PERMISSION_DENIED: 'PERMISSION_DENIED',
|
|
62
|
+
/** Tool timeout */
|
|
63
|
+
TIMEOUT: 'TIMEOUT',
|
|
64
|
+
/** Tool not available in current context */
|
|
65
|
+
NOT_AVAILABLE: 'NOT_AVAILABLE',
|
|
66
|
+
/** Schema validation failed */
|
|
67
|
+
SCHEMA_VALIDATION_FAILED: 'SCHEMA_VALIDATION_FAILED',
|
|
68
|
+
/** Missing required argument */
|
|
69
|
+
MISSING_ARGUMENT: 'MISSING_ARGUMENT',
|
|
70
|
+
/** Invalid argument type */
|
|
71
|
+
INVALID_ARGUMENT_TYPE: 'INVALID_ARGUMENT_TYPE',
|
|
72
|
+
/** Tool already registered */
|
|
73
|
+
DUPLICATE_TOOL: 'DUPLICATE_TOOL',
|
|
74
|
+
/** Provider adapter error */
|
|
75
|
+
PROVIDER_ERROR: 'PROVIDER_ERROR',
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Tool execution status values
|
|
79
|
+
*/
|
|
80
|
+
export const TOOL_STATUS = {
|
|
81
|
+
/** Tool execution pending */
|
|
82
|
+
PENDING: 'pending',
|
|
83
|
+
/** Tool currently executing */
|
|
84
|
+
RUNNING: 'running',
|
|
85
|
+
/** Tool execution completed successfully */
|
|
86
|
+
SUCCESS: 'success',
|
|
87
|
+
/** Tool execution failed */
|
|
88
|
+
FAILED: 'failed',
|
|
89
|
+
/** Tool execution timed out */
|
|
90
|
+
TIMEOUT: 'timeout',
|
|
91
|
+
/** Tool execution cancelled */
|
|
92
|
+
CANCELLED: 'cancelled',
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Default timeout for tool execution (milliseconds)
|
|
96
|
+
*/
|
|
97
|
+
export const DEFAULT_TOOL_TIMEOUT_MS = 30000; // 30 seconds
|
|
98
|
+
/**
|
|
99
|
+
* Maximum number of retries for transient failures
|
|
100
|
+
*/
|
|
101
|
+
export const MAX_TOOL_RETRIES = 3;
|