llm_meta_widget 0.11.0 → 0.11.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e975d248dfe98bfeb8af1a17aeec7aa411f38b6b60a6563a52894faf70efed5b
4
- data.tar.gz: a23323a6012fbc7ce3effb0527026a42d1ae0e6c2f2b57e0049bd53a0cc6625d
3
+ metadata.gz: a7169f9db8dacb339f604b908494879c8db5c32635cbcc76d5cda807eb1e4dfd
4
+ data.tar.gz: ad8200955697be3b0d5e9f31cc0cde13882213537cf93582e36a612f348b5d4f
5
5
  SHA512:
6
- metadata.gz: 98014e701daaddb224748b7eb130b3092f8cf6653a05c9fb1f7cd5b63cdd17985ec8f65ce647f4cd1800c6b4f191ac9e5a35fb4229b7237673acdf6317222114
7
- data.tar.gz: 183fb69e15ec08f3cc4724ba467ff6da5078579c39c85c2a349b5333c30b57e6196a1a45e43514fddfd05903752a02d35ac99d703f3b40bf2584c18aa4ab9714
6
+ metadata.gz: 95b8f1577f51acd48d50fff55c6c28534656ab448041fa3b247230ae6cee3ba06b1046b4e9e8d94af20c570f06bcebaa519a9caac1e81fedd1bd17c433349762
7
+ data.tar.gz: 6cb12977d3457b7c288242cb1244e0af36dea798df12104a0f1ec6fc5c64acdee95bfb04ed59a5e53e1d9e9e71632bf9e7367bfa8bd10a1e323734f3b9ea2eef
data/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  This file starts at 0.8.0, the first release with a breaking change worth
4
4
  calling out. Earlier releases are in the git history (`git log --oneline v0.7.6`).
5
5
 
6
+ ## 0.11.1
7
+
8
+ ### Fixed: a page action that navigates no longer loses the turn
9
+
10
+ The transcript was saved once, after the chat loop finished. A page action that
11
+ navigates — submitting a form, following a link — unloads the page while the
12
+ loop is still running, so that turn was never saved: not the question, not
13
+ whatever the assistant had already said, and not the record of which tools ran.
14
+ After the navigation the panel came back with the previous turns and nothing of
15
+ the one that had just happened.
16
+
17
+ The turn is now saved as it happens. The question is saved before the model is
18
+ called, streamed text is saved as it arrives, and a save always happens
19
+ immediately before a tool call runs, because that call may be the one that
20
+ navigates.
21
+
22
+ This matters to any page that declares an action which navigates. Nothing to
23
+ change in your page.
24
+
6
25
  ## 0.11.0
7
26
 
8
27
  ### Added: a page can say where its handlers live
data/README.md CHANGED
@@ -61,7 +61,7 @@ Option 3 if it does not.
61
61
 
62
62
  ```ruby
63
63
  # Gemfile
64
- gem "llm_meta_widget", "~> 0.11.0"
64
+ gem "llm_meta_widget", "~> 0.11.1"
65
65
  ```
66
66
 
67
67
  ```bash
@@ -302,6 +302,17 @@ function boot(cfg) {
302
302
  model: MODEL
303
303
  });
304
304
  }
305
+
306
+ // Saving on every streamed delta would write to sessionStorage hundreds of
307
+ // times for one answer, so the stream saves at most this often. The moments
308
+ // that MUST save at once — the turn starting, a tool call about to run, the
309
+ // turn ending — call persistConversation directly.
310
+ var lastPersist = 0;
311
+ function persistSoon() {
312
+ if (Date.now() - lastPersist < 400) return;
313
+ lastPersist = Date.now();
314
+ persistConversation();
315
+ }
305
316
  // The page card is the same static-primitives envelope a server puts in
306
317
  // its Server Card, delivered in the document. Its `tools` REPLACE the
307
318
  // older #ai-actions schema tag rather than merging with it: two sources
@@ -1196,6 +1207,14 @@ function boot(cfg) {
1196
1207
  .concat(conversation.map(function(t) { return { role: t.role, content: t.content }; }))
1197
1208
  .concat([{ role: "user", content: userText }]);
1198
1209
 
1210
+ // Recorded before the loop runs, and saved, so a page action that
1211
+ // navigates cannot take the turn with it. `messages` above was already
1212
+ // built from the previous turns, so this does not double-send anything.
1213
+ conversation.push({ role: "user", content: userText });
1214
+ var liveTurn = { role: "assistant", content: "", tools: [] };
1215
+ conversation.push(liveTurn);
1216
+ persistConversation();
1217
+
1199
1218
  var result = await runChatLoop({
1200
1219
  baseUrl: LLM_BASE,
1201
1220
  toolHubUrl: TOOL_HUB_BASE,
@@ -1209,8 +1228,19 @@ function boot(cfg) {
1209
1228
  maxRounds: MAX_ROUNDS,
1210
1229
  provider: LLM_PROVIDER === "ollama" ? "ollama" : "hub",
1211
1230
  signal: currentAbort.signal,
1212
- onToolCall: function(toolCall) { announceToolCall(toolCall); },
1213
- onToolDispatched: function(outcome) { resolveToolCall(outcome); },
1231
+ onToolCall: function(toolCall) {
1232
+ announceToolCall(toolCall);
1233
+ // At once, not throttled: this call may be the one that navigates, and
1234
+ // after it nothing of this turn would be saved.
1235
+ persistConversation();
1236
+ },
1237
+ onToolDispatched: function(outcome) {
1238
+ resolveToolCall(outcome);
1239
+ liveTurn.tools = liveTurn.tools.concat([ outcome.error
1240
+ ? { name: outcome.toolCall.name, error: true }
1241
+ : { name: outcome.toolCall.name } ]);
1242
+ persistConversation();
1243
+ },
1214
1244
  onPhase: function(name) {
1215
1245
  // 'thinking' covers the long silence before the first
1216
1246
  // token; 'responding' means text is on its way.
@@ -1241,18 +1271,19 @@ function boot(cfg) {
1241
1271
  collapseThinkingBlock();
1242
1272
  assistantMarkdown += delta;
1243
1273
  renderMarkdownInto(assistantBody, assistantMarkdown);
1274
+ liveTurn.content = assistantMarkdown;
1275
+ persistSoon();
1244
1276
  historyEl.scrollTop = historyEl.scrollHeight;
1245
1277
  }
1246
1278
  });
1247
- conversation.push({ role: "user", content: userText });
1248
- conversation.push({
1249
- role: "assistant",
1250
- content: result.content,
1251
- // Kept so a restored transcript still shows what ran — losing
1252
- // that record is what made a navigating action unbearable.
1253
- tools: result.dispatched.map(function(d) {
1254
- return d.error ? { name: d.toolCall.name, error: true } : { name: d.toolCall.name };
1255
- })
1279
+ // The turn was recorded here until 0.11.1, after the loop returned — which
1280
+ // a page action that navigates never lets happen. Submitting a form
1281
+ // mid-turn therefore lost the whole turn: the question, whatever the
1282
+ // assistant had already said, and the record of what ran. It is recorded as
1283
+ // it happens now, and only finalised here.
1284
+ liveTurn.content = result.content;
1285
+ liveTurn.tools = result.dispatched.map(function(d) {
1286
+ return d.error ? { name: d.toolCall.name, error: true } : { name: d.toolCall.name };
1256
1287
  });
1257
1288
  persistConversation();
1258
1289
 
@@ -3963,6 +3963,12 @@ function boot(cfg) {
3963
3963
  model: MODEL
3964
3964
  });
3965
3965
  }
3966
+ var lastPersist = 0;
3967
+ function persistSoon() {
3968
+ if (Date.now() - lastPersist < 400) return;
3969
+ lastPersist = Date.now();
3970
+ persistConversation();
3971
+ }
3966
3972
  var typedCards = document.querySelectorAll('script[type="' + PAGE_CARD_MEDIA_TYPE + '"]');
3967
3973
  var pageCard;
3968
3974
  if (typedCards.length) {
@@ -4625,6 +4631,10 @@ function boot(cfg) {
4625
4631
  var messages = [{ role: "system", content: currentSystemPrompt(resourceLines) }].concat(conversation.map(function(t) {
4626
4632
  return { role: t.role, content: t.content };
4627
4633
  })).concat([{ role: "user", content: userText }]);
4634
+ conversation.push({ role: "user", content: userText });
4635
+ var liveTurn = { role: "assistant", content: "", tools: [] };
4636
+ conversation.push(liveTurn);
4637
+ persistConversation();
4628
4638
  var result = await runChatLoop({
4629
4639
  baseUrl: LLM_BASE,
4630
4640
  toolHubUrl: TOOL_HUB_BASE,
@@ -4640,9 +4650,12 @@ function boot(cfg) {
4640
4650
  signal: currentAbort.signal,
4641
4651
  onToolCall: function(toolCall) {
4642
4652
  announceToolCall(toolCall);
4653
+ persistConversation();
4643
4654
  },
4644
4655
  onToolDispatched: function(outcome) {
4645
4656
  resolveToolCall(outcome);
4657
+ liveTurn.tools = liveTurn.tools.concat([outcome.error ? { name: outcome.toolCall.name, error: true } : { name: outcome.toolCall.name }]);
4658
+ persistConversation();
4646
4659
  },
4647
4660
  onPhase: function(name) {
4648
4661
  if (name === "responding") markDone(assistantBody.roleLabel);
@@ -4663,18 +4676,14 @@ function boot(cfg) {
4663
4676
  collapseThinkingBlock();
4664
4677
  assistantMarkdown += delta;
4665
4678
  renderMarkdownInto(assistantBody, assistantMarkdown);
4679
+ liveTurn.content = assistantMarkdown;
4680
+ persistSoon();
4666
4681
  historyEl.scrollTop = historyEl.scrollHeight;
4667
4682
  }
4668
4683
  });
4669
- conversation.push({ role: "user", content: userText });
4670
- conversation.push({
4671
- role: "assistant",
4672
- content: result.content,
4673
- // Kept so a restored transcript still shows what ran — losing
4674
- // that record is what made a navigating action unbearable.
4675
- tools: result.dispatched.map(function(d) {
4676
- return d.error ? { name: d.toolCall.name, error: true } : { name: d.toolCall.name };
4677
- })
4684
+ liveTurn.content = result.content;
4685
+ liveTurn.tools = result.dispatched.map(function(d) {
4686
+ return d.error ? { name: d.toolCall.name, error: true } : { name: d.toolCall.name };
4678
4687
  });
4679
4688
  persistConversation();
4680
4689
  result.dispatched.forEach(function(d) {
@@ -1,3 +1,3 @@
1
1
  module LlmMetaWidget
2
- VERSION = "0.11.0"
2
+ VERSION = "0.11.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm_meta_widget
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - jdkim