# @robinpath/core

The core runtime for [RobinPath](https://robinpath.com) — a scripting language with a built-in AI workflow engine. Write automations in plain English, let AI handle the routing.

```robinpath
ask "Paste customer feedback:" into $feedback

@known @desc "Route positive reviews to marketing"
def positive_review $feedback
  slack.send "#wins" $feedback
enddef

@known @desc "Create Jira ticket for bugs"
def bug_report $feedback
  jira.create "BUG" $feedback
enddef

think tools [@known]
  Review this feedback and handle it: $feedback
endthink
```

## Installation

```bash
npm i @robinpath/core
```

## Quick Start

```typescript
import { RobinPath } from '@robinpath/core';

const rp = new RobinPath();

await rp.executeScript(`
  $items = ["apples", "bananas", "cherries"]
  for $item in $items
    log "Item: " + $item
  endfor
`);
```

## AI Workflow Engine

RobinPath replaces complex if/else trees with AI-powered routing. Define actions, let the AI decide which to run.

### The Pattern: input -> AI decides -> human approves -> execute

```robinpath
# 1. Get input
ask "Customer email:" into $email
ask "Plan:" ["starter", "pro", "enterprise"] into $plan

# 2. Define available actions
@known @desc "Create Salesforce account"
def create_account $email $plan
  salesforce.create $plan $email
enddef

@known @desc "Send welcome email"
def send_welcome $email $plan
  gmail.send $email "Welcome to " + $plan + "!"
enddef

@known @desc "Notify team on Slack"
def notify_slack $channel $message
  slack.send $channel $message
enddef

# 3. AI creates an execution plan
think as plan into $steps tools [@known]
  New customer: email=$email, plan=$plan
  Create the right onboarding steps.
endthink

# 4. Execute with human approval
run $steps "approve"
```

This replaces what would be 60+ if/else branches with a single AI decision.

### Three Routing Options

**Option A** — AI decides AND executes (automatic):
```robinpath
think tools [@known]
  Review this feedback and route it: $feedback
endthink
```

**Option B** — AI decides, script controls execution:
```robinpath
think guard ["billing", "hr", "engineering"] into $dept
  Which department handles this? $feedback
endthink
approve "Route to " + $dept + "?"
call $dept $feedback
```

**Option C** — AI creates a multi-step plan:
```robinpath
think as plan into $steps tools [@known]
  Onboard this enterprise customer in EU.
endthink
run $steps "approve"
```

### Key Features

| Feature | Syntax | Purpose |
|---------|--------|---------|
| `ask` | `ask "prompt" into $var` | Interactive input (supports choices) |
| `approve` | `approve "message"` | Human approval gate |
| `think` | `think [options] ... endthink` | AI reasoning and routing |
| `@known` | `@known def func ... enddef` | Mark function as AI-callable |
| `@by` | `@by "model"` | Restrict which AI model can call it |
| `call` | `call $func_name` | Dynamic function dispatch |
| `run` | `run $plan "approve"` | Execute plan with approval gates |
| `remember` | `remember ... endremember` | Persistent AI memory |
| `as plan` | `think as plan into $steps` | AI returns execution plan |
| `tools [@known]` | `think tools [@known]` | Auto-discover @known functions |

### Named AI Agents

```robinpath
# Register agents with different models and personas
# rp.registerAgent("support", { model: "claude-sonnet-4.6", systemPrompt: "You are a support specialist." })

think support into $reply
  Customer says: $message
  Draft a helpful response.
endthink
```

### Persistent Memory

```robinpath
remember "customer_prefs"
  customer prefers email over phone
  customer is on enterprise plan
endremember

# Later, AI can reference this context
think memory "customer_prefs"
  How should we reach out to this customer?
endthink

# Remove specific memories
unremember "customer_prefs"
  customer prefers email over phone
endunremember
```

## Host Integration

### Unified Setup (Recommended)

Configure everything with one call via `RobinPathHost`:

```typescript
import { RobinPath, RobinPathHost } from '@robinpath/core';

const rp = new RobinPath();

rp.setHost({
  think: myAIProvider,
  ask: {
    ask: async (prompt, options) => {
      // Show prompt in your UI, return user's response
      // options.choices contains constrained options if provided
      return await showInputDialog(prompt, options);
    },
    approve: async (message, options) => {
      // Show approval dialog, return true/false
      return await showConfirmDialog(message);
    },
  },
  remember: {
    load: async (key) => db.get(`memory:${key}`) || [],
    save: async (key, entries) => db.set(`memory:${key}`, entries),
    clear: async (key) => db.delete(`memory:${key}`),
    list: async () => db.keys('memory:*'),
  },
  onStreamToken: (delta) => process.stdout.write(delta),
});
```

Individual setters also work: `setThinkHandler()`, `setAskHandler()`, `setRememberHandler()`, `registerAgent()`.

**Console fallbacks:** When no handler is set, `ask` falls back to stdin readline and `approve` auto-approves with a warning — scripts are testable without full host setup.

## Language Basics

### Variables and Last Value

```robinpath
$name = "Alice"
$age = 25

math.add 10 20
log $              # 30 — $ holds last result

math.add 5 3 into $sum
log $sum           # 8
```

### Control Flow

```robinpath
if $score >= 90
  log "Grade: A"
elseif $score >= 80
  log "Grade: B"
else
  log "Grade: F"
endif

for $item in $items
  log $item
endfor

for $i from 1 to 10
  log $i
endfor
```

### Functions

```robinpath
@desc "Calculate total with tax"
@param number $amount "Base amount"
@param number $rate "Tax rate"
def withTax $amount $rate
  return $amount + ($amount * $rate)
enddef

withTax 100 0.2 into $total
log $total   # 120
```

### Do Blocks and Error Handling

```robinpath
do
  $result = http.get "https://api.example.com/data"
catch $err
  log "Failed: " + $err
enddo
```

### Parallel Execution

```robinpath
together
  do into $users
    http.get "https://api.example.com/users"
  enddo
  do into $posts
    http.get "https://api.example.com/posts"
  enddo
endtogether
```

### Think Blocks (AI Reasoning)

```robinpath
# Simple prompt
think into $answer
  What is the capital of France?
endthink

# Structured output
think as json { name: string, sentiment: string } into $analysis
  Analyze: $review
endthink

# Constrained output
think guard ["bug", "feature", "question"] into $category
  Classify this issue: $title
endthink

# Agent tool loop
think tools [http, file] into $result
  Fetch weather data and save to weather.json
endthink
```

### Decorators

```robinpath
@desc "Fetch with retry"
@retry 3
@timeout 10000
do
  http.get "https://flaky-api.example.com"
enddo

@known                            # AI-callable
@by "anthropic/claude-haiku-4.5"  # Model restriction
@desc "Quick text classification"
@pos 100 200                      # Visual canvas position
def classify $text
  think.classify $text ["positive", "negative", "neutral"]
enddef
```

## 250+ Modules

Install external modules for real integrations:

```bash
npm i @robinpath/slack @robinpath/jira @robinpath/gmail
```

```robinpath
slack.send "#general" "Hello from RobinPath!"
jira.create "BUG" "Login page broken"
gmail.send "team@company.com" "Report" $report
```

Available modules include: `slack`, `jira`, `github`, `gmail`, `notion`, `airtable`, `salesforce`, `hubspot`, `shopify`, `discord`, `telegram`, `whatsapp`, `twilio`, `zendesk`, `linear`, `mongodb`, `postgres`, `redis`, `s3`, `firebase`, `supabase`, `google-sheets`, `google-drive`, `google-calendar`, `excel`, `pdf`, `openai`, `anthropic`, and [200+ more](https://robinpath.com/modules).

## Advanced SDK

### REPL Mode

```typescript
const rp = new RobinPath();
await rp.executeLine('$x = 10');
await rp.executeLine('math.add $x 20');
console.log(rp.getLastValue()); // 30
```

### Threads

```typescript
const rp = new RobinPath({ threadControl: true });
const thread = rp.createThread('user-123');
await thread.executeScript('$count = 10');
```

### Custom Builtins and Modules

```typescript
rp.registerBuiltin('greet', (args) => `Hello, ${args[0]}!`);

rp.registerModule('myapp', {
  process: (args) => processData(args[0]),
  validate: (args) => isValid(args[0]),
});
```

### Execution Control

```typescript
rp.pause();     // Pause execution
rp.resume();    // Resume
rp.cancel();    // Cancel
rp.step();      // Execute single step
```

## Full Language Reference

See [CORE.md](./CORE.md) for the complete language specification.

## License

MIT
