loopengine 0.1.64 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,9 +117,9 @@ code changes or redeploy needed for most of it:
117
117
  | --- | --- |
118
118
  | **Chat** | Talk to the agent, approve or deny tool calls as they come up, and follow each step (model calls, tool calls, permission checks) in the Run trace. Past conversations are under History. |
119
119
  | **Overview** | A card per tab (tools, permissions, skills, settings), plus the system prompt, model, hooks and limits, each editable in place. |
120
+ | **Abilities** | Install, upgrade, and uninstall abilities (see [Ability system](#ability-system)). |
120
121
  | **Tools** | Your hand-written tools, tools from integrations (e.g. [Composio](https://composio.dev)) and subagents, with whether each call runs on its own, asks first, or is denied. Build an HTTP tool or connect an integration without touching a file. |
121
122
  | **Skills** | Create, edit, and delete `SKILL.md` files for this agent directly in the browser — write the body, preview the rendered markdown, save. |
122
- | **Abilities** | Install, upgrade, and uninstall abilities (see [Ability system](#ability-system)). |
123
123
  | **Permissions** | Add, edit, and delete permission rules (actauth) — who, tool, decision — and choose what happens when no rule matches. |
124
124
  | **Environment** | Every setting an installed ability reads, with its project-wide value and this agent's own value side by side, and which one the agent actually uses. A secret is never shown again once set. |
125
125
 
@@ -600,11 +600,13 @@ ${consoleShellScript}
600
600
  }
601
601
  return '<div class="le-cards" style="margin-bottom:28px">' +
602
602
  card(null, 'Model', escapeHtml(modelValue), escapeHtml(modelDetail)) +
603
+ (cfg.abilityCount != null
604
+ ? card('abilities', 'Abilities', String(cfg.abilityCount), cfg.abilityCount ? 'Installed for this agent' : 'Add tools, skills and rules in one install')
605
+ : card('abilities', 'Abilities', 'Browse', 'Add tools, skills and rules in one install')) +
603
606
  card('tools', 'Tools', String(cfg.tools.length), escapeHtml(toolNames.slice(0, 3).join(', ') + (toolNames.length > 3 ? ', \u2026' : '')) || 'None yet') +
607
+ card('skills', 'Skills', String(cfg.skills.length), escapeHtml(cfg.skills.map(function (k) { return k.name; }).join(', ')) || 'None yet') +
604
608
  card('actauth', 'Permissions', rules.length + (rules.length === 1 ? ' rule' : ' rules'),
605
609
  (asks ? asks + ' need approval \u00b7 ' : '') + 'unmatched calls: ' + escapeHtml(cfg.permissions.defaultDecision)) +
606
- card('skills', 'Skills', String(cfg.skills.length), escapeHtml(cfg.skills.map(function (k) { return k.name; }).join(', ')) || 'None yet') +
607
- card('abilities', 'Abilities', 'Browse', 'Add tools, skills and rules in one install') +
608
610
  card('env', 'Environment', 'Settings', '<span data-le-env-count="' + escapeHtml(cfg.name) + '">' + leShell.envCountHtml(cfg.name) + '</span> Values your installed abilities read') +
609
611
  '</div>';
610
612
  }
@@ -1634,6 +1636,8 @@ ${consoleShellScript}
1634
1636
  if (!content) return;
1635
1637
  content.innerHTML = renderAbilitiesConfigHtml(data);
1636
1638
  var installedNames = (data.abilities || []).map(function (a) { return a.name; });
1639
+ // Keeps the tab badge right after an install or uninstall here.
1640
+ leShell.setCount('abilities', installedNames.length);
1637
1641
  wireAbilitiesHandlers(name, installedNames);
1638
1642
  abilitiesLoadedFor = name;
1639
1643
  }
@@ -2537,7 +2541,7 @@ ${consoleShellScript}
2537
2541
  prompt: cfg.systemPrompt,
2538
2542
  chips: [modelChip(cfg), { text: 'unmatched calls: ' + cfg.permissions.defaultDecision }],
2539
2543
  tab: currentTab,
2540
- counts: { tools: cfg.tools.length, skills: cfg.skills.length, actauth: cfg.permissions.rules.length },
2544
+ counts: { tools: cfg.tools.length, skills: cfg.skills.length, abilities: cfg.abilityCount, actauth: cfg.permissions.rules.length },
2541
2545
  }) +
2542
2546
  '<div class="le-scroll"><div class="le-page" style="display:block">' +
2543
2547
  '<div class="tab-panel" data-tab-panel="overview">' + renderOverviewHtml(cfg) + '</div>' +
@@ -41,8 +41,8 @@ export const consoleShellScript = `<script>
41
41
  // after the list loads.
42
42
  var toSet = {};
43
43
  var TABS = [
44
- ['chat', 'Chat'], ['overview', 'Overview'], ['tools', 'Tools'], ['skills', 'Skills'],
45
- ['abilities', 'Abilities'], ['actauth', 'Permissions'], ['env', 'Environment']
44
+ ['chat', 'Chat'], ['overview', 'Overview'], ['abilities', 'Abilities'], ['tools', 'Tools'],
45
+ ['skills', 'Skills'], ['actauth', 'Permissions'], ['env', 'Environment']
46
46
  ];
47
47
 
48
48
  function esc(s) {
@@ -134,6 +134,15 @@ export const consoleShellScript = `<script>
134
134
  renderList();
135
135
  }
136
136
 
137
+ // Updates one tab's count badge in place (e.g. after an install).
138
+ function setCount(tab, n) {
139
+ var link = document.querySelector('.le-tab[data-tab="' + tab + '"]');
140
+ if (!link) return;
141
+ var badge = link.querySelector('.le-count');
142
+ if (!badge) { badge = document.createElement('span'); badge.className = 'le-count'; link.appendChild(badge); }
143
+ badge.textContent = String(n);
144
+ }
145
+
137
146
  function setActive(name) {
138
147
  activeAgent = name;
139
148
  renderList();
@@ -151,6 +160,6 @@ export const consoleShellScript = `<script>
151
160
  if (app.classList.contains('nav-open') && !ev.target.closest('.le-sidebar')) app.classList.remove('nav-open');
152
161
  });
153
162
 
154
- window.leShell = { ready: ready, renderHead: renderHead, setTab: setTab, setActive: setActive, esc: esc, tabHref: tabHref, envCountHtml: envCountHtml };
163
+ window.leShell = { ready: ready, renderHead: renderHead, setTab: setTab, setActive: setActive, esc: esc, tabHref: tabHref, envCountHtml: envCountHtml, setCount: setCount };
155
164
  })();
156
165
  </script>`;
@@ -1424,7 +1424,7 @@ ${consoleShellScript}
1424
1424
  var counts = {};
1425
1425
  if (cfg) {
1426
1426
  chips.push({ text: typeof cfg.model === 'string' ? cfg.model : cfg.model.provider + ' \u00b7 ' + (cfg.model.model || 'default model'), mono: true });
1427
- counts = { tools: cfg.tools.length, skills: cfg.skills.length, actauth: cfg.permissions.rules.length };
1427
+ counts = { tools: cfg.tools.length, skills: cfg.skills.length, abilities: cfg.abilityCount, actauth: cfg.permissions.rules.length };
1428
1428
  }
1429
1429
  head.innerHTML = leShell.renderHead({ name: name, prompt: agent.systemPrompt, chips: chips, tab: 'chat', counts: counts });
1430
1430
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopengine",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "type": "module",
5
5
  "description": "Runtime for tool-using AI agents with a transparent ReAct loop.",
6
6
  "license": "MIT",