-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Add content creation workflow using Motia #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis change introduces a new "Social Media Automation" workflow project in the Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API Step
participant Scrape Step
participant Generate Step
participant Schedule Step
participant Typefully API
Client->>API Step: POST /api/content-generation (url)
API Step->>Scrape Step: emit scrape-article (requestId, url, timestamp)
Scrape Step->>Generate Step: emit generate-content (requestId, url, title, content, timestamp)
Generate Step->>Schedule Step: emit schedule-content (requestId, url, title, twitter, linkedin, metadata)
Schedule Step->>Typefully API: POST draft (twitter thread)
Schedule Step->>Typefully API: POST draft (linkedin post)
Schedule Step-->>Client: (logs/notifications)
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (14)
motia-content-creation/.env.example (2)
1-4: Add inline comments & safer placeholders to prevent accidental secret leaksConsider adding a short
#description beside each variable and wrap placeholders in angle-brackets (e.g.<your_openai_api_key>) so that newcomers immediately recognise that real secrets must never be committed.-OPENAI_API_KEY=your_openai_api_key +# OpenAI secret used by generate.step.py +OPENAI_API_KEY=<your_openai_api_key>Do the same for the other three keys.
This tiny change fosters security hygiene without affecting runtime.
5-5: Ensure file ends with a newlineMany linters flag missing trailing newlines; add one to avoid noisy diffs in future commits.
motia-content-creation/prompts/linkedin-prompt.txt (1)
60-64: Hard-codingcharacterCountto 1250 may mislead downstream logicIf your scheduling step later validates the field, the model will always output
1250, not the real length.
Either:
- Drop the field, or
- Instruct the model to compute it:
"characterCount": "{{len(post)}}".Clarify this before the pipeline relies on the value.
motia-content-creation/.gitignore (1)
27-30: Duplicatedist/entry – keep list DRY
dist/appears twice (lines 27 and 81). Remove one to avoid merge-conflict churn.-27 dist/ +27 dist/ -81 distAlso applies to: 81-82
motia-content-creation/package.json (1)
4-11: Consider cross-platform compatibility for scripts.The scripts use Unix-specific commands (
source,rm -rf) which won't work on Windows. Consider using cross-platform alternatives or providing Windows-specific scripts."scripts": { - "prepare": "python3 -m venv python_modules && source python_modules/bin/activate && pip install -r requirements.txt", - "dev": "source python_modules/bin/activate && motia dev", - "dev:debug": "source python_modules/bin/activate && motia dev --debug", - "build": "source python_modules/bin/activate && motia build", - "clean": "rm -rf dist .motia .mermaid node_modules python_modules", + "prepare": "python3 -m venv python_modules && npm run activate && pip install -r requirements.txt", + "activate": "python_modules/bin/activate || python_modules\\Scripts\\activate.bat", + "dev": "npm run activate && motia dev", + "dev:debug": "npm run activate && motia dev --debug", + "build": "npm run activate && motia build", + "clean": "npx rimraf dist .motia .mermaid node_modules python_modules", "generate:config": "motia get-config --output ./" },You'll need to add
rimrafas a dev dependency for cross-platform file deletion.motia-content-creation/README.md (3)
12-12: Fix markdown heading structure.Use proper heading syntax instead of emphasis for the "Workflow" section.
-**Workflow** +### Workflow
16-18: Add language specification to code block.Specify the language for better syntax highlighting and accessibility.
-``` +```mermaid API → Scrape → Generate → Schedule--- `91-106`: **Add language specification to code block.** Specify the language for the project structure tree. ```diff -``` +```text social-media-automation/ ├── steps/ │ ├── api.step.ts # API endpoint handler │ ├── scrape.step.ts # Firecrawl integration │ ├── generate.step.ts # Parallel OpenAI calls │ └── schedule.step.ts # Typefully scheduling ├── prompts/ │ ├── twitter-prompt.txt # Twitter generation prompt │ └── linkedin-prompt.txt # LinkedIn generation prompt ├── config/ │ └── index.js # Configuration management ├── package.json ├── tsconfig.json └── README.md</blockquote></details> <details> <summary>motia-content-creation/steps/api.step.py (1)</summary><blockquote> `2-2`: **Remove unused import.** The `datetime` import is not used in this file and should be removed. ```diff -from datetime import datetimemotia-content-creation/steps/scrape.step.py (1)
4-4: Remove unused import.The
datetimeimport is not used in this file and should be removed.-from datetime import datetimemotia-content-creation/steps/generate.step.py (3)
5-5: Remove unused import.The
OpenAIimport is not used in the code - onlyAsyncOpenAIis utilized.-from openai import OpenAI -from openai import AsyncOpenAI +from openai import AsyncOpenAI
36-40: Consider using absolute paths for prompt templates.The current relative paths may cause issues if the working directory changes. Consider using
os.path.joinorpathlibfor more robust path handling.- with open("prompts/twitter-prompt.txt", "r", encoding='utf-8') as f: - twitterPromptTemplate = f.read() - - with open("prompts/linkedin-prompt.txt", "r", encoding='utf-8') as f: - linkedinPromptTemplate = f.read() + base_dir = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(base_dir, "..", "prompts", "twitter-prompt.txt"), "r", encoding='utf-8') as f: + twitterPromptTemplate = f.read() + + with open(os.path.join(base_dir, "..", "prompts", "linkedin-prompt.txt"), "r", encoding='utf-8') as f: + linkedinPromptTemplate = f.read()
69-69: Remove unnecessary f-string prefix.The string doesn't contain any placeholders, so the f-string prefix is unnecessary.
- context.logger.info(f"🎉 Content generated successfully!") + context.logger.info("🎉 Content generated successfully!")motia-content-creation/steps/schedule.step.ts (1)
47-47: Add specific error handling for API failures.Consider adding more specific error handling for different types of API failures (network errors, authentication failures, etc.).
- const twitterResponse = await axios.post(`${typefullyApiUrl}`, twitterPayload, { headers }) + const twitterResponse = await axios.post(`${typefullyApiUrl}`, twitterPayload, { headers }) + .catch(error => { + if (error.response?.status === 401) { + throw new Error('Typefully API authentication failed. Check your API key.') + } + throw new Error(`Typefully API error: ${error.message}`) + })Also applies to: 60-60
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
motia-content-creation/.env.example(1 hunks)motia-content-creation/.gitignore(1 hunks)motia-content-creation/README.md(1 hunks)motia-content-creation/config/index.js(1 hunks)motia-content-creation/package.json(1 hunks)motia-content-creation/prompts/linkedin-prompt.txt(1 hunks)motia-content-creation/prompts/twitter-prompt.txt(1 hunks)motia-content-creation/requirements.txt(1 hunks)motia-content-creation/steps/api.step.py(1 hunks)motia-content-creation/steps/generate.step.py(1 hunks)motia-content-creation/steps/schedule.step.ts(1 hunks)motia-content-creation/steps/scrape.step.py(1 hunks)motia-content-creation/types.d.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
motia-content-creation/steps/api.step.py (3)
motia-content-creation/config/index.js (1)
config(3-29)motia-content-creation/steps/scrape.step.py (1)
handler(26-50)motia-content-creation/steps/generate.step.py (1)
handler(31-92)
motia-content-creation/steps/scrape.step.py (3)
motia-content-creation/config/index.js (1)
config(3-29)motia-content-creation/steps/api.step.py (1)
handler(32-56)motia-content-creation/steps/generate.step.py (1)
handler(31-92)
motia-content-creation/steps/schedule.step.ts (4)
motia-content-creation/config/index.js (1)
config(3-29)motia-content-creation/steps/api.step.py (1)
handler(32-56)motia-content-creation/steps/scrape.step.py (1)
handler(26-50)motia-content-creation/steps/generate.step.py (1)
handler(31-92)
🪛 markdownlint-cli2 (0.17.2)
motia-content-creation/README.md
12-12: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
16-16: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
91-91: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 LanguageTool
motia-content-creation/prompts/twitter-prompt.txt
[style] ~19-~19: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: ...we delve into the details, let's take a quick look at its formula: (2/n) <add an il...
(QUICK_BRIEF)
[style] ~83-~83: Using many exclamation marks might seem excessive (in this case: 7 exclamation marks for a text that’s 2793 characters long)
Context: ...share tutorials on above topics! Cheers! 🥂 7/n ##############################...
(EN_EXCESSIVE_EXCLAMATION)
🪛 Ruff (0.11.9)
motia-content-creation/steps/api.step.py
2-2: datetime.datetime imported but unused
Remove unused import: datetime.datetime
(F401)
motia-content-creation/steps/generate.step.py
5-5: openai.OpenAI imported but unused
Remove unused import: openai.OpenAI
(F401)
69-69: f-string without any placeholders
Remove extraneous f prefix
(F541)
motia-content-creation/steps/scrape.step.py
4-4: datetime.datetime imported but unused
Remove unused import: datetime.datetime
(F401)
🔇 Additional comments (6)
motia-content-creation/config/index.js (1)
21-31: Excellent validation approach.The validation function with immediate execution ensures required environment variables are present at startup, preventing runtime failures later in the workflow.
motia-content-creation/package.json (1)
20-33: Well-chosen dependencies for the workflow.The dependency selection is appropriate for the social media automation use case, with proper version constraints and necessary TypeScript support.
motia-content-creation/README.md (1)
1-121: Excellent documentation structure.The README provides comprehensive setup instructions, clear workflow explanation, and helpful usage examples. The project structure overview is particularly valuable for understanding the codebase.
motia-content-creation/steps/api.step.py (1)
17-30: Well-structured configuration and schema definitions.The configuration properly defines the API endpoint with appropriate schemas and event flow specification. The Pydantic models provide good type safety.
motia-content-creation/steps/scrape.step.py (1)
26-50: Excellent error handling and workflow integration.The scraping logic properly handles Firecrawl failures and integrates well with the workflow by emitting the correct event with all necessary data for the next step.
motia-content-creation/types.d.ts (1)
1-20: Auto-generated type definitions look correct.The type definitions properly declare the handler interfaces and match the implementations in the step files. The warning about not editing manually is appropriate.
| pydantic>=2.11.7 | ||
| openai>=1.93.1 | ||
| firecrawl>=2.15.0 | ||
| python-dotenv>=1.1.1 | ||
| requests>=2.32.3 No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Pin exact versions for reproducible builds
Using >= lets pip pull the latest minor/patch version, which can silently break the workflow months from now.
Unless you have an automated depend-on-latest policy, switch to strict pins:
-pydantic>=2.11.7
-openai>=1.93.1
-firecrawl>=2.15.0
-python-dotenv>=1.1.1
-requests>=2.32.3
+pydantic==2.11.7
+openai==1.93.1
+firecrawl==2.15.0 # verify still compatible with requests 2.32.3
+python-dotenv==1.1.1
+requests==2.32.3Locking versions eliminates “works-on-my-machine” surprises and makes container builds deterministic.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| pydantic>=2.11.7 | |
| openai>=1.93.1 | |
| firecrawl>=2.15.0 | |
| python-dotenv>=1.1.1 | |
| requests>=2.32.3 | |
| pydantic==2.11.7 | |
| openai==1.93.1 | |
| firecrawl==2.15.0 # verify still compatible with requests 2.32.3 | |
| python-dotenv==1.1.1 | |
| requests==2.32.3 |
🤖 Prompt for AI Agents
In motia-content-creation/requirements.txt lines 1 to 5, the dependencies use
minimum version specifiers (>=), which can lead to unpredictable builds. Change
each dependency to pin an exact version by replacing >= with == and specifying
the exact version number to ensure reproducible and deterministic builds.
| ], | ||
| "totalTweets": 5 | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed totalTweets contradicts dynamic 3-7 range – likely to break validation
You ask for 3-7 tweets, but the example JSON forces "totalTweets": 5.
The LLM will mimic the example and ignore the 3-7 instruction, causing an off-by-N error.
- "totalTweets": 5
+ "totalTweets": "{{tweets|length}}"Or let the backend derive the count instead of asking the model.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ], | |
| "totalTweets": 5 | |
| } | |
| ], | |
| "totalTweets": "{{tweets|length}}" | |
| } |
🤖 Prompt for AI Agents
In motia-content-creation/prompts/twitter-prompt.txt around lines 116 to 118,
the fixed "totalTweets" value of 5 contradicts the dynamic 3-7 tweet range
requested, which can cause validation errors. To fix this, remove the hardcoded
"totalTweets" value from the example JSON so the model does not mimic a fixed
count, or alternatively, modify the backend to calculate the total tweet count
dynamically instead of relying on the model's output.
| motia: { | ||
| port: parseInt(process.env.MOTIA_PORT) || 3000, | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for MOTIA_PORT parsing.
The parseInt() function could return NaN if MOTIA_PORT is not a valid number, which would cause issues downstream.
motia: {
- port: parseInt(process.env.MOTIA_PORT) || 3000,
+ port: parseInt(process.env.MOTIA_PORT, 10) || 3000,
},Consider adding explicit validation:
motia: {
- port: parseInt(process.env.MOTIA_PORT) || 3000,
+ port: (() => {
+ const port = parseInt(process.env.MOTIA_PORT, 10);
+ return isNaN(port) ? 3000 : port;
+ })(),
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| motia: { | |
| port: parseInt(process.env.MOTIA_PORT) || 3000, | |
| }, | |
| motia: { | |
| - port: parseInt(process.env.MOTIA_PORT) || 3000, | |
| + port: (() => { | |
| + const port = parseInt(process.env.MOTIA_PORT, 10); | |
| + return isNaN(port) ? 3000 : port; | |
| + })(), | |
| }, |
🤖 Prompt for AI Agents
In motia-content-creation/config/index.js around lines 17 to 19, the port value
is set using parseInt on process.env.MOTIA_PORT without validating if the result
is a valid number. To fix this, add explicit validation after parsing MOTIA_PORT
to check if the result is NaN; if it is, fallback to the default port 3000. This
ensures the port configuration is always a valid number and prevents downstream
errors.
| async def handler(req, context): | ||
| # Extract request data | ||
| # req = input['req'] | ||
| url = str(req['body']['url']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Clean up commented code and add input validation.
Remove the commented legacy code and add proper input validation using the defined schema.
async def handler(req, context):
# Extract request data
- # req = input['req']
+ # Validate request body against schema
+ try:
+ request_body = RequestBody(**req['body'])
+ url = str(request_body.url)
+ except Exception as e:
+ return {
+ 'status': 400,
+ 'body': {'error': f'Invalid request body: {str(e)}'}
+ }
+
- url = str(req['body']['url'])
-
context.logger.info('🚀 Starting content generation workflow...')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async def handler(req, context): | |
| # Extract request data | |
| # req = input['req'] | |
| url = str(req['body']['url']) | |
| async def handler(req, context): | |
| # Extract request data | |
| # Validate request body against schema | |
| try: | |
| request_body = RequestBody(**req['body']) | |
| url = str(request_body.url) | |
| except Exception as e: | |
| return { | |
| 'status': 400, | |
| 'body': {'error': f'Invalid request body: {str(e)}'} | |
| } | |
| context.logger.info('🚀 Starting content generation workflow...') |
🤖 Prompt for AI Agents
In motia-content-creation/steps/api.step.py around lines 32 to 35, remove the
commented-out legacy code that extracts request data. Then, add input validation
by using the defined schema to validate the incoming request data before
processing it. This ensures the input is correctly structured and prevents
errors downstream.
| from dotenv import load_dotenv | ||
|
|
||
| load_dotenv() | ||
|
|
||
| FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY') | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove redundant environment loading and add API key validation.
The load_dotenv() call is redundant since the configuration in config/index.js already handles environment variables. Also add validation for the API key.
-from dotenv import load_dotenv
-
-load_dotenv()
-
-FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY')
+FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY')
+
+if not FIRECRAWL_API_KEY:
+ raise ValueError("FIRECRAWL_API_KEY environment variable is required")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| from dotenv import load_dotenv | |
| load_dotenv() | |
| FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY') | |
| # (remove the `dotenv` import and load call) | |
| FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY') | |
| if not FIRECRAWL_API_KEY: | |
| raise ValueError("FIRECRAWL_API_KEY environment variable is required") |
🤖 Prompt for AI Agents
In motia-content-creation/steps/scrape.step.py around lines 5 to 10, remove the
redundant call to load_dotenv() since environment variables are already loaded
in config/index.js. Additionally, add validation to check if FIRECRAWL_API_KEY
is set after retrieving it with os.getenv, and raise an appropriate error or
handle the missing key scenario to ensure the API key is available before
proceeding.
| twitter_content = json.loads(twitter_response.choices[0].message.content) | ||
| linkedin_content = json.loads(linkedin_response.choices[0].message.content) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for JSON parsing.
The code assumes the OpenAI response will always contain valid JSON. Consider adding error handling for malformed JSON responses.
- twitter_content = json.loads(twitter_response.choices[0].message.content)
- linkedin_content = json.loads(linkedin_response.choices[0].message.content)
+ try:
+ twitter_content = json.loads(twitter_response.choices[0].message.content)
+ linkedin_content = json.loads(linkedin_response.choices[0].message.content)
+ except json.JSONDecodeError as e:
+ context.logger.error(f"Failed to parse OpenAI response as JSON: {e}")
+ raise ValueError("Invalid JSON response from OpenAI") from e📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| twitter_content = json.loads(twitter_response.choices[0].message.content) | |
| linkedin_content = json.loads(linkedin_response.choices[0].message.content) | |
| try: | |
| twitter_content = json.loads(twitter_response.choices[0].message.content) | |
| linkedin_content = json.loads(linkedin_response.choices[0].message.content) | |
| except json.JSONDecodeError as e: | |
| context.logger.error(f"Failed to parse OpenAI response as JSON: {e}") | |
| raise ValueError("Invalid JSON response from OpenAI") from e |
🤖 Prompt for AI Agents
In motia-content-creation/steps/generate.step.py around lines 66 to 67, the code
parses JSON from OpenAI responses without handling potential JSON decoding
errors. Add try-except blocks around the json.loads calls to catch
JSONDecodeError exceptions, and handle these errors gracefully, such as logging
the error and providing fallback behavior or raising a clear exception.
| logger.info(`💼 Scheduling LinkedIn post...`) | ||
|
|
||
| const linkedinPayload = { | ||
| content: input.content.linkedin.post, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add null safety for LinkedIn post access.
Similar to the Twitter thread, ensure the LinkedIn post content exists before using it.
- const linkedinPayload = {
- content: input.content.linkedin.post,
- schedule_date: null // Will be posted as draft
- }
+ const linkedinPost = input.content.linkedin?.post
+
+ if (!linkedinPost) {
+ throw new Error('LinkedIn post content is missing or invalid')
+ }
+
+ const linkedinPayload = {
+ content: linkedinPost,
+ schedule_date: null // Will be posted as draft
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| content: input.content.linkedin.post, | |
| const linkedinPost = input.content.linkedin?.post | |
| if (!linkedinPost) { | |
| throw new Error('LinkedIn post content is missing or invalid') | |
| } | |
| const linkedinPayload = { | |
| content: linkedinPost, | |
| schedule_date: null // Will be posted as draft | |
| } |
🤖 Prompt for AI Agents
In motia-content-creation/steps/schedule.step.ts at line 56, the code accesses
input.content.linkedin.post without checking if linkedin or post exists, which
can cause runtime errors. Add a null or undefined check for
input.content.linkedin and input.content.linkedin.post before accessing post,
using optional chaining or conditional checks to ensure safe access.
| twitter: z.any(), | ||
| linkedin: z.any() | ||
| }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve schema validation for content structure.
Using z.any() for the content objects bypasses type safety. Consider defining more specific schemas based on the expected structure from the content generation step.
- content: z.object({
- twitter: z.any(),
- linkedin: z.any()
- }),
+ content: z.object({
+ twitter: z.object({
+ thread: z.array(z.object({
+ content: z.string()
+ }))
+ }),
+ linkedin: z.object({
+ post: z.string()
+ })
+ }),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| twitter: z.any(), | |
| linkedin: z.any() | |
| }), | |
| content: z.object({ | |
| twitter: z.object({ | |
| thread: z.array(z.object({ | |
| content: z.string() | |
| })) | |
| }), | |
| linkedin: z.object({ | |
| post: z.string() | |
| }) | |
| }), |
🤖 Prompt for AI Agents
In motia-content-creation/steps/schedule.step.ts around lines 24 to 26, the
schema uses z.any() for twitter and linkedin fields, which bypasses type safety.
Replace z.any() with more specific zod schemas that reflect the expected
structure of the content objects from the content generation step, defining the
exact fields and their types to improve validation and type safety.
| logger.info(`📱 Scheduling Twitter thread...`) | ||
|
|
||
| // Convert Twitter thread to Typefully format | ||
| const twitterThread = input.content.twitter.thread.map((tweet: any) => tweet.content).join('\n\n\n\n') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add null safety for nested property access.
The code assumes input.content.twitter.thread exists and is an array. This could cause runtime errors if the structure is different.
- const twitterThread = input.content.twitter.thread.map((tweet: any) => tweet.content).join('\n\n\n\n')
+ const twitterThread = input.content.twitter?.thread?.map((tweet: any) => tweet.content).join('\n\n\n\n')
+
+ if (!twitterThread) {
+ throw new Error('Twitter thread content is missing or invalid')
+ }Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In motia-content-creation/steps/schedule.step.ts at line 40, the code accesses
input.content.twitter.thread without checking if these nested properties exist,
which can cause runtime errors. Add null or undefined checks for input.content,
input.content.twitter, and input.content.twitter.thread before mapping over the
array. Use optional chaining or conditional checks to safely access the thread
array and handle cases where it might be missing or not an array.
Summary by CodeRabbit
New Features
Documentation
Chores