loopengine 0.1.33 → 0.1.35

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.
@@ -1136,7 +1136,7 @@ export const agentsConfigPageHtml = `<!doctype html>
1136
1136
  : '';
1137
1137
  return '<tr>' +
1138
1138
  '<td><code>' + escapeHtml(v.name) + '</code></td>' +
1139
- '<td>' + escapeHtml(v.description || '') + '</td>' +
1139
+ '<td style="max-width:320px">' + escapeHtml(v.description || '') + '</td>' +
1140
1140
  '<td class="hint">' + escapeHtml(v.abilityNames.join(', ')) + sharedNote + '</td>' +
1141
1141
  '<td>' + (v.set ? '<span class="hint">set</span>' : '<span class="error">not set</span>') + '</td>' +
1142
1142
  '<td><form class="add-source env-var-form" data-name="' + escapeHtml(v.name) + '">' +
@@ -1149,7 +1149,7 @@ export const agentsConfigPageHtml = `<!doctype html>
1149
1149
  function renderEnvConfigHtml(vars) {
1150
1150
  if (!vars.length) return '<p class="hint">No installed ability has declared any environment variables for this agent yet.</p>';
1151
1151
  var rows = vars.map(renderEnvRow).join('');
1152
- return '<table><thead><tr><th>Name</th><th>Description</th><th>Required by</th><th>Status</th><th>Set value</th></tr></thead><tbody>' + rows + '</tbody></table>';
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>';
1153
1153
  }
1154
1154
 
1155
1155
  function envContentEl() {
@@ -1246,7 +1246,7 @@ export const agentsConfigPageHtml = `<!doctype html>
1246
1246
  : '<p class="hint">No abilities installed for this agent yet.</p>';
1247
1247
 
1248
1248
  return '<h3>Installed</h3>' + installedHtml +
1249
- '<h3>Search public abilities</h3>' +
1249
+ '<h3 style="margin-top:24px">Search public abilities</h3>' +
1250
1250
  '<form id="abilitySearchForm" class="add-source">' +
1251
1251
  '<input type="text" name="q" placeholder="Search by name or keyword (optional)">' +
1252
1252
  '<button type="submit">Search</button>' +
@@ -2187,9 +2187,14 @@ export const agentsConfigPageHtml = `<!doctype html>
2187
2187
  // so only Overview is left needing a re-fetch.
2188
2188
  function refreshOverviewPanel(name) {
2189
2189
  fetch('/agents/' + encodeURIComponent(name) + '/config')
2190
- .then(function (r) { return r.json(); })
2191
- .then(function (cfg) {
2190
+ .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); })
2191
+ .then(function (result) {
2192
2192
  if (currentName !== name) return;
2193
+ // A non-ok body is {error: "..."}, not a real config — bail out
2194
+ // to the catch below rather than rendering it as one (same risk
2195
+ // selectAgent's own /config fetch has — see its own comment).
2196
+ if (!result.ok) throw new Error(result.body.error || 'request failed');
2197
+ var cfg = result.body;
2193
2198
  currentCfg = cfg;
2194
2199
  var overviewPanel = detail.querySelector('[data-tab-panel="overview"]');
2195
2200
  if (overviewPanel) {
@@ -2225,9 +2230,13 @@ export const agentsConfigPageHtml = `<!doctype html>
2225
2230
  // re-rendering both it and Overview from a fresh /config fetch.
2226
2231
  function refreshSkillsDependentPanels(name) {
2227
2232
  fetch('/agents/' + encodeURIComponent(name) + '/config')
2228
- .then(function (r) { return r.json(); })
2229
- .then(function (cfg) {
2233
+ .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); })
2234
+ .then(function (result) {
2230
2235
  if (currentName !== name) return;
2236
+ // Same "don't render an {error: ...} body as if it were a real
2237
+ // config" guard as refreshOverviewPanel/selectAgent above.
2238
+ if (!result.ok) throw new Error(result.body.error || 'request failed');
2239
+ var cfg = result.body;
2231
2240
  currentCfg = cfg;
2232
2241
  var overviewPanel = detail.querySelector('[data-tab-panel="overview"]');
2233
2242
  var skillsPanel = skillsPanelEl();
@@ -2295,10 +2304,18 @@ export const agentsConfigPageHtml = `<!doctype html>
2295
2304
  empty.style.display = 'none';
2296
2305
  detail.style.display = 'block';
2297
2306
  fetch('/agents/' + encodeURIComponent(name) + '/config')
2298
- .then(function (r) { return r.json(); })
2299
- .then(function (cfg) {
2307
+ .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); })
2308
+ .then(function (result) {
2300
2309
  if (currentName !== name) return;
2301
- renderDetail(cfg);
2310
+ // A non-ok response's body is {error: "..."}, not a real config
2311
+ // — rendering it as one would crash somewhere deep in
2312
+ // renderDetail (e.g. reading .model.provider off an object with
2313
+ // no .model at all) with a confusing, unrelated-looking message
2314
+ // instead of the actual server-side error this route already
2315
+ // went out of its way to surface clearly (see handleAgentConfig
2316
+ // Get's own doc comment).
2317
+ if (!result.ok) throw new Error(result.body.error || 'request failed');
2318
+ renderDetail(result.body);
2302
2319
  })
2303
2320
  .catch(function (err) {
2304
2321
  if (currentName !== name) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopengine",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
4
4
  "type": "module",
5
5
  "description": "Runtime for tool-using AI agents with a transparent ReAct loop.",
6
6
  "license": "MIT",