@e-llm-studio/instant-learning
v1.3.0-alpha.120
Published
The library exposes two independently consumable components:
Maintainers
Keywords
Readme
Instant Learning Library
Usage & Integration
The library exposes two independently consumable components:
LearningManagement— renders the full Learning Management screen (scope tree, learnings, access, change history).TeachMePlugin— renders the Teach Me popup, an AI-assisted rule/learning creation interface. Can be mounted on its own, anywhere.
Install:
npm install @e-llm-studio/instant-learning1. LearningManagement
Renders the Learning Management screen. It uses @tanstack/react-query internally, so it must be wrapped in a QueryClientProvider by the consumer.
Import & sample usage
import LearningManagement from '@e-llm-studio/instant-learning';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<LearningManagement
userDetails={userDetails} // logged-in user + access token
llmStudioUrl="https://devllmstudio.creativeworkspace.ai"
audacyBackendUrl="https://dev-audacy-traffic-manager.techo.camp"
config={config} // runtime config (BASE_URL, ASSISTANT_NAME, …)
rbacConfig={rbacConfig} // RBAC / AppSec identifiers
auditLogConfig={{ configId: '6a1825e9fb722c37637b9490' }}
ilLabels={{
setupLabel: 'Learning Setup',
ruleTitle: 'Learning Title',
ruleDescriptionTitle: 'Learning Description',
}}
app_integration_id="019eb639-8eca-715a-95c1-efe0ee237ecc"
backwardCompatibility={false}
cognitiveCompareCompatibility={false}
modeDetails={{
activeModeName: 'Instant Learning Mode',
modeNameFromURL: 'Instant Learning Mode',
submodeNameFromURL: '',
}}
/>
</QueryClientProvider>
);
}Props
| Prop | Type | Required | Description |
|---|---|:---:|---|
| userDetails | User | ✅ | Logged-in user object. Must include accessToken (used for all API calls and as the GraphQL userDetails param). |
| llmStudioUrl | string | ✅ | Base URL of LLM Studio; used for tiers, IL instance, and rule APIs. |
| audacyBackendUrl | string | ✅ | Base URL of the client/product backend. |
| config | object (any) | ✅ | Runtime config consumed by the rule-creation flow (BASE_URL, BASE_WEBSOCKET_URL, ASSISTANT_NAME, ORGANIZATION_NAME, CHAT_TITLE, SOCKET_TIMEOUT, etc.). |
| rbacConfig | RbacConfig | ✅ | RBAC/AppSec identifiers: applicationName, applicationId, moduleId, applicationModuleId, applicationResourceId, appsecRbacUrl, appsecBaseUrl. Drives permission resolution. |
| auditLogConfig | AuditLogConfig | ✅ | Audit log config — { configId: string }. |
| ilLabels | { setupLabel; ruleTitle; ruleDescriptionTitle } | ✅ | Label overrides for the rule setup form (all three strings required). |
| app_integration_id | string | ⚠️ Optional* | Integration context used to load the per-integration remote JSON config (dt()/dtt() values) and scoped API calls. *Effectively required in non-backward-compat mode — without it the remote config won't load. |
| backwardCompatibility | boolean | ❌ Optional | Enables legacy mode (legacy create modal, legacy inherit API). Default false. |
| cognitiveCompareCompatibility | boolean | ❌ Optional | Enables cognitive-compare behavior. Default false. |
| modeId | string | ❌ Optional | Mode identifier passed through to the layout / rule content. |
| modeDetails | { activeModeName; modeNameFromURL; submodeNameFromURL } | ❌ Optional | Active mode metadata used for base-mode naming. |
Note: When
backwardCompatibility={false}, the screen reads its labels/dialogs from the remote config resolved viaapp_integration_idusing thedt()helper. Missing keys fall back to built-in defaults.
2. TeachMePlugin
Renders the AI-assisted Teach Me rule-creation popup. Unlike LearningManagement, it provides its own QueryClientProvider internally — no extra wrapper needed.
Import & sample usage
import TeachMePlugin from '@e-llm-studio/instant-learning';
// Required config fields for TeachMePlugin
const configuration = {
BASE_URL: 'https://devllmstudio.creativeworkspace.ai',
BASE_WEBSOCKET_URL: 'wss://devllmstudio.creativeworkspace.ai/graphql',
ORGANIZATION_NAME: 'techolution',
ASSISTANT_NAME: 'preview',
};
function CreateLearningButton({ open, setOpen, token }) {
return (
<TeachMePlugin
app_integration_id="019ecbcf-98c9-71bb-a663-ea962085c118"
isOpen={open}
onClose={() => setOpen(false)}
token={token} // bearer token for API calls
mode="ADD" // "ADD" | "EDIT"
config={configuration} // required runtime config (see table below)
pluginPayload={{
initialScope: 'global', // {scope} value for titles
ruleSet: selectedRuleSet, // optional ruleset context
// renderer-specific context (Radio Traffic, etc.):
editingRule: null,
editingTier: null,
editingVariants: null,
// optionally inline the config instead of remote-loading:
// teachMe: { teachMe, template, learningManagement, agents },
// tiers: [...],
}}
/>
);
}Props
| Prop | Type | Required | Description |
|---|---|:---:|---|
| isOpen | boolean | ✅ | Controls popup visibility. |
| onClose | () => void | ✅ | Called when the dialog requests to close. |
| token | string | ✅ | Bearer token for API calls. |
| mode | "ADD" \| "EDIT" | ✅ | Whether the popup is creating a new learning or editing an existing one. |
| config | object | ✅ | Runtime config for the chat/socket. See required config fields below. |
| app_integration_id | string | ⚠️ Optional* | Resolves the correct renderer template and remote config. *Optional only in backward-compat mode; otherwise required to load the template/config. |
| pluginPayload | Record<string, any> | ❌ Optional | Free-form data passed straight through to the active renderer. Recognized keys: initialScope ({scope} value), ruleSet, tiers (sets tiers directly), and teachMe ({ teachMe, template, learningManagement, agents } to inline config instead of remote-loading). Any other keys are forwarded to the renderer (e.g. editingRule, editingTier, editingVariants, focusedVariantIndex, triggerAddVariant, triggerFixGaps, copiedRule, initialDraftMessage, modeId). |
Required config fields
| Field | Type | Required | Description |
|---|---|:---:|---|
| BASE_URL | string | ✅ | LLM Studio base URL; used for the chat/REST calls. |
| BASE_WEBSOCKET_URL | string | ✅ | WebSocket (GraphQL) endpoint used by the live chat. |
| ORGANIZATION_NAME | string | ✅ | Organization identifier for the assistant. |
| ASSISTANT_NAME | string | ✅ | Name of the assistant that powers the Teach Me flow. |
const configuration = {
BASE_URL: 'https://devllmstudio.creativeworkspace.ai',
BASE_WEBSOCKET_URL: 'wss://devllmstudio.creativeworkspace.ai/graphql',
ORGANIZATION_NAME: 'techolution',
ASSISTANT_NAME: 'preview',
};Template resolution: The renderer is chosen from the
templatekey (inpluginPayload.teachMe.templateor the remote config) viaTemplateRegistry. Unknown values fall back to"Default". See the v17 changelog entry below for the registry and full config JSON.
Configuration Reference
Both LearningManagement and TeachMePlugin are fully label-driven. The UI text — titles, buttons, dialog copy, placeholders — comes from a JSON config loaded per appIntegrationId (or passed inline via pluginPayload.teachMe). Values are resolved at runtime with the dt() (LMS) and dtt() (TeachMe) helpers; any missing key falls back to a built-in default, so you only need to override what you want to change.
Top-level structure
{
"template": "Default",
"agents": { "LearningTerm": "Instruction" },
"teachMe": { "...": "TeachMe popup labels" },
"learningManagement": { "...": "Learning Management screen labels" }
}| Key | Type | Required | Description |
|---|---|:---:|---|
| template | string | ✅ | Renderer key. Must be present for any customisation to apply; must match a TemplateRegistry key ("Default", "Radio Traffic Learning", "Guidelines", …). Unknown values fall back to "Default". |
| agents.LearningTerm | string | ❌ | Word used for a "learning" across the UI (e.g. "Instruction", "Guideline"). |
| teachMe | object | ❌ | Labels for the Teach Me popup. See teachMe fields. |
| learningManagement | object | ❌ | Labels for the Learning Management screen (maps to LMSConfig). See learningManagement fields. |
Placeholders supported in values: {scope} / {scope_name} / {parent} (names), {count} / {N} (counts), {variant_name} (approve/reject dialogs), {rule_title} (enable/disable dialogs). They are interpolated at runtime.
{
"template": "Default",
"agents": {
"LearningTerm": "Instruction"
},
"teachMe": {
"welcomeMessage": "Hi! 👋 I'm your Instant Learning Concierge.",
"welcomeMessageSubtitle": "I can help you create and manage instructions.\nSelect an option below or type your requirement.",
"actions": [
{ "label": "Add new instruction", "value": "I would want to add a new Instruction" },
{ "label": "Update an instruction", "value": "I would want to edit an existing instruction" }
],
"chatTitle": "Teach Me ILOTJ - {scope} - Add Instruction",
"chatTitleEdit": "Teach Me ILOTJ - {scope} - Edit Instruction",
"chatTextareaPlaceholder": "Tell me about the instruction you want to create",
"formTitle": "Add Instruction",
"setupLabel": "Configure your IL",
"ruleTitle": "Main Instruction Name",
"scopeLabel": "Define Scope",
"tierLabel": "Select Tiers",
"ruleDescriptionTitle": "Explanation of the instruction",
"whenToApplyTitle": "Trigger Events (When to Apply)",
"addWhenToApplyBtnLabel": "Add WTA",
"whenNotToApplyTitle": "Exclusion Events (When NOT to Apply)",
"addWhenNotToApplyBtnLabel": "Add WNTA",
"configTitle": "Advanced Settings",
"saveBtnLabel": "Save Instruction",
"saveBtnLoadingLabel": "Saving Instruction...",
"showScope": false,
"showConfiguration": false
},
"learningManagement": {
"pageTitle": "Instruction Management",
"middleDrawer": {
"scope": "Scope",
"addScope": "Add Scope",
"addSubScope": "Add Subscope",
"subScope": "Subscope",
"treeMenu": {
"search": "Search for scopes",
"submenu": {
"learnings": "Instructions",
"access": "Access",
"changeHistory": "Change History"
},
"contextMenu": {
"addScope": "Add Scope",
"rename": "Rename",
"delete": "Delete {scope}",
"addSubScope": "Add SubScope"
}
},
"addScopeDialog": {
"title": "Add Scope",
"globalTitle": "Add Global Scope",
"subtitle": "This scope will be created under {parent} and will inherit its Learnings by default.",
"globalSubtitle": "This global scope defines base learnings that apply across all scopes.",
"scopeName": "Scope Name",
"submitButton": "Create Scope",
"cancel": "Cancel",
"learningApprovalSettings": {
"title": "Instruction Approval Settings",
"approvalRequired": {
"title": "Approval Required before Publishing",
"subtitle": "Learnings require approval before publishing"
},
"publishWithoutApproval": {
"title": "Publish Without Approval",
"subtitle": "Instructions can be published directly"
}
}
},
"scopeDisplayLimit": {
"enabled": "true",
"count": "3",
"compactView": "true",
"applyToLevels": "",
"viewMoreText": "show {count} more...",
"title": "Stations",
"description": "Manage the stations assigned to the {scope} scope.",
"searchPlaceholder": "Search station...",
"onboardBtn": "Onboard a station",
"viewText": "View"
}
},
"learnings": {
"header": {
"title": "{scope} Instructions",
"exportButton": "Export",
"addNewLearningButton": "Add New Instruction"
},
"tier": {
"showTierHeader": true,
"tierHeader": "Tier",
"subtitle": "These are the system-wide instructions applied across all documents.",
"tierHeaderNoOfLearnings": "Instructions",
"deleteDialog": {
"title": "Delete Tier {N}?",
"description": "This will permanently delete all rules and variants under this tier, including any inherited rules. This action cannot be undone.",
"cancel": "Cancel",
"submit": "Yes, Delete"
},
"learning": {
"inheritance": "Inheritance",
"actions": {
"disable": "Disable",
"enable": "Enable",
"approve": "Approve All",
"reject": "Reject All",
"delete": "Delete"
},
"approveDialog": {
"title": "Approve Guideline",
"desc": "{variant_name} will be published and become active within the selected scope after approval.",
"footer": "Take a moment to check the configuration before moving forward.",
"cancel": "Cancel",
"approveLearning": "Approve Guideline"
},
"rejectDialog": {
"title": "Reject Guideline",
"desc": "{variant_name} will not be published or applied within the selected scope. You can provide feedback before rejecting.",
"feedbackTitle": "Feedback",
"feedbackPlaceholder": "Add feedback or reason for rejection",
"deleteCheckboxLabel": "Also delete this guideline",
"cancel": "Cancel",
"rejectLearning": "Reject Guideline"
},
"deleteDialog": {
"title": "Delete",
"desc": "Are you sure you want to delete this rule? This action cannot be undone.",
"warningText": "This will permanently delete the rule configuration.",
"cancelText": "Cancel",
"deleteText": "Delete"
}
}
}
},
"emptyStateLearning": {
"title": "No instructions have been added !",
"desc": "Start by adding instructions that should apply across all documents.",
"createNewLearning": "Create New Instruction",
"createGlobalScope": "Create Global Scope",
"noAccessTitle": "Access Restricted",
"noAccessDesc": "You do not have access for this application.",
"requestAccessButton": "Request Access",
"requestSentButton": "Request Sent"
}
}
}teachMe fields
Drives the LHS of the Teach Me popup (greeting, quick actions, form labels). Resolved via dtt().
"teachMe": {
"welcomeMessage": "Hi! 👋 I'm your Instant Learning Concierge.",
"welcomeMessageSubtitle": "I can help you create and manage instructions.\nSelect an option below or type your requirement.",
"actions": [
{ "label": "Add new instruction", "value": "I would want to add a new Instruction" },
{ "label": "Update an instruction", "value": "I would want to edit an existing instruction" }
],
"chatTitle": "Teach Me ILOTJ - {scope} - Add Instruction",
"chatTitleEdit": "Teach Me ILOTJ - {scope} - Edit Instruction",
"chatTextareaPlaceholder": "Tell me about the instruction you want to create",
"formTitle": "Add Instruction",
"setupLabel": "Configure your IL",
"ruleTitle": "Main Instruction Name",
"scopeLabel": "Define Scope",
"tierLabel": "Select Tiers",
"ruleDescriptionTitle": "Explanation of the instruction",
"whenToApplyTitle": "Trigger Events (When to Apply)",
"addWhenToApplyBtnLabel": "Add WTA",
"whenNotToApplyTitle": "Exclusion Events (When NOT to Apply)",
"addWhenNotToApplyBtnLabel": "Add WNTA",
"configTitle": "Advanced Settings",
"saveBtnLabel": "Save Instruction",
"saveBtnLoadingLabel": "Saving Instruction...",
"showScope": false,
"showConfiguration": false
}| Field | Type | Description | Default |
|---|---|---|---|
| welcomeMessage | string | Primary greeting shown at the top of the chat. | "Hi! 👋 I'm your Instant Learning Concierge." |
| welcomeMessageSubtitle | string | Subtitle under the greeting. Supports Markdown and \n line breaks. | "How would you like to get started?…" |
| actions | Array<{ label, value }> | Quick-action buttons. label is the button text; value is the message sent to the agent when clicked. | 6 default actions |
| chatTitle | string | Popup title in Add mode. Supports {scope}. | "Teach Me OTJ - {scope} - Add Learning" |
| chatTitleEdit | string | Popup title in Edit mode. Supports {scope}. | "Teach Me OTJ - {scope} - Edit Learning" |
| chatTextareaPlaceholder | string | Placeholder for the freeform chat textarea. | "Tell me more about this learning.." |
| formTitle | string | Title of the inline rule form section. | "Rule setup" |
| setupLabel | string | Label for the setup/configuration area. | "Configure your IL" |
| ruleTitle | string | Label for the rule/learning name field. | "Main Rule Name" |
| scopeLabel | string | Label for the scope selector. | "Define Scope" |
| tierLabel | string | Label for the tier selector. | "Select Tiers" |
| ruleDescriptionTitle | string | Label for the description field. | "Learning Explanation" |
| whenToApplyTitle | string | Section title for trigger events. | "Trigger Events (When to Apply)" |
| addWhenToApplyBtnLabel | string | Button to add a "when to apply" entry. | "Add WTA" |
| whenNotToApplyTitle | string | Section title for exclusion events. | "Exclusion Events (When NOT to Apply)" |
| addWhenNotToApplyBtnLabel | string | Button to add a "when NOT to apply" entry. | "Add WNTA" |
| configTitle | string | Title for the advanced settings area. | "Advanced Settings" |
| saveBtnLabel | string | Save button label. | "Save Rule" |
| saveBtnLoadingLabel | string | Save button label while saving. | "Saving Rule..." |
| showScope | boolean | Whether to show the scope selection section. | false |
| showConfiguration | boolean | Whether to show the advanced configuration section. | false |
learningManagement fields
Maps to LMSConfig and drives the Learning Management screen. Resolved via dt(). Grouped below by area.
Page & middle drawer
"learningManagement": {
"pageTitle": "Instruction Management",
"middleDrawer": {
"scope": "Scope",
"addScope": "Add Scope",
"addSubScope": "Add Subscope",
"subScope": "Subscope",
"treeMenu": {
"search": "Search for scopes",
"submenu": { "learnings": "Instructions", "access": "Access", "changeHistory": "Change History" },
"contextMenu": { "addScope": "Add Scope", "rename": "Rename", "delete": "Delete {scope}", "addSubScope": "Add SubScope" }
},
"addScopeDialog": {
"title": "Add Scope",
"subtitle": "This scope will be created under {parent} and will inherit its Learnings by default.",
"scopeName": "Scope Name",
"submitButton": "Create Scope",
"cancel": "Cancel",
"learningApprovalSettings": {
"title": "Instruction Approval Settings",
"approvalRequired": { "title": "Approval Required before Publishing", "subtitle": "Learnings require approval before publishing" },
"publishWithoutApproval": { "title": "Publish Without Approval", "subtitle": "Instructions can be published directly" }
}
},
"scopeDisplayLimit": {
"enabled": "true",
"count": "3",
"compactView": "true",
"applyToLevels": "",
"viewMoreText": "show {count} more...",
"title": "Stations",
"description": "Manage the stations assigned to the {scope} scope.",
"searchPlaceholder": "Search station...",
"onboardBtn": "Onboard a station",
"viewText": "View"
}
}
}| Field (path under middleDrawer) | Type | Description |
|---|---|---|
| pageTitle (sibling of middleDrawer) | string | Title shown in the LMS header. |
| scope | string | Heading word for the current scope. |
| addScope / addSubScope / subScope | string | Labels for add-scope, add-subscope buttons and the subscope node. |
| treeMenu.search | string | Placeholder for the scope-tree search input. |
| treeMenu.submenu.{learnings, access, changeHistory} | string | Tree submenu labels. |
| treeMenu.contextMenu.{addScope, rename, delete, addSubScope} | string | Right-click context-menu actions. delete supports {scope}. |
| addScopeDialog.title / globalTitle | string | Dialog title for creating a scope / global scope. |
| addScopeDialog.subtitle / globalSubtitle | string | Dialog subtitle. Supports {parent}. |
| addScopeDialog.scopeName | string | Label for the scope-name field. |
| addScopeDialog.submitButton / cancel | string | Dialog action buttons. |
| addScopeDialog.learningApprovalSettings.title | string | Approval-settings section title. |
| …approvalRequired.{title, subtitle} | string | Copy for the "approval required" option. |
| …publishWithoutApproval.{title, subtitle} | string | Copy for the "publish without approval" option. |
| scopeDisplayLimit.enabled | string ("true"/"false") | Toggles the per-level display limit. |
| scopeDisplayLimit.count | string (number) | How many items to show before collapsing. |
| scopeDisplayLimit.compactView | string ("true"/"false") | Enables compact rendering. |
| scopeDisplayLimit.applyToLevels | string | JSON array of 1-indexed levels to limit, e.g. "[1,2]". Empty = all levels. |
| scopeDisplayLimit.viewMoreText | string | "See more" toggle text. Supports {count}. |
| scopeDisplayLimit.title | string | Word substituted for "Stations" in headers. Supports {scope}. |
| scopeDisplayLimit.description | string | Description under the Stations header. Supports {scope}. |
| scopeDisplayLimit.searchPlaceholder | string | Station search placeholder. |
| scopeDisplayLimit.onboardBtn | string | "Onboard a station" button label. |
| scopeDisplayLimit.viewText | string | Per-station "View" button label. |
Learnings, tiers & dialogs
"learnings": {
"header": { "title": "{scope} Instructions", "exportButton": "Export", "addNewLearningButton": "Add New Instruction" },
"tier": {
"showTierHeader": true,
"tierHeader": "Tier",
"subtitle": "These are the system-wide instructions applied across all documents.",
"tierHeaderNoOfLearnings": "Instructions",
"deleteDialog": { "title": "Delete Tier {N}?", "description": "This will permanently delete all rules…", "cancel": "Cancel", "submit": "Yes, Delete" },
"learning": {
"inheritance": "Inheritance",
"actions": { "disable": "Disable", "enable": "Enable", "approve": "Approve All", "reject": "Reject All", "delete": "Delete" },
"approveDialog": { "title": "Approve Guideline", "desc": "{variant_name} will be published…", "footer": "Take a moment to check…", "cancel": "Cancel", "approveLearning": "Approve Guideline" },
"rejectDialog": { "title": "Reject Guideline", "desc": "{variant_name} will not be published…", "feedbackTitle": "Feedback", "feedbackPlaceholder": "Add feedback…", "deleteCheckboxLabel": "Also delete this guideline", "cancel": "Cancel", "rejectLearning": "Reject Guideline" },
"deleteDialog": { "title": "Delete", "desc": "Are you sure…", "warningText": "This will permanently delete…", "cancelText": "Cancel", "deleteText": "Delete" }
}
}
}| Field (path under learnings) | Type | Description |
|---|---|---|
| header.title | string | Learnings page title. Supports {scope}. |
| header.exportButton | string | Export button label. |
| header.addNewLearningButton | string | "Add new learning" button label. |
| tier.showTierHeader | boolean | Whether the tier header region is shown. |
| tier.tierHeader | string | Tier header title. |
| tier.subtitle | string | Tier subtitle / description. |
| tier.tierHeaderNoOfLearnings | string | Word for the learnings count label. |
| tier.deleteDialog.{title, description, cancel, submit} | string | Bulk tier-delete dialog copy. title supports {N}. |
| tier.learning.inheritance | string | Label for the inheritance indicator. |
| tier.learning.actions.{disable, enable, approve, reject, delete} | string | Per-learning action labels. |
| tier.learning.approveDialog.{title, desc, footer, cancel, approveLearning} | string | Approve dialog copy. desc supports {variant_name}. |
| tier.learning.rejectDialog.{title, desc, feedbackTitle, feedbackPlaceholder, deleteCheckboxLabel, cancel, rejectLearning} | string | Reject dialog copy. desc supports {variant_name}. |
| tier.learning.deleteDialog.{title, desc, warningText, cancelText, deleteText} | string | Single-learning delete dialog copy. |
Empty state
"emptyStateLearning": {
"title": "No instructions have been added !",
"desc": "Start by adding instructions that should apply across all documents.",
"createNewLearning": "Create New Instruction",
"createGlobalScope": "Create Global Scope",
"noAccessTitle": "Access Restricted",
"noAccessDesc": "You do not have access for this application.",
"requestAccessButton": "Request Access",
"requestSentButton": "Request Sent"
}| Field | Type | Required | Description |
|---|---|:---:|---|
| title | string | ✅ | Empty-state heading. |
| desc | string | ✅ | Empty-state description. |
| createNewLearning | string | ✅ | CTA to create a learning. |
| createGlobalScope | string | ✅ | CTA to create a global scope. |
| noAccessTitle | string | ❌ | Heading when the user has no access. |
| noAccessDesc | string | ❌ | Description when the user has no access. |
| requestAccessButton | string | ❌ | "Request access" button label. |
| requestSentButton | string | ❌ | "Request sent" state label. |
Changelog
1.3.0-alpha.31 - 2026, June 10th
-Hide "Copy to Tier" option -Hide Tier Accordian in Learning Management screen -Configuring Max hirearchy from ILKB config and its UI changes
1.3.0-alpha.31 - 2026, June 10th
Backward Compatibility support for Save from AI changes
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 theresolvedDatastore field are all gone. hasPermission()andhasApplicationAccess()now run against the rawaccessDatavia a new internalgetUnionPermissionsForResource()helper that builds aSetof 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.chatTitleandteachMe.chatTitleEdit. Both support{scope}placeholder which is replaced at runtime with the selected scope name. - Welcome Message: Configurable greeting via
teachMe.welcomeMessage. Subtitle viateachMe.welcomeMessageSubtitlewith full Markdown support rendered viaReactMarkdown. - Action Buttons: Configurable via
teachMe.actionsarray — each entry has alabel(button text) andvalue(message sent to agent on click). - Textarea Placeholder: Configurable via
teachMe.textareaPlaceholder. - Backward Compatibility: TeachMe popup customisation is supported with
backwardCompatibilityflag.
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:
userDetailsobject 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 byvalue_type_config.teachMeJSON loaded perappIntegrationIdand resolved at runtime through thedtt()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_configJSON:
{
"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
templatekey at the root ofvalue_type_configmust be provided for any JSON customisation to take effect. Without it, the system falls back to resolving the renderer viavalue_type_namefrom the API, and config values may not be applied.{ "template": "Default" }The value must exactly match a key registered in
TemplateRegistry:|
templatevalue | Renderer | |---|---| |"Default"|DefaultTeachMeRenderer| |"Radio Traffic Learning"|RadioTrafficLearningRenderer| |"Guidelines"|GuidelinesTeachMeRenderer|For custom plugins, use the exact key you registered in
TemplateRegistryinTeachMePlugin.tsx: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
templatevalue is not found inTemplateRegistry, 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 thedt()helper instead of being hardcoded.dt()— read a config value anywhere
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 ?? pathwhen the key is not found or config is not loaded.
Examples:
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:
parentScopeIdnow correctly receives the parent scope's ID (global ID) when creating a new scope from a child node, instead of always beingnull - Auth Fallback: Added optional chaining (
?.) onuserDetails.accessTokento prevent crashes on reload - Access Section: Fixed logic that was hiding the Access section — it is now always visible regardless of
backwardCompatibilityflag
Alpha Release Commands
Create the first alpha version (e.g. 0.1.0-alpha.0)
npm version prerelease --preid=alpha
Increment the alpha version (e.g. 0.1.0-alpha.1)
npm version prerelease --preid=alpha
Publish the package under the alpha tag
npm publish --tag alpha
Install a specific alpha version
npm install @e-llm-studio/[email protected]
