@operatingtag/dsh-unclesam 1.3.4 → 1.3.5

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 (55) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.ar.md +1 -1
  3. package/README.az.md +1 -1
  4. package/README.bg.md +1 -1
  5. package/README.bn.md +1 -1
  6. package/README.cs.md +1 -1
  7. package/README.da.md +1 -1
  8. package/README.de.md +1 -1
  9. package/README.el.md +1 -1
  10. package/README.es.md +1 -1
  11. package/README.fa.md +1 -1
  12. package/README.fi.md +1 -1
  13. package/README.fr.md +1 -1
  14. package/README.he.md +1 -1
  15. package/README.hi.md +1 -1
  16. package/README.hr.md +1 -1
  17. package/README.hu.md +1 -1
  18. package/README.id.md +1 -1
  19. package/README.it.md +1 -1
  20. package/README.ja.md +1 -1
  21. package/README.ka.md +1 -1
  22. package/README.kk.md +1 -1
  23. package/README.km.md +1 -1
  24. package/README.ko.md +1 -1
  25. package/README.lt.md +1 -1
  26. package/README.md +1 -1
  27. package/README.mr.md +1 -1
  28. package/README.ms.md +1 -1
  29. package/README.my.md +1 -1
  30. package/README.ne.md +1 -1
  31. package/README.nl.md +1 -1
  32. package/README.no.md +1 -1
  33. package/README.pl.md +1 -1
  34. package/README.pt.md +1 -1
  35. package/README.ro.md +1 -1
  36. package/README.ru.md +1 -1
  37. package/README.si.md +1 -1
  38. package/README.sk.md +1 -1
  39. package/README.sl.md +1 -1
  40. package/README.sr.md +1 -1
  41. package/README.sv.md +1 -1
  42. package/README.sw.md +1 -1
  43. package/README.ta.md +1 -1
  44. package/README.te.md +1 -1
  45. package/README.th.md +1 -1
  46. package/README.tl.md +1 -1
  47. package/README.tr.md +1 -1
  48. package/README.uk.md +1 -1
  49. package/README.ur.md +1 -1
  50. package/README.uz.md +1 -1
  51. package/README.vi.md +1 -1
  52. package/README.zh.md +1 -1
  53. package/index.js +45 -2
  54. package/lib/prompt.mjs +124 -3
  55. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -8,6 +8,32 @@ fixes the patch.
8
8
 
9
9
  ---
10
10
 
11
+ ## 1.3.5
12
+
13
+ **A live web turn came apart into a loop, and the audit it prompted fixed three things.**
14
+
15
+ Asked to glob a workspace it had misread, the web model invented a tool format
16
+ (`<tool name="glob" string="true">{…}</tool>`), the parser did not accept it, nothing told the model so, and
17
+ it repeated the block until the transcript was full of copies.
18
+
19
+ - **The invented shape is now accepted.** `parseToolCall` recognises `<tool name="…">…</tool>` and
20
+ `<tool_call>…</tool_call>`, and `stripToolCall` removes them, so a model that drifts to tags still gets a
21
+ running call instead of a dead one.
22
+ - **A reply that loops is stopped, not displayed.** `looksDegenerate` fires on three `<tool` openings or
23
+ four identical substantial lines, and the turn ends with a plain `web_loop` error naming what happened.
24
+ Nothing was wrong with the page; the model was stuck, and the person no longer has to watch it write one
25
+ line for minutes.
26
+ - **Two audit findings, reproduced against the running code:**
27
+ - `findCallForm` treated an EMPTY tool list as "accept anything", so ordinary prose like `log(2)` and
28
+ `figure(2)` was silently deleted from every non-tool turn. The empty list now means "nothing is a call".
29
+ - A malformed call before a valid one (`read(bad) and pwsh({…})`) returned nothing, hiding the valid call
30
+ and leaking its text into the transcript. A bad candidate now skips to the next instead of aborting.
31
+
32
+ `dev/test-call-form.mjs` gained the loop, tag, empty-list and malformed-candidate cases; the suite is 15
33
+ suites, all green.
34
+
35
+ ---
36
+
11
37
  ## 1.3.4
12
38
 
13
39
  **A tool call is now written `name({...})` instead of a JSON envelope, so the answer can stream.**
package/README.ar.md CHANGED
@@ -250,7 +250,7 @@ Copyright (c) 2026 Darren T. Weldon، منشور تحت اسم Operating Tag.
250
250
  Uncle Sam إضافة مستقلة. غير مرتبطة بـ DeepSeek، ولا تحظى بتأييدهم أو دعمهم.
251
251
 
252
252
  ```
253
- @operatingtag/dsh-unclesam v1.3.4
253
+ @operatingtag/dsh-unclesam v1.3.5
254
254
  المؤلف Operating Tag
255
255
  الترخيص CC BY-NC-ND 4.0 — مجاني للاستخدام، لا للتغيير أو المشاركة أو البيع
256
256
  ```
package/README.az.md CHANGED
@@ -256,7 +256,7 @@ soruşun — aydın cavab və aydın qiymət alacaqsınız.
256
256
  Uncle Sam müstəqil plagindir. DeepSeek ilə bağlı deyil, onlar tərəfindən təsdiqlənməyib və dəstəklənmir.
257
257
 
258
258
  ```
259
- @operatingtag/dsh-unclesam v1.3.4
259
+ @operatingtag/dsh-unclesam v1.3.5
260
260
  Müəllif Operating Tag
261
261
  Lisenziya CC BY-NC-ND 4.0 — istifadə üçün pulsuz, dəyişdirmək, paylaşmaq və ya satmaq üçün deyil
262
262
  ```
package/README.bg.md CHANGED
@@ -259,7 +259,7 @@ Copyright (c) 2026 Darren T. Weldon, публикувано под името Op
259
259
  Uncle Sam е независима приставка. Не е свързана с DeepSeek, не е одобрена или поддържана от тях.
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  Автор Operating Tag
264
264
  Лиценз CC BY-NC-ND 4.0 — свободно за използване, не за промяна, споделяне или продажба
265
265
  ```
package/README.bn.md CHANGED
@@ -254,7 +254,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag নামে প্রকা
254
254
  Uncle Sam একটি স্বাধীন প্লাগইন। DeepSeek-এর সঙ্গে যুক্ত নয়, তাদের অনুমোদন বা সমর্থন নেই।
255
255
 
256
256
  ```
257
- @operatingtag/dsh-unclesam v1.3.4
257
+ @operatingtag/dsh-unclesam v1.3.5
258
258
  লেখক Operating Tag
259
259
  লাইসেন্স CC BY-NC-ND 4.0 — ব্যবহারে বিনামূল্যে, পরিবর্তন, শেয়ার বা বিক্রিতে নয়
260
260
  ```
package/README.cs.md CHANGED
@@ -256,7 +256,7 @@ Závazný je soubor [LICENSE](LICENSE) a začíná stejným shrnutím v jednoduc
256
256
  Uncle Sam je nezávislý plugin. Není spojený s DeepSeek, není jimi schválený ani podporovaný.
257
257
 
258
258
  ```
259
- @operatingtag/dsh-unclesam v1.3.4
259
+ @operatingtag/dsh-unclesam v1.3.5
260
260
  Autor Operating Tag
261
261
  Licence CC BY-NC-ND 4.0 — zdarma k použití, ne ke změně, sdílení nebo prodeji
262
262
  ```
package/README.da.md CHANGED
@@ -257,7 +257,7 @@ Filen [LICENSE](LICENSE) er den gældende, og den begynder med samme resumé på
257
257
  Uncle Sam er et uafhængigt plugin. Ikke knyttet til DeepSeek, ikke godkendt eller støttet af dem.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  Forfatter Operating Tag
262
262
  Licens CC BY-NC-ND 4.0 — frit at bruge, ikke at ændre, dele eller sælge
263
263
  ```
package/README.de.md CHANGED
@@ -270,7 +270,7 @@ Englisch.
270
270
  Uncle Sam ist ein unabhängiges Plugin. Nicht mit DeepSeek verbunden, von ihnen weder unterstützt noch gefördert.
271
271
 
272
272
  ```
273
- @operatingtag/dsh-unclesam v1.3.4
273
+ @operatingtag/dsh-unclesam v1.3.5
274
274
  Autor Operating Tag
275
275
  Lizenz CC BY-NC-ND 4.0 — frei zur Nutzung, nicht zum Ändern, Weitergabe oder Verkauf
276
276
  ```
package/README.el.md CHANGED
@@ -266,7 +266,7 @@ Copyright (c) 2026 Darren T. Weldon, δημοσιευμένο με το όνομ
266
266
  Το Uncle Sam είναι ανεξάρτητο πρόσθετο. Δεν συνδέεται με τη DeepSeek, δεν εγκρίνεται ούτε υποστηρίζεται από αυτούς.
267
267
 
268
268
  ```
269
- @operatingtag/dsh-unclesam v1.3.4
269
+ @operatingtag/dsh-unclesam v1.3.5
270
270
  Δημιουργός Operating Tag
271
271
  Άδεια CC BY-NC-ND 4.0 — ελεύθερο για χρήση, όχι για αλλαγή, κοινή χρήση ή πώληση
272
272
  ```
package/README.es.md CHANGED
@@ -264,7 +264,7 @@ El archivo [LICENSE](LICENSE) es el que rige, y abre con el mismo resumen en ing
264
264
  Uncle Sam es un plugin independiente. No está afiliado, respaldado ni soportado por DeepSeek.
265
265
 
266
266
  ```
267
- @operatingtag/dsh-unclesam v1.3.4
267
+ @operatingtag/dsh-unclesam v1.3.5
268
268
  Autor Operating Tag
269
269
  Licencia CC BY-NC-ND 4.0 — gratis para usar, no para cambiar, compartir o vender
270
270
  ```
package/README.fa.md CHANGED
@@ -256,7 +256,7 @@ Copyright (c) 2026 Darren T. Weldon، منتشرشده با نام Operating Tag
256
256
  Uncle Sam یک افزونه مستقل است. وابسته به DeepSeek نیست، تأیید یا پشتیبانی نمی‌شود.
257
257
 
258
258
  ```
259
- @operatingtag/dsh-unclesam v1.3.4
259
+ @operatingtag/dsh-unclesam v1.3.5
260
260
  نویسنده Operating Tag
261
261
  پروانه CC BY-NC-ND 4.0 — آزاد برای استفاده، نه برای تغییر، اشتراک یا فروش
262
262
  ```
package/README.fi.md CHANGED
@@ -258,7 +258,7 @@ Tiedosto [LICENSE](LICENSE) on ratkaiseva, ja se alkaa samalla yhteenvedolla yks
258
258
  Uncle Sam on itsenäinen lisäosa. Ei sidoksissa DeepSeekiin, ei heidän hyväksymänsä tai tukemansa.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Tekijä Operating Tag
263
263
  Lisenssi CC BY-NC-ND 4.0 — vapaa käytettäväksi, ei muutettavaksi, jaettavaksi tai myytäväksi
264
264
  ```
package/README.fr.md CHANGED
@@ -268,7 +268,7 @@ Le fichier [LICENSE](LICENSE) fait foi, et il s'ouvre sur le même résumé en a
268
268
  Uncle Sam est un plugin indépendant. Non affilié à DeepSeek, ni approuvé ni soutenu par eux.
269
269
 
270
270
  ```
271
- @operatingtag/dsh-unclesam v1.3.4
271
+ @operatingtag/dsh-unclesam v1.3.5
272
272
  Auteur Operating Tag
273
273
  Licence CC BY-NC-ND 4.0 — gratuit à l'usage, pas au changement, au partage ou à la vente
274
274
  ```
package/README.he.md CHANGED
@@ -248,7 +248,7 @@ Copyright (c) 2026 Darren T. Weldon, פורסם תחת השם Operating Tag.
248
248
  Uncle Sam הוא תוסף עצמאי. לא קשור ל‑DeepSeek, לא מאושר ולא נתמך על ידם.
249
249
 
250
250
  ```
251
- @operatingtag/dsh-unclesam v1.3.4
251
+ @operatingtag/dsh-unclesam v1.3.5
252
252
  יוצר Operating Tag
253
253
  רישיון CC BY-NC-ND 4.0 — חופשי לשימוש, לא לשינוי, שיתוף או מכירה
254
254
  ```
package/README.hi.md CHANGED
@@ -259,7 +259,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag नाम से प्रक
259
259
  Uncle Sam एक स्वतंत्र प्लगइन है। DeepSeek से जुड़ा नहीं, उनका समर्थन या अनुमोदन नहीं।
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  लेखक Operating Tag
264
264
  लाइसेंस CC BY-NC-ND 4.0 — इस्तेमाल मुफ़्त, बदलना, बाँटना या बेचना नहीं
265
265
  ```
package/README.hr.md CHANGED
@@ -256,7 +256,7 @@ Datoteka [LICENSE](LICENSE) je obvezujuća i počinje istim sažetkom na jednost
256
256
  Uncle Sam je neovisni dodatak. Nije povezan s DeepSeekom, nije odobren ni podržan od njih.
257
257
 
258
258
  ```
259
- @operatingtag/dsh-unclesam v1.3.4
259
+ @operatingtag/dsh-unclesam v1.3.5
260
260
  Autor Operating Tag
261
261
  Licencija CC BY-NC-ND 4.0 — besplatno za korištenje, ne za izmjenu, dijeljenje ili prodaju
262
262
  ```
package/README.hu.md CHANGED
@@ -260,7 +260,7 @@ A [LICENSE](LICENSE) fájl a mérvadó, és ugyanazzal az egyszerű angol össze
260
260
  Az Uncle Sam független bővítmény. Nem kapcsolódik a DeepSeekhez, ő nem hagyja jóvá és nem támogatja.
261
261
 
262
262
  ```
263
- @operatingtag/dsh-unclesam v1.3.4
263
+ @operatingtag/dsh-unclesam v1.3.5
264
264
  Szerző Operating Tag
265
265
  Licenc CC BY-NC-ND 4.0 — szabadon használható, nem módosítható, osztható meg vagy adható el
266
266
  ```
package/README.id.md CHANGED
@@ -260,7 +260,7 @@ Berkas [LICENSE](LICENSE) yang mengikat, dan ia dibuka dengan ringkasan yang sam
260
260
  Uncle Sam adalah plugin independen. Tidak berafiliasi dengan DeepSeek, tidak didukung maupun disponsori oleh mereka.
261
261
 
262
262
  ```
263
- @operatingtag/dsh-unclesam v1.3.4
263
+ @operatingtag/dsh-unclesam v1.3.5
264
264
  Penulis Operating Tag
265
265
  Lisensi CC BY-NC-ND 4.0 — bebas dipakai, tidak untuk diubah, dibagikan, atau dijual
266
266
  ```
package/README.it.md CHANGED
@@ -264,7 +264,7 @@ Il file [LICENSE](LICENSE) è quello che fa fede, e si apre con lo stesso riassu
264
264
  Uncle Sam è un plugin indipendente. Non affiliato a DeepSeek, né approvato né supportato da loro.
265
265
 
266
266
  ```
267
- @operatingtag/dsh-unclesam v1.3.4
267
+ @operatingtag/dsh-unclesam v1.3.5
268
268
  Autore Operating Tag
269
269
  Licenza CC BY-NC-ND 4.0 — libero da usare, non da modificare, condividere o vendere
270
270
  ```
package/README.ja.md CHANGED
@@ -259,7 +259,7 @@ Copyright (c) 2026 Darren T. Weldon、Operating Tag 名義で公開。
259
259
  Uncle Sam は独立したプラグインです。DeepSeek とは関係がなく、承認も支援も受けていません。
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  作者 Operating Tag
264
264
  ライセンス CC BY-NC-ND 4.0 — 使用は自由、変更・共有・販売は不可
265
265
  ```
package/README.ka.md CHANGED
@@ -257,7 +257,7 @@ Copyright (c) 2026 Darren T. Weldon, გამოქვეყნებული
257
257
  Uncle Sam დამოუკიდებელი დანამატია. არ არის დაკავშირებული DeepSeek-თან, მათ მიერ არ არის დამტკიცებული ან მხარდაჭერილი.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  ავტორი Operating Tag
262
262
  ლიცენზია CC BY-NC-ND 4.0 — თავისუფალი გამოსაყენებლად, არა შესაცვლელად, გასაზიარებლად ან გასაყიდად
263
263
  ```
package/README.kk.md CHANGED
@@ -258,7 +258,7 @@ Operating Tag-тан сұраңыз — нақты жауап және нақт
258
258
  Uncle Sam — тәуелсіз плагин. DeepSeek-пен байланысты емес, олар мақұлдамаған немесе қолдамаған.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Авторы Operating Tag
263
263
  Лицензия CC BY-NC-ND 4.0 — пайдалануға тегін, өзгертуге, бөлісуге немесе сатуға емес
264
264
  ```
package/README.km.md CHANGED
@@ -253,7 +253,7 @@ Tag — អ្នកនឹងទទួលបានចម្លើយច្បា
253
253
  Uncle Sam គឺជាកម្មវិធីបន្ថែមឯករាជ្យ។ មិនពាក់ព័ន្ធនឹង DeepSeek មិនត្រូវបានអនុម័ត ឬគាំទ្រដោយពួកគេ។
254
254
 
255
255
  ```
256
- @operatingtag/dsh-unclesam v1.3.4
256
+ @operatingtag/dsh-unclesam v1.3.5
257
257
  អ្នកនិពន្ធ Operating Tag
258
258
  អាជ្ញាបណ្ណ CC BY-NC-ND 4.0 — ប្រើឥតគិតថ្លៃ មិនមែនសម្រាប់កែប្រែ ចែករំលែក ឬលក់
259
259
  ```
package/README.ko.md CHANGED
@@ -254,7 +254,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag 이름으로 공개.
254
254
  Uncle Sam은 독립적인 플러그인입니다. DeepSeek과 무관하며, 그들의 보증이나 지원을 받지 않습니다.
255
255
 
256
256
  ```
257
- @operatingtag/dsh-unclesam v1.3.4
257
+ @operatingtag/dsh-unclesam v1.3.5
258
258
  저자 Operating Tag
259
259
  라이선스 CC BY-NC-ND 4.0 — 사용은 자유, 변경·공유·판매는 불가
260
260
  ```
package/README.lt.md CHANGED
@@ -257,7 +257,7 @@ Failas [LICENSE](LICENSE) yra privalomas, ir jis prasideda ta pačia santrauka p
257
257
  Uncle Sam yra nepriklausomas papildinys. Nesusijęs su DeepSeek, jų nepatvirtintas ir neremiamas.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  Autorius Operating Tag
262
262
  Licencija CC BY-NC-ND 4.0 — nemokama naudoti, ne keisti, bendrinti ar parduoti
263
263
  ```
package/README.md CHANGED
@@ -257,7 +257,7 @@ The [LICENSE](LICENSE) file governs, and it opens with the same summary in plain
257
257
  Uncle Sam is an independent plugin. Not affiliated with, endorsed by, or supported by DeepSeek.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  Author Operating Tag
262
262
  Licence CC BY-NC-ND 4.0 — free to use, not to change, share or sell
263
263
  ```
package/README.mr.md CHANGED
@@ -254,7 +254,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag नावाने प्र
254
254
  Uncle Sam एक स्वतंत्र प्लगइन आहे. DeepSeek शी संबंधित नाही, त्यांची मान्यता किंवा समर्थन नाही.
255
255
 
256
256
  ```
257
- @operatingtag/dsh-unclesam v1.3.4
257
+ @operatingtag/dsh-unclesam v1.3.5
258
258
  लेखक Operating Tag
259
259
  परवाना CC BY-NC-ND 4.0 — वापरण्यास मोफत, बदलण्यास, सामायिक करण्यास किंवा विकण्यास नाही
260
260
  ```
package/README.ms.md CHANGED
@@ -261,7 +261,7 @@ mudah.
261
261
  Uncle Sam ialah pemalam bebas. Tidak berkaitan dengan DeepSeek, tidak disokong atau ditaja oleh mereka.
262
262
 
263
263
  ```
264
- @operatingtag/dsh-unclesam v1.3.4
264
+ @operatingtag/dsh-unclesam v1.3.5
265
265
  Penulis Operating Tag
266
266
  Lesen CC BY-NC-ND 4.0 — bebas digunakan, bukan untuk diubah, dikongsi atau dijual
267
267
  ```
package/README.my.md CHANGED
@@ -262,7 +262,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag အမည်ဖြင့်
262
262
  Uncle Sam သည် သီးခြားလွတ်လပ်သော plugin ဖြစ်သည်။ DeepSeek နှင့် မသက်ဆိုင်ပါ၊ ၎င်းတို့က အတည်မပြု၊ မပံ့ပိုးပါ။
263
263
 
264
264
  ```
265
- @operatingtag/dsh-unclesam v1.3.4
265
+ @operatingtag/dsh-unclesam v1.3.5
266
266
  စာရေးသူ Operating Tag
267
267
  လိုင်စင် CC BY-NC-ND 4.0 — အသုံးပြုရန် အခမဲ့၊ ပြောင်းလဲရန်၊ မျှဝေရန် သို့မဟုတ် ရောင်းရန် မဟုတ်
268
268
  ```
package/README.ne.md CHANGED
@@ -254,7 +254,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag नाममा प्रक
254
254
  Uncle Sam स्वतन्त्र प्लगइन हो। DeepSeek सँग सम्बन्धित छैन, उनीहरूको स्वीकृति वा समर्थन छैन।
255
255
 
256
256
  ```
257
- @operatingtag/dsh-unclesam v1.3.4
257
+ @operatingtag/dsh-unclesam v1.3.5
258
258
  लेखक Operating Tag
259
259
  इजाजतपत्र CC BY-NC-ND 4.0 — प्रयोग गर्न निःशुल्क, परिवर्तन, बाँड्न वा बेच्न होइन
260
260
  ```
package/README.nl.md CHANGED
@@ -262,7 +262,7 @@ Het bestand [LICENSE](LICENSE) is bindend, en het begint met dezelfde samenvatti
262
262
  Uncle Sam is een onafhankelijke plugin. Niet verbonden met DeepSeek, door hen niet goedgekeurd of ondersteund.
263
263
 
264
264
  ```
265
- @operatingtag/dsh-unclesam v1.3.4
265
+ @operatingtag/dsh-unclesam v1.3.5
266
266
  Auteur Operating Tag
267
267
  Licentie CC BY-NC-ND 4.0 — vrij om te gebruiken, niet om te wijzigen, delen of verkopen
268
268
  ```
package/README.no.md CHANGED
@@ -257,7 +257,7 @@ Filen [LICENSE](LICENSE) er den gjeldende, og den begynner med det samme sammend
257
257
  Uncle Sam er en uavhengig utvidelse. Ikke knyttet til DeepSeek, ikke godkjent eller støttet av dem.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  Forfatter Operating Tag
262
262
  Lisens CC BY-NC-ND 4.0 — fritt å bruke, ikke å endre, dele eller selge
263
263
  ```
package/README.pl.md CHANGED
@@ -262,7 +262,7 @@ Wiążący jest plik [LICENSE](LICENSE), a otwiera się tym samym podsumowaniem
262
262
  Uncle Sam to niezależna wtyczka. Niepowiązana z DeepSeek, nie firmowana ani nie wspierana przez nich.
263
263
 
264
264
  ```
265
- @operatingtag/dsh-unclesam v1.3.4
265
+ @operatingtag/dsh-unclesam v1.3.5
266
266
  Autor Operating Tag
267
267
  Licencja CC BY-NC-ND 4.0 — wolno używać, nie wolno zmieniać, udostępniać ani sprzedawać
268
268
  ```
package/README.pt.md CHANGED
@@ -261,7 +261,7 @@ O arquivo [LICENSE](LICENSE) é o que vale, e ele abre com o mesmo resumo em ing
261
261
  O Uncle Sam é um plugin independente. Não afiliado ao DeepSeek, nem endossado nem apoiado por ele.
262
262
 
263
263
  ```
264
- @operatingtag/dsh-unclesam v1.3.4
264
+ @operatingtag/dsh-unclesam v1.3.5
265
265
  Autor Operating Tag
266
266
  Licença CC BY-NC-ND 4.0 — livre para usar, não para alterar, compartilhar ou vender
267
267
  ```
package/README.ro.md CHANGED
@@ -258,7 +258,7 @@ Fișierul [LICENSE](LICENSE) este cel care guvernează și începe cu același r
258
258
  Uncle Sam este un plugin independent. Neafiliat cu DeepSeek, neaprobat și nesprijinit de ei.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Autor Operating Tag
263
263
  Licență CC BY-NC-ND 4.0 — liber de folosit, nu de modificat, partajat sau vândut
264
264
  ```
package/README.ru.md CHANGED
@@ -265,7 +265,7 @@ International. Copyright (c) 2026 Darren T. Weldon, опубликовано п
265
265
  Uncle Sam — независимый плагин. Не связан с DeepSeek, не одобрен и не поддерживается им.
266
266
 
267
267
  ```
268
- @operatingtag/dsh-unclesam v1.3.4
268
+ @operatingtag/dsh-unclesam v1.3.5
269
269
  Автор Operating Tag
270
270
  Лицензия CC BY-NC-ND 4.0 — бесплатно для использования, не для изменения, передачи или продажи
271
271
  ```
package/README.si.md CHANGED
@@ -255,7 +255,7 @@ Copyright (c) 2026 Darren T. Weldon, Operating Tag නාමයෙන් ප්
255
255
  Uncle Sam ස්වාධීන ප්ලගීනයකි. DeepSeek සමඟ සම්බන්ධ නැත, ඔවුන් අනුමත හෝ අනුග්‍රහය නොදක්වයි.
256
256
 
257
257
  ```
258
- @operatingtag/dsh-unclesam v1.3.4
258
+ @operatingtag/dsh-unclesam v1.3.5
259
259
  කතෘ Operating Tag
260
260
  බලපත්‍රය CC BY-NC-ND 4.0 — භාවිතයට නොමිලේ, වෙනස් කිරීමට, බෙදා ගැනීමට හෝ විකිණීමට නොවේ
261
261
  ```
package/README.sk.md CHANGED
@@ -257,7 +257,7 @@ Záväzný je súbor [LICENSE](LICENSE) a začína rovnakým zhrnutím v jednodu
257
257
  Uncle Sam je nezávislý doplnok. Nie je spojený s DeepSeek, nie je nimi schválený ani podporovaný.
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  Autor Operating Tag
262
262
  Licencia CC BY-NC-ND 4.0 — zadarmo na používanie, nie na zmenu, zdieľanie alebo predaj
263
263
  ```
package/README.sl.md CHANGED
@@ -258,7 +258,7 @@ Zavezujoča je datoteka [LICENSE](LICENSE) in se začne z istim povzetkom v prep
258
258
  Uncle Sam je neodvisen vtičnik. Ni povezan z DeepSeek, ni odobren ali podprt z njihove strani.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Avtor Operating Tag
263
263
  Licenca CC BY-NC-ND 4.0 — brezplačno za uporabo, ne za spreminjanje, deljenje ali prodajo
264
264
  ```
package/README.sr.md CHANGED
@@ -258,7 +258,7 @@ Copyright (c) 2026 Darren T. Weldon, објављено под именом Oper
258
258
  Uncle Sam је независни додатак. Није повезан са DeepSeek, није одобрен ни подржан од њих.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Аутор Operating Tag
263
263
  Лиценца CC BY-NC-ND 4.0 — бесплатно за употребу, не за измену, дељење или продају
264
264
  ```
package/README.sv.md CHANGED
@@ -259,7 +259,7 @@ Filen [LICENSE](LICENSE) är den som gäller, och den börjar med samma sammanfa
259
259
  Uncle Sam är ett fristående insticksprogram. Inte knutet till DeepSeek, inte godkänt eller stött av dem.
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  Författare Operating Tag
264
264
  Licens CC BY-NC-ND 4.0 — fritt att använda, inte att ändra, dela eller sälja
265
265
  ```
package/README.sw.md CHANGED
@@ -259,7 +259,7 @@ Faili [LICENSE](LICENSE) ndiyo inayotumika, na inaanza na muhtasari huo huo kwa
259
259
  Uncle Sam ni programu-jalizi huru. Haijahusishwa na DeepSeek, haijaidhinishwa wala kuungwa mkono nao.
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  Mwandishi Operating Tag
264
264
  Leseni CC BY-NC-ND 4.0 — huru kutumika, si kubadilisha, kushiriki au kuuza
265
265
  ```
package/README.ta.md CHANGED
@@ -262,7 +262,7 @@ Tag ஐக் கேளுங்கள் — தெளிவான பதில
262
262
  Uncle Sam ஒரு சுயாதீனச் செருகல். DeepSeek உடன் தொடர்பில்லை, அவர்களின் ஒப்புதல் அல்லது ஆதரவு இல்லை.
263
263
 
264
264
  ```
265
- @operatingtag/dsh-unclesam v1.3.4
265
+ @operatingtag/dsh-unclesam v1.3.5
266
266
  ஆசிரியர் Operating Tag
267
267
  உரிமம் CC BY-NC-ND 4.0 — பயன்படுத்த இலவசம், மாற்ற, பகிர அல்லது விற்க அல்ல
268
268
  ```
package/README.te.md CHANGED
@@ -256,7 +256,7 @@ Tag ను అడగండి — స్పష్టమైన సమాధాన
256
256
  Uncle Sam స్వతంత్ర ప్లగిన్. DeepSeek తో సంబంధం లేదు, వారి ఆమోదం లేదా మద్దతు లేదు.
257
257
 
258
258
  ```
259
- @operatingtag/dsh-unclesam v1.3.4
259
+ @operatingtag/dsh-unclesam v1.3.5
260
260
  రచయిత Operating Tag
261
261
  లైసెన్స్ CC BY-NC-ND 4.0 — వాడటానికి ఉచితం, మార్చడానికి, పంచుకోవడానికి లేదా అమ్మడానికి కాదు
262
262
  ```
package/README.th.md CHANGED
@@ -252,7 +252,7 @@ Operating Tag แล้วคุณจะได้คำตอบที่ชั
252
252
  Uncle Sam เป็นปลั๊กอินอิสระ ไม่เกี่ยวข้องกับ DeepSeek ไม่ได้รับการรับรองหรือสนับสนุนจากพวกเขา
253
253
 
254
254
  ```
255
- @operatingtag/dsh-unclesam v1.3.4
255
+ @operatingtag/dsh-unclesam v1.3.5
256
256
  ผู้เขียน Operating Tag
257
257
  สัญญาอนุญาต CC BY-NC-ND 4.0 — ใช้ฟรี ไม่ใช่เพื่อดัดแปลง แบ่งปัน หรือขาย
258
258
  ```
package/README.tl.md CHANGED
@@ -265,7 +265,7 @@ Ang file na [LICENSE](LICENSE) ang namamahala, at nagsisimula ito sa parehong bu
265
265
  Ang Uncle Sam ay isang malayang plugin. Hindi kaanib sa DeepSeek, hindi inendorso o sinusuportahan nila.
266
266
 
267
267
  ```
268
- @operatingtag/dsh-unclesam v1.3.4
268
+ @operatingtag/dsh-unclesam v1.3.5
269
269
  May-akda Operating Tag
270
270
  Lisensya CC BY-NC-ND 4.0 — libre gamitin, hindi para baguhin, ibahagi o ibenta
271
271
  ```
package/README.tr.md CHANGED
@@ -261,7 +261,7 @@ Uncle Sam bağımsız bir eklentidir. DeepSeek ile bağlantılı değildir, onla
261
261
  desteklenmemiştir.
262
262
 
263
263
  ```
264
- @operatingtag/dsh-unclesam v1.3.4
264
+ @operatingtag/dsh-unclesam v1.3.5
265
265
  Yazar Operating Tag
266
266
  Lisans CC BY-NC-ND 4.0 — kullanması serbest, değiştirmesi, paylaşması veya satması değil
267
267
  ```
package/README.uk.md CHANGED
@@ -261,7 +261,7 @@ International. Copyright (c) 2026 Darren T. Weldon, опубліковано п
261
261
  Uncle Sam — незалежний плагін. Не пов'язаний із DeepSeek, не схвалений і не підтриманий ними.
262
262
 
263
263
  ```
264
- @operatingtag/dsh-unclesam v1.3.4
264
+ @operatingtag/dsh-unclesam v1.3.5
265
265
  Автор Operating Tag
266
266
  Ліцензія CC BY-NC-ND 4.0 — вільно використовувати, не змінювати, передавати чи продавати
267
267
  ```
package/README.ur.md CHANGED
@@ -257,7 +257,7 @@ Copyright (c) 2026 Darren T. Weldon، Operating Tag نام سے شائع شدہ
257
257
  Uncle Sam ایک خودمختار پلگ ان ہے۔ DeepSeek سے وابستہ نہیں، ان کی توثیق یا معاونت حاصل نہیں۔
258
258
 
259
259
  ```
260
- @operatingtag/dsh-unclesam v1.3.4
260
+ @operatingtag/dsh-unclesam v1.3.5
261
261
  مصنف Operating Tag
262
262
  لائسنس CC BY-NC-ND 4.0 — استعمال کے لیے مفت، تبدیلی، اشتراک یا فروخت کے لیے نہیں
263
263
  ```
package/README.uz.md CHANGED
@@ -258,7 +258,7 @@ Tag dan so'rang — aniq javob va aniq narx olasiz.
258
258
  Uncle Sam — mustaqil plagin. DeepSeek bilan bog'liq emas, ular tomonidan ma'qullanmagan yoki qo'llab-quvvatlanmagan.
259
259
 
260
260
  ```
261
- @operatingtag/dsh-unclesam v1.3.4
261
+ @operatingtag/dsh-unclesam v1.3.5
262
262
  Muallif Operating Tag
263
263
  Litsenziya CC BY-NC-ND 4.0 — foydalanish uchun bepul, o'zgartirish, ulashish yoki sotish uchun emas
264
264
  ```
package/README.vi.md CHANGED
@@ -259,7 +259,7 @@ Tệp [LICENSE](LICENSE) là văn bản có hiệu lực, và nó mở đầu b
259
259
  Uncle Sam là một plugin độc lập. Không liên kết với DeepSeek, không được họ chứng thực hay hỗ trợ.
260
260
 
261
261
  ```
262
- @operatingtag/dsh-unclesam v1.3.4
262
+ @operatingtag/dsh-unclesam v1.3.5
263
263
  Tác giả Operating Tag
264
264
  Giấy phép CC BY-NC-ND 4.0 — miễn phí để dùng, không được sửa, chia sẻ hay bán
265
265
  ```
package/README.zh.md CHANGED
@@ -244,7 +244,7 @@ Copyright (c) 2026 Darren T. Weldon,以 Operating Tag 名义发布。
244
244
  Uncle Sam 是一个独立插件。与 DeepSeek 无关联,未获其背书,也未获其支持。
245
245
 
246
246
  ```
247
- @operatingtag/dsh-unclesam v1.3.4
247
+ @operatingtag/dsh-unclesam v1.3.5
248
248
  作者 Operating Tag
249
249
  许可 CC BY-NC-ND 4.0 —— 可免费使用,不可修改、共享或出售
250
250
  ```
package/index.js CHANGED
@@ -27,8 +27,8 @@
27
27
  * prose instead of a call, and the harness sees no tool use that turn.
28
28
  */
29
29
 
30
- import { writeFileSync } from 'node:fs';
31
- import { ChatSession, WebChatError } from './lib/engine.mjs';import { buildPrompt, messageText, parseToolCall, stripToolCall, streamSafeCut } from './lib/prompt.mjs';
30
+ import { writeFileSync } from 'node:fs';
31
+ import { ChatSession, WebChatError } from './lib/engine.mjs';import { buildPrompt, looksDegenerate, messageText, parseToolCall, stripToolCall, streamSafeCut } from './lib/prompt.mjs';
32
32
  import { SavingsMeter, estimateTokens as estimateTokensForSavings } from './lib/savings.mjs';
33
33
  import { Locales } from './lib/i18n.mjs';
34
34
  import { Prefs, prefsPath, profileDir } from './lib/prefs.mjs';
@@ -464,6 +464,9 @@ export function apply(ctx, config = {}) {
464
464
  * Without the list, prose like `see figure(2)` would look like a call.
465
465
  */
466
466
  const toolNames = wantTools ? options.tools.map((t) => t?.name).filter(Boolean) : [];
467
+
468
+ /** Set when the reply collapsed into repetition; the turn then ends with an error, not garbage. */
469
+ let stoppedAsLoop = false;
467
470
  const switches = switchesFor(model, settings);
468
471
  // A search answer is delivered as two blocks: what was searched and where it looked, then the
469
472
  // answer. That means the text cannot stream while search is on - the sources are only readable
@@ -584,6 +587,23 @@ export function apply(ctx, config = {}) {
584
587
  if (!chunk.text) continue;
585
588
  assembled += chunk.text;
586
589
 
590
+ /*
591
+ * Stop a reply that has come apart into a loop.
592
+ *
593
+ * MEASURED, live: a web turn emitted the same malformed `<tool …>` block hundreds of times and the
594
+ * adapter streamed every copy, so the person watched a page write one line for minutes and
595
+ * reasonably concluded the plugin was broken. Nothing was wrong with the page — the model had
596
+ * invented a call format, the call never ran, and nothing told it so.
597
+ *
598
+ * The loop is now cut at the source: the turn ends with a plain error that says what happened,
599
+ * instead of displaying the wreckage. Only checked when the new text could contribute, so ordinary
600
+ * turns pay nothing for it.
601
+ */
602
+ if (/<tool/i.test(chunk.text) && looksDegenerate(assembled)) {
603
+ stoppedAsLoop = true;
604
+ break;
605
+ }
606
+
587
607
  if (wantSearch) {
588
608
  // held for ordering; nothing is emitted until the sources are known
589
609
  continue;
@@ -612,6 +632,29 @@ export function apply(ctx, config = {}) {
612
632
 
613
633
  // Search answers are emitted as two visible blocks so the transcript shows BOTH what was asked
614
634
  // of the web and what came back, before the answer that used it.
635
+ /*
636
+ * A reply that collapsed into repetition ends here, with an error that says so.
637
+ *
638
+ * The alternative - what used to happen - is that the loop is streamed to the transcript in full,
639
+ * which reads as the plugin having broken when in fact the model is stuck. Naming it is the whole
640
+ * point: the person can see that the page looped, not that their harness failed.
641
+ */
642
+ if (stoppedAsLoop) {
643
+ yield {
644
+ type: 'finish',
645
+ reason: {
646
+ kind: 'error',
647
+ failure: new WebChatError(
648
+ 'The web reply collapsed into repetition - the same block written over and over - so the ' +
649
+ 'turn was stopped. Nothing was lost: send the message again, or switch to an API model ' +
650
+ 'for this one.',
651
+ 'web_loop',
652
+ ),
653
+ },
654
+ };
655
+ return;
656
+ }
657
+
615
658
  if (wantSearch) {
616
659
  /*
617
660
  * The query is the person's newest message - and ONLY the person's.
package/lib/prompt.mjs CHANGED
@@ -393,6 +393,49 @@ function finish(text, expectsToolCall, continuing) {
393
393
  * that merely CONTAINS the word tool but no valid object is treated as prose, because treating it as a
394
394
  * malformed call would throw away a perfectly good answer.
395
395
  */
396
+ /**
397
+ * Detect a reply that has come apart into repetition.
398
+ *
399
+ * MEASURED, live: asked to glob a workspace it had misread, the web model emitted the same malformed block
400
+ * — `<tool name="glob" string="true">{…}</tool>` — over and over, filling the transcript with hundreds of
401
+ * copies. The adapter streamed every one of them, because nothing was looking for that shape of failure.
402
+ *
403
+ * A format mismatch is recoverable: the call does not run and the model is told. A LOOP is not, because the
404
+ * person sits watching a page write the same line for minutes and concludes the plugin is broken.
405
+ *
406
+ * WHAT COUNTS AS DEGENERATE
407
+ * Four identical substantial lines, or three `<tool` openings. Both are far beyond anything a real answer
408
+ * does; an answer that repeats a sentence twice is fine and stays fine.
409
+ */
410
+ export function looksDegenerate(reply) {
411
+ const s = String(reply ?? '');
412
+
413
+ /*
414
+ * Tag stacking first, and without a length floor.
415
+ *
416
+ * The floor exists so a short answer cannot be judged on a handful of lines. It must not gate this check:
417
+ * three `<tool` openings is three calls attempted in one reply, which is wrong however short the text is.
418
+ * Measured: the first version returned false for a three-tag reply because it was under 200 characters -
419
+ * the guard missed exactly the shape it was written for.
420
+ */
421
+ const tags = s.match(/<tool\b/gi);
422
+ if (tags && tags.length >= 3) return true;
423
+
424
+ /*
425
+ * No length floor on the line check either.
426
+ *
427
+ * It was there to stop a short answer being judged on a few lines, and it was wrong twice: a five-line
428
+ * loop sat under the floor and went undetected, which is precisely the case the guard exists for. Four
429
+ * identical lines of twenty characters or more is already far outside ordinary prose on its own.
430
+ */
431
+ const lines = s.split('\n').map((l) => l.trim()).filter((l) => l.length >= 20);
432
+ const counts = new Map();
433
+ for (const line of lines) counts.set(line, (counts.get(line) || 0) + 1);
434
+ for (const n of counts.values()) if (n >= 4) return true;
435
+
436
+ return false;
437
+ }
438
+
396
439
  /**
397
440
  * Find `name({...})` in a reply, where `name` is one of the tools that was offered.
398
441
  *
@@ -410,7 +453,15 @@ function finish(text, expectsToolCall, continuing) {
410
453
  * argument may contain a parenthesis or a brace inside a string and a regex would stop there.
411
454
  */
412
455
  function findCallForm(text, names) {
413
- const wanted = Array.isArray(names) && names.length ? names : null;
456
+ /*
457
+ * `hasList` distinguishes "no list supplied" from "an empty list supplied", and that distinction is the
458
+ * whole of two bugs.
459
+ *
460
+ * An EMPTY list means "no tools are offered", so nothing can be a call - and a word followed by parentheses
461
+ * in ordinary prose, like `log(2)` or `figure(2)`, must be left alone. The old code collapsed both cases
462
+ * into `null` ("accept anything"), so a turn with no tools deleted such prose from the answer.
463
+ */
464
+ const hasList = Array.isArray(names);
414
465
 
415
466
  for (let i = 0; i < text.length; i += 1) {
416
467
  if (!/[A-Za-z_]/.test(text[i])) continue;
@@ -423,7 +474,7 @@ function findCallForm(text, names) {
423
474
  j += 1;
424
475
  }
425
476
  if (!word) continue;
426
- if (wanted && !wanted.includes(word)) {
477
+ if (hasList && !names.includes(word)) {
427
478
  i = j - 1;
428
479
  continue;
429
480
  }
@@ -467,7 +518,15 @@ function findCallForm(text, names) {
467
518
  try {
468
519
  args = JSON.parse(inside);
469
520
  } catch {
470
- return null; // parentheses that are not a call, or arguments not yet valid
521
+ /*
522
+ * Skip this candidate and keep scanning, instead of aborting.
523
+ *
524
+ * MEASURED: `read(bad) and pwsh({"command":"dir"})` returned nothing, because the first malformed
525
+ * candidate returned null for the whole reply and the valid `pwsh(...)` behind it was never reached.
526
+ * A bad call earlier in a reply must not hide a good one later. Resume just past this closing paren.
527
+ */
528
+ i = end;
529
+ continue;
471
530
  }
472
531
  }
473
532
 
@@ -502,6 +561,46 @@ export function parseToolCall(reply, names) {
502
561
  const direct = findCallForm(text, names);
503
562
  if (direct) return { name: direct.name, arguments: direct.arguments };
504
563
 
564
+ /*
565
+ * Shape 2: the tags a model reaches for when it invents its own protocol.
566
+ *
567
+ * MEASURED, live: asked to run a glob, the web model answered
568
+ * `<tool name="glob" string="true">{"pattern":"…"}</tool>` — a shape nothing here had ever taught it, and
569
+ * one the parser did not accept. The call never ran, nothing said so, and the model repeated the block
570
+ * until the turn was full of copies. Accepting the shape ends the loop at its cause instead of only
571
+ * masking the symptom.
572
+ */
573
+ const xmlTag = /<tool\s+name\s*=\s*"([^"]+)"[^>]*>([\s\S]*?)<\/tool>/i.exec(text);
574
+ if (xmlTag) {
575
+ const name = xmlTag[1].trim();
576
+ if (!names?.length || names.includes(name)) {
577
+ let args = {};
578
+ const body = xmlTag[2].trim();
579
+ if (body) {
580
+ try {
581
+ args = JSON.parse(body);
582
+ } catch {
583
+ args = {};
584
+ }
585
+ }
586
+ return { name, arguments: JSON.stringify(args) };
587
+ }
588
+ }
589
+
590
+ const xmlBlock = /<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/i.exec(text);
591
+ if (xmlBlock) {
592
+ try {
593
+ const parsed = JSON.parse(xmlBlock[1]);
594
+ const name = parsed?.name ?? parsed?.tool;
595
+ if (typeof name === 'string' && name && (!names?.length || names.includes(name))) {
596
+ const raw = parsed.arguments ?? {};
597
+ return { name, arguments: typeof raw === 'string' ? raw : JSON.stringify(raw) };
598
+ }
599
+ } catch {
600
+ /* fall through to the JSON scan below */
601
+ }
602
+ }
603
+
505
604
  const candidates = [];
506
605
  // fenced blocks first
507
606
  const fence = /```(?:json)?\s*([\s\S]*?)```/gi;
@@ -619,6 +718,24 @@ export function streamSafeCut(text, names) {
619
718
  }
620
719
  }
621
720
 
721
+ /**
722
+ * Hold at a tag that may be turning into `<tool …>` or `<tool_call>`.
723
+ *
724
+ * The same reasoning as the name fragment: a reply that is writing one of these must not show its opening
725
+ * characters first, or the transcript gains a partial tag that no parser will ever match.
726
+ */
727
+ for (let i = s.indexOf('<'); i !== -1; i = s.indexOf('<', i + 1)) {
728
+ const frag = s.slice(i + 1);
729
+ if (frag.length === 0) return i;
730
+ const letters = /^[A-Za-z_]*/.exec(frag)[0];
731
+ if (letters.length < frag.length) {
732
+ // The tag name is complete; only an exact match to one we hold is interesting.
733
+ if (letters === 'tool' || letters === 'tool_call') return i;
734
+ continue;
735
+ }
736
+ if ('tool'.startsWith(letters) || 'tool_call'.startsWith(letters)) return i;
737
+ }
738
+
622
739
  /**
623
740
  * Could the brace at `i` still turn out to be the start of a tool object?
624
741
  *
@@ -664,6 +781,10 @@ export function stripToolCall(reply, names) {
664
781
  text = text.slice(0, found.start) + ' ' + text.slice(found.end);
665
782
  }
666
783
 
784
+ // The tagged shapes, before anything else, so their inner JSON is never treated as prose.
785
+ text = text.replace(/<tool\s+name\s*=\s*"[^"]+"[^>]*>[\s\S]*?<\/tool>/gi, ' ');
786
+ text = text.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, ' ');
787
+
667
788
  // Fenced calls first: the fence marks the whole block, so no brace counting is needed.
668
789
  text = text.replace(/```(?:json)?\s*\{\s*"tool"[\s\S]*?\}\s*```/gi, '');
669
790
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operatingtag/dsh-unclesam",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Uncle Sam — answers through chat.deepseek.com in a real browser tab instead of the metered API. Switch between the API and the web account from the composer; web replies are signed so you always know which route answered.",