loopengine 0.1.35 → 0.1.36

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.
@@ -1128,16 +1128,19 @@ export const agentsConfigPageHtml = `<!doctype html>
1128
1128
  // More than one ability declaring the same name doesn't get resolved
1129
1129
  // here — there's one .env per project, so both read whatever single
1130
1130
  // value ends up set, whether that's actually correct or a coincidence
1131
- // (see env-admin.ts's own doc comment). Listing every ability instead
1132
- // of just the first one seen at least makes that visible to whoever's
1133
- // looking, instead of silently hiding all but one.
1131
+ // (see env-admin.ts's own doc comment). Naming every declaring
1132
+ // ability instead of just the first one seen makes that visible to
1133
+ // whoever's looking, instead of silently hiding all but one — shown
1134
+ // here (not a separate "Required by" column, now that rows are
1135
+ // already grouped under one ability's own card) only when there
1136
+ // actually is more than one, since inside its own card which ability
1137
+ // this is is already obvious from context.
1134
1138
  var sharedNote = v.abilityNames.length > 1
1135
- ? ' <span class="hint" title="More than one installed ability declares this name — there is only one value for it project-wide, so check whether they actually need the same one.">(shared)</span>'
1139
+ ? ' <span class="hint" title="Also declared by: ' + escapeHtml(v.abilityNames.join(', ')) + '. There is only one value for it project-wide, so check whether they actually need the same one.">(shared)</span>'
1136
1140
  : '';
1137
1141
  return '<tr>' +
1138
- '<td><code>' + escapeHtml(v.name) + '</code></td>' +
1142
+ '<td><code>' + escapeHtml(v.name) + '</code>' + sharedNote + '</td>' +
1139
1143
  '<td style="max-width:320px">' + escapeHtml(v.description || '') + '</td>' +
1140
- '<td class="hint">' + escapeHtml(v.abilityNames.join(', ')) + sharedNote + '</td>' +
1141
1144
  '<td>' + (v.set ? '<span class="hint">set</span>' : '<span class="error">not set</span>') + '</td>' +
1142
1145
  '<td><form class="add-source env-var-form" data-name="' + escapeHtml(v.name) + '">' +
1143
1146
  '<input type="' + (v.secret ? 'password' : 'text') + '" name="value" placeholder="' + (v.set ? 'unchanged unless you type a new value' : 'value') + '" required>' +
@@ -1146,10 +1149,52 @@ export const agentsConfigPageHtml = `<!doctype html>
1146
1149
  '</tr>';
1147
1150
  }
1148
1151
 
1152
+ // One card per ability, matching the same .source/.source-head/
1153
+ // status-ok/status-error look Gateway Tools sources already use — so
1154
+ // an operator scanning the tab sees, per ability, whether it's fully
1155
+ // configured or not, instead of hunting through one long flat table
1156
+ // for rows that belong to whichever ability they're actually trying to
1157
+ // set up right now.
1158
+ function renderEnvAbilityCard(abilityName, vars) {
1159
+ var missing = vars.filter(function (v) { return !v.set; }).length;
1160
+ var statusHtml = missing === 0
1161
+ ? '<span class="status-ok">all set</span>'
1162
+ : '<span class="status-error">' + missing + ' of ' + vars.length + ' not set</span>';
1163
+ var rows = vars.map(renderEnvRow).join('');
1164
+ return '<div class="source">' +
1165
+ '<div class="source-head"><h4>' + escapeHtml(abilityName) + '</h4>' + statusHtml + '</div>' +
1166
+ '<table><thead><tr><th>Name</th><th style="max-width:320px">Description</th><th>Status</th><th>Set value</th></tr></thead><tbody>' + rows + '</tbody></table>' +
1167
+ '</div>';
1168
+ }
1169
+
1149
1170
  function renderEnvConfigHtml(vars) {
1150
1171
  if (!vars.length) return '<p class="hint">No installed ability has declared any environment variables for this agent yet.</p>';
1151
- var rows = vars.map(renderEnvRow).join('');
1152
- return '<table><thead><tr><th>Name</th><th style="max-width:320px">Description</th><th>Required by</th><th>Status</th><th>Set value</th></tr></thead><tbody>' + rows + '</tbody></table>';
1172
+
1173
+ var missingCount = vars.filter(function (v) { return !v.set; }).length;
1174
+ var summaryHtml = '<p class="hint">' + vars.length + ' environment variable' + (vars.length === 1 ? '' : 's') + ' across every installed ability' +
1175
+ (missingCount ? ' — <span class="error">' + missingCount + ' still not set</span>.' : ' — all set.') + '</p>';
1176
+
1177
+ // Grouped by declaring ability, not a single flat list — a var
1178
+ // declared by more than one ability (rare, but see renderEnvRow's
1179
+ // own comment) appears once under each, since either ability's own
1180
+ // card is a place an operator setting that ability up would
1181
+ // reasonably look for it.
1182
+ var byAbility = {};
1183
+ var abilityNames = [];
1184
+ vars.forEach(function (v) {
1185
+ v.abilityNames.forEach(function (abilityName) {
1186
+ if (!byAbility[abilityName]) {
1187
+ byAbility[abilityName] = [];
1188
+ abilityNames.push(abilityName);
1189
+ }
1190
+ byAbility[abilityName].push(v);
1191
+ });
1192
+ });
1193
+ abilityNames.sort();
1194
+
1195
+ return summaryHtml + abilityNames.map(function (abilityName) {
1196
+ return renderEnvAbilityCard(abilityName, byAbility[abilityName]);
1197
+ }).join('');
1153
1198
  }
1154
1199
 
1155
1200
  function envContentEl() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopengine",
3
- "version": "0.1.35",
3
+ "version": "0.1.36",
4
4
  "type": "module",
5
5
  "description": "Runtime for tool-using AI agents with a transparent ReAct loop.",
6
6
  "license": "MIT",