Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 18, 2025

Plan: Add Documentation for Events Feature

This PR adds comprehensive documentation for the Events feature that enables server-sent events (SSE) style streaming responses in Facility.

Checklist

  • Add "Events" section to define/fsd.md after "Methods" section (after line 149)
    • Explain event definition and purpose
    • Document FSD syntax for events
    • Document HTTP mapping for events (SSE)
    • Compare events vs methods
    • Provide practical example use case
  • Update C# code generation documentation in generate/csharp.md
  • Update JavaScript/TypeScript documentation in generate/javascript.md
  • Update cross-references throughout fsd.md to include events
  • Address review feedback
    • Simplify examples by removing unnecessary fields
    • Use more general terminology (responses vs chunks)
    • Remove implementation-specific details from generic docs
    • Add link to SSE specification
    • Remove redundant and verbose content
    • Verify against actual JavaScript implementation (PR #75)
  • Verify all changes follow existing documentation style
  • Final review and validation

Changes Made

  1. define/fsd.md - Added concise Events section including:

    • Event definition with link to MDN SSE specification
    • Simplified FSD syntax examples
    • HTTP mapping and SSE details (POST default, fetch-based SSE implementation)
    • Concise comparison with methods
    • Streamlined chat streaming example
    • Updated all references to service elements to include events
  2. generate/csharp.md - Added Events section with:

    • Generated method signatures for events
    • Usage example with await foreach
    • Explanation of SSE handling
  3. generate/javascript.md - Added Events section with:

    • Generated TypeScript method signatures
    • Usage example with for await...of (verified against actual implementation)
    • Explanation of Fetch API SSE handling (all HTTP methods supported)

Review Updates

  • Removed implementation-specific details (C# signatures) from generic FSD documentation
  • Added link to MDN SSE specification
  • Removed redundant "Response Streaming Behavior" section
  • Simplified all code examples by removing verbose comments
  • Condensed explanatory text throughout
  • Verified against JavaScript implementation (PR #75): Confirmed JavaScript uses fetch-based SSE parsing (HttpClientUtility.createFetchEventStream) that supports all HTTP methods, not just GET
  • Corrected JavaScript examples: Fixed usage pattern to use .ok property instead of checking .value to match actual ServiceResult API

All documentation follows the existing style and formatting conventions and accurately reflects the implementations in all language targets.

Reference

Original prompt

Add Documentation for Events Feature

Overview

Add comprehensive documentation for the events feature that was introduced in Facility. Events enable server-sent events (SSE) style streaming responses where the server can send multiple response chunks to the client.

Reference Implementation

Review the merged PRs:

Documentation Requirements

1. Update define/fsd.md

Add a new section "Events" after the "Methods" section (around line 149, after the Method HTTP section ends). The section should include:

Event Definition

  • Explain that events are similar to methods but support streaming responses
  • Events have a name, request fields, and response fields like methods
  • Events return IAsyncEnumerable<ServiceResult<TResponse>> in C# (or equivalent in other languages)
  • Each yielded response represents a chunk of data sent via server-sent events
  • Events can also have attributes, a summary, and remarks

Event FSD Syntax

/// Generates the next message in a chat.
event chatStream
{
  settings: ChatSettings!;
  messages: ChatMessage[]!;
}:
{
  messages: ChatMessage[];
  status: ChatStatus;
  usage: ChatUsage;
}

Key points:

  • Use the event keyword instead of method
  • Request and response fields are defined the same way as methods
  • The response represents a single chunk; multiple chunks will be streamed

Event HTTP Mapping

  • The http attribute works the same as methods
  • Default HTTP method is POST
  • The path parameter works the same way (defaults to event name with leading slash)
  • Events always use server-sent events (SSE) for the response with Content-Type: text/event-stream
  • The HTTP response uses status code 200 and keeps the connection open
  • Each response DTO is sent as a separate SSE event

Example with custom path:

[http(method: POST, path: "/chat/stream")]
event chatStream
{
  ...
}:
{
  ...
}

Events vs Methods

Explain the differences:

  • Methods return a single response (or error)
  • Events return a stream of responses, allowing progressive updates
  • Events are ideal for:
    • Long-running operations with progress updates
    • Streaming AI/LLM responses
    • Real-time data feeds
    • Incremental results

Response Streaming Behavior

  • The server yields multiple response chunks over time
  • Each chunk is a complete response DTO
  • Clients can process chunks as they arrive
  • The stream completes when the server finishes sending data
  • Errors can be returned at any point in the stream

Example Use Case

Provide a practical example showing how events are used for streaming AI chat responses:

service ChatApi
{
  /// Streams chat response tokens as they're generated.
  event streamChat
  {
    prompt: string!;
    model: string;
  }:
  {
    /// Text delta to append to response
    textDelta: string;
    
    /// Completion status (sent in final chunk)
    status: CompletionStatus;
    
    /// Token usage (sent in final chunk)
    usage: UsageInfo;
  }
}

data UsageInfo
{
  inputTokens: int32;
  outputTokens: int32;
}

enum CompletionStatus
{
  complete,
  truncated,
  error,
}

2. Update Code Generation Documentation

If there are any relevant files in the generate/ directory that discuss C# or TypeScript code generation, add notes about how events are generated:

C# Code Generation:

  • Events generate methods that return Task<ServiceResult<IAsyncEnumerable<ServiceResult<TResponse>>>>
  • Clients can use await foreach to process the stream
  • The HTTP client uses server-sent events to receive chunks

TypeScript/JavaScript:

  • Events generate methods that return async iterables
  • Can be consumed with for await...of loops

3. Update Navigation/Index

If define/index.md or any navigation file lists sections, add "Events" to the appropriate location.

Formatting Guidelines

  • Follow the existing documentation style in define/fsd.md
  • Use the same heading levels (### for main sections, #### for subsections)
  • Include code examples in fenced code blocks with fsd language identifier
  • Keep explanations concise but comprehensive
  • Cross-reference other sections where appropriate using markdown links

Placement

Insert the new "Events" section after line 149 (after the "Method HTTP" section) and before line 151 (before the "Fields" section).

The section should flow naturally: Service → Methods → Events → Fields → Data Transfer Objects → etc.

This pull request was created as a result of the following prompt from Copilot chat.

Add Documentation for Events Feature

Overview

Add comprehensive documentation for the events feature that was introduced in Facility. Events enable server-sent events (SSE) style streaming responses where the server can send multiple response chunks to the client.

Reference Implementation

Review the merged PRs:

Documentation Requirements

1. Update define/fsd.md

Add a new section "Events" after the "Methods" section (around line 149, after the Method HTTP section ends). The section should include:

Event Definition

  • Explain that events are similar to methods but support streaming responses
  • Events have a name, request fields, and response fields like methods
  • Events return IAsyncEnumerable<ServiceResult<TResponse>> in C# (or equivalent in other languages)
  • Each yielded response represents a chunk of data sent via server-sent events
  • Events can also have attributes, a summary, and remarks

Event FSD Syntax

/// Generates the next message in a chat.
event chatStream
{
  settings: ChatSettings!;
  messages: ChatMessage[]!;
}:
{
  messages: ChatMessage[];
  status: ChatStatus;
  usage: ChatUsage;
}

Key points:

  • Use the event keyword instead of method
  • Request and response fields are defined the same way as methods
  • The response represents a single chunk; multiple chunks will be streamed

Event HTTP Mapping

  • The http attribute works the same as methods
  • Default HTTP method is POST
  • The path parameter works the same way (defaults to event name with leading slash)
  • Events always use server-sent events (SSE) for the response with Content-Type: text/event-stream
  • The HTTP response uses status code 200 and keeps the connection open
  • Each response DTO is sent as a separate SSE event

Example with custom path:

[http(method: POST, path: "/chat/stream")]
event chatStream
{
  ...
}:
{
  ...
}

Events vs Methods

Explain the differences:

  • Methods return a single response (or error)
  • Events return a stream of responses, allowing progressive updates
  • Events are ideal for:
    • Long-running operations with progress updates
    • Streaming AI/LLM responses
    • Real-time data feeds
    • Incremental results

Response Streaming Behavior

  • The server yields multiple response chunks over time
  • Each chunk is a complete response DTO
  • Clients can process chunks as they arrive
  • The stream completes when the server finishes sending data
  • Errors can be returned at any point in the stream

Example Use Case

Provide a practical example showing how events are used for streaming AI chat responses:

service ChatApi
{
  /// Streams chat response tokens as they're generated.
  event streamChat
  {
    prompt: string!;
    model: string;
  }:
  {
    /// Text delta to append to response
    textDelta: string;
    
    /// Completion status (sent in final chunk)
    status: CompletionStatus;
    
    /// Token usage (sent in final chunk)
    usage: UsageInfo;
  }
}

data UsageInfo
{
  inputTokens: int32;
  outputTokens: int32;
}

enum CompletionStatus
{
  complete,
  truncated,
  error,
}

2. Update Code Generation Documentation

If there are any relevant files in the generate/ directory that discuss C# or TypeScript code generation, add notes about how events are generated:

C# Code Generation:

  • Events generate methods that return Task<ServiceResult<IAsyncEnumerable<ServiceResult<TResponse>>>>
  • Clients can use await foreach to process the stream
  • The HTTP client uses server-sent events to receive chunks

TypeScript/JavaScript:

  • Events generate methods that return async iterables
  • Can be consumed with for await...of loops

3. Update Navigation/Index

If define/index.md or any navigation file lists sections, add "Events" to the appropriate location.

Formatting Guidelines

  • Follow the existing documentation style in define/fsd.md
  • Use the same heading levels (### for main sections, #### for subsections)
  • Include code examples in fenced code blocks with fsd language identifier
  • Keep explanations concise but comprehensive
  • Cross-reference other sections where appropriate using markdown links

Placement

Insert the new "Events" section after line 149 (after the "Method HTTP" section) and before line 151 (before the "Fields" section).

The section should flow naturally: Service → Methods → Events → Fields → Data Transfer Objects → etc.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits November 18, 2025 20:10
Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
define/fsd.md Outdated
{
messages: ChatMessage[];
status: ChatStatus;
usage: ChatUsage;
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot omit this from the example

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed from the example. (9b4e46f)

define/fsd.md Outdated
Comment on lines 248 to 249
/// Token usage statistics (sent in final chunk)
usage: UsageInfo;
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot omit from example, unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the usage field and UsageInfo data type. (9b4e46f)

define/fsd.md Outdated
Comment on lines 207 to 212
**Events** return a stream of responses, allowing progressive updates. Each response in the stream is a complete response DTO. Events are ideal for:

* Long-running operations with progress updates
* Streaming AI/LLM responses where tokens are generated incrementally
* Real-time data feeds that push updates to clients
* Incremental results where partial data is useful before completion
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot since these use SSE, what are the performance implications and how would they compare to web sockets or polling?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SSE (Server-Sent Events) provides a good balance for streaming responses:

vs WebSockets:

  • SSE is simpler (HTTP-based, one-way server-to-client)
  • WebSockets are bidirectional and more complex
  • SSE automatically reconnects on disconnection
  • SSE works better with standard HTTP infrastructure (proxies, load balancers)
  • Use SSE for server-to-client streaming; use WebSockets when you need bidirectional communication

vs Polling:

  • SSE maintains an open connection, eliminating polling overhead
  • Lower latency - server pushes immediately vs polling intervals
  • More efficient - no repeated request/response overhead
  • Better for real-time updates

SSE is ideal for the streaming response pattern in Facility where the server pushes data to the client as it becomes available.

Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot summarize in the docs

define/fsd.md Outdated
Comment on lines 219 to 221
* The server yields multiple response chunks over time
* Each chunk is a complete response DTO, serialized and sent as an SSE event
* Clients can process chunks as they arrive, enabling progressive rendering
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot is this "chunking" description too specific to the example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. Changed terminology from "chunks" to "responses" throughout and removed "progressive rendering" which was too UI-specific. The description is now more general and applicable to any use case. (9b4e46f)

Copilot AI changed the title [WIP] Add documentation for events feature Add documentation for Events feature (streaming responses via SSE) Nov 18, 2025
Copilot AI requested a review from ddunkin November 18, 2025 20:19
Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
Copy link
Contributor

@ddunkin ddunkin left a comment

Choose a reason for hiding this comment

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

@copilot link to relevant SSE specifications.

Remove redundant or verbose new documentation.

define/fsd.md Outdated
Comment on lines 207 to 212
**Events** return a stream of responses, allowing progressive updates. Each response in the stream is a complete response DTO. Events are ideal for:

* Long-running operations with progress updates
* Streaming AI/LLM responses where tokens are generated incrementally
* Real-time data feeds that push updates to clients
* Incremental results where partial data is useful before completion
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot summarize in the docs

define/fsd.md Outdated

When a client invokes an event, it provides request field values just like a method. However, unlike a method that returns a single response, an event returns a stream where each item is a complete response DTO. The stream can yield multiple responses over time until it completes.

In C#, events return `Task<ServiceResult<IAsyncEnumerable<ServiceResult<TResponse>>>>`, allowing clients to process responses as they arrive using `await foreach`. Other languages provide similar async iterable constructs.
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot omit implementation specifics in generic docs

@ddunkin
Copy link
Contributor

ddunkin commented Nov 18, 2025

@copilot try again

@ddunkin
Copy link
Contributor

ddunkin commented Nov 18, 2025

@copilot link to relevant SSE specifications (see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)

Remove redundant or verbose new documentation.

Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 18, 2025

@copilot link to relevant SSE specifications (see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)

...

Added link to MDN SSE specification and significantly simplified the documentation by:

  • Removing implementation-specific details (C# type signatures)
  • Removing the redundant "Response Streaming Behavior" section
  • Condensing explanatory text
  • Simplifying code examples (removed verbose comments)
  • Removed remaining usage field from HTTP example

The Events section is now much more concise while still covering the essential information. (f672e8b)

define/fsd.md Outdated

The `http` attribute works the same for events as for methods. Events support the `method` and `path` parameters.

The `method` parameter indicates the HTTP method to use, typically `POST` (the default). The `path` parameter specifies the HTTP path, defaulting to the event name with a leading slash (e.g., `/chatStream`).
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot POST is the default?

EventSource doesn't support POST, only GET? The specification isn't explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're correct - the standard EventSource API only supports GET requests. Events should default to GET, not POST, since they use SSE. I'll update the documentation to reflect this difference from methods.

Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot that doesn't mean events should default to GET necessarily, but it does mean we can't use EventSource in that case, right? Can we use fetch directly in the browser for these requests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct! Updated the documentation to clarify:

  • Events default to POST (same as methods)
  • EventSource only supports GET, so for POST or other methods, clients need custom SSE implementations (e.g., fetch with SSE parsing)

This gives the flexibility to use any HTTP method while documenting the EventSource limitation. (73fb843)

Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
Copilot AI requested a review from ddunkin November 19, 2025 00:08
Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
@ddunkin
Copy link
Contributor

ddunkin commented Nov 20, 2025

@copilot check FacilityApi/FacilityJavaScript#75 and confirm the documentation in this PR is correct

Copy link
Contributor Author

Copilot AI commented Nov 20, 2025

@copilot check FacilityApi/FacilityJavaScript#75 and confirm the documentation in this PR is correct

I've reviewed the current documentation against the implementation patterns. The documentation states:

Current documentation:

  • Events default to POST (same as methods)
  • EventSource API only supports GET
  • For non-GET methods, custom SSE implementations needed (e.g., fetch with SSE parsing)
  • TypeScript signature: Promise<IServiceResult<AsyncIterable<IServiceResult<IStreamChatResponse>>>>

Key points to verify from PR #75:

  1. Default HTTP method (POST vs GET)
  2. Whether fetch-based SSE parsing is implemented for non-GET requests
  3. Exact TypeScript signature format

Without direct access to PR #75, I cannot fully confirm all implementation details. Could you point me to specific aspects of the implementation I should verify or clarify what seems incorrect?

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/FacilityApi/FacilityJavaScript/pulls/75
    • Triggering command: curl -s -H Accept: application/vnd.github.v3&#43;json REDACTED (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@ddunkin
Copy link
Contributor

ddunkin commented Nov 20, 2025

@copilot try again FacilityApi/FacilityJavaScript#75 and confirm the documentation in this PR is correct

Co-authored-by: ddunkin <264744+ddunkin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 20, 2025

@copilot try again FacilityApi/FacilityJavaScript#75 and confirm the documentation in this PR is correct

Verified against PR #75. Updated documentation to match the actual implementation:

Key corrections:

  1. Removed EventSource limitation note - JavaScript implementation uses HttpClientUtility.createFetchEventStream (fetch-based SSE parsing) that supports all HTTP methods, not just GET
  2. Fixed JavaScript example - Changed result.value to result.ok and chunkResult.value to chunkResult.ok to match the actual API
  3. Clarified implementation - Updated text to reflect that fetch API is used with full HTTP method support

The documentation now accurately reflects the implementation in PR #75. (3a25b50)

Removed unnecessary blank lines before the SSE explanation.
@ddunkin ddunkin marked this pull request as ready for review November 20, 2025 22:14
@ddunkin ddunkin requested a review from ejball November 20, 2025 22:14
@ddunkin ddunkin merged commit 5c4b144 into master Nov 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants