Add agent skill (SKILL.md + per-domain reference)
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
# Scenarios + effects — `client.effects`
|
||||
|
||||
Scenarios are server-authored node graphs (configured in the dashboard) that
|
||||
run per player. The SDK's scenario runtime is deliberately **not** part of the
|
||||
public client surface: scenario nodes surface as typed effects through
|
||||
`client.effects` (source: `src/effects/EffectsCenter.ts`), and the engine
|
||||
itself loads lazily on first login.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
- The runtime starts after login: scenario state is restored from persistence,
|
||||
then the login event (`'player_login'` by default) is fired to trigger
|
||||
event-driven scenarios.
|
||||
- Runs persist to IndexedDB by default, so waits and pending nodes survive
|
||||
page reloads. On restore, each run is reconciled with the server
|
||||
(`unknown_run` / `expired` runs are dropped).
|
||||
- `logout()` / `dispose()` clear all runs and persisted state.
|
||||
|
||||
### Runtime options (`RudderClientOptions.runtime`)
|
||||
|
||||
```ts
|
||||
runtime?: {
|
||||
// Scenario plan persistence. undefined = default IndexedDB store (created
|
||||
// lazily); null = disable persistence entirely; or pass a PlanStateStore.
|
||||
planStateStore?: PlanStateStore | null;
|
||||
|
||||
// Scenario event fired automatically after login.
|
||||
// undefined = 'player_login'; null = fire nothing.
|
||||
loginEvent?: string | null;
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribing
|
||||
|
||||
Every `on*` method takes a handler `(effect) => void | Promise<void>` and
|
||||
returns an unsubscribe function. Errors thrown inside handlers go to the
|
||||
`onEffectError` client option (default `console.error`).
|
||||
|
||||
```ts
|
||||
const off = client.effects.onNotification(async (n) => {
|
||||
showToast(n.title, n.message);
|
||||
await n.done(); // always resolve the session or the run stalls
|
||||
});
|
||||
```
|
||||
|
||||
## Effect types
|
||||
|
||||
```ts
|
||||
interface Effects {
|
||||
onNotification(handler): EffectUnsubscribe;
|
||||
onStoreOffer(handler): EffectUnsubscribe;
|
||||
onLeaderboard(handler): EffectUnsubscribe;
|
||||
onConfigChanged(handler): EffectUnsubscribe;
|
||||
onWait(handler): EffectUnsubscribe;
|
||||
onScenarioCompleted(handler): EffectUnsubscribe;
|
||||
onScenarioFailed(handler): EffectUnsubscribe;
|
||||
onQuest(handler): EffectUnsubscribe;
|
||||
onBattlePass(handler): EffectUnsubscribe;
|
||||
onBattlePassLevel(handler): EffectUnsubscribe;
|
||||
}
|
||||
```
|
||||
|
||||
### `NotificationEffect` — a notification node became active
|
||||
|
||||
```ts
|
||||
{ readonly title: string; readonly message: string; done(): Promise<void> }
|
||||
```
|
||||
|
||||
### `StoreOfferEffect` — a store node became active
|
||||
|
||||
```ts
|
||||
{
|
||||
readonly store: ShopHandle;
|
||||
readonly offers: readonly OfferHandle[];
|
||||
readonly message?: string;
|
||||
buy(offer: OfferHandle, options?: BuyOptions): Promise<PurchaseOfferResponse>;
|
||||
dismiss(): Promise<void>; // declines the offer and advances the run
|
||||
}
|
||||
```
|
||||
|
||||
### `LeaderboardEffect` — a leaderboard node became active
|
||||
|
||||
```ts
|
||||
{ end(): Promise<void>; rewardClaimed(): Promise<void> }
|
||||
```
|
||||
|
||||
### `ConfigChangedEffect` — a `remote_config_override` node patched config
|
||||
|
||||
```ts
|
||||
{ readonly key: string } // client.remoteConfig.get(key) already returns the override
|
||||
```
|
||||
|
||||
### `WaitEffect` — a wait node became active
|
||||
|
||||
```ts
|
||||
{ readonly deadlineUtc: Date } // run resumes automatically at the deadline
|
||||
```
|
||||
|
||||
### `QuestEffect` — a scenario quest node became active
|
||||
|
||||
```ts
|
||||
{
|
||||
readonly name: string;
|
||||
readonly objectives: ReadonlyArray<Record<string, unknown>>;
|
||||
reportProgress(objectiveId: string, amount?: number): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
The node auto-completes server-side once every objective is satisfied; the SDK
|
||||
crosses the `onComplete` boundary itself when the server reports completion.
|
||||
|
||||
### `BattlePassEffect` — a battle pass node became active
|
||||
|
||||
```ts
|
||||
{
|
||||
getProgress(): Promise<GetBattlePassProgressResponse>;
|
||||
addXp(source: string, amount: number): Promise<AddBattlePassXpResponse>;
|
||||
claimReward(level: number, track?: 'free' | 'premium'): Promise<ClaimBattlePassRewardResponse>;
|
||||
purchasePremium(): Promise<PurchaseBattlePassPremiumResponse>;
|
||||
levelUp(): Promise<void>;
|
||||
end(): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
These wrap `client.battlePass` with the run's `scenarioId`/`nodeId`/`runId`
|
||||
already bound — prefer them over calling the service manually.
|
||||
|
||||
### `BattlePassLevelEffect` — a `battlepass_level` node (single claimable tier)
|
||||
|
||||
```ts
|
||||
{ readonly level: number; claim(): Promise<void> }
|
||||
```
|
||||
|
||||
### Run lifecycle effects
|
||||
|
||||
```ts
|
||||
interface ScenarioCompletedEffect { readonly runId: string; readonly scenarioId: string }
|
||||
interface ScenarioFailedEffect {
|
||||
readonly runId: string; readonly scenarioId: string; readonly nodeId: string;
|
||||
readonly error: Error; // transport gave up, or unsupported node type
|
||||
}
|
||||
```
|
||||
|
||||
Always subscribe to `onScenarioFailed` — otherwise run failures surface only
|
||||
as console warnings.
|
||||
|
||||
## Supported node types
|
||||
|
||||
`wait`, `remote_config_override`, `notification`, `store`, `leaderboard`,
|
||||
`quest`, `battlepass`, `battlepass_level`. Any other node type fails the run
|
||||
(surfaced via `onScenarioFailed`).
|
||||
|
||||
## Reliability notes
|
||||
|
||||
- Node completion is idempotent client-side (completed handles are tracked).
|
||||
- Transient boundary failures (network error, 5xx) leave the node active for
|
||||
retry on reconnect; terminal server errors fail the run.
|
||||
- Server scenario errors use the typed codes `run_expired`, `run_not_active`,
|
||||
`node_not_active`, `scenario_not_active`, `unknown_run`,
|
||||
`early_completion`, `objectives_incomplete`, `level_not_reached`,
|
||||
`forbidden` (`RudderErrorCodes`).
|
||||
Reference in New Issue
Block a user