Skip to content

Es lint prettier support#62

Open
ChubbyMmoh wants to merge 4 commits into
Flamki:masterfrom
ChubbyMmoh:ESLint-Prettier-Support
Open

Es lint prettier support#62
ChubbyMmoh wants to merge 4 commits into
Flamki:masterfrom
ChubbyMmoh:ESLint-Prettier-Support

Conversation

@ChubbyMmoh
Copy link
Copy Markdown

@ChubbyMmoh ChubbyMmoh commented May 29, 2026

feat: add ESLint + Prettier support, npm lint/format scripts, and CI format check

Summary

Added ESLint and Prettier integration for consistent code style. Added npm run lint, npm run lint:fix, npm run format, and npm run format:check. Updated lint.yml to run both ESLint and Prettier checks in CI.

Validation

  • Ran relevant local command(s)
  • Verified no secrets were added
  • Updated docs if behavior changed

Checklist

  • No .env or private keys committed
  • No sensitive data in screenshots/logs
  • README.md and examples still accurate

Completed: Create .prettierignore file. (10/10)

Closes #8
Screenshot 2026-05-29 at 3 09 34 PM

Summary by CodeRabbit

  • New Features

    • Added automated linting and formatting checks via CI.
  • Chores

    • Configured ESLint and Prettier and added lint/format scripts.
    • Applied consistent code-style updates across the codebase.
  • Documentation

    • Updated contributing/README and expanded comprehensive pricing guides and quick-start docs.
  • Bug Fixes

    • Improved premium payment/settlement handling and orchestrator response parsing for more reliable payment flows.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

@ChubbyMmoh is attempting to deploy a commit to the flamki's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds Prettier and ESLint configs, npm scripts, and a GitHub Actions lint workflow; documents formatting rules; reapplies consistent semicolon-free formatting across many files; updates pricing docs and refactors orchestrator x402/payment parsing, planning, and broadcast/result wiring.

Changes

ESLint, Prettier, and CI Linting Infrastructure

Layer / File(s) Summary
Linting and formatting configuration
eslint.config.js, .prettierrc, .prettierignore
Adds Prettier rules and ignore patterns, and an ESLint flat config wired with Prettier plugin and rules for unused vars, console usage, and Prettier enforcement.
npm scripts and GitHub Actions workflow
package.json, .github/workflows/lint.yml
Adds lint, lint:fix, format, format:check scripts; updates devDependencies for ESLint/Prettier; adds CI workflow that runs lint and format checks on push/PR.

Documentation Updates and Pricing/Quick-start Docs

Layer / File(s) Summary
CONTRIBUTING and README updates
CONTRIBUTING.md, README.md, DEMO_RECORDING_SCRIPT.md
Documents formatting and linting commands, updates contributor verification steps, reflows README text, and adjusts demo markdown spacing.
Pricing docs and indexes
PRICING_INDEX.md, PRICING_REFACTOR.md, PRICING_QUICK_START.md, PRICING_ERROR_EXAMPLES.md, PRICING_*
Expands/refactors pricing documentation, documents new src/pricing.config.js/src/pricing.validator.js, adds usage examples, tests instructions, and error scenarios.

Orchestrator and x402 Payment Flow

Layer / File(s) Summary
Orchestrator x402 and broadcast handling
src/agents/orchestrator.js
Adds PREMIUM_ENDPOINT_MAP and explorer URL derivation, guards x402 client init, implements wallet readiness caching, normalizes response body parsing, refines settlement parsing to conditionally populate tx metadata and warnings, adds truncated retry excerpts on non-OK responses, improves planning JSON extraction, enforces budget skipping with explicit results, and records payments/results for broadcasts and final return payload.

Repo-wide Reformat and Peripheral Script Updates

Layer / File(s) Summary
Core service and config reformat
src/server.js, src/config.js, src/agents/*, src/middleware/*, src/stellar/*, src/pricing.*
Applies semicolon-free, consistent formatting across core services and config files; preserves control flow, exported signatures, and runtime behavior.
Demo, recording, voiceover, and setup scripts
convert-to-mp4.js, record_demo.js, src/record-demo-video.js, src/demo-preflight.js, src/demo.js, src/generate-demo-voiceover.js, src/render-narrated-demo.js, src/setup-usdc.js, src/setup-wallets.js
Reformats automation and utility scripts to new code style without changing logic or I/O behavior.
Pricing validator and tests
src/pricing.validator.js, src/pricing.config.js, tests/*
Reformats validator and tests; validator functions, return shapes, and test assertions remain unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Flamki/stellarmind#53: touches the pricing refactor codepaths and documentation, related to the pricing/index/validator changes.

"🐇 I hopped through code with tidy paws,
Semicolons dropped like autumn leaves,
Lint and Prettier stitched the laws,
Docs polished, orchestrator breathes.
A tidy burrow, one small cheer—Stellarmind's code looks dear."

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and uses non-descriptive phrasing ('Es lint prettier support'); it does not clearly convey the main change despite relating to the changeset. Revise to a more descriptive and specific title, such as 'Add ESLint and Prettier integration with npm scripts for code formatting and linting.'
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description covers the main changes and mostly follows the template structure with completed checkboxes, though one validation checkbox remains unchecked.
Linked Issues check ✅ Passed All objectives from issue #8 are met: ESLint + Prettier configured, npm scripts added (lint, lint:fix, format, format:check), CI workflow updated, CONTRIBUTING.md documented, and formatting applied across the repository.
Out of Scope Changes check ✅ Passed All changes are in scope: configuration files, npm scripts, documentation updates, and code reformatting for consistency with the new linting/formatting standards align with issue #8 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/agents/orchestrator.js (1)

198-242: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't signal a fallback here unless you actually take it.

When settle reports failure, this branch emits x402_retry with fallback: true, but it still returns immediately from the x402 path. The XLM fallback below never runs, so settlement failures are treated as completed calls with paidVia: 'none'.

Suggested fix
       if (response.ok) {
         const settle = parseSettlementHeader(response)
         const txHash = extractTxHash(settle)
         const settlementFailed =
           settle?.success === false || Boolean(settle?.error || settle?.errorReason)
         if (settlementFailed) {
           const reason = settle?.errorReason || settle?.error || 'x402 settlement failed'
           broadcastFn?.({
             type: 'x402_retry',
             agent: agent.name,
             agentId: agent.id,
             reason,
             fallback: true,
             timestamp: new Date().toISOString(),
           })
           console.warn(`  x402 settlement reported failure: ${reason}`)
-        } else {
+        } else {
           const verification = txHash ? 'verified' : 'unverified'
           broadcastFn?.({
             type: 'x402_payment',
             agent: agent.name,
             agentId: agent.id,
             flow: '402 -> sign -> settle -> 200',
             protocol: 'x402',
             amount: agent.price,
             currency: agent.currency,
             verification,
             txHash: txHash || null,
             explorerUrl: buildExplorerUrl(txHash),
             timestamp: new Date().toISOString(),
           })
-        }
-
-        return {
-          result: data.result || JSON.stringify(data),
-          paymentMethod: 'x402',
-          paymentSuccess: !settlementFailed,
-          paidVia: !settlementFailed ? 'x402' : 'none',
-          txHash: !settlementFailed ? txHash || null : null,
-          explorerUrl: !settlementFailed ? buildExplorerUrl(txHash) : null,
-          warning:
-            !settlementFailed && !txHash
-              ? 'x402 settlement completed without transaction hash header'
-              : undefined,
-        }
+          return {
+            result: data.result ?? JSON.stringify(data),
+            paymentMethod: 'x402',
+            paymentSuccess: true,
+            paidVia: 'x402',
+            txHash: txHash || null,
+            explorerUrl: buildExplorerUrl(txHash),
+            warning: !txHash
+              ? 'x402 settlement completed without transaction hash header'
+              : undefined,
+          }
+        }
+      } else {
+        const responseExcerpt =
+          typeof data === 'string' ? data.substring(0, 120) : JSON.stringify(data).substring(0, 120)
+        const reason = `x402 endpoint returned ${response.status}: ${responseExcerpt}`
+        broadcastFn?.({
+          type: 'x402_retry',
+          agent: agent.name,
+          agentId: agent.id,
+          reason,
+          fallback: true,
+          timestamp: new Date().toISOString(),
+        })
+        console.warn(`  ${reason}`)
       }
-
-      const responseExcerpt =
-        typeof data === 'string' ? data.substring(0, 120) : JSON.stringify(data).substring(0, 120)
-      const reason = `x402 endpoint returned ${response.status}: ${responseExcerpt}`
-      broadcastFn?.({
-        type: 'x402_retry',
-        agent: agent.name,
-        agentId: agent.id,
-        reason,
-        fallback: true,
-        timestamp: new Date().toISOString(),
-      })
-      console.warn(`  ${reason}`)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/agents/orchestrator.js` around lines 198 - 242, The code treats a
reported x402 settlement failure as a completed path by broadcasting an
x402_retry with fallback: true and then immediately returning; instead, when
parseSettlementHeader/extractTxHash indicate settlementFailed you should
broadcast the failure without claiming fallback (remove or set fallback:false)
and avoid returning from this x402 branch so the subsequent XLM fallback logic
can run; concretely, keep the broadcastFn call (use agent.name/agent.id/reason)
but remove the immediate return branch that builds and returns the x402 result,
only return inside the successful (else) branch where verification is set, and
let the function continue to the XLM fallback handling when settlementFailed is
true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/lint.yml:
- Around line 12-14: The workflow's matrix syntax is invalid because
strategy.matrix.node-version is set to a scalar; either remove the matrix block
and set node-version directly under jobs.<job>.runs-on/steps, or change
strategy.matrix.node-version to an array (e.g., node-version: [22]); update the
YAML to use strategy.matrix.node-version: [22] if you want to keep the matrix,
or eliminate the entire strategy.matrix section and place node-version: 22
directly where the job's setup-node action reads it.

In `@convert-to-mp4.js`:
- Around line 60-64: The fallback path that uses execSync to create
tmpDir/frame_0000.png pushes a frame with only duration, causing writeFileSync
later to crash because frames[i].data is undefined; modify the fallback in
convert-to-mp4.js so after running execSync(`dwebp ... -o frame_0000.png`) you
read the generated PNG into memory (fs.readFileSync(path.join(tmpDir,
'frame_0000.png'))) and set frames.push({ duration: 1000, data: <buffer> }) so
subsequent code that calls writeFileSync(..., frames[i].data) succeeds; apply
the same change to the alternate fallback at lines 68-71.
- Line 63: Replace shell-string execSync calls with non-shell variants that pass
the program and arguments as an array and validate/escape input paths: stop
using execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir,
'frame_0000.png')}"`) and instead use child_process.execFileSync or spawnSync
with the executable ('dwebp') and an args array [inputWebp, '-o',
path.join(tmpDir, 'frame_0000.png')]; do the same for the per-frame ffmpeg
invocation (the loop that runs ffmpeg for each frame) and the final ffmpeg
stitch command (the calls building the full ffmpeg command near where outputMp4
is used). Also validate that inputWebp/outputMp4/tmpDir are safe (e.g.,
path.isAbsolute or whitelist) before executing and avoid shell:true so filenames
with metacharacters cannot be interpreted by the shell.

In `@package.json`:
- Around line 15-16: Remove the unsupported CLI option --ext from the npm
scripts "lint" and "lint:fix" in package.json because eslint is using flat
config (eslint.config.js) which already scopes files via files:
['**/*.{js,mjs,cjs}']; update the "lint" script to just run eslint . and the
"lint:fix" script to run eslint . --fix so ESLint runs with the flat config
without the incompatible --ext flag.

In `@README.md`:
- Around line 129-141: Add the missing npm script entry for "npm run
format:check" to the commands table so docs match the package/CI; specifically
update the README table (the Commands/Purpose rows shown) to include a row with
the unique script name "npm run format:check" and a concise purpose like "Check
formatting with Prettier (no file changes)" so readers and CI references align
with the repository's non-mutating Prettier check.

In `@src/agents/orchestrator.js`:
- Around line 231-232: The current return in the orchestrator rewrites
legitimate falsy agent results by using the || operator on data.result; change
the expression in the return object (the result field in the function that
returns { result: ... }) to use nullish coalescing (??) so that only null or
undefined trigger JSON.stringify(data), preserving '', 0, and false.

In `@src/server.js`:
- Around line 311-313: The current expression using parseFloat(budget) || 0.15
treats 0 as falsy and incorrectly substitutes the default; change it to parse
the budget and only fall back when the parsed value is NaN (e.g.
parseFloat/Number.parseFloat into a let/const and use Number.isNaN or
Number.isFinite to decide the default). Update the occurrence that defines
budgetNum (and the analogous occurrence around lines 323-325) so that a
caller-supplied 0 is preserved while non-numeric inputs still default to 0.15,
leaving the call to orchestrate(task, budgetNum, broadcast) unchanged.

In `@src/stellar/wallet.js`:
- Around line 84-86: The fundWithFriendbot helper currently returns { success:
true, data } unconditionally after calling response.json(); update
fundWithFriendbot to first check response.ok and only return success: true when
response.ok is true, otherwise read the error body (use response.text() or
response.json() safely) and return { success: false, status: response.status,
error: <body> } (or throw an Error) so callers can distinguish failure;
reference the fundWithFriendbot function, the response variable, and the
publicKey usage to locate and modify the logic.

---

Outside diff comments:
In `@src/agents/orchestrator.js`:
- Around line 198-242: The code treats a reported x402 settlement failure as a
completed path by broadcasting an x402_retry with fallback: true and then
immediately returning; instead, when parseSettlementHeader/extractTxHash
indicate settlementFailed you should broadcast the failure without claiming
fallback (remove or set fallback:false) and avoid returning from this x402
branch so the subsequent XLM fallback logic can run; concretely, keep the
broadcastFn call (use agent.name/agent.id/reason) but remove the immediate
return branch that builds and returns the x402 result, only return inside the
successful (else) branch where verification is set, and let the function
continue to the XLM fallback handling when settlementFailed is true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 150f968a-fc7e-4cb3-a6b0-57bb1503768a

📥 Commits

Reviewing files that changed from the base of the PR and between c008153 and 7e12e4c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (25)
  • .github/workflows/lint.yml
  • .prettierignore
  • .prettierrc
  • CONTRIBUTING.md
  • DEMO_RECORDING_SCRIPT.md
  • README.md
  • convert-to-mp4.js
  • eslint.config.js
  • package.json
  • public/index.html
  • record_demo.js
  • src/agents/orchestrator.js
  • src/agents/registry.js
  • src/agents/services.js
  • src/config.js
  • src/demo-preflight.js
  • src/demo.js
  • src/generate-demo-voiceover.js
  • src/middleware/errorHandler.js
  • src/record-demo-video.js
  • src/render-narrated-demo.js
  • src/server.js
  • src/setup-usdc.js
  • src/setup-wallets.js
  • src/stellar/wallet.js

Comment on lines +12 to +14
strategy:
matrix:
node-version: 22
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix matrix syntax error.

The node-version value should be an array when using a matrix strategy. Currently, it's a plain value which will cause the workflow to fail.

🔧 Proposed fix (Option 1 - recommended: remove matrix since only one version)
     runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        node-version: 22
     steps:
       - name: Checkout repository
         uses: actions/checkout@v4
 
       - name: Setup Node.js
         uses: actions/setup-node@v4
         with:
-          node-version: ${{ matrix.node-version }}
+          node-version: 22
           cache: "npm"
🔧 Alternative fix (Option 2: keep matrix with proper syntax)
     strategy:
       matrix:
-        node-version: 22
+        node-version: [22]
📝 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.

Suggested change
strategy:
matrix:
node-version: 22
strategy:
matrix:
node-version: [22]
🧰 Tools
🪛 actionlint (1.7.12)

[error] 14-14: expecting a single ${{...}} expression or array value for matrix variations, but found plain text node

(syntax-check)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/lint.yml around lines 12 - 14, The workflow's matrix
syntax is invalid because strategy.matrix.node-version is set to a scalar;
either remove the matrix block and set node-version directly under
jobs.<job>.runs-on/steps, or change strategy.matrix.node-version to an array
(e.g., node-version: [22]); update the YAML to use strategy.matrix.node-version:
[22] if you want to keep the matrix, or eliminate the entire strategy.matrix
section and place node-version: 22 directly where the job's setup-node action
reads it.

Comment thread convert-to-mp4.js
Comment on lines 60 to +64
if (frames.length === 0) {
console.error('No frames found. Trying alternative method...');
console.error('No frames found. Trying alternative method...')
// Try using dwebp if available
execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' });
frames.push({ duration: 1000 });
execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' })
frames.push({ duration: 1000 })
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix the zero-frame fallback path.

When no ANMF chunks are found, this creates a PNG directly with dwebp but still pushes a frame object with no data. The next loop then calls writeFileSync(..., frames[i].data) and the fallback path crashes instead of recovering.

Suggested fix
   if (frames.length === 0) {
     console.error('No frames found. Trying alternative method...')
     // Try using dwebp if available
-    execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' })
-    frames.push({ duration: 1000 })
+    const fallbackPng = path.join(tmpDir, 'frame_00000.png')
+    execSync(`dwebp "${inputWebp}" -o "${fallbackPng}"`, { stdio: 'pipe' })
+    frames.push({ duration: 1000, pngReady: true })
   }
@@
   for (let i = 0; i < frames.length; i++) {
     const framePath = path.join(tmpDir, `frame_${String(i).padStart(5, '0')}.webp`)
     const pngPath = path.join(tmpDir, `frame_${String(i).padStart(5, '0')}.png`)
-    fs.writeFileSync(framePath, frames[i].data)
+    if (frames[i].pngReady) continue
+    fs.writeFileSync(framePath, frames[i].data)

Also applies to: 68-71

🧰 Tools
🪛 OpenGrep (1.22.0)

[ERROR] 63-63: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@convert-to-mp4.js` around lines 60 - 64, The fallback path that uses execSync
to create tmpDir/frame_0000.png pushes a frame with only duration, causing
writeFileSync later to crash because frames[i].data is undefined; modify the
fallback in convert-to-mp4.js so after running execSync(`dwebp ... -o
frame_0000.png`) you read the generated PNG into memory
(fs.readFileSync(path.join(tmpDir, 'frame_0000.png'))) and set frames.push({
duration: 1000, data: <buffer> }) so subsequent code that calls
writeFileSync(..., frames[i].data) succeeds; apply the same change to the
alternate fallback at lines 68-71.

Comment thread convert-to-mp4.js
// Try using dwebp if available
execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' });
frames.push({ duration: 1000 });
execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' })
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file
fd -a "convert-to-mp4.js" . || true

# If found, print the relevant sections with line numbers
FILE="$(fd -a "convert-to-mp4.js" . | head -n1 || true)"
if [ -z "${FILE}" ]; then
  echo "convert-to-mp4.js not found"
  exit 0
fi

echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,140p'
nl -ba "$FILE" | sed -n '140,260p'

Repository: Flamki/stellarmind

Length of output: 210


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="$(fd -a "convert-to-mp4.js" . | head -n1 || true)"
echo "== File: $FILE =="

# Show file with line numbers around the reported areas
python3 - <<'PY'
import pathlib, itertools, sys, os
path = os.environ.get("FILE")
p = pathlib.Path(path)
lines = p.read_text(errors="replace").splitlines()
def show(a,b):
    for i in range(a-1,b):
        if 0 <= i < len(lines):
            print(f"{i+1}:{lines[i]}")
show(50,110)
PY
echo "== execSync occurrences =="
rg -n --fixed-string "execSync" "$FILE" || true
echo "== execFileSync occurrences =="
rg -n --fixed-string "execFileSync" "$FILE" || true

echo "== Inputs (try to spot where inputWebp/framePath/pgnPath/outputMp4/fps come from) =="
rg -n "inputWebp|framePath|pngPath|outputMp4|fps" "$FILE" || true

Repository: Flamki/stellarmind

Length of output: 663


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="$(fd -a "convert-to-mp4.js" . | head -n1 || true)"
echo "== File: $FILE =="

python3 - <<'PY'
import os, pathlib
p = pathlib.Path(os.environ["FILE"])
lines = p.read_text(errors="replace").splitlines()

def show(a,b):
    a=max(1,a); b=min(b,len(lines))
    for i in range(a-1,b):
        print(f"{i+1}:{lines[i]}")
show(1,130)
PY
echo "== execSync occurrences =="
rg -n --fixed-string "execSync" "$FILE" || true
echo "== execFileSync occurrences =="
rg -n --fixed-string "execFileSync" "$FILE" || true

echo "== Inputs (try to spot where inputWebp/framePath/pngPath/outputMp4/fps come from) =="
rg -n "inputWebp|framePath|pngPath|outputMp4|fps" "$FILE" || true

Repository: Flamki/stellarmind

Length of output: 266


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="$(fd -a "convert-to-mp4.js" . | head -n1 || true)"
echo "== File: $FILE =="

python3 - <<PY
import pathlib
p = pathlib.Path(r"""$FILE""")
lines = p.read_text(errors="replace").splitlines()

def show(a,b):
    a=max(1,a); b=min(b,len(lines))
    for i in range(a-1,b):
        print(f"{i+1}:{lines[i]}")

# show the relevant ranges around the review comment
show(50,110)
print("== middle ==")
show(70,110)
print("== later ==")
show(90,130)
PY

echo "== execSync occurrences =="
rg -n --fixed-string "execSync" "$FILE" || true

echo "== execFileSync occurrences =="
rg -n --fixed-string "execFileSync" "$FILE" || true

echo "== relevant variable assignments/usages =="
rg -n "inputWebp|framePath|pngPath|outputMp4|fps" "$FILE" || true

echo "== any 'shell:' options in execSync calls =="
rg -n "execSync\\(|shell\\s*:" "$FILE" || true

Repository: Flamki/stellarmind

Length of output: 7693


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="$(fd -a "convert-to-mp4.js" . | head -n1 || true)"
echo "== File: $FILE =="

python3 - <<PY
import pathlib, os
p = pathlib.Path(r"""$FILE""")
lines = p.read_text(errors="replace").splitlines()
for i in range(1,50):
    if i <= len(lines):
        print(f"{i}:{lines[i-1]}")
PY

python3 - <<PY
import pathlib, os
p = pathlib.Path(r"""$FILE""")
lines = p.read_text(errors="replace").splitlines()
# show around where tmpDir/outputMp4 are defined
for i in range(1,30):
    if i <= len(lines):
        print(f"{i}:{lines[i-1]}")
print("---")
for i in range(10,40):
    if i <= len(lines):
        print(f"{i}:{lines[i-1]}")
PY

Repository: Flamki/stellarmind

Length of output: 4407


Fix command injection risk in convert-to-mp4.js by avoiding execSync shell-interpreted command strings for CLI paths.

inputWebp and outputMp4 come directly from process.argv, and their derived paths are interpolated into template-literal command strings passed to execSync (shell-interpreted). Shell metacharacters (e.g., $(), backticks) and unescaped quotes in filenames can lead to arbitrary command execution. This occurs at the dwebp call (line 63), the per-frame ffmpeg call (line 74), and the final ffmpeg stitch call (lines 96-99).

Suggested fix
-import { execSync } from 'child_process'
+import { execFileSync } from 'child_process'
@@
-    execSync(`dwebp "${inputWebp}" -o "${path.join(tmpDir, 'frame_0000.png')}"`, { stdio: 'pipe' })
+    execFileSync('dwebp', [inputWebp, '-o', path.join(tmpDir, 'frame_0000.png')], {
+      stdio: 'pipe',
+    })
@@
-      execSync(`ffmpeg -y -i "${framePath}" "${pngPath}" 2>&1`, { stdio: 'pipe' })
+      execFileSync('ffmpeg', ['-y', '-i', framePath, pngPath], { stdio: 'pipe' })
@@
-  execSync(
-    `ffmpeg -y -framerate ${fps} -i "${path.join(tmpDir, 'frame_%05d.png')}" -c:v libx264 -pix_fmt yuv420p -crf 23 -movflags +faststart "${outputMp4}"`,
-    { stdio: 'inherit' }
-  )
+  execFileSync(
+    'ffmpeg',
+    [
+      '-y',
+      '-framerate',
+      String(fps),
+      '-i',
+      path.join(tmpDir, 'frame_%05d.png'),
+      '-c:v',
+      'libx264',
+      '-pix_fmt',
+      'yuv420p',
+      '-crf',
+      '23',
+      '-movflags',
+      '+faststart',
+      outputMp4,
+    ],
+    { stdio: 'inherit' }
+  )
🧰 Tools
🪛 OpenGrep (1.22.0)

[ERROR] 63-63: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@convert-to-mp4.js` at line 63, Replace shell-string execSync calls with
non-shell variants that pass the program and arguments as an array and
validate/escape input paths: stop using execSync(`dwebp "${inputWebp}" -o
"${path.join(tmpDir, 'frame_0000.png')}"`) and instead use
child_process.execFileSync or spawnSync with the executable ('dwebp') and an
args array [inputWebp, '-o', path.join(tmpDir, 'frame_0000.png')]; do the same
for the per-frame ffmpeg invocation (the loop that runs ffmpeg for each frame)
and the final ffmpeg stitch command (the calls building the full ffmpeg command
near where outputMp4 is used). Also validate that inputWebp/outputMp4/tmpDir are
safe (e.g., path.isAbsolute or whitelist) before executing and avoid shell:true
so filenames with metacharacters cannot be interpreted by the shell.

Comment thread package.json
Comment on lines +15 to +16
"lint": "eslint . --ext .js,.mjs,.cjs",
"lint:fix": "eslint . --ext .js,.mjs,.cjs --fix",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Is the --ext flag deprecated in ESLint 10 when using flat config?

💡 Result:

The --ext flag is not explicitly documented as deprecated in ESLint 10, but it is effectively obsolete and unnecessary when using flat config [1]. In the legacy configuration system (.eslintrc), the --ext flag was required to define which file extensions ESLint should process [2][1]. However, with flat config (which is the only supported configuration format in ESLint 10), file processing is controlled directly within the eslint.config.js file using the files property [1]. Because flat config makes file matching explicit via your configuration file, the CLI no longer relies on the --ext flag to determine which files to lint [1]. While the flag may still exist in the CLI interface [3], it serves no purpose in a flat config environment, as the configuration itself defines the scope and types of files that the linter should process [1]. Migrating to flat config means replacing --ext usage with explicit glob patterns in your configuration [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package.json scripts (lines ~1-120) =="
ls -la package.json || true
sed -n '1,120p' package.json | nl -ba | sed -n '1,120p'

echo
echo "== find eslint config files =="
ls -la eslint.config.* .eslintrc* 2>/dev/null || true
fd -t f -a -ejs -ejson -ejsx -ets -ejs -e.mjs -e.cjs -ects -ejs -g "eslint.config.*" . || true
fd -t f -g "*eslint*" . | head -n 50

echo
echo "== eslint.config.js / mjs / cjs (show matching files only) =="
for f in eslint.config.js eslint.config.mjs eslint.config.cjs; do
  if [ -f "$f" ]; then
    echo "--- $f (first 200 lines) ---"
    sed -n '1,200p' "$f" | nl -ba
  fi
done

Repository: Flamki/stellarmind

Length of output: 227


🌐 Web query:

ESLint CLI --ext flag flat config eslint.config.js deprecated

💡 Result:

The --ext CLI flag is no longer supported when using ESLint's flat config format (eslint.config.js), which became the default in ESLint v9.0.0 [1][2][3]. In the previous eslintrc-based configuration system, the --ext flag was used to specify which file extensions ESLint should process when a directory was passed as an argument [4][5][3]. With flat config, this functionality has been removed because file matching is now handled entirely within the configuration file itself [2][3]. To define which file extensions or patterns ESLint should lint, you must now use the files property within your eslint.config.js file [2][3]. For example, if you previously used --ext.jsx, you would update your configuration to include a pattern that matches those files [2]: export default [ { files: ["/.jsx", "/.js"], //... rules } ]; When you run ESLint (e.g., npx eslint.), it will automatically apply the configuration to the files that match the patterns defined in your files array [2][3]. If you are still using a legacy setup and require the --ext flag, you must be using the older eslintrc format, which may require setting the ESLINT_USE_FLAT_CONFIG environment variable to false (though support for legacy configurations has been removed as of ESLint v10.0.0) [1][6][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package.json (scripts section) =="
# Print scripts keys around lint entries (avoid assuming line numbers)
awk '
  BEGIN{in_scripts=0}
  /"scripts"\s*:/ {in_scripts=1}
  in_scripts {print}
  in_scripts && /^\s*},/ {in_scripts=0; exit}
' package.json

echo
echo "== package.json lint commands =="
rg -n '"lint' package.json || true

echo
echo "== find ESLint config files =="
ls -la eslint.config.* .eslintrc* 2>/dev/null || true
fd -t f -a -ejs -ejson -ejs -ejson -e.mjs -e.cjs -ects -g "eslint.config.*" . || true
fd -t f -g "*eslint*" . | head -n 50

Repository: Flamki/stellarmind

Length of output: 1075


🌐 Web query:

ESLint flat config --ext flag eslint.config.js supported or deprecated

💡 Result:

The --ext flag is not supported when using ESLint flat configuration (eslint.config.js) [1][2]. While the CLI reference still lists --ext, it is explicitly marked as "eslintrc Mode Only" [1][3]. In the flat config system, you must specify the file patterns you want to lint directly within your eslint.config.js file using the files property [1][4]. For example, to lint files with specific extensions such as.js,.ts, and.tsx, you would define them in your configuration object like this [4][2]: export default [ { files: ["/.js", "/.ts", "/*.tsx"], rules: { // your rules here } } ]; Once these patterns are defined in your configuration file, ESLint will automatically include those files when you run the CLI, making the use of the --ext flag unnecessary [1][5][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== eslint.config.js: first 220 lines =="
sed -n '1,220p' eslint.config.js

echo
echo "== eslint.config.js: grep for files/ignores/extensions scope =="
rg -n --hidden --no-ignore -S '"files"\s*:|files\s*:|ignores\s*:|ignorePatterns|--ext' eslint.config.js || true

Repository: Flamki/stellarmind

Length of output: 1002


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n '"eslint"\s*:' package.json && sed -n '1,120p' package.json

Repository: Flamki/stellarmind

Length of output: 1756


Remove --ext from ESLint scripts (flat config)
eslint.config.js is using flat config and already limits scope via files: ['**/*.{js,mjs,cjs}'], while the CLI --ext option is eslintrc-mode only (not supported with flat config).

✨ Proposed fix
-    "lint": "eslint . --ext .js,.mjs,.cjs",
-    "lint:fix": "eslint . --ext .js,.mjs,.cjs --fix",
+    "lint": "eslint .",
+    "lint:fix": "eslint . --fix",
📝 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.

Suggested change
"lint": "eslint . --ext .js,.mjs,.cjs",
"lint:fix": "eslint . --ext .js,.mjs,.cjs --fix",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 15 - 16, Remove the unsupported CLI option --ext
from the npm scripts "lint" and "lint:fix" in package.json because eslint is
using flat config (eslint.config.js) which already scopes files via files:
['**/*.{js,mjs,cjs}']; update the "lint" script to just run eslint . and the
"lint:fix" script to run eslint . --fix so ESLint runs with the flat config
without the incompatible --ext flag.

Comment thread README.md
Comment on lines +129 to +141
| Command | Purpose |
| ------------------------- | ------------------------------------------------------- |
| `npm run dev` | Start local server |
| `npm run demo` | Run end-to-end demo flow |
| `npm run preflight` | Validate readiness (x402, wallets, model, payment path) |
| `npm run setup` | Generate/fund Stellar testnet wallets |
| `npm run setup:usdc` | Add USDC trustlines for settlement |
| `npm run lint` | Run ESLint against the repository |
| `npm run lint:fix` | Fix ESLint issues automatically |
| `npm run format` | Format source and docs with Prettier |
| `npm run record:video` | Capture website-only demo video |
| `npm run voiceover` | Generate narration track |
| `npm run record:narrated` | Full narrated demo render pipeline |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Document npm run format:check here too.

This table looks like the canonical command list, but the PR also adds a non-mutating Prettier check script. Leaving it out makes the docs drift from the actual npm surface and from the CI workflow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 129 - 141, Add the missing npm script entry for "npm
run format:check" to the commands table so docs match the package/CI;
specifically update the README table (the Commands/Purpose rows shown) to
include a row with the unique script name "npm run format:check" and a concise
purpose like "Check formatting with Prettier (no file changes)" so readers and
CI references align with the repository's non-mutating Prettier check.

Comment on lines 231 to 232
return {
result: data.result || JSON.stringify(data),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve falsy agent results.

Line 232 treats '', 0, and false as missing and replaces them with JSON.stringify(data). If an agent legitimately returns a falsy result, the orchestrator will rewrite the payload. Use nullish coalescing here instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/agents/orchestrator.js` around lines 231 - 232, The current return in the
orchestrator rewrites legitimate falsy agent results by using the || operator on
data.result; change the expression in the return object (the result field in the
function that returns { result: ... }) to use nullish coalescing (??) so that
only null or undefined trigger JSON.stringify(data), preserving '', 0, and
false.

Comment thread src/server.js
Comment on lines +311 to +313
const budgetNum = parseFloat(budget) || 0.15
const result = await orchestrate(task, budgetNum, broadcast)
res.json(result)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve explicit zero budgets.

parseFloat(...) || 0.15 treats 0 as missing, so a caller asking for a zero budget gets the default 0.15 instead.

Suggested fix
-    const budgetNum = parseFloat(budget) || 0.15
+    const parsedBudget = Number.parseFloat(budget)
+    const budgetNum = Number.isFinite(parsedBudget) ? parsedBudget : 0.15
     const result = await orchestrate(task, budgetNum, broadcast)
-    const budget = parseFloat(req.query.budget) || 0.15
-    const result = await orchestrate(task, budget, broadcast)
+    const parsedBudget = Number.parseFloat(req.query.budget)
+    const budget = Number.isFinite(parsedBudget) ? parsedBudget : 0.15
+    const result = await orchestrate(task, budget, broadcast)

Also applies to: 323-325

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server.js` around lines 311 - 313, The current expression using
parseFloat(budget) || 0.15 treats 0 as falsy and incorrectly substitutes the
default; change it to parse the budget and only fall back when the parsed value
is NaN (e.g. parseFloat/Number.parseFloat into a let/const and use Number.isNaN
or Number.isFinite to decide the default). Update the occurrence that defines
budgetNum (and the analogous occurrence around lines 323-325) so that a
caller-supplied 0 is preserved while non-numeric inputs still default to 0.15,
leaving the call to orchestrate(task, budgetNum, broadcast) unchanged.

Comment thread src/stellar/wallet.js
Comment on lines +84 to +86
const response = await fetch(`https://friendbot.stellar.org?addr=${publicKey}`)
const data = await response.json()
return { success: true, data }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Locate and display the relevant section of src/stellar/wallet.js
ls -la
sed -n '1,200p' src/stellar/wallet.js | nl -ba | sed -n '1,200p'
echo "----"
# show around the reported lines 70-110 with line numbers
sed -n '60,130p' src/stellar/wallet.js | nl -ba | sed -n '60,130p'
echo "----"
# search for fundWithFriendbot usage
rg -n "fundWithFriendbot" -S .

Repository: Flamki/stellarmind

Length of output: 2087


🏁 Script executed:

#!/bin/bash
set -euo pipefail
ls -la
# show file with line numbers (limited)
sed -n '1,220p' src/stellar/wallet.js | nl -ba | sed -n '1,220p'
echo "----"
# show around reported lines
sed -n '70,130p' src/stellar/wallet.js | nl -ba | sed -n '70,130p'
echo "----"
# find callers
rg -n "fundWithFriendbot" -S .

Repository: Flamki/stellarmind

Length of output: 2087


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Basic sanity
ls -la src/stellar || true
echo "----"

# Show wallet.js with line numbers around the reported region
awk 'NR>=1 && NR<=220 {printf "%4d\t%s\n", NR, $0}' src/stellar/wallet.js | sed -n '1,220p'
echo "---- region 70-130 ----"
awk 'NR>=60 && NR<=140 {printf "%4d\t%s\n", NR, $0}' src/stellar/wallet.js
echo "----"

# Find fundWithFriendbot definition and usages
rg -n "function fundWithFriendbot|fundWithFriendbot\s*\(" -S src/stellar/wallet.js src || true
rg -n "fundWithFriendbot" -S src || true

Repository: Flamki/stellarmind

Length of output: 9000


🏁 Script executed:

#!/bin/bash
set -euo pipefail
awk 'NR>=1 && NR<=140 {printf "%4d\t%s\n", NR, $0}' src/setup-wallets.js | sed -n '1,140p'
echo "----"
sed -n '1,120p' src/setup-wallets.js | nl -ba 2>/dev/null || true

Repository: Flamki/stellarmind

Length of output: 5634


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "export async function fundWithFriendbot|fundWithFriendbot\(" src
rg -n "from ['\"]\.{1,2}/stellar/wallet['\"]|from ['\"].*/stellar/wallet['\"]" src || true
rg -n "fundWithFriendbot" -S src

Repository: Flamki/stellarmind

Length of output: 872


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "from ['\"].*stellar/wallet['\"]" -S src . || true
rg -n "import\s*\{[^}]*\bfundWithFriendbot\b[^}]*\}\s*from\s*['\"].*stellar/wallet['\"]" -S src . || true
rg -n "import\s*['\"].*stellar/wallet['\"]" -S src . || true
rg -n "fundWithFriendbot\(" -S src . || true

Repository: Flamki/stellarmind

Length of output: 882


Check Friendbot HTTP status before marking funding as successful.

src/stellar/wallet.js’s exported fundWithFriendbot returns { success: true, data } after response.json() without checking response.ok, so non-2xx Friendbot responses would still be treated as success.

Note: this exported helper isn’t referenced elsewhere in the repo (the setup script uses its own res.ok-checked Friendbot call in src/setup-wallets.js), but fixing it prevents incorrect results for any external callers.

Suggested fix
   try {
     const response = await fetch(`https://friendbot.stellar.org?addr=${publicKey}`)
     const data = await response.json()
+    if (!response.ok) {
+      return {
+        success: false,
+        error: data?.detail || data?.error || `Friendbot request failed with status ${response.status}`,
+      }
+    }
     return { success: true, data }
   } catch (err) {
     return { success: false, error: err.message }
   }
📝 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.

Suggested change
const response = await fetch(`https://friendbot.stellar.org?addr=${publicKey}`)
const data = await response.json()
return { success: true, data }
const response = await fetch(`https://friendbot.stellar.org?addr=${publicKey}`)
const data = await response.json()
if (!response.ok) {
return {
success: false,
error: data?.detail || data?.error || `Friendbot request failed with status ${response.status}`,
}
}
return { success: true, data }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/stellar/wallet.js` around lines 84 - 86, The fundWithFriendbot helper
currently returns { success: true, data } unconditionally after calling
response.json(); update fundWithFriendbot to first check response.ok and only
return success: true when response.ok is true, otherwise read the error body
(use response.text() or response.json() safely) and return { success: false,
status: response.status, error: <body> } (or throw an Error) so callers can
distinguish failure; reference the fundWithFriendbot function, the response
variable, and the publicKey usage to locate and modify the logic.

@Flamki
Copy link
Copy Markdown
Owner

Flamki commented May 30, 2026

@ChubbyMmoh could you plz resove this issues and fix conflicts

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 31, 2026

@ChubbyMmoh Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@ChubbyMmoh
Copy link
Copy Markdown
Author

hello @Flamki
I have resolved the conflicts.

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.

Add ESLint + Prettier with npm scripts for consistent code style

2 participants