# Instant Learning Library


## Changelog

### 1.3.0-alpha.21 - 2026, June 8th
**Permissions — Union-based access resolution**

- **Union model**: When a user holds multiple roles on the same resource (e.g. inherited group role + direct assignment), permissions from all roles are merged. If any role grants a permission, the user has it.
- **Removed**: `ROLE_HIERARCHY`, `getRolePrecedence()`, `resolveHighestRolePerResource()`, and the `resolvedData` store field are all gone.
- **`hasPermission()`** and **`hasApplicationAccess()`** now run against the raw `accessData` via a new internal `getUnionPermissionsForResource()` helper that builds a `Set` of all permissions across matching records.
- `fetchPermissions()` no longer calls the resolver — stores raw API response only.

### 1.3.0-alpha.20 - 2026, June 8th
**TeachMe Popup — LHS Customisation via `dtt()`**

- **Chat Title**: Configurable for both Add and Edit modes via `teachMe.chatTitle` and `teachMe.chatTitleEdit`. Both support `{scope}` placeholder which is replaced at runtime with the selected scope name.
- **Welcome Message**: Configurable greeting via `teachMe.welcomeMessage`. Subtitle via `teachMe.welcomeMessageSubtitle` with full **Markdown** support rendered via `ReactMarkdown`.
- **Action Buttons**: Configurable via `teachMe.actions` array — each entry has a `label` (button text) and `value` (message sent to agent on click).
- **Textarea Placeholder**: Configurable via `teachMe.textareaPlaceholder`.
- **Backward Compatibility**: TeachMe popup customisation is supported with `backwardCompatibility` flag.

Keys added in this version:

| JSON Key | Default |
|---|---|
| `teachMe.chatTitle` | `"Teach Me OTJ - {scope} - Add Learning"` |
| `teachMe.chatTitleEdit` | `"Teach Me OTJ - {scope} - Edit Learning"` |
| `teachMe.welcomeMessageSubtitle` | `"How would you like to get started?..."` |
| `teachMe.actions` | Array of `{ label, value }` — see sample JSON in v17 |
| `teachMe.textareaPlaceholder` | `"Tell me more about this learning.."` |

### 1.3.0-alpha.19 - 2026, June 6th
- **Cognitive Compare UI**: Updated comparison UI with visual changes
- **GraphQL Params**: `userDetails` object is now passed through as a GraphQL parameter

### 1.3.0-alpha.18 - 2026, June 6th
Patch Fix: Removal of underscore for all labels

### 1.3.0-alpha.17 - 2026, June 6th
**Without BackwardCompatibiltity Support**
- **TeachMe Renderer**: Added valuetype json support to render teachMe popup and create rule from the same.

  **Configurable UI via `dtt()`** — all LHS labels in the TeachMe popup are driven by `value_type_config.teachMe` JSON loaded per `appIntegrationId` and resolved at runtime through the `dtt()` helper.

  **Supported keys:**

  | JSON Key | Default |
  |---|---|
  | `teachMe.welcomeMessage` | `"Hi! 👋 I'm your Instant Learning Concierge."` |
  | `teachMe.formTitle` | `"Rule setup"` |
  | `teachMe.setupLabel` | `"Configure your IL"` |
  | `teachMe.ruleTitle` | `"Main Rule Name"` |
  | `teachMe.scopeLabel` | `"Define Scope"` |
  | `teachMe.tierLabel` | `"Select Tiers"` |
  | `teachMe.ruleDescriptionTitle` | `"Learning Explanation"` |
  | `teachMe.whenToApplyTitle` | `"Trigger Events (When to Apply)"` |
  | `teachMe.addWhenToApplyBtnLabel` | `"Add WTA"` |
  | `teachMe.whenNotToApplyTitle` | `"Exclusion Events (When NOT to Apply)"` |
  | `teachMe.addWhenNotToApplyBtnLabel` | `"Add WNTA"` |
  | `teachMe.configTitle` | `"Advanced Settings"` |
  | `teachMe.saveBtnLabel` | `"Save Rule"` |
  | `teachMe.saveBtnLoadingLabel` | `"Saving Rule..."` |
  | `teachMe.showConfiguration` | `false` |
  | `teachMe.showScope` | `false` |

  **Full sample `value_type_config` JSON:**

```json
  {
    "template": "Default",
    "teachMe": {
      "welcomeMessage": "Hi! 👋 I'm your Instant Learning Concierge.",
      "welcomeMessageSubtitle": "How would you like to get started?\nYou can select an option below or **describe the rule** you'd like to create.",
      "actions": [
        { "label": "Separation rule",          "value": "I would want to add a separation rule" },
        { "label": "Max priority rule",        "value": "I would want to set a max priority rule" },
        { "label": "Break code matching",      "value": "I would want to add a break code matching rule" },
        { "label": "Inventory code matching",  "value": "I would want to add a inventory window matching rule" },
        { "label": "Enter a rule description", "value": "I want to add a rule description" },
        { "label": "Tester Genie",             "value": "Loading prompt..." }
      ],
      "chatTitle": "Teach Me OTJ - {scope} - Add Learning",
      "chatTitleEdit": "Teach Me OTJ - {scope} - Edit Learning",
      "formTitle": "Rule Setup",
      "setupLabel": "Configure your IL",
      "ruleTitle": "Main Rule Name",
      "scopeLabel": "Define Scope",
      "tierLabel": "Select Tiers",
      "ruleDescriptionTitle": "Learning Explanation",
      "whenToApplyTitle": "Trigger Events (When to Apply)",
      "addWhenToApplyBtnLabel": "Add WTA",
      "whenNotToApplyTitle": "Exclusion Events (When NOT to Apply)",
      "addWhenNotToApplyBtnLabel": "Add WNTA",
      "configTitle": "Advanced Settings",
      "saveBtnLabel": "Save Rule",
      "saveBtnLoadingLabel": "Saving Rule...",
      "textareaPlaceholder": "Tell me more about this learning..",
      "showConfiguration": false,
      "showScope": false
    },
    "learningManagement": {}
  }
```

  > ⚠️ **Important**: The `template` key at the root of `value_type_config` **must** be provided for any JSON customisation to take effect. Without it, the system falls back to resolving the renderer via `value_type_name` from the API, and config values may not be applied.
  >
  > ```json
  > {
  >   "template": "Default"
  > }
  > ```
  >
  > The value must exactly match a key registered in `TemplateRegistry`:
  >
  > | `template` value | Renderer |
  > |---|---|
  > | `"Default"` | `DefaultTeachMeRenderer` |
  > | `"Radio Traffic Learning"` | `RadioTrafficLearningRenderer` |
  > | `"Guidelines"` | `GuidelinesTeachMeRenderer` |
  >
  > For custom plugins, use the exact key you registered in `TemplateRegistry` in `TeachMePlugin.tsx`:
  >
  > ```ts
  > export const TemplateRegistry: Record<string, React.FC<TeachMeWrapperProps>> = {
  >   "Default": DefaultTeachMeRenderer,
  >   "Radio Traffic Learning": RadioTrafficLearningRenderer,
  >   "Guidelines": GuidelinesTeachMeRenderer,
  >   "Your Template Name": YourCustomRenderer, // ← use this exact string in "template"
  > };
  > ```
  >
  > If the provided `template` value is not found in `TemplateRegistry`, the system automatically falls back to `"Default"`.

- **Learning Management Renderer**: Added valuetype json support to render Learning Management Screen and create rule from the same.

  **Configurable UI via `dt()`**

  The LMS UI is driven by a remote JSON config loaded per `appIntegrationId`. Every label, button text, and dialog copy is resolved at runtime through the `dt()` helper instead of being hardcoded.

  `dt()` — read a config value anywhere

```ts
  function dt(
    path: string,                             // dot-notation key into LMSConfig
    fallback?: string,                        // returned when key is missing
    params?: Record<string, string | number>  // fills {placeholder} tokens in the value
  ): string
```

  - Reads directly from the Zustand store (no hook — works outside React components).
  - Returns `fallback ?? path` when the key is not found or config is not loaded.

  **Examples:**

```ts
  dt('pageTitle')
  // → value of lmsConfig.pageTitle

  dt('middleDrawer.addScope', 'Add Scope')
  // → config value or fallback 'Add Scope'

  dt('learnings.tier.deleteDialog.title', 'Delete {N} learnings', { N: 3 })
  // → "Delete 3 learnings"  (placeholder replaced)

  dt('learnings.tier.learning.approveDialog.desc', undefined, { variant_name: 'Rule A' })
  // → config string with {variant_name} replaced by "Rule A"
```

### 1.3.0-alpha.16 - 2026, June 5th
- **Scope Management**: Added appIntegrationId support to scope creation and deletion flows in AddScopeModal and related API endpoints
- **Override History**: Included appIntegrationId when fetching override history to ensure correct integration context
- **Rule Retrieval**: Added appIntegrationId support when fetching rules by ruleId
- **Scope Deletion**: Fixed deletion logic for station scopes so that associated stations are correctly removed when type = station

### 1.3.0-alpha.15 - 2026, June 5th
- **Teach Me Renderer**: Modified default Teach Me renderer — switched from generic renderer to Radio Traffic value type renderer to support rule creation flow

### 1.3.0-alpha.14 - 2026, June 5th
- **IL Mode - Scope Creation**: `parentScopeId` now correctly receives the parent scope's ID (global ID) when creating a new scope from a child node, instead of always being `null`
- **Auth Fallback**: Added optional chaining (`?.`) on `userDetails.accessToken` to prevent crashes on reload
- **Access Section**: Fixed logic that was hiding the Access section — it is now always visible regardless of `backwardCompatibility` flag

---

## Alpha Release Commands

1. npm version prerelease --preid=alpha

becomes 0.0.0-alpha.0

2. run this again to bump it: npm version prerelease --preid=alpha

3. during publish: npm publish --tag alpha

4. installation: npm install @e-llm-studio/instant-learning@0.1.0-alpha.1