Skip to main content

Quick start

# Terminal 1: SAP connector (mock mode — no SAP connection needed)
cd connector
SAP_MOCK_MODE=true java -jar target/connector-0.1.0.jar

# Terminal 2: Cloudflare Worker
npm run dev

# Terminal 3: Vite frontend
npm run dev:frontend
The frontend runs on http://localhost:5173 and proxies API requests to the Worker on port 8787.

Scripts

CommandWhat it does
npm run devStart Cloudflare Worker on port 8787
npm run dev:frontendStart Vite dev server on port 5173
npm run buildBuild frontend + dry-run deploy
npm run deployBuild + deploy to Cloudflare Workers
npm testRun all tests once
npm run test:watchRun tests in watch mode
npm run test:coverageGenerate coverage report
npm run test:uiLaunch Vitest UI in browser
npm run lintRun ESLint
npm run typecheckTypeScript check (no emit)
npm run cf-typegenGenerate Cloudflare Workers types from wrangler.toml
./dev.shStart connectors + worker + frontend (Docker-based)
./dev.sh --rebuildRebuild connector image then start everything

Generalized SAP connections

This project now uses workspace_connections (multiple named SAP connections per workspace) instead of hardcoded s4_connector_url / ecc_connector_url columns on workspaces. Key implications:
  • Routing is connection-based (connection_id), not system_type-based
  • Dashboard/indexing/source/connection-test APIs use connection IDs
  • Agent tool context carries connections[] and tools route by connection_id
  • Cross-connection ETL tools use source_connection_id / target_connection_id

Project structure

aisi/
├── src/
│   ├── index.ts                     # Worker entry point (Hono router)
│   ├── types.ts                     # Global type definitions
│   ├── agents/
│   │   ├── agent.ts             # Durable Object class
│   │   ├── types.ts                 # Message, PendingApproval types
│   │   ├── system-prompt.ts         # System prompt builder
│   │   └── zod-schema.ts            # Zod → JSON Schema converter
│   ├── middleware/
│   │   ├── auth.ts                  # JWT auth + CORS
│   │   └── rate-limit.ts            # Rate limiting (60 req/min)
│   ├── routes/
│   │   ├── agents.ts                # /api/agents endpoints
│   │   ├── workspaces.ts            # /api/workspaces CRUD + /connections CRUD
│   │   ├── connection-test.ts       # Connector health + connection capability tests
│   │   ├── testing.ts               # SAP testing framework routes
│   │   ├── credentials.ts           # Connection secrets + user SAP credentials APIs
│   │   ├── indexing.ts              # SAP metadata indexing
│   │   ├── dashboard.ts             # Inventory + analytics
│   │   ├── clean-core.ts            # Clean Core / readiness endpoints
│   │   ├── docs.ts                  # Generated docs endpoints
│   │   ├── source.ts                # ABAP source fetch endpoints
│   │   ├── orgs.ts                  # Organization management
│   │   ├── files.ts                 # R2 file upload/download
│   │   ├── sandbox-callback.ts     # Sandbox tool callback route
│   │   └── scheduled.ts            # Cron handler
│   ├── services/
│   │   ├── sap-indexer.ts           # Background SAP indexer
│   │   ├── clean-core-analyzer.ts   # Clean Core analysis engine
│   │   ├── conversion-readiness-analyzer.ts # ECC conversion readiness
│   │   ├── doc-generator.ts         # Module + technical docs generator
│   │   ├── embedding-service.ts     # OpenAI embeddings for search
│   │   └── business-process-inferrer.ts # Process inference
│   ├── workflows/
│   │   └── sap-sync-workflow.ts     # Index + enrichment workflow
│   ├── tools/
│   │   ├── tool-definitions.ts      # Base SAP tool definitions
│   │   ├── sap-tools.ts             # buildSapTools(), connection_id routing
│   │   ├── sap-connector-client.ts  # HTTP client for Java connector
│   │   ├── mock-data.ts             # Fallback mock data generators
│   │   ├── sandbox/
│   │   │   ├── execute-code.ts      # execute_code tool definition
│   │   │   ├── bridge-codegen.ts    # Python bridge code generator
│   │   │   └── types.ts             # Sandbox request/response types
│   │   └── etl/
│   │       ├── types.ts             # ETL type definitions
│   │       ├── etl-tools.ts         # 4 ETL tool definitions
│   │       └── transformers.ts      # 12 pure transform functions
│   ├── lib/
│   │   ├── supabase.ts              # Supabase client factory
│   │   ├── auth-helpers.ts          # requireMembership, requireAdmin
│   │   └── encryption.ts            # AES-256-GCM helpers for SAP passwords
│   ├── data/                        # Ingestion + prompt assets for scans
│   └── frontend/
│       ├── main.tsx                 # React entry
│       ├── App.tsx                  # Route definitions
│       ├── context/                 # AuthContext, DashboardContext
│       ├── pages/                   # Login, Dashboard, Workspace, Agent, Settings
│       ├── components/
│       │   ├── chat/                # ChatInterface, MessageBubble, ApprovalCard, ToolCard
│       │   ├── layout/              # Sidebar, Layout
│       │   ├── workspaces/          # WorkspaceGrid, WorkspaceCard
│       │   └── ui/                  # Radix UI wrappers (button, card, dialog, etc.)
│       └── styles/
│           └── globals.css          # Tailwind + CSS variables
├── connector/                       # Java SAP connector (see /connector)
├── supabase/
│   ├── config.toml
│   ├── migrations/                  # Postgres schema migrations
│   └── seed.sql
├── tests/
│   ├── setup.ts                     # Vitest setup
│   └── stubs/                       # Mock modules (cloudflare-workers, anthropic-sdk, cloudflare-sandbox)
├── docs/                            # Mintlify documentation
├── wrangler.toml                    # Cloudflare Workers config
├── vite.config.ts
├── vitest.config.ts
├── tailwind.config.js
├── tsconfig.json
└── .eslintrc.cjs

Environment variables

Worker (.dev.vars):
VariableRequiredDescription
ANTHROPIC_API_KEYYesClaude API key
SUPABASE_URLYesSupabase project URL
SUPABASE_ANON_KEYYesSupabase anon key
SUPABASE_SERVICE_ROLE_KEYYesSupabase service role key
ENCRYPTION_KEYYes64-char hex key (32 bytes) for encrypting/decrypting SAP user passwords
OPENAI_API_KEYNoRequired for embeddings and doc search (scan pipeline)
PRIMARY_MODELNoDefault “primary” model in provider:model format (e.g. anthropic:claude-opus-4-5)
SECONDARY_MODELNoDefault “secondary” model in provider:model format (e.g. anthropic:claude-haiku-4-5)
DOC_CONCURRENCYNoOverride doc generation concurrency in workflows
DEV_ITEM_LIMITNoCap entries for fast workflow runs
connector_key is now stored per connection in connection_secrets (not in Worker env vars). Worker (wrangler.toml vars):
VariableDefaultDescription
ENVIRONMENTdevelopmentdevelopment or production
CORS_ORIGINhttp://localhost:5173,http://localhost:8787Comma-separated allowed origins
WORKER_URLhttp://host.docker.internal:8787Used by sandbox containers for callbacks
Connector (environment or application.yml):
VariableDefaultDescription
SAP_MOCK_MODEfalseRun without SAP connection
SAP_HOSTSAP application server
SAP_SYSTEM_NUMBER00System number
SAP_CLIENT100Mandant/client number
SAP_USERSAP username
SAP_PASSWORDSAP password
SAP_LANGUAGEENSAP logon language
SAP_POOL_CAPACITY5JCo connection pool size
CONNECTOR_API_KEYMust match that connection’s connection_secrets.connector_key

Testing

Configuration

Vitest is configured in vitest.config.ts:
  • Environment: jsdom (for React component tests)
  • Setup: tests/setup.ts
  • Coverage: v8 provider, 80% thresholds on branches/functions/lines/statements

Path aliases in tests

// vitest.config.ts aliases
'@/''./src/'
'@/components/''./src/frontend/components/'
'@/lib/''./src/lib/'
'@/pages/''./src/frontend/pages/'
'cloudflare:workers''./tests/stubs/cloudflare-workers.ts'
'@anthropic-ai/sdk''./tests/stubs/anthropic-sdk.ts'
'@cloudflare/sandbox''./tests/stubs/cloudflare-sandbox.ts'
The Cloudflare Workers, Anthropic SDK, and Cloudflare Sandbox stubs mock out platform-specific APIs so tests can run in Node.js.

Running tests

npm test                  # Run all tests once
npm run test:watch        # Watch mode
npm run test:coverage     # With coverage report
npm run test:ui           # Vitest UI in browser

Wrangler config

Key sections of wrangler.toml:
name = "ai-si"
main = "src/index.ts"
compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"]

# Durable Objects
[[durable_objects.bindings]]
name = "AGENT"
class_name = "Agent"

# Sandbox Durable Object
[[durable_objects.bindings]]
name = "SANDBOX"
class_name = "Sandbox"

# Workflows
[[workflows]]
name = "sap-sync-workflow"
binding = "SAP_SYNC_WORKFLOW"
class_name = "SAPSyncWorkflow"

# Static assets (Vite build output)
[assets]
directory = "./dist"

# R2 file storage
[[r2_buckets]]
binding = "FILE_STORAGE"
bucket_name = "aisi-file-storage"

# Rate limiting
[[unsafe.bindings]]
name = "RATE_LIMITER"
type = "ratelimit"
namespace_id = "1"
simple = { limit = 60, period = 60 }

Deploying secrets

Secrets can’t go in wrangler.toml. Set them via CLI:
wrangler secret put ANTHROPIC_API_KEY
wrangler secret put OPENAI_API_KEY
wrangler secret put SUPABASE_URL
wrangler secret put SUPABASE_ANON_KEY
wrangler secret put SUPABASE_SERVICE_ROLE_KEY
wrangler secret put ENCRYPTION_KEY
ENCRYPTION_KEY must be a 64-character hex string (generate with openssl rand -hex 32).

TypeScript config

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "types": ["@cloudflare/workers-types", "vite/client"]
  }
}
Path aliases (@/*, @/components/*, @/lib/*, @/pages/*) are configured in both tsconfig.json and vite.config.ts.

Linting

ESLint config in .eslintrc.cjs:
  • Extends: eslint:recommended, @typescript-eslint/recommended, react, react-hooks
  • Key rules: no unused vars (except _ prefix), warn on any, no react-in-jsx-scope
npm run lint

Common tasks

Reset Durable Object state

During development, you may want to clear an agent’s conversation state:
# Use wrangler local mode for easy resets
wrangler dev --local

Type-check before committing

npm run typecheck && npm run lint

Generate Cloudflare types

After changing wrangler.toml bindings, regenerate types:
npm run cf-typegen
This updates the Env type to reflect current bindings (Durable Objects, R2, rate limiter, vars, secrets).