Skip to content

Conversation

notJoon
Copy link
Contributor

@notJoon notJoon commented Jul 21, 2025

Summary

WIP

Related Issue

Reference the related issue(s) by number, e.g.:

Changes

List the specific modifications made in this PR.
Focus on what was changed without going into detail about impact.

Benefits

Describe the advantages or improvements brought by these changes.
Explain how these changes affect the project, users, or performance.

Checklist

  • Did you add a changelog entry to the CHANGES.md?
  • Did you write some relevant docs about this change (if it's a new feature)?
  • Did you write a regression test to reproduce the bug (if it's a bug fix)?
  • Did you write some tests for this change (if it's a new feature)?
  • Did you run deno task test-all on your machine?

Additional Notes

Include any other information, context, or considerations.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @notJoon, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new debugging capability to the CLI, enabling developers to gain real-time insights into ActivityPub federation traffic. It provides a flexible and powerful toolset for monitoring inbound and outbound activities, offering both a web-based dashboard for visual analysis and a terminal interface for command-line driven debugging. This feature will greatly assist in understanding and troubleshooting ActivityPub interactions within the application.

Highlights

  • New debug CLI Command: Introduces a powerful new debug command to the CLI for real-time monitoring and analysis of ActivityPub federation activities.
  • Dual Debugging Interfaces: Provides two distinct ways to debug: a web-based dashboard for a rich, interactive experience and a terminal-based interface for quick, command-line inspection.
  • Real-time Activity Monitoring: The core functionality allows users to intercept and view inbound and outbound ActivityPub activities as they happen.
  • Comprehensive Activity Data: Captured activities include direction (inbound/outbound), type, timestamp, and the full raw ActivityPub JSON, aiding in detailed debugging.
  • Activity Storage and Search: Activities are stored in a circular buffer (ActivityStore) with configurable capacity, enabling retrieval, filtering by type, direction, and time range, and statistical analysis.
  • Flexible Terminal Output: The terminal debugger offers options for following real-time streams, showing the last N activities, filtering, displaying statistics, and viewing raw activity JSON, with customizable colorization.
  • Web Dashboard API & WebSockets: The web dashboard exposes REST API endpoints for activities and statistics, and a WebSocket endpoint for real-time updates, facilitating external tool integration or custom UI development.
  • Modular Design: The debugging functionality is built with modular components (ActivityInterceptor, ActivityStore, DebugServer, TerminalFormatter, TerminalDebugger), promoting maintainability and extensibility.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added activitypub/interop Interoperability issues component/cli CLI tools related discussion Needs discussion priority/medium Medium priority issues type/enhancement Improvements to existing features labels Jul 21, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a real-time ActivityPub debug dashboard, a significant new feature for the CLI. The code is well-structured with a clear separation of concerns and includes an impressive suite of tests. My review focuses on improving correctness, robustness, and clarity. I've identified a critical bug in the terminal filtering logic and made several medium-severity suggestions to enhance input validation, unique ID generation, and code readability.

cli/debug.tsx Outdated
Comment on lines 67 to 69
"--direction=<direction:string>",
"Filter by direction: inbound or outbound (terminal mode only).",
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve correctness and provide better command-line validation, consider using EnumType from cliffy to restrict the allowed values for the --direction option. This enhances the user experience by showing allowed values in the help text and validating input.

    "--direction=<direction:direction>",
    "Filter by direction: inbound or outbound (terminal mode only).",
    { type: new EnumType(["inbound", "outbound"]) },

Comment on lines 12 to 23
private colorStrategy: ColorStrategy;
constructor(private options: FormatterOptions = {}) {
this.options = {
showRawActivity: false,
showTimestamp: true,
colorize: true,
...options,
};
this.colorStrategy = options.colorize === false
? new ColorizeOff()
: new ColorizeOn();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve code clarity, refactor the constructor logic to explicitly define the options property and streamline the colorStrategy assignment.

  private readonly colorStrategy: ColorStrategy;
  private readonly options: Required<FormatterOptions>;

  constructor(options: FormatterOptions = {}) {
    this.options = {
      showRawActivity: false,
      showTimestamp: true,
      colorize: true,
      ...options,
    };
    this.colorStrategy = this.options.colorize
      ? new ColorizeOn()
      : new ColorizeOff();
  }

}

return {
id: `debug-${++this.activityCounter}-${Date.now()}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For more robust unique ID generation, consider using crypto.randomUUID() instead of Date.now(), which is available as a global in Deno.

Suggested change
id: `debug-${++this.activityCounter}-${Date.now()}`,
id: crypto.randomUUID(),

Comment on lines 71 to 73
const clientId = `client-${Date.now()}-${
Math.random().toString(36).substring(7)
}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For more robust client ID generation, consider using crypto.randomUUID() instead of Date.now() and Math.random().

      const clientId = crypto.randomUUID();

Comment on lines 100 to 105
socket.onerror = (evt) => {
logger.error("WebSocket error for {clientId}: {error}", {
clientId,
error: evt,
});
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve error logging, check if the event in socket.onerror is an ErrorEvent and log its message property for better diagnostics.

      socket.onerror = (evt) => {
        const errorMessage = evt instanceof ErrorEvent ? evt.message : "WebSocket error";
        logger.error("WebSocket error for {clientId}: {error}", {
          clientId,
          error: errorMessage,
        });
      };

Comment on lines 82 to 86
function assert(condition: boolean, message?: string): void {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To maintain consistency, use the standard library's assert function instead of defining a custom helper function. Update the import on line 1 to include assert.

@malkoG
Copy link
Contributor

malkoG commented Jul 21, 2025

Would you rebase? .vocab.ts file is now in gitignore

@notJoon
Copy link
Contributor Author

notJoon commented Jul 21, 2025

Would you rebase? .vocab.ts file is now in gitignore

@malkoG Done 👍

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@dahlia
Copy link
Member

dahlia commented Jul 23, 2025

Thank you so much for all the hard work you've put into implementing this real-time ActivityPub debug dashboard! 🙏 The architecture you've built with the ActivityInterceptor, web server, and terminal interface is really solid and shows great engineering.

I feel a bit bad suggesting a different direction after you've already done so much work, but I had some thoughts about the integration approach that might make this feature even more useful for developers. Please know that I really appreciate the effort you've already invested—the core concepts and implementation details you've built are excellent and could largely be reused.

Your current approach with the standalone CLI debug command is well-architected with clean separation between ActivityInterceptor, ActivityStore, and DebugServer, plus both web dashboard and terminal interfaces with WebSocket support for real-time updates. The main challenge I see is that the ActivityInterceptor isn't currently connected to the actual federation middleware—it would need integration hooks in the core federation system to capture real ActivityPub traffic.

What if we integrated the debugger directly into the FederationBuilder/FederationOptions system instead? This would eliminate the integration gap since the debugger would be built into the federation middleware, provide a better developer experience where developers could debug their running app directly at http://localhost:3000/__debugger__ without needing a separate CLI process, and follow existing patterns similar to how allowPrivateAddress and skipSignatureVerification work in FederationOptions.

The proposed API would add a debugger?: string | boolean option to FederationOptions, where false (default) disables the debug dashboard, true enables it at /__debugger__, and a string value allows a custom debug endpoint path. Usage would be as simple as:

const federation = createFederation({
  kv: new MemoryKvStore(),
  debugger: true, // Enables /__debugger__ endpoint
});

Since the federation router already handles various endpoints like .well-known/webfinger and actor paths, we could add the /__debugger__ route to the existing Router system, intercept activities directly in handleInbox/sendActivity where they're already being processed, and serve HTML for browsers or JSON API for programmatic access following existing content negotiation patterns.

Most of your excellent implementation could be reused—your ActivityStore with circular buffer logic, WebSocket real-time update system, terminal formatting and filtering logic, and web server API endpoints. The main changes would be moving from standalone CLI to federation middleware integration, connecting activity capture to the actual federation request flow, and adapting the Hono server logic to work within the federation router.

I'm really sorry to suggest this direction change after you've built so much! Your implementation is genuinely impressive and the core architecture is sound. Would you be interested in exploring this federation-integrated approach, or do you prefer to continue with the CLI-based direction? Either way, I think this debug dashboard will be incredibly valuable for Fedify developers. Thank you again for taking this on! 🚀

@dahlia
Copy link
Member

dahlia commented Jul 23, 2025

I've created a related issue #323 that proposes a more general interface approach, which would enable your debug dashboard implementation while keeping the core package lean and extensible for other use cases. Would love to hear your thoughts on this direction!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
activitypub/interop Interoperability issues component/cli CLI tools related discussion Needs discussion priority/medium Medium priority issues type/enhancement Improvements to existing features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Real-time ActivityPub debug dashboard
3 participants