Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@
"manual_run": "Manuelle Ausführung",
"scheduled_run": "Geplante Ausführung",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "Unbekannter Ausführungstyp"
},
"run_status_chips": {
Expand Down
2 changes: 2 additions & 0 deletions public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,8 @@
"scheduled_run": "Scheduled",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "Unknown Run Type"
},
"run_status_chips": {
Expand Down
3 changes: 3 additions & 0 deletions public/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@
"manual_run": "Ejecución Manual",
"scheduled_run": "Ejecución Programada",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "Tipo de Ejecución Desconocido"
},
"run_status_chips": {
Expand Down
3 changes: 3 additions & 0 deletions public/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,9 @@
"manual_run": "手動実行",
"scheduled_run": "スケジュール実行",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "不明な実行タイプ"
},
"run_status_chips": {
Expand Down
3 changes: 3 additions & 0 deletions public/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@
"manual_run": "Manuel",
"scheduled_run": "Zamanlanmış",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "Bilinmeyen"
},
"run_status_chips": {
Expand Down
3 changes: 3 additions & 0 deletions public/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,9 @@
"manual_run": "手动运行",
"scheduled_run": "计划运行",
"api": "API",
"sdk": "SDK",
"mcp": "MCP",
"cli": "CLI",
"unknown_run_type": "未知运行类型"
},
"run_status_chips": {
Expand Down
17 changes: 11 additions & 6 deletions server/src/api/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ function formatRunResponse(run: any) {
runByScheduleId: run.runByScheduleId,
runByAPI: run.runByAPI,
runBySDK: run.runBySDK,
runByMCP: run.runByMCP,
runByCLI: run.runByCLI,
data: {
textData: {},
listData: {},
Expand Down Expand Up @@ -477,7 +479,7 @@ router.get("/robots/:id/runs/:runId", requireAPIKey, async (req: Request, res: R
}
});

async function createWorkflowAndStoreMetadata(id: string, userId: string, isSDK: boolean) {
async function createWorkflowAndStoreMetadata(id: string, userId: string, runSource: 'api' | 'sdk' | 'mcp' | 'cli') {
try {
const recording = await Robot.findOne({
where: {
Expand Down Expand Up @@ -522,8 +524,10 @@ async function createWorkflowAndStoreMetadata(id: string, userId: string, isSDK:
log: '',
runId,
runByUserId: userId,
runByAPI: !isSDK,
runBySDK: isSDK,
runByAPI: runSource === 'api',
runBySDK: runSource === 'sdk',
runByMCP: runSource === 'mcp',
runByCLI: runSource === 'cli',
serializableOutput: {},
binaryOutput: {},
retryCount: 0
Expand Down Expand Up @@ -1194,11 +1198,11 @@ async function executeRun(id: string, userId: string, requestedFormats?: string[
}
}

export async function handleRunRecording(id: string, userId: string, isSDK: boolean = false, requestedFormats?: string[]) {
export async function handleRunRecording(id: string, userId: string, runSource: 'api' | 'sdk' | 'mcp' | 'cli' = 'api', requestedFormats?: string[]) {
let socket: Socket | null = null;

try {
const result = await createWorkflowAndStoreMetadata(id, userId, isSDK);
const result = await createWorkflowAndStoreMetadata(id, userId, runSource);
const { browserId, runId: newRunId } = result;

if (!browserId || !newRunId || !userId) {
Expand Down Expand Up @@ -1378,7 +1382,8 @@ router.post("/robots/:id/runs", requireAPIKey, async (req: AuthenticatedRequest,
}

const requestedFormats = req.body?.formats;
const runId = await handleRunRecording(req.params.id, req.user.id, false, requestedFormats);
const runSource = req.headers['x-run-source'] === 'mcp' ? 'mcp' : 'api';
const runId = await handleRunRecording(req.params.id, req.user.id, runSource, requestedFormats);

if (!runId) {
throw new Error('Run ID is undefined');
Expand Down
3 changes: 2 additions & 1 deletion server/src/api/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ router.post("/sdk/robots/:id/execute", requireAPIKey, async (req: AuthenticatedR

logger.info(`[SDK] Starting execution for robot ${robotId}`);

const runId = await handleRunRecording(robotId, user.id.toString(), true);
const runSource = req.headers['x-run-source'] === 'cli' ? 'cli' : 'sdk';
const runId = await handleRunRecording(robotId, user.id.toString(), runSource);
Comment on lines +492 to +493
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

Handle mcp explicitly when deriving runSource.

Line 492 currently maps only 'cli'; every other value (including 'mcp') is forced to 'sdk'. That causes MCP runs (sent with x-run-source: mcp from server/src/mcp-worker.ts, Line 41) to be persisted as SDK, so runByMCP never gets set in server/src/api/record.ts.

💡 Proposed fix
-        const runSource = req.headers['x-run-source'] === 'cli' ? 'cli' : 'sdk';
+        const headerRunSource = Array.isArray(req.headers['x-run-source'])
+            ? req.headers['x-run-source'][0]
+            : req.headers['x-run-source'];
+        const runSource: 'sdk' | 'cli' | 'mcp' =
+            headerRunSource === 'cli' || headerRunSource === 'mcp'
+                ? headerRunSource
+                : 'sdk';
         const runId = await handleRunRecording(robotId, user.id.toString(), runSource);
📝 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 runSource = req.headers['x-run-source'] === 'cli' ? 'cli' : 'sdk';
const runId = await handleRunRecording(robotId, user.id.toString(), runSource);
const headerRunSource = Array.isArray(req.headers['x-run-source'])
? req.headers['x-run-source'][0]
: req.headers['x-run-source'];
const runSource: 'sdk' | 'cli' | 'mcp' =
headerRunSource === 'cli' || headerRunSource === 'mcp'
? headerRunSource
: 'sdk';
const runId = await handleRunRecording(robotId, user.id.toString(), runSource);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/src/api/sdk.ts` around lines 492 - 493, The runSource derivation
currently maps only 'cli' to 'cli' and forces every other header value to 'sdk',
causing MCP runs to be misclassified; update the logic that sets runSource (the
line reading req.headers['x-run-source'] and the value passed into
handleRunRecording) to explicitly detect 'mcp' and set runSource to 'mcp' (in
addition to preserving 'cli'), so handleRunRecording receives 'mcp' for MCP
requests and downstream code in record handling (e.g., runByMCP in
server/src/api/record.ts) is set correctly.

if (!runId) {
throw new Error('Failed to start robot execution');
}
Expand Down
1 change: 1 addition & 0 deletions server/src/mcp-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class MaxunMCPWorker {
const headers = {
'Content-Type': 'application/json',
'x-api-key': this.apiKey,
'x-run-source': 'mcp',
...options.headers
};

Expand Down
12 changes: 12 additions & 0 deletions server/src/models/Run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface RunAttributes {
runByScheduleId?: string;
runByAPI?: boolean;
runBySDK?: boolean;
runByMCP?: boolean;
runByCLI?: boolean;
serializableOutput: Record<string, any>;
binaryOutput: Record<string, string>;
retryCount?: number;
Expand All @@ -47,6 +49,8 @@ class Run extends Model<RunAttributes, RunCreationAttributes> implements RunAttr
public runByScheduleId!: string;
public runByAPI!: boolean;
public runBySDK!: boolean;
public runByMCP!: boolean;
public runByCLI!: boolean;
public serializableOutput!: Record<string, any>;
public binaryOutput!: Record<string, any>;
public retryCount!: number;
Expand Down Expand Up @@ -119,6 +123,14 @@ Run.init(
type: DataTypes.BOOLEAN,
allowNull: true,
},
runByMCP: {
type: DataTypes.BOOLEAN,
allowNull: true,
},
runByCLI: {
type: DataTypes.BOOLEAN,
allowNull: true,
},
Comment on lines +126 to +133
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for migration files that might add runByMCP or runByCLI columns
fd -e js -e ts migration | xargs -I{} grep -l -E 'runByMCP|runByCLI' {} 2>/dev/null || echo "No migration found"

# Also check for any migration files in common locations
fd -t f -e js -e ts . -p 'migrations|migrate' 2>/dev/null | head -20

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# First, let's check the actual Run.ts file at the specified lines
head -140 server/src/models/Run.ts | tail -20

Repository: getmaxun/maxun

Length of output: 452


🏁 Script executed:

# Check if migrations directory exists and what's in it
find . -type d -name migrations -o -type d -name migrate 2>/dev/null | head -10

Repository: getmaxun/maxun

Length of output: 84


🏁 Script executed:

# Look for any SQL migration files
find . -type f -name "*.sql" 2>/dev/null | head -20

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Check for Sequelize configuration and migration patterns
find . -type f \( -name ".sequelizerc" -o -name "sequelize.config.*" -o -name "config.json" \) 2>/dev/null

Repository: getmaxun/maxun

Length of output: 100


🏁 Script executed:

# List all TypeScript/JS files in common migration paths
fd -t f -e js -e ts -e sql . -p '(migration|migrate|db/|database/)' 2>/dev/null | head -30

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Check what's in the migrations directory
ls -la server/src/db/migrations/

Repository: getmaxun/maxun

Length of output: 432


🏁 Script executed:

# Count and list migration files
find server/src/db/migrations -type f | sort

Repository: getmaxun/maxun

Length of output: 248


🏁 Script executed:

# Check .sequelizerc content to understand migration setup
cat .sequelizerc

Repository: getmaxun/maxun

Length of output: 349


🏁 Script executed:

# Check the config.json to see Sequelize setup
cat server/config/config.json

Repository: getmaxun/maxun

Length of output: 634


🏁 Script executed:

# Search the entire migrations directory for any reference to runByMCP or runByCLI
rg -i 'runByMCP|runByCLI' server/src/db/migrations/

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# List all files in migrations directory with more details
find server/src/db/migrations -type f -exec basename {} \; | sort

Repository: getmaxun/maxun

Length of output: 173


🏁 Script executed:

# Check the most recent migration file
cat server/src/db/migrations/20250612000000-add-robot-name-unique-index.js

Repository: getmaxun/maxun

Length of output: 469


🏁 Script executed:

# Check the first migration which appears to add columns
cat server/src/db/migrations/20250327111003-add-airtable-columns.js

Repository: getmaxun/maxun

Length of output: 3263


🏁 Script executed:

# Check the Run.ts model to see all attributes and when they might have been added
grep -n "runBy\|type: DataTypes.BOOLEAN" server/src/models/Run.ts | head -30

Repository: getmaxun/maxun

Length of output: 685


🏁 Script executed:

# Check the webhooks migration
cat server/src/db/migrations/20250527105655-add-webhooks.js

Repository: getmaxun/maxun

Length of output: 853


🏁 Script executed:

# Verify which table the Run model uses
grep -n "tableName\|table:" server/src/models/Run.ts | head -5

Repository: getmaxun/maxun

Length of output: 83


🏁 Script executed:

# Search across all migrations for any reference to 'run' table
rg -i "addColumn.*'run'|addColumn.*\"run\"" server/src/db/migrations/

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Check git status to see what files are in this PR
git status --short

Repository: getmaxun/maxun

Length of output: 71


🏁 Script executed:

# Check if there are any uncommitted migration files
git diff --name-only

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Look for any migration files that might be timestamped with recent dates (April 2026)
ls -lt server/src/db/migrations/ | head -10

Repository: getmaxun/maxun

Length of output: 329


🏁 Script executed:

# Get the full Run.ts file to understand the context better
wc -l server/src/models/Run.ts

Repository: getmaxun/maxun

Length of output: 86


🏁 Script executed:

# Check if runBySDK was already in the model previously or if it's new
git log -1 --name-only server/src/models/Run.ts 2>/dev/null || echo "Not in git history"

Repository: getmaxun/maxun

Length of output: 257


🏁 Script executed:

# Check recent commits to the Run model
git log --oneline -n 10 -- server/src/models/Run.ts 2>/dev/null || echo "Unable to get git log"

Repository: getmaxun/maxun

Length of output: 99


🏁 Script executed:

# Let's check if there's a pending migration file that hasn't been added yet
find . -name "*runBy*" -o -name "*run-*.js" -o -name "*run-*.ts" 2>/dev/null | grep -i migrat

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Get the complete Run.ts model around the new columns
sed -n '110,140p' server/src/models/Run.ts

Repository: getmaxun/maxun

Length of output: 683


🏁 Script executed:

# Check if runBySDK exists in migrations (if it does, it shows a pattern)
rg -i 'runBySDK' server/src/db/migrations/

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Verify the table name one more time and check git diff for this file
git diff HEAD -- server/src/models/Run.ts | head -100

Repository: getmaxun/maxun

Length of output: 40


🏁 Script executed:

# Check what's actually staged for commit
git status -s

Repository: getmaxun/maxun

Length of output: 71


🏁 Script executed:

# Check the current HEAD to see what's committed vs what's being reviewed
git show --stat HEAD | head -30

Repository: getmaxun/maxun

Length of output: 1698


🏁 Script executed:

# Final verification: list all migration files with timestamps to see if any cover runBy* columns
ls -la server/src/db/migrations/ && echo "---" && grep -r "runByMCP\|runByCLI" server/src/db/migrations/ || echo "No runBy* columns in migrations"

Repository: getmaxun/maxun

Length of output: 468


Missing database migration for new columns.

The model defines runByMCP and runByCLI columns in the run table (lines 126-133), but no corresponding migration exists. Existing databases will throw a "column does not exist" error at runtime when attempting to write these fields.

Add a migration to alter the run table:

ALTER TABLE run ADD COLUMN "runByMCP" BOOLEAN;
ALTER TABLE run ADD COLUMN "runByCLI" BOOLEAN;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/src/models/Run.ts` around lines 126 - 133, The Run model now defines
two new nullable boolean fields runByMCP and runByCLI but there is no DB
migration; add a new migration that alters the run table to ADD COLUMN
"runByMCP" BOOLEAN and ADD COLUMN "runByCLI" BOOLEAN (nullable) and implement
the corresponding down migration to DROP those columns so existing databases get
the new columns; reference the Run model (Run.ts) and the run table/column names
when creating the migration.

serializableOutput: {
type: DataTypes.JSONB,
allowNull: true,
Expand Down
28 changes: 19 additions & 9 deletions src/components/run/ColapsibleRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,16 @@ interface RunTypeChipProps {
runByScheduledId?: string;
runByAPI: boolean;
runBySDK?: boolean;
runByMCP?: boolean;
runByCLI?: boolean;
}

const RunTypeChip: React.FC<RunTypeChipProps> = ({ runByUserId, runByScheduledId, runByAPI, runBySDK }) => {
const RunTypeChip: React.FC<RunTypeChipProps> = ({ runByUserId, runByScheduledId, runByAPI, runBySDK, runByMCP, runByCLI }) => {
const { t } = useTranslation();

if (runByScheduledId) return <Chip label={t('runs_table.run_type_chips.scheduled_run')} color="primary" variant="outlined" />;
if (runByCLI) return <Chip label={t('runs_table.run_type_chips.cli')} color="primary" variant="outlined" />;
if (runByMCP) return <Chip label={t('runs_table.run_type_chips.mcp')} color="primary" variant="outlined" />;
if (runBySDK) return <Chip label={t('runs_table.run_type_chips.sdk')} color="primary" variant="outlined" />;
if (runByAPI) return <Chip label={t('runs_table.run_type_chips.api')} color="primary" variant="outlined" />;
if (runByUserId) return <Chip label={t('runs_table.run_type_chips.manual_run')} color="primary" variant="outlined" />;
Expand All @@ -86,14 +90,18 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu
const [openSettingsModal, setOpenSettingsModal] = useState(false);
const [userEmail, setUserEmail] = useState<string | null>(null);
const runByLabel = row.runByScheduleId
? `${row.runByScheduleId}`
: row.runByUserId
? `${userEmail}`
: row.runBySDK
? 'SDK'
: row.runByAPI
? 'API'
: 'Unknown';
? `${row.runByScheduleId}`
: row.runByUserId
? `${userEmail}`
: row.runByCLI
? 'CLI'
: row.runByMCP
? 'MCP'
: row.runBySDK
? 'SDK'
: row.runByAPI
? 'API'
: 'Unknown';

const logEndRef = useRef<HTMLDivElement | null>(null);

Expand Down Expand Up @@ -259,6 +267,8 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu
runByScheduledId={row.runByScheduleId}
runByAPI={row.runByAPI ?? false}
runBySDK={row.runBySDK}
runByMCP={row.runByMCP}
runByCLI={row.runByCLI}
/>
</Box>
</Box>
Expand Down
2 changes: 2 additions & 0 deletions src/components/run/RunsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export interface Data {
browserId: string;
runByAPI?: boolean;
runBySDK?: boolean;
runByMCP?: boolean;
runByCLI?: boolean;
log: string;
runId: string;
robotId: string;
Expand Down