* fix(logs): split summary/detail contracts to make trace tab gate type-safe The Trace tab was silently missing from the Log Details sidepanel because list and detail rows shared one WorkflowLog type with executionData: z.unknown(). The UI couldn't distinguish a summary row (no spans) from a detail row (with spans), so the tab gate read undefined and hid itself. Splits into WorkflowLogSummary (list) and WorkflowLogDetail (typed executionData with optional traceSpans). Detail and by-execution routes both write through to the same logKeys.detail(id) cache, eliminating the two-key fragmentation that caused the merge memo workaround. List route moves to cursor pagination on (sortValue, id) with proper NULLS LAST handling and SQL-side sort across workflow + job execution tables. Detail route now requires and asserts workspaceId. Deep-link path uses useLogByExecutionId instead of auto-paginating the entire workspace. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): audit follow-ups — render side-effect, stats invalidation, enhanced spread order - Move onActiveTabChange call from render into useEffect to avoid side-effects during render (StrictMode safety). - Re-add logKeys.stats() invalidation to cancel/retry mutations so the dashboard reflects status flips immediately. - Reorder enhanced: true after ...execData spread in detail and by-execution routes so the literal discriminator is never overwritten by stale execData. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): mirror SQL NULLS LAST in JS merge for cursor consistency The in-memory merge of workflow + job pages negated the comparator for DESC, which placed null sort values at the start. SQL orders both ASC and DESC with NULLS LAST, so DESC pages emitted a cursor {v: <last non-null>, id: ...} while null rows still satisfied the cursor predicate (OR sort_expr IS NULL) on the next page — producing duplicate null rows across pages on cost/duration sorts. Handle nulls explicitly in the JS comparator so they always sort last regardless of direction, matching the SQL ordering. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): final-audit follow-ups — stable tab callback, byExecution invalidation, optimistic detail patch, trace loading state - Wrap LogDetails -> LogDetailsContent onActiveTabChange in useCallback so the child useEffect doesn't refire on every parent render. - Add logKeys.byExecutionAll() to cancel + retry invalidation so the table-embedded sidebar picks up status changes immediately. - Optimistic write-through to logKeys.detail in useCancelExecution so the open sidebar reflects 'cancelling' instantly; rolls back on error. - Distinguish trace loading from trace-empty: when log.executionData is not yet fetched, render "Loading trace…" instead of the empty state. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(logs): migrate stores/components to contract types Replace the legacy `WorkflowLog` / `LogsResponse` / `WorkflowData` / `CostMetadata` / `ToolCallMetadata` shapes in `stores/logs/filters/types.ts` with direct use of the contract types `WorkflowLogSummary`, `WorkflowLogDetail`, and a new `WorkflowLogRow` alias for surfaces that render either form. Removes the `summaryToWorkflowLog` / `detailToWorkflowLog` bridge in the React Query layer along with their double-cast annotations. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(logs): address PR review feedback - Whitelist sort columns against logSortBy enum to prevent client crash when non-sortable headers (workflow, trigger) reach the contract parser. - Extract fetchLogDetail helper shared by /api/logs/[id] and /api/logs/by-execution/[executionId] — collapses ~360 duplicated lines to a single source of truth keyed on lookup column. * fix(logs): exclude job logs when level filter is workflow-only When level=running or level=pending (workflow-only states involving endedAt/pausedExecutions semantics), jobLevelConditions stayed empty so no level constraint reached jobConditions — every job log in the workspace leaked into the result. Skip the job side entirely when the level filter has no job-applicable values (error/info). * chore(logs): drop dead utils — mapToExecutionLog and friends Remove ExecutionLog/RawLogResponse/ExecutionCost/LogWithExecutionData/ TraceSpan/BlockExecution interfaces and the mapToExecutionLog, mapToExecutionLogAlt, extractOutput functions — all unreferenced after the contract split. -212 lines. * chore(logs): drop unused LOG_COLUMN_ORDER and LogColumnKey * fix(logs): hydrate filters from URL synchronously on mount The previous useEffect-based initializeFromURL caused useLogsList and useDashboardStats to fire once with default store filters, then refetch after the effect updated filters from the URL. Move the initial hydrate into a useState lazy initializer so the first render already reads URL-derived filters; the popstate handler keeps the existing effect for back/forward navigation. * chore(logs): trim verbose comments added during PR Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): guard navigation arrows when selected log is off-page Deep-linked logs resolved via useLogByExecutionId may not be in the current page list, leaving selectedLogIndex at -1. The hasNext prop was evaluating -1 < logs.length - 1 (true for any non-empty list), which enabled the next arrow and jumped to the first item on click. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): sync active-tab callback before paint to keep keyboard guards aligned Run the resolvedTab → onActiveTabChange propagation in useLayoutEffect so the parent's activeTabRef updates synchronously before the next paint. This closes the brief window where window keydown handlers in the logs page would still see activeTabRef.current === 'trace' and short-circuit arrow-key navigation immediately after switching to a log without a Trace tab. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Block Documentation Generator
This directory contains scripts to automatically generate documentation for all blocks in the Sim platform.
Available Scripts
generate-docs.sh: Generates documentation for all blockssetup-doc-generator.sh: Installs dependencies required for the documentation generator
How It Works
The documentation generator:
- Scans the
apps/sim/blocks/blocks/directory for all block definition files - Extracts metadata from each block including:
- Name, description, and category
- Input and output specifications
- Configuration parameters
- Generates standardized Markdown documentation for each block
- Updates the navigation metadata in
meta.json
Running the Generator
To generate documentation manually:
# From the project root
./scripts/generate-docs.sh
Troubleshooting TypeScript Errors
If you encounter TypeScript errors when running the documentation generator, run the setup script to install the necessary dependencies:
./scripts/setup-doc-generator.sh
This will:
- Install TypeScript, ts-node, and necessary type definitions
- Create a proper tsconfig.json for the scripts directory
- Configure the scripts directory to use ES modules
Common Issues
- Missing Type Declarations: Run the setup script to install @types/node and @types/react
- JSX Errors in block-info-card.tsx: These don't affect functionality and can be ignored if you've run the setup script
- Module Resolution: The setup script configures proper ES module support
CI Integration
The documentation generator runs automatically as part of the CI/CD pipeline whenever changes are pushed to the main branch. The updated documentation is committed back to the repository.
Adding Support for New Block Properties
If you add new properties to block definitions that should be included in the documentation, update the generateMarkdownForBlock function in scripts/generate-docs.ts.
Preserving Manual Content
The documentation generator now supports preserving manually added content when regenerating docs. This allows you to enhance the auto-generated documentation with custom examples, additional context, or any other content without losing your changes when the docs are regenerated.
How It Works
- The generator creates clean documentation without any placeholders or markers
- If you add manual content to a file using special comment markers, that content will be preserved during regeneration
- The manual content is intelligently inserted at the appropriate section when docs are regenerated
Using Manual Content Markers
To add custom content to any tool's documentation, insert MDX comment blocks with section markers:
{/_ MANUAL-CONTENT-START:sectionName _/}
Your custom content here (Markdown formatting supported)
{/_ MANUAL-CONTENT-END _/}
Replace sectionName with one of the supported section names:
intro- Content at the top of the document after the BlockInfoCardusage- Additional usage instructions and examplesconfiguration- Custom configuration detailsoutputs- Additional output information or examplesnotes- Extra notes at the end of the document
Example
To add custom examples to a tool doc:
{/_ MANUAL-CONTENT-START:usage _/}
## Examples
### Basic Usage
```json
{
"parameter": "value",
"anotherParameter": "anotherValue"
}
```
Advanced Configuration
Here's how to use this tool for a specific use case... {/_ MANUAL-CONTENT-END _/}
When the documentation is regenerated, your manual content will be preserved in the appropriate section automatically. The script will not add any placeholders or markers to files by default.