registerTool method

void registerTool(
  1. ToolLifecycle lifecycle
)

Register tool lifecycle callbacks.

Implementation

void registerTool(ToolLifecycle lifecycle) {
  if (lifecycle.onToolRegistered != null) {
    _register(
      HookRegistration(
        id: 'lifecycle:tool:registered',
        type: HookType.onToolRegistration,
        priority: HookPriority.normal,
        name: 'Tool Registered Lifecycle',
        source: 'lifecycle',
        asyncHandler: (context) async {
          final event = ToolRegisteredEvent(
            timestamp: context.timestamp,
            sessionId: context.sessionId,
            metadata: context.metadata,
            toolName: context.metadata['toolName'] as String? ?? '',
            source: context.metadata['source'] as String? ?? 'unknown',
          );
          await lifecycle.onToolRegistered!(event);
          _emitEvent(event);
          return const HookContinue();
        },
      ),
    );
  }

  if (lifecycle.onToolBeforeExecution != null) {
    _register(
      HookRegistration(
        id: 'lifecycle:tool:before',
        type: HookType.preToolExecution,
        priority: HookPriority.normal,
        name: 'Tool Before Execution Lifecycle',
        source: 'lifecycle',
        asyncHandler: (context) async {
          if (context is! ToolHookContext) return const HookContinue();
          final event = ToolBeforeExecutionEvent(
            timestamp: context.timestamp,
            sessionId: context.sessionId,
            metadata: context.metadata,
            toolName: context.toolName,
            input: context.toolInput,
          );
          final modifiedInput = await lifecycle.onToolBeforeExecution!(event);
          _emitEvent(event);
          if (modifiedInput != null) {
            return HookTransform(modifiedInput);
          }
          return const HookContinue();
        },
      ),
    );
  }

  if (lifecycle.onToolAfterExecution != null) {
    _register(
      HookRegistration(
        id: 'lifecycle:tool:after',
        type: HookType.postToolExecution,
        priority: HookPriority.normal,
        name: 'Tool After Execution Lifecycle',
        source: 'lifecycle',
        asyncHandler: (context) async {
          if (context is! ToolHookContext) return const HookContinue();
          final event = ToolAfterExecutionEvent(
            timestamp: context.timestamp,
            sessionId: context.sessionId,
            metadata: context.metadata,
            toolName: context.toolName,
            input: context.toolInput,
            output: context.toolOutput ?? '',
            isError: context.toolIsError ?? false,
            executionDuration: context.executionDuration ?? Duration.zero,
          );
          final modifiedOutput = await lifecycle.onToolAfterExecution!(event);
          _emitEvent(event);
          if (modifiedOutput != null) {
            return HookTransform({'output': modifiedOutput});
          }
          return const HookContinue();
        },
      ),
    );
  }

  if (lifecycle.onToolError != null) {
    _register(
      HookRegistration(
        id: 'lifecycle:tool:error',
        type: HookType.onError,
        priority: HookPriority.normal,
        name: 'Tool Error Lifecycle',
        source: 'lifecycle',
        matcher: (context) =>
            context is ErrorHookContext && context.source == 'tool',
        asyncHandler: (context) async {
          if (context is! ErrorHookContext) return const HookContinue();
          final event = ToolErrorEvent(
            timestamp: context.timestamp,
            sessionId: context.sessionId,
            metadata: context.metadata,
            toolName: context.metadata['toolName'] as String? ?? '',
            input:
                context.metadata['toolInput'] as Map<String, dynamic>? ?? {},
            error: context.error,
            stackTrace: context.stackTrace,
          );
          final action = await lifecycle.onToolError!(event);
          _emitEvent(event);
          return switch (action) {
            ToolRecoveryAction.propagate => const HookContinue(),
            ToolRecoveryAction.retry => const HookRetry(Duration(seconds: 1)),
            ToolRecoveryAction.retryWithModifiedInput => const HookRetry(
              Duration(seconds: 1),
            ),
            ToolRecoveryAction.suppress => const HookSkip('Error suppressed'),
            ToolRecoveryAction.abortTurn => const HookAbort(
              'Turn aborted due to tool error',
            ),
          };
        },
      ),
    );
  }

  if (lifecycle.onToolTimeout != null) {
    _register(
      HookRegistration(
        id: 'lifecycle:tool:timeout',
        type: HookType.onError,
        priority: HookPriority.normal,
        name: 'Tool Timeout Lifecycle',
        source: 'lifecycle',
        matcher: (context) =>
            context is ErrorHookContext &&
            context.errorCategory == 'timeout' &&
            context.source == 'tool',
        asyncHandler: (context) async {
          if (context is! ErrorHookContext) return const HookContinue();
          final event = ToolTimeoutEvent(
            timestamp: context.timestamp,
            sessionId: context.sessionId,
            metadata: context.metadata,
            toolName: context.metadata['toolName'] as String? ?? '',
            input:
                context.metadata['toolInput'] as Map<String, dynamic>? ?? {},
            timeoutDuration:
                context.metadata['timeout'] as Duration? ??
                const Duration(seconds: 30),
          );
          await lifecycle.onToolTimeout!(event);
          _emitEvent(event);
          return const HookContinue();
        },
      ),
    );
  }
}