@runcore-sh/runcore 0.5.15 → 0.6.0

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.
Files changed (66) hide show
  1. package/brain-template/templates/spawn-policy.yaml +12 -6
  2. package/dictionary.json +2 -2
  3. package/dist/agents/autonomous.d.ts.map +1 -1
  4. package/dist/agents/runtime/config.d.ts.map +1 -1
  5. package/dist/agents/runtime/driver.d.ts +12 -3
  6. package/dist/agents/runtime/driver.d.ts.map +1 -1
  7. package/dist/agents/runtime/types.d.ts +4 -0
  8. package/dist/agents/runtime/types.d.ts.map +1 -1
  9. package/dist/agents/runtime.js +3 -3
  10. package/dist/agents/runtime.js.map +1 -1
  11. package/dist/agents/spawn-policy.d.ts +15 -7
  12. package/dist/agents/spawn-policy.d.ts.map +1 -1
  13. package/dist/agents/spawn.d.ts.map +1 -1
  14. package/dist/agents/store.d.ts.map +1 -1
  15. package/dist/agents/store.js +94 -49
  16. package/dist/agents/store.js.map +1 -1
  17. package/dist/agents/types.d.ts +6 -0
  18. package/dist/agents/types.d.ts.map +1 -1
  19. package/dist/alert.d.ts +6 -0
  20. package/dist/alert.d.ts.map +1 -1
  21. package/dist/alert.js +16 -3
  22. package/dist/alert.js.map +1 -1
  23. package/dist/capabilities/definitions/email.d.ts +3 -2
  24. package/dist/capabilities/definitions/email.d.ts.map +1 -1
  25. package/dist/capabilities/definitions/email.js +74 -60
  26. package/dist/capabilities/definitions/email.js.map +1 -1
  27. package/dist/cli.js +49 -12
  28. package/dist/cli.js.map +1 -1
  29. package/dist/goals/planner.d.ts +40 -0
  30. package/dist/goals/planner.d.ts.map +1 -0
  31. package/dist/goals/planner.js +302 -0
  32. package/dist/goals/planner.js.map +1 -0
  33. package/dist/health/alert-defaults.js +6 -6
  34. package/dist/health/alert-defaults.js.map +1 -1
  35. package/dist/health/checks.d.ts.map +1 -1
  36. package/dist/health/checks.js +4 -6
  37. package/dist/health/checks.js.map +1 -1
  38. package/dist/llm/tools/handlers.js +1 -1
  39. package/dist/llm/tools/handlers.js.map +1 -1
  40. package/dist/llm/tools/loop.d.ts +2 -2
  41. package/dist/llm/tools/loop.d.ts.map +1 -1
  42. package/dist/llm/tools/loop.js +36 -8
  43. package/dist/llm/tools/loop.js.map +1 -1
  44. package/dist/queue/grooming.d.ts.map +1 -1
  45. package/dist/queue/grooming.js +27 -3
  46. package/dist/queue/grooming.js.map +1 -1
  47. package/dist/server.d.ts.map +1 -1
  48. package/dist/server.js +121 -50
  49. package/dist/server.js.map +1 -1
  50. package/dist/services/routine-patterns.d.ts.map +1 -1
  51. package/dist/services/routine-patterns.js +9 -0
  52. package/dist/services/routine-patterns.js.map +1 -1
  53. package/dist/services/traceInsights.d.ts.map +1 -1
  54. package/dist/services/traceInsights.js +48 -32
  55. package/dist/services/traceInsights.js.map +1 -1
  56. package/dist/settings.js +2 -2
  57. package/dist/settings.js.map +1 -1
  58. package/dist/tier/token.d.ts.map +1 -1
  59. package/dist/tier/token.js +4 -1
  60. package/dist/tier/token.js.map +1 -1
  61. package/dist/vault/store.d.ts +3 -1
  62. package/dist/vault/store.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/public/index.html +102 -16
  65. package/public/settings.html +1411 -0
  66. package/public/sw.js +9 -59
package/public/index.html CHANGED
@@ -1672,6 +1672,24 @@
1672
1672
  animation: tool-spin 0.6s linear infinite;
1673
1673
  }
1674
1674
  @keyframes tool-spin { to { transform: rotate(360deg); } }
1675
+ /* Status line above composer — shows what Dash is doing */
1676
+ .chat-status-line {
1677
+ display: flex;
1678
+ align-items: center;
1679
+ gap: 8px;
1680
+ padding: 6px 20px;
1681
+ font-size: 12px;
1682
+ font-family: var(--mono);
1683
+ color: var(--text-dim);
1684
+ background: rgba(109,93,252,0.06);
1685
+ border-top: 1px solid rgba(109,93,252,0.12);
1686
+ max-width: var(--max-width);
1687
+ margin: 0 auto;
1688
+ width: 100%;
1689
+ }
1690
+ .chat-status-line .tool-spinner { width: 10px; height: 10px; border-width: 1.5px; }
1691
+ .chat-status-line .status-label { color: var(--accent); font-weight: 500; }
1692
+ .chat-status-line .status-elapsed { color: var(--text-dim); opacity: 0.5; margin-left: auto; font-variant-numeric: tabular-nums; }
1675
1693
 
1676
1694
  .agent-block {
1677
1695
  margin: 8px 0;
@@ -2752,6 +2770,7 @@
2752
2770
  <div id="question-chips" class="question-chips"></div>
2753
2771
  </div>
2754
2772
  <div class="messages" id="messages"></div>
2773
+ <div id="chat-status-line" class="chat-status-line" style="display:none;"></div>
2755
2774
  <div class="composer" id="composer">
2756
2775
  <div class="incognito-label">incognito — local only, no memory</div>
2757
2776
  <div class="attachment-preview" id="attachment-preview"></div>
@@ -3079,7 +3098,7 @@
3079
3098
 
3080
3099
  // Voice state
3081
3100
  let voiceStatus = { tts: false, stt: false };
3082
- let ttsAutoPlay = true;
3101
+ let ttsAutoPlay = false;
3083
3102
  let micRecording = false;
3084
3103
  let mediaRecorder = null;
3085
3104
  let micStream = null;
@@ -3318,12 +3337,12 @@
3318
3337
  });
3319
3338
  item.querySelector(".thread-delete-btn").addEventListener("click", async (e) => {
3320
3339
  e.stopPropagation();
3321
- const tid = e.target.dataset ? e.target.dataset.threadId : null;
3340
+ e.preventDefault();
3341
+ var tid = t.id;
3322
3342
  if (!tid) return;
3343
+ if (!confirm("Delete this chat?")) return;
3323
3344
  try {
3324
- await api("/api/threads/" + encodeURIComponent(tid) + "?sessionId=" + encodeURIComponent(sessionId), {
3325
- method: "DELETE",
3326
- });
3345
+ await api("/api/threads/" + encodeURIComponent(tid), { method: "DELETE" });
3327
3346
  if (currentThreadId === tid) await createAndSwitchNewThread();
3328
3347
  loadThreads();
3329
3348
  } catch (err) { console.log("Delete thread failed:", err.message); }
@@ -5106,6 +5125,8 @@
5106
5125
  const decoder = new TextDecoder();
5107
5126
  let buffer = "";
5108
5127
  let streamingText = "";
5128
+ var _responseStartTime = Date.now();
5129
+ var _toolsUsedThisTurn = [];
5109
5130
 
5110
5131
  while (true) {
5111
5132
  const { done, value } = await reader.read();
@@ -5133,23 +5154,44 @@
5133
5154
  messagesEl.scrollTop = messagesEl.scrollHeight;
5134
5155
  }
5135
5156
  if (data.toolCall) {
5136
- // Model is calling a tool — show indicator
5157
+ var _tn = data.toolCall.name || "tool";
5158
+ _toolsUsedThisTurn.push(_tn);
5159
+ var _fl = ({"memory_retrieve":"Searching memory","memory_learn":"Saving to memory","memory_list":"Listing memory","web_fetch":"Fetching page","files_search":"Searching files","read_brain_file":"Reading file","send_alert":"Sending alert","get_settings":"Reading settings","whiteboard_plant":"Planting question","loop_open":"Opening loop","loop_resolve":"Resolving loop"})[_tn] || _tn.replace(/_/g, " ");
5160
+ // Pill in message body
5137
5161
  var toolEl = document.createElement("div");
5138
5162
  toolEl.className = "tool-indicator";
5139
- toolEl.innerHTML = '<span class="tool-spinner"></span> Using <strong>' + (data.toolCall.name || "tool").replace(/</g,"&lt;") + '</strong>...';
5163
+ toolEl.innerHTML = '<span class="tool-spinner"></span> <strong>' + _fl.replace(/</g,"&lt;") + '</strong>';
5140
5164
  if (contentEl && contentEl.parentElement) {
5141
5165
  contentEl.parentElement.appendChild(toolEl);
5142
- messagesEl.scrollTop = messagesEl.scrollHeight;
5143
5166
  }
5167
+ // Status line above composer
5168
+ var _sl = document.getElementById("chat-status-line");
5169
+ if (_sl) {
5170
+ _sl.style.display = "flex";
5171
+ if (!_sl._startTime) _sl._startTime = Date.now();
5172
+ _sl.innerHTML = '<span class="tool-spinner"></span> <span class="status-label">' + _fl.replace(/</g,"&lt;") + '</span><span class="status-elapsed">0s</span>';
5173
+ if (_sl._timer) clearInterval(_sl._timer);
5174
+ _sl._timer = setInterval(function() {
5175
+ var el = _sl.querySelector(".status-elapsed");
5176
+ if (el && _sl._startTime) el.textContent = Math.round((Date.now() - _sl._startTime) / 1000) + "s";
5177
+ }, 1000);
5178
+ }
5179
+ messagesEl.scrollTop = messagesEl.scrollHeight;
5144
5180
  }
5145
5181
  if (data.toolResult) {
5146
- // Tool finished update indicator
5147
- var indicators = document.querySelectorAll(".tool-indicator");
5182
+ var _tn2 = data.toolResult.name || "tool";
5183
+ var _fl2 = ({"memory_retrieve":"Searched memory","memory_learn":"Saved to memory","memory_list":"Listed memory","web_fetch":"Fetched page","files_search":"Searched files","read_brain_file":"Read file","send_alert":"Alert sent","get_settings":"Read settings","whiteboard_plant":"Planted question","loop_open":"Opened loop","loop_resolve":"Resolved loop"})[_tn2] || _tn2.replace(/_/g, " ");
5184
+ var indicators = document.querySelectorAll(".tool-indicator:not(.tool-done):not(.tool-error)");
5148
5185
  if (indicators.length > 0) {
5149
5186
  var last = indicators[indicators.length - 1];
5150
- last.innerHTML = (data.toolResult.isError ? "&#10007; " : "&#10003; ") + '<strong>' + (data.toolResult.name || "tool").replace(/</g,"&lt;") + '</strong>';
5187
+ last.innerHTML = (data.toolResult.isError ? "&#10007; " : "&#10003; ") + '<strong>' + _fl2.replace(/</g,"&lt;") + '</strong>';
5151
5188
  last.className = "tool-indicator " + (data.toolResult.isError ? "tool-error" : "tool-done");
5152
5189
  }
5190
+ // Update status line to show completed tool
5191
+ var _sl2 = document.getElementById("chat-status-line");
5192
+ if (_sl2) {
5193
+ _sl2.innerHTML = '<span class="tool-spinner"></span> <span class="status-label">' + _fl2.replace(/</g,"&lt;") + ' done</span><span class="status-elapsed">' + (_sl2._startTime ? Math.round((Date.now() - _sl2._startTime) / 1000) + "s" : "") + '</span>';
5194
+ }
5153
5195
  }
5154
5196
  if (data.agentSpawned) {
5155
5197
  // Server spawned an agent — render block immediately with real task ID
@@ -5236,12 +5278,47 @@
5236
5278
  .trim();
5237
5279
  }
5238
5280
 
5281
+ // Clean up status line
5282
+ var _slEnd = document.getElementById("chat-status-line");
5283
+ if (_slEnd) {
5284
+ if (_slEnd._timer) clearInterval(_slEnd._timer);
5285
+ if (_toolsUsedThisTurn.length > 0 && _slEnd._startTime) {
5286
+ var _totalSec = Math.round((Date.now() - _slEnd._startTime) / 1000);
5287
+ _slEnd.innerHTML = '<span style="color:var(--green);">&#10003;</span> Done in ' + _totalSec + 's';
5288
+ setTimeout(function() { _slEnd.style.display = "none"; _slEnd._startTime = null; }, 3000);
5289
+ } else {
5290
+ _slEnd.style.display = "none";
5291
+ _slEnd._startTime = null;
5292
+ }
5293
+ }
5294
+
5239
5295
  // Remove streaming cursor and re-render final clean markdown
5240
5296
  if (contentEl) {
5241
5297
  contentEl.classList.remove("streaming-cursor");
5298
+ // If response is empty but tools were used, show what happened
5299
+ if (!finalText && _toolsUsedThisTurn.length > 0) {
5300
+ var _elapsed = Math.round((Date.now() - _responseStartTime) / 1000);
5301
+ var _unique = _toolsUsedThisTurn.reduce(function(acc, t) { acc[t] = (acc[t] || 0) + 1; return acc; }, {});
5302
+ var _friendlyNames = {"memory_retrieve":"searched memory","memory_learn":"saved to memory","memory_list":"listed memory","web_fetch":"fetched pages","files_search":"searched files","read_brain_file":"read files","send_alert":"sent alert","get_settings":"read settings"};
5303
+ var _summary = Object.keys(_unique).map(function(k) {
5304
+ var label = _friendlyNames[k] || k.replace(/_/g, " ");
5305
+ return _unique[k] > 1 ? label + " (" + _unique[k] + "x)" : label;
5306
+ }).join(", ");
5307
+ finalText = "*Done in " + _elapsed + "s: " + _summary + ".*";
5308
+ }
5242
5309
  contentEl.innerHTML = finalText ? renderMarkdown(finalText) : "";
5243
5310
  applyPrivacySeals(contentEl);
5244
5311
  if (window._serverSealValues) applyServerSeals(contentEl, window._serverSealValues);
5312
+ // Show elapsed time when tools were used
5313
+ if (_toolsUsedThisTurn.length > 0) {
5314
+ var _elapsedFinal = Math.round((Date.now() - _responseStartTime) / 1000);
5315
+ if (_elapsedFinal >= 2) {
5316
+ var _timeEl = document.createElement("div");
5317
+ _timeEl.style.cssText = "font-size:11px;color:var(--text-dim);opacity:0.5;margin-top:6px;font-family:var(--mono);";
5318
+ _timeEl.textContent = _elapsedFinal + "s";
5319
+ if (contentEl.parentElement) contentEl.parentElement.appendChild(_timeEl);
5320
+ }
5321
+ }
5245
5322
  messagesEl.scrollTop = messagesEl.scrollHeight;
5246
5323
 
5247
5324
  // Add drift tracking for assistant response
@@ -5633,6 +5710,10 @@
5633
5710
  const vaultError = document.getElementById("vault-error");
5634
5711
 
5635
5712
  function openSettings() {
5713
+ window.location.href = "/settings";
5714
+ }
5715
+
5716
+ function openSettingsPanel() {
5636
5717
  vaultOverlay.classList.add("open");
5637
5718
  document.getElementById("settings-your-name").value = userName || "";
5638
5719
  document.getElementById("settings-agent-name").value = agentName || "Core";
@@ -5744,8 +5825,10 @@
5744
5825
  try {
5745
5826
  const data = await api("/api/models");
5746
5827
  const models = data.models || [];
5747
- const ollamaModels = models.filter(function(m) { return m.source === "ollama"; });
5748
- const openrouterModels = models.filter(function(m) { return m.source === "openrouter"; });
5828
+ const ollamaModels = models.filter(function(m) { return m.source === "ollama"; })
5829
+ .sort(function(a, b) { return a.name.localeCompare(b.name); });
5830
+ const openrouterModels = models.filter(function(m) { return m.source === "openrouter"; })
5831
+ .sort(function(a, b) { return a.name.localeCompare(b.name); });
5749
5832
 
5750
5833
  var dropdowns = [
5751
5834
  { el: modelChatSelect, current: selectedChat, autoLabel: "Auto (best available)" },
@@ -6499,7 +6582,7 @@
6499
6582
  // Load settings for autoPlay and toggle states
6500
6583
  try {
6501
6584
  const settings = await api("/api/settings");
6502
- ttsAutoPlay = settings.tts?.autoPlay !== false;
6585
+ ttsAutoPlay = settings.tts?.autoPlay === true;
6503
6586
  document.getElementById("tts-toggle").checked = settings.tts?.enabled !== false;
6504
6587
  document.getElementById("stt-toggle").checked = settings.stt?.enabled !== false;
6505
6588
  document.getElementById("autoplay-toggle").checked = ttsAutoPlay;
@@ -6875,7 +6958,7 @@
6875
6958
  },
6876
6959
  },
6877
6960
  });
6878
- ttsAutoPlay = result.tts?.autoPlay !== false;
6961
+ ttsAutoPlay = result.tts?.autoPlay === true;
6879
6962
  statusEl.classList.add("visible");
6880
6963
  setTimeout(() => statusEl.classList.remove("visible"), 2000);
6881
6964
  } catch (err) {
@@ -7341,8 +7424,11 @@ async function loadPairedDevices() {
7341
7424
  })();
7342
7425
  </script>
7343
7426
  <script>
7427
+ // Unregister any existing service worker — it caused latency and stale data
7344
7428
  if ("serviceWorker" in navigator) {
7345
- navigator.serviceWorker.register("/sw.js").catch(function() {});
7429
+ navigator.serviceWorker.getRegistrations().then(function(regs) {
7430
+ regs.forEach(function(r) { r.unregister(); });
7431
+ });
7346
7432
  }
7347
7433
  </script>
7348
7434
  </body>