# Scripting API

Execute JavaScript scripts that orchestrate tool calls with tracing and dry-run support.

## Quick Start

```typescript
handler: async (input, ctx) => {
  const result = await ctx.majk.scripting.execute_script({
    code: `
      const reports = await tools.ReportsService.list_reports({ limit: 10 });
      console.log('Found', reports.total, 'reports');
      return { count: reports.total };
    `,
    dryRun: false
  });

  return result.result;
}
```

## API Reference

### execute_script(input)

Execute a JavaScript script.

```typescript
const result = await ctx.majk.scripting.execute_script({
  code?: string,                    // JavaScript code to execute
  rerun?: string,                   // Trace ID to re-run
  params?: Record<string, unknown>, // Parameters available as `params`
  dryRun?: boolean,                 // Mock write operations
  dryRunOptions?: {
    maxAIMocks?: number             // Limit AI mock responses
  },
  timeoutMs?: number                // Execution timeout
});

// Returns:
{
  success: boolean,
  result?: any,                     // Script return value
  error?: ScriptError,
  traceId: string,                  // For debugging/re-running
  traceFormatted: string,           // Human-readable trace
  trace: {
    summary: ScriptTraceSummary,
    events: ScriptTraceEvent[],
    toolCalls?: ScriptToolCallRecord[]
  }
}
```

### Tool Access in Scripts

Scripts access tools via the `tools` object:

```javascript
// Pattern: tools.ServiceName.function_name(params)

// Reports
const reports = await tools.ReportsService.list_reports({ pathPrefix: '/research/' });
await tools.ReportsService.write_report({ path: '/output.md', content: '...' });

// Delegation
const teammates = await tools.DelegationService.list_teammates();
const task = await tools.DelegationService.delegate_task({ teammate: 'dev', task: '...' });

// Batch
const job = await tools.BatchService.create_batch_job({ name: 'Process', ... });

// Tool Discovery
const tools = await tools.ToolDiscoveryService.discover_tools();
```

### expand_trace(input)

Get details for a specific tool call.

```typescript
const details = await ctx.majk.scripting.expand_trace({
  traceId: string,
  callSeq: number  // Sequence number from trace
});
// Returns: { call, fullParams, fullResult, functionSchema? }
```

### list_traces()

List recent script executions.

```typescript
const { traces, count } = await ctx.majk.scripting.list_traces();
// traces: Array<{ id, storedAt, summary: { success, totalCalls, durationMs, dryRun } }>
```

### get_trace_formatted(input)

Get formatted trace output.

```typescript
const trace = await ctx.majk.scripting.get_trace_formatted({ traceId: string });
// Returns: { traceFormatted, success, totalCalls, durationMs }
```

## Dry-Run Mode

Test scripts without making changes:

```typescript
const result = await ctx.majk.scripting.execute_script({
  code: `
    // This won't actually write
    await tools.ReportsService.write_report({
      path: '/test.md',
      content: 'Test content'
    });
    return 'done';
  `,
  dryRun: true
});

// Trace shows what WOULD have happened
console.log(result.traceFormatted);
```

## Parameterized Scripts

```typescript
// First run
const result = await ctx.majk.scripting.execute_script({
  code: `
    const reports = await tools.ReportsService.list_reports({
      pathPrefix: params.prefix,
      limit: params.limit
    });
    return reports;
  `,
  params: { prefix: '/research/', limit: 5 }
});

// Re-run with different params
const result2 = await ctx.majk.scripting.execute_script({
  rerun: result.traceId,
  params: { prefix: '/docs/', limit: 10 }
});
```

## Complex Orchestration

```typescript
const result = await ctx.majk.scripting.execute_script({
  code: `
    // Find all TypeScript files
    const files = await tools.FileSystem.glob({ pattern: 'src/**/*.ts' });

    // Create batch job to analyze them
    const { job } = await tools.BatchService.create_batch_job({
      name: 'Analyze TS files',
      input: { source: { type: 'list', items: files } },
      processor: { type: 'rpc', functionName: 'analyze_file' },
      autoStart: true
    });

    // Wait for completion
    const result = await tools.BatchService.await_batch_job({ jobId: job.id });

    // Write summary report
    await tools.ReportsService.write_report({
      path: '/analysis/summary.md',
      content: \`# Analysis Summary\\n\\nProcessed \${result.finalProgress.completedItems} files.\`
    });

    return result.finalProgress;
  `
});
```

## Error Handling

```typescript
const result = await ctx.majk.scripting.execute_script({
  code: `
    try {
      const data = await tools.SomeService.risky_operation();
      return { success: true, data };
    } catch (error) {
      console.error('Operation failed:', error.message);
      return { success: false, error: error.message };
    }
  `
});

if (!result.success) {
  console.log('Script error:', result.error);
  console.log('Trace:', result.traceFormatted);
}
```

## Debugging with Traces

```typescript
// Execute script
const result = await ctx.majk.scripting.execute_script({ code: '...' });

// View formatted trace
console.log(result.traceFormatted);

// Inspect specific call
const callDetails = await ctx.majk.scripting.expand_trace({
  traceId: result.traceId,
  callSeq: 3  // Third tool call
});
console.log('Params:', callDetails.fullParams);
console.log('Result:', callDetails.fullResult);
```

## Best Practices

1. **Use dry-run first** - Test scripts before real execution
2. **Add error handling** - Wrap risky operations in try/catch
3. **Use parameters** - Make scripts reusable
4. **Check traces** - Debug issues with trace inspection
5. **Keep scripts focused** - One clear purpose per script

## Next Steps

Run `npx @majkapp/plugin-kit --tool-discovery` - Discover available tools
Run `npx @majkapp/plugin-kit --batch` - Batch processing API
Run `npx @majkapp/plugin-kit --delegation` - Task delegation API
