@bendyline/gezel-service 1.1.1 → 1.1.2

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 (185) hide show
  1. package/dist/NOTICE.md +3 -3
  2. package/dist/bin/gezeld.js +8471 -5311
  3. package/dist/handboek-content/technical/building-connected-apps-with-gezel-app-sdk.md +78 -0
  4. package/dist/handboek-content/whats-new/{1.26250.md → 1.26251.md} +5 -5
  5. package/dist/index-store/static-index-worker.js +160 -51
  6. package/dist/index.d.ts +416 -71
  7. package/dist/index.js +8465 -5305
  8. package/dist/memory/embed-worker.js +132 -4
  9. package/dist/memory/image-embed-worker.js +14 -5
  10. package/dist/providers/mlx/python/cache_persist.py +52 -8
  11. package/dist/providers/mlx/python/gezel_mlx_server.py +44 -1
  12. package/dist/providers/mlx/python/qwen4_ple.py +159 -0
  13. package/dist/providers/mlx/python/spec_decode.py +73 -31
  14. package/dist/providers/mlx/python/tool_call_stream.py +10 -2
  15. package/dist/providers/mlx/python/tool_grammar.py +16 -0
  16. package/dist/ui/assets/{AmbientDashboardCard-DcVHxEdC.js → AmbientDashboardCard-_xnAQGnk.js} +1 -1
  17. package/dist/ui/assets/{AudioEngineSettings-BFM2S1mm.js → AudioEngineSettings-CgXgbX0i.js} +1 -1
  18. package/dist/ui/assets/{BenchmarksView-84-YeULA.js → BenchmarksView-BlExZpYA.js} +1 -1
  19. package/dist/ui/assets/CatalogBrowser-DYXUZQ_t.js +1 -0
  20. package/dist/ui/assets/{ChannelsSettings-7NAVUk4k.js → ChannelsSettings-EH27HcqZ.js} +1 -1
  21. package/dist/ui/assets/ChatTimelineView-Dn1TNyVn.js +7 -0
  22. package/dist/ui/assets/{ConnectedAppsPanel-CIgF4Q3R.js → ConnectedAppsPanel-BROry-Y0.js} +1 -1
  23. package/dist/ui/assets/CraftbookEditor-B2RNJnFf.js +1 -0
  24. package/dist/ui/assets/{CraftbookScriptEditorView-Ck5tzj3Y.js → CraftbookScriptEditorView-B-vySmHP.js} +1 -1
  25. package/dist/ui/assets/{CraftbookTabContent-BWg7FhK_.js → CraftbookTabContent-BW_2KC89.js} +1 -1
  26. package/dist/ui/assets/{CraftbookToolsetSetup-EuFOiUzR.js → CraftbookToolsetSetup-J7rEa835.js} +1 -1
  27. package/dist/ui/assets/{CraftbooksView-BIzQ1VVn.js → CraftbooksView-BjBUWPGF.js} +1 -1
  28. package/dist/ui/assets/DiffpackReviewView-CD4qJmgT.js +1 -0
  29. package/dist/ui/assets/DocumentDetail-SYozruTJ.js +1 -0
  30. package/dist/ui/assets/DocumentsView-DE7eL49Z.js +1 -0
  31. package/dist/ui/assets/{Ds4Settings-9soZCSeO.js → Ds4Settings-DGzc7JcD.js} +1 -1
  32. package/dist/ui/assets/{EmbeddedChat-Cce7nxXT.js → EmbeddedChat-D92TaJQ8.js} +1 -1
  33. package/dist/ui/assets/{FaceRecognitionCard-BVZyOwB8.js → FaceRecognitionCard-CB1Dt9X4.js} +1 -1
  34. package/dist/ui/assets/FileMapView-kVBG22FU.js +1 -0
  35. package/dist/ui/assets/FoldersSettings-BWFQU5B4.js +1 -0
  36. package/dist/ui/assets/GezelDetail-Br4v42Nv.js +1 -0
  37. package/dist/ui/assets/{GezelJsonEditor-DXXt165-.js → GezelJsonEditor-B9XEiW5Y.js} +1 -1
  38. package/dist/ui/assets/GezellenView-DheEBAy4.js +1 -0
  39. package/dist/ui/assets/{GildeUpdatesCard-CtY8mUTA.js → GildeUpdatesCard-BeIYv09f.js} +1 -1
  40. package/dist/ui/assets/{GithubSignInChip-DT3l6E0Q.js → GithubSignInChip-eEGCe9ar.js} +1 -1
  41. package/dist/ui/assets/{HandboekMediaProvider-ByJ4NAzz.js → HandboekMediaProvider-D0zcbbpf.js} +1 -1
  42. package/dist/ui/assets/HandboekView-p0BZT1rH.js +1 -0
  43. package/dist/ui/assets/{HistoryView-CkinzFEC.js → HistoryView-CKWcWW-Y.js} +1 -1
  44. package/dist/ui/assets/{HomeView-DNBrQnwy.js → HomeView-b_TT5oV3.js} +1 -1
  45. package/dist/ui/assets/{ImageEngineSettings-BfM9HSd_.js → ImageEngineSettings-CJfk4OJ4.js} +1 -1
  46. package/dist/ui/assets/{ImageRecognitionSettings-CaSQu5Br.js → ImageRecognitionSettings-DzbvZk5S.js} +1 -1
  47. package/dist/ui/assets/{IncompleteDownloads-C36lTCMG.js → IncompleteDownloads-C8_XyP8O.js} +1 -1
  48. package/dist/ui/assets/{KnowledgeCatalogsCard-CK9bqdf6.js → KnowledgeCatalogsCard-CHopG_j-.js} +1 -1
  49. package/dist/ui/assets/KnowledgeView-CXNKZUJq.js +1 -0
  50. package/dist/ui/assets/{LlamaCppSettings-CdNMHBbp.js → LlamaCppSettings-ohcM7kes.js} +1 -1
  51. package/dist/ui/assets/{MarkdownField-Dugmfr_e.js → MarkdownField-BX0qsaFq.js} +1 -1
  52. package/dist/ui/assets/{MemoriesTree-CgFqUNEr.js → MemoriesTree-BPj5Rod8.js} +1 -1
  53. package/dist/ui/assets/{MicrophoneSettings-DzDe9y1q.js → MicrophoneSettings-CWjeYnfI.js} +1 -1
  54. package/dist/ui/assets/MlxSettings-Dq6dRpcl.js +1 -0
  55. package/dist/ui/assets/{ModelPicker-BVkJhNAH.js → ModelPicker-0Ue-eEKj.js} +1 -1
  56. package/dist/ui/assets/NewPathDialog-BhAZm9dp.js +1 -0
  57. package/dist/ui/assets/{NewScriptDialog-TEAd0KLl.js → NewScriptDialog-DuryIe50.js} +1 -1
  58. package/dist/ui/assets/NewTaskDialog-BX24flMY.js +2 -0
  59. package/dist/ui/assets/{OllamaSettings-CPy2vxyZ.js → OllamaSettings-Boj8Nd1G.js} +1 -1
  60. package/dist/ui/assets/ProjectChat-Dhw_M5bq.js +5 -0
  61. package/dist/ui/assets/ProjectConnectionsTab-BwpMQNrg.js +1 -0
  62. package/dist/ui/assets/{ProjectGitStatusBar-BgHZ2ijN.js → ProjectGitStatusBar-BORGYx5l.js} +1 -1
  63. package/dist/ui/assets/{ProjectGithubView-BV2uTNU0.js → ProjectGithubView-CTP1BOMv.js} +1 -1
  64. package/dist/ui/assets/{ProjectMailTab-DLtJdXSL.js → ProjectMailTab-qFmAeV3M.js} +1 -1
  65. package/dist/ui/assets/{ProjectOverviewView-ZMs9nL5N.js → ProjectOverviewView-Cq1FsoaT.js} +1 -1
  66. package/dist/ui/assets/{ProjectTimeline-CTPcn4Kc.js → ProjectTimeline-Cqae2Z92.js} +1 -1
  67. package/dist/ui/assets/ProjectsView-D0uJjUB-.js +7 -0
  68. package/dist/ui/assets/{RecommendedBadge-iUoisQBi.js → RecommendedBadge-CN1jEmSn.js} +1 -1
  69. package/dist/ui/assets/{RemoteServersPanel-CTVJ0IRh.js → RemoteServersPanel-CMakvCCM.js} +1 -1
  70. package/dist/ui/assets/{ScriptEditorTabs-CCDFZjdC.js → ScriptEditorTabs-st6dJePd.js} +2 -2
  71. package/dist/ui/assets/{ScriptEditorView-CergLqKj.js → ScriptEditorView-BkySh57_.js} +2 -2
  72. package/dist/ui/assets/{ScriptsView-v7ckdhDi.js → ScriptsView-7uPKwjDB.js} +1 -1
  73. package/dist/ui/assets/{SecurityComplianceSettings-Bd0-66Gs.js → SecurityComplianceSettings-Tsv_pXfy.js} +1 -1
  74. package/dist/ui/assets/SessionSwitcher-D0fSeeHO.js +1 -0
  75. package/dist/ui/assets/SettingsView-cli_z8ZW.js +3 -0
  76. package/dist/ui/assets/{SquisqIntegration-C5l_OPvD.js → SquisqIntegration-BTZ1kBlg.js} +1 -1
  77. package/dist/ui/assets/{StorageCleanupDialog-3kv9-2mT.js → StorageCleanupDialog-CDBjl8JQ.js} +1 -1
  78. package/dist/ui/assets/{StorageUsageCard-7sWTrZFa.js → StorageUsageCard-DXY1j0dZ.js} +1 -1
  79. package/dist/ui/assets/TaskTabContent-C0P681SL.js +1 -0
  80. package/dist/ui/assets/TasksView-Ddwz10ri.js +1 -0
  81. package/dist/ui/assets/{TerminalCodeEditor-ChmdzmCz.js → TerminalCodeEditor-BkNQ6QoQ.js} +2 -2
  82. package/dist/ui/assets/ToolsetsEditor-KVigemfL.js +8 -0
  83. package/dist/ui/assets/{TransformToolbarButton-gzIxUBH7.js → TransformToolbarButton-8wfJR1bO.js} +2 -2
  84. package/dist/ui/assets/{UnrecognizedModels-0hptopv6.js → UnrecognizedModels-BzdU1clO.js} +1 -1
  85. package/dist/ui/assets/{VideoEngineSettings-BdNzCEdR.js → VideoEngineSettings-f79ff57u.js} +1 -1
  86. package/dist/ui/assets/{WorkspaceIndexPane-DnsOO916.js → WorkspaceIndexPane-fu5V6o1W.js} +1 -1
  87. package/dist/ui/assets/{api-C0I7spBl.js → api-CmrgM5Rf.js} +1 -1
  88. package/dist/ui/assets/chat-thread-memory-8MCtb17Q.js +1 -0
  89. package/dist/ui/assets/{chunk-6ECMNUIP-BvCy0HUI.js → chunk-6ECMNUIP-D5AA6ozp.js} +1 -1
  90. package/dist/ui/assets/{chunk-A6N6IN3I-ofeM4l8g.js → chunk-A6N6IN3I-BpxihS5H.js} +1 -1
  91. package/dist/ui/assets/{chunk-ATWVNF7D-CYuW1Yc6.js → chunk-ATWVNF7D-CKIWh7bN.js} +1 -1
  92. package/dist/ui/assets/{chunk-UBFT2CDQ-FexGDigd.js → chunk-CW24CH7I-BD0FIooX.js} +1 -1
  93. package/dist/ui/assets/{chunk-DXYWKZ52-zxe8pjH4.js → chunk-DXYWKZ52-DMKPZnpo.js} +1 -1
  94. package/dist/ui/assets/chunk-IIQYS2YH-BtDJt4Xr.js +1 -0
  95. package/dist/ui/assets/{chunk-KGWT454C-v5-l6U5m.js → chunk-KGWT454C-DsQOBuLg.js} +1 -1
  96. package/dist/ui/assets/{chunk-Q77KNJIN-BLuPdsQF.js → chunk-Q77KNJIN-BdWizq9s.js} +1 -1
  97. package/dist/ui/assets/{chunk-USU6HTKB-B_p-YcDp.js → chunk-USU6HTKB-DyGZplh4.js} +1 -1
  98. package/dist/ui/assets/{chunk-UXEANVBI-Bt0kX-0Z.js → chunk-UXEANVBI-BUBXvqyE.js} +1 -1
  99. package/dist/ui/assets/{chunk-O7JILDEF-CqcO1qaI.js → chunk-X7BNDUNI-D14WIvlD.js} +2 -2
  100. package/dist/ui/assets/{chunk-AE3IUKMM-mZjzzO8Z.js → chunk-ZSU5DJLX-CrjQf-vs.js} +1 -1
  101. package/dist/ui/assets/{container-BI8hxN1N.js → container-iFj1r6Hk.js} +1 -1
  102. package/dist/ui/assets/csv-Di411Mv-.js +1 -0
  103. package/dist/ui/assets/data-Q05qqAp4.js +1 -0
  104. package/dist/ui/assets/{dist-APSIK7H3.js → dist-1FNFiksd.js} +3 -3
  105. package/dist/ui/assets/dist-BMZhqfv7.js +2 -0
  106. package/dist/ui/assets/dist-CE5CbmDb.js +225 -0
  107. package/dist/ui/assets/doc-BHcGsJZd.js +587 -0
  108. package/dist/ui/assets/{document-import-DPK4r8Am.js → document-import-B2Ya6sbf.js} +1 -1
  109. package/dist/ui/assets/{docx-DRLuCTaC.js → docx-B8Pwz5Ih.js} +1 -1
  110. package/dist/ui/assets/{epub-a0p2Xb1b.js → epub-BQ4g8Q9j.js} +1 -1
  111. package/dist/ui/assets/{export-options-BqYFyzWx.js → export-options-Dylv69b3.js} +1 -1
  112. package/dist/ui/assets/file-browser-BLOPfnS0.js +5 -0
  113. package/dist/ui/assets/{html-BbQNmJ5X.js → html-BnA7qFwq.js} +1 -1
  114. package/dist/ui/assets/icons-CyM7Cg4E.js +1 -0
  115. package/dist/ui/assets/index-DW6qHqhU.css +1 -0
  116. package/dist/ui/assets/index-DivKnJyx.js +36 -0
  117. package/dist/ui/assets/{mail-link-CWfsP5Aq.js → mail-link-NtlcX5OE.js} +1 -1
  118. package/dist/ui/assets/{markdown-ryKA_OmY.js → markdown-CLKH_zzl.js} +1 -1
  119. package/dist/ui/assets/markdown-baseline-0dqv9qbV.js +1 -0
  120. package/dist/ui/assets/materialize-G4WC5UG3-xq2dcwS8.js +1 -0
  121. package/dist/ui/assets/{monaco-base-C0VTMpv-.js → monaco-base-BSvdAweA.js} +1 -1
  122. package/dist/ui/assets/{monaco-setup-CX8q88c5.js → monaco-setup-CT7LZ0o_.js} +1 -1
  123. package/dist/ui/assets/{new-project-meta-ZmDPGYzC.js → new-project-meta-5Y9Blozr.js} +1 -1
  124. package/dist/ui/assets/outside-in-Msmhxf_U.js +3 -0
  125. package/dist/ui/assets/{pdf-BHrygJa5.js → pdf-C4BhW3zg.js} +1 -1
  126. package/dist/ui/assets/{pending-drafts-27ujtQxX.js → pending-drafts-BD227X9H.js} +1 -1
  127. package/dist/ui/assets/{poppetje-CfaAvFkE.js → poppetje-DvCJO36y.js} +3 -3
  128. package/dist/ui/assets/{pptx-nDW64jAN.js → pptx-B6uaM2s7.js} +3 -3
  129. package/dist/ui/assets/{run-export-86KzLZ7R.js → run-export-TscWwR6y.js} +2 -2
  130. package/dist/ui/assets/{standalone-source-7QdiNsDW.js → standalone-source-Cw9SF7Zk.js} +1 -1
  131. package/dist/ui/assets/storage-Cmhlwx70.js +1 -0
  132. package/dist/ui/assets/styles-BjDaWeMA.css +1 -0
  133. package/dist/ui/assets/styles-CqO-rmOt.js +554 -0
  134. package/dist/ui/assets/{terminal-monaco-setup-Bar-sYKd.js → terminal-monaco-setup-me523-j-.js} +1 -1
  135. package/dist/ui/assets/{transform-CmAXy0Ck.js → transform-DxJCwK68.js} +1 -1
  136. package/dist/ui/assets/{use-local-model-manager-D1yiurrC.js → use-local-model-manager-8wvk-I-y.js} +1 -1
  137. package/dist/ui/assets/{useCompactLayout-BDtPQcDh.js → useCompactLayout-cm4E9Vja.js} +0 -0
  138. package/dist/ui/assets/{useCopilotAvailability-BHOfHrfT.js → useCopilotAvailability-D9hglSH_.js} +1 -1
  139. package/dist/ui/assets/{useDiffpacks-B0kYhlWQ.js → useDiffpacks-1BN2XJWg.js} +1 -1
  140. package/dist/ui/assets/{useGitSync-DOt-ODiw.js → useGitSync-7m9YA7h5.js} +1 -1
  141. package/dist/ui/assets/{useShowWorkInProgressFeatures-BtpredG7.js → useShowWorkInProgressFeatures-D6QOaTUT.js} +1 -1
  142. package/dist/ui/assets/{useTotalRamBytes-B8NFM27w.js → useTotalRamBytes-Durk383U.js} +1 -1
  143. package/dist/ui/assets/{xlsx-B_pu1ZvY.js → xlsx-BbHA9bxA.js} +1 -1
  144. package/dist/ui/index.html +15 -15
  145. package/package.json +12 -11
  146. package/dist/ui/assets/CatalogBrowser-7_jHy5Q3.js +0 -1
  147. package/dist/ui/assets/ChatTimelineView-Cg_kLK_U.js +0 -7
  148. package/dist/ui/assets/CraftbookEditor-BKAIsnXv.js +0 -1
  149. package/dist/ui/assets/DiffpackReviewView-B2a3zgE-.js +0 -1
  150. package/dist/ui/assets/DocumentDetail-GCYhwQqV.js +0 -1
  151. package/dist/ui/assets/DocumentsView-Cm3RaQ5N.js +0 -1
  152. package/dist/ui/assets/FileMapView-BKJovLcL.js +0 -1
  153. package/dist/ui/assets/FoldersSettings-CuJd2JdE.js +0 -1
  154. package/dist/ui/assets/GezelDetail-D_KIPDhQ.js +0 -1
  155. package/dist/ui/assets/GezellenView-BOOW1QQU.js +0 -1
  156. package/dist/ui/assets/HandboekView-gRzJcIbJ.js +0 -1
  157. package/dist/ui/assets/KnowledgeView-DJ3cJVHA.js +0 -1
  158. package/dist/ui/assets/MlxSettings-45mBFHbA.js +0 -1
  159. package/dist/ui/assets/NewTaskDialog-CIXVunZn.js +0 -2
  160. package/dist/ui/assets/ProjectChat-BiJRweob.js +0 -5
  161. package/dist/ui/assets/ProjectConnectionsTab-CQgaIzuv.js +0 -1
  162. package/dist/ui/assets/ProjectsView-BUdR76n6.js +0 -7
  163. package/dist/ui/assets/SessionSwitcher-BgZqyiRn.js +0 -1
  164. package/dist/ui/assets/SettingsView-DLhOYiR5.js +0 -3
  165. package/dist/ui/assets/TaskTabContent-CG2KmfwV.js +0 -1
  166. package/dist/ui/assets/TasksView-Dy5Ue4zS.js +0 -1
  167. package/dist/ui/assets/ToolsetsEditor-J9XxQ5Ms.js +0 -8
  168. package/dist/ui/assets/chat-thread-memory-CI2-giEq.js +0 -1
  169. package/dist/ui/assets/chunk-IIQYS2YH-DEkyBlHg.js +0 -1
  170. package/dist/ui/assets/csv-B0D9jJG2.js +0 -1
  171. package/dist/ui/assets/data-BIL84EaT.js +0 -1
  172. package/dist/ui/assets/dist-CJqyWK6E.js +0 -2
  173. package/dist/ui/assets/dist-DOqbRmFj.js +0 -225
  174. package/dist/ui/assets/doc-C2Ph2FWI.js +0 -584
  175. package/dist/ui/assets/document-companion-aDThLOwl.js +0 -1
  176. package/dist/ui/assets/file-browser-DVyWN0LD.js +0 -5
  177. package/dist/ui/assets/icons-DWaUNQbT.js +0 -1
  178. package/dist/ui/assets/index-DDu8nyO6.js +0 -34
  179. package/dist/ui/assets/index-DEDUSiCx.css +0 -1
  180. package/dist/ui/assets/markdown-baseline-9B52XlX2.js +0 -1
  181. package/dist/ui/assets/materialize-G4WC5UG3-BlZQe-88.js +0 -1
  182. package/dist/ui/assets/outside-in-BmIIeMid.js +0 -3
  183. package/dist/ui/assets/storage-B-vhjyV2.js +0 -1
  184. package/dist/ui/assets/styles-BvkZd-EV.js +0 -550
  185. package/dist/ui/assets/styles-IQ4adxWr.css +0 -1
@@ -19,6 +19,8 @@ If the experience should live inside a Gezel project as a custom crew, dashboard
19
19
 
20
20
  The [Connected apps](../conceptual/connected-apps.md) article explains what the user sees. This article covers the developer side.
21
21
 
22
+ This article teaches the SDK. For what is promised rather than how to use it — which exports are stable, what cancellation guarantees, and what a store build must do differently — see the [App SDK surface](../../app-sdk-surface.md) contract.
23
+
22
24
  ## Install and connect
23
25
 
24
26
  The Node entry requires Node.js 24 or newer:
@@ -139,6 +141,82 @@ This pairing is the supported route for a rich integration: the app SDK owns dis
139
141
 
140
142
  Ordinary third-party apps should ask the user to start Gezel when discovery reports `daemon_not_running`. The optional start-if-missing path is only for native integrations that deliberately bundle the matching `gezeld` package.
141
143
 
144
+ ## Host Gezel inside your app
145
+
146
+ The flow above needs a Gezel the person already runs. An application that must
147
+ work either way can host one itself: `@bendyline/gezel-app-sdk/host` connects to
148
+ their Gezel when it is running, and otherwise starts a daemon inside your own
149
+ process. Application code is the same afterwards.
150
+
151
+ ```ts
152
+ import { connectOrHost } from '@bendyline/gezel-app-sdk/host';
153
+
154
+ const gezel = await connectOrHost({
155
+ appId: 'acme.travel',
156
+ appName: 'Acme Travel',
157
+ host: { nodePath: bundledNodePath },
158
+ });
159
+
160
+ await gezel.ensureModel({ model: 'gemma4-e2b-q4' });
161
+ const project = await gezel.ensureProject({ package: shippedGezapp, folder: travelFolder });
162
+ const chat = await project.openChat({ role: 'travel-guide' });
163
+ ```
164
+
165
+ `Gezel` is the central object — the connection, the models, the projects. Most
166
+ work happens in the `GezelProject` it hands back, because chats and tools are
167
+ both project-scoped, and an application that has the project never has to pass
168
+ its id back in. `gezel.openProject(id)` reaches a project that already exists.
169
+
170
+ A hosted daemon keeps its state under `~/.gezel/apps/<appId>/`, so the projects
171
+ and gezels an application creates for itself never appear in the person's own
172
+ workshop, and the two daemons never contend for one runtime directory. Models
173
+ the person already installed are read from their home rather than downloaded
174
+ again.
175
+
176
+ Both `ensureModel` and `ensureProject` are idempotent and meant to run on every
177
+ launch. `ensureModel` uses an installed model first, then a `.gezmodel` bundle
178
+ the application ships, and only then the network — so a first run can work
179
+ offline. `ensureProject` keeps the person's edits to seeded files and reuses the
180
+ crew already on the roster.
181
+
182
+ Hosting requires `@bendyline/gezel-service` beside the SDK; it is an optional
183
+ peer dependency, so applications that only connect never download it. Under
184
+ Electron, pass a real Node binary as `host.nodePath`: Gezel runs its tool server
185
+ as a child process, and an Electron binary cannot stand in for Node.
186
+
187
+ ## Tools your application runs
188
+
189
+ An application can offer its own tools to the gezels in its project. The model
190
+ sees them beside Gezel's built-in tools; when one is called, the handler runs in
191
+ the application's process and what it returns becomes the tool's output.
192
+
193
+ ```ts
194
+ await project.registerTools({
195
+ tools: [
196
+ {
197
+ name: 'add_travel_points',
198
+ description: 'Award travel points to the traveller.',
199
+ inputSchema: {
200
+ type: 'object',
201
+ properties: { points: { type: 'number' } },
202
+ required: ['points'],
203
+ },
204
+ handler: async ({ points }) => awardPoints(Number(points)),
205
+ },
206
+ ],
207
+ });
208
+ ```
209
+
210
+ The registration lives as long as the connection that made it. A brief
211
+ disconnection is held open for a grace window and reconnects on its own; a
212
+ closed application's tools are withdrawn, because a tool whose handler is gone
213
+ would accept a call and never answer it. Arguments are checked against the
214
+ declared schema before they leave the daemon, a handler that throws is reported
215
+ to the model as an ordinary tool failure, and each call has a timeout the
216
+ application sets. Tool calls appear in the transcript and the history log like
217
+ any other tool. This needs the `product` scope, or a daemon the application
218
+ hosts.
219
+
142
220
  ## TLS, browsers, and errors
143
221
 
144
222
  The local daemon uses a per-launch self-signed certificate. The Node SDK reads the public certificate from Gezel's runtime directory and constructs a pinned `fetch`, so you should not disable TLS verification globally or replace the transport with an unpinned client.
@@ -1,14 +1,14 @@
1
1
  ---
2
- id: whats-new/1.26250
3
- title: 1.26250 — 7 September 2026
4
- order: -26250
2
+ id: whats-new/1.26251
3
+ title: 1.26251 — 8 September 2026
4
+ order: -26251
5
5
  summary: Engines that reserve memory instead of colliding, llama.cpp v0.4 loading controls, GLM 5.3 on DwarfStar, and catalogs built from a folder of Markdown.
6
6
  ogHeadline: Engines stop fighting over memory
7
7
  ---
8
8
 
9
- # 1.26250 — 7 September 2026
9
+ # 1.26251 — 8 September 2026
10
10
 
11
- Three days after **1.26247**, and this one lives mostly under the floor. The visible half is a set of new controls over how a local model loads; the invisible half is the reason those controls are now safe to use.
11
+ Four days after **1.26247**, and this one lives mostly under the floor. The visible half is a set of new controls over how a local model loads; the invisible half is the reason those controls are now safe to use.
12
12
 
13
13
  If you read only one thing: when two things on your machine both want the memory, they now take turns instead of colliding.
14
14
 
@@ -4,7 +4,7 @@
4
4
  import { parentPort } from "worker_threads";
5
5
 
6
6
  // src/index-store/content-indexer.ts
7
- import { readFile as readFile3, readdir as readdir2, rm as rm4, stat as stat3 } from "fs/promises";
7
+ import { readFile as readFile3, readdir as readdir2, rm as rm5, stat as stat4 } from "fs/promises";
8
8
  import { extname as extname3, join as join10 } from "path";
9
9
  import { createLogger as createLogger6, nowIso as nowIso2 } from "@bendyline/gezel";
10
10
  import { PROJECT_SHADOW_DIR_NAME as PROJECT_SHADOW_DIR_NAME2, projectLocalIndexDbFile } from "@bendyline/gezel/paths";
@@ -343,7 +343,7 @@ async function runGit(args, opts = {}) {
343
343
  "credential.interactive=false",
344
344
  ...cleanedArgs
345
345
  ];
346
- return new Promise((resolve3, reject) => {
346
+ return new Promise((resolve4, reject) => {
347
347
  const hasStdinPayload = opts.stdin !== void 0;
348
348
  const child = hasStdinPayload ? spawn("git", gitArgs, {
349
349
  cwd: opts.cwd,
@@ -398,11 +398,11 @@ async function runGit(args, opts = {}) {
398
398
  return;
399
399
  }
400
400
  if (code === 0) {
401
- resolve3({ stdout, stderr });
401
+ resolve4({ stdout, stderr });
402
402
  return;
403
403
  }
404
404
  if (code !== null && opts.acceptExitCodes?.includes(code)) {
405
- resolve3({ stdout, stderr, code });
405
+ resolve4({ stdout, stderr, code });
406
406
  return;
407
407
  }
408
408
  reject(
@@ -1205,7 +1205,7 @@ async function resolveNodePermissionFlag(nodeBin) {
1205
1205
  }
1206
1206
  }
1207
1207
  async function readNodeHelp(nodeBin) {
1208
- return await new Promise((resolve3, reject) => {
1208
+ return await new Promise((resolve4, reject) => {
1209
1209
  const child = spawn2(nodeBin, ["--help"], {
1210
1210
  stdio: ["ignore", "pipe", "pipe"],
1211
1211
  env: sandboxEnv(process.env),
@@ -1223,13 +1223,13 @@ async function readNodeHelp(nodeBin) {
1223
1223
  });
1224
1224
  child.once("error", reject);
1225
1225
  child.once("close", (code) => {
1226
- if (code === 0) resolve3(stdout);
1226
+ if (code === 0) resolve4(stdout);
1227
1227
  else reject(new Error(`failed to inspect Node permission support (${code}): ${stderr}`));
1228
1228
  });
1229
1229
  });
1230
1230
  }
1231
1231
  async function runSandboxChild(command, args, opts) {
1232
- return await new Promise((resolve3) => {
1232
+ return await new Promise((resolve4) => {
1233
1233
  const child = spawn2(command, args, {
1234
1234
  cwd: opts.cwd,
1235
1235
  stdio: opts.rpcChannel ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
@@ -1307,7 +1307,7 @@ async function runSandboxChild(command, args, opts) {
1307
1307
  if (timer) clearTimeout(timer);
1308
1308
  const signalSuffix = code === null && signal ? `[process closed by signal ${signal}]
1309
1309
  ` : "";
1310
- resolve3({
1310
+ resolve4({
1311
1311
  exitCode: code ?? -1,
1312
1312
  signal,
1313
1313
  stdout,
@@ -1438,12 +1438,12 @@ async function wrapForPlatform(command, args, ctx) {
1438
1438
  }
1439
1439
  var macSandboxProbe;
1440
1440
  function canApplyMacSandbox() {
1441
- macSandboxProbe ??= new Promise((resolve3) => {
1441
+ macSandboxProbe ??= new Promise((resolve4) => {
1442
1442
  let settled = false;
1443
1443
  const finish = (ok) => {
1444
1444
  if (settled) return;
1445
1445
  settled = true;
1446
- resolve3(ok);
1446
+ resolve4(ok);
1447
1447
  };
1448
1448
  const child = spawn2("sandbox-exec", ["-p", "(version 1)\n(allow default)", "/usr/bin/true"], {
1449
1449
  stdio: ["ignore", "ignore", "ignore"],
@@ -1465,12 +1465,12 @@ function canApplyMacSandbox() {
1465
1465
  var linuxSystemdSandboxProbe;
1466
1466
  function canApplyLinuxSystemdSandbox() {
1467
1467
  if (process.platform !== "linux") return Promise.resolve(false);
1468
- linuxSystemdSandboxProbe ??= new Promise((resolve3) => {
1468
+ linuxSystemdSandboxProbe ??= new Promise((resolve4) => {
1469
1469
  let settled = false;
1470
1470
  const finish = (ok) => {
1471
1471
  if (settled) return;
1472
1472
  settled = true;
1473
- resolve3(ok);
1473
+ resolve4(ok);
1474
1474
  };
1475
1475
  const probe = "const net=require('node:net');const s=net.connect({host:'127.0.0.1',port:9});s.once('connect',()=>process.exit(9));s.once('error',e=>process.exit(['EAFNOSUPPORT','EPERM','EACCES'].includes(e.code)?0:2));setTimeout(()=>process.exit(3),1000);";
1476
1476
  const child = spawn2(
@@ -2193,7 +2193,7 @@ import {
2193
2193
  } from "@bendyline/gezel";
2194
2194
 
2195
2195
  // src/memory/embed-core.ts
2196
- import { createHash as createHash3 } from "crypto";
2196
+ import { createHash as createHash4 } from "crypto";
2197
2197
  import { createLogger as createLogger3 } from "@bendyline/gezel";
2198
2198
  import {
2199
2199
  EmbedderUnavailableError,
@@ -2204,10 +2204,13 @@ import {
2204
2204
  } from "@bendyline/gezel-knowledge";
2205
2205
 
2206
2206
  // src/transformers-cache.ts
2207
- import { mkdir as mkdir3 } from "fs/promises";
2208
- import { join as join8 } from "path";
2207
+ import { createHash as createHash3 } from "crypto";
2208
+ import { mkdir as mkdir3, rm as rm4, stat as stat3, writeFile as writeFile5 } from "fs/promises";
2209
+ import { dirname as dirname6, join as join8, resolve as resolve3 } from "path";
2209
2210
  import { createLogger as createLogger2 } from "@bendyline/gezel";
2210
2211
  var log2 = createLogger2("service");
2212
+ var DEFAULT_MODEL_LOCK_TIMEOUT_MS = 10 * 60 * 1e3;
2213
+ var DEFAULT_MODEL_LOCK_STALE_MS = 2 * 60 * 60 * 1e3;
2211
2214
 
2212
2215
  // src/memory/embed-core.ts
2213
2216
  var log3 = createLogger3("memory");
@@ -2229,7 +2232,7 @@ function passageInstruction() {
2229
2232
  return "";
2230
2233
  }
2231
2234
  function embedProfileId() {
2232
- const sha8 = (s) => createHash3("sha256").update(s, "utf8").digest("hex").slice(0, 8);
2235
+ const sha8 = (s) => createHash4("sha256").update(s, "utf8").digest("hex").slice(0, 8);
2233
2236
  const dim = Number(process.env.GEZEL_EMBED_DIM) || 384;
2234
2237
  return `${embedModelId()}|d${dim}|mean|norm|q:${sha8(queryInstruction())}|p:${sha8(passageInstruction())}`;
2235
2238
  }
@@ -2256,6 +2259,138 @@ function imageEmbedModelId() {
2256
2259
  return process.env.GEZEL_IMAGE_EMBED_MODEL || DEFAULT_IMAGE_EMBED_MODEL;
2257
2260
  }
2258
2261
 
2262
+ // src/index-store/query-terms.ts
2263
+ var QUERY_STOP_WORDS = /* @__PURE__ */ new Set([
2264
+ // articles + determiners
2265
+ "a",
2266
+ "an",
2267
+ "the",
2268
+ "this",
2269
+ "that",
2270
+ "these",
2271
+ "those",
2272
+ "some",
2273
+ "any",
2274
+ "all",
2275
+ "each",
2276
+ "both",
2277
+ "every",
2278
+ "other",
2279
+ "another",
2280
+ "same",
2281
+ "such",
2282
+ // pronouns
2283
+ "i",
2284
+ "me",
2285
+ "my",
2286
+ "we",
2287
+ "us",
2288
+ "our",
2289
+ "you",
2290
+ "your",
2291
+ "it",
2292
+ "its",
2293
+ "he",
2294
+ "him",
2295
+ "his",
2296
+ "she",
2297
+ "her",
2298
+ "they",
2299
+ "them",
2300
+ "their",
2301
+ // be / have / do
2302
+ "am",
2303
+ "is",
2304
+ "are",
2305
+ "was",
2306
+ "were",
2307
+ "be",
2308
+ "been",
2309
+ "being",
2310
+ "have",
2311
+ "has",
2312
+ "had",
2313
+ "do",
2314
+ "does",
2315
+ "did",
2316
+ "done",
2317
+ // modals
2318
+ "can",
2319
+ "could",
2320
+ "will",
2321
+ "would",
2322
+ "shall",
2323
+ "should",
2324
+ "may",
2325
+ "might",
2326
+ "must",
2327
+ // question words
2328
+ "how",
2329
+ "what",
2330
+ "when",
2331
+ "where",
2332
+ "which",
2333
+ "who",
2334
+ "whom",
2335
+ "why",
2336
+ // prepositions + conjunctions
2337
+ "about",
2338
+ "and",
2339
+ "as",
2340
+ "at",
2341
+ "but",
2342
+ "by",
2343
+ "for",
2344
+ "from",
2345
+ "if",
2346
+ "in",
2347
+ "into",
2348
+ "of",
2349
+ "on",
2350
+ "or",
2351
+ "so",
2352
+ "than",
2353
+ "then",
2354
+ "there",
2355
+ "to",
2356
+ "with",
2357
+ // request scaffolding + degree words
2358
+ "please",
2359
+ "help",
2360
+ "let",
2361
+ "tell",
2362
+ "want",
2363
+ "need",
2364
+ "create",
2365
+ "make",
2366
+ "give",
2367
+ "get",
2368
+ "got",
2369
+ "use",
2370
+ "using",
2371
+ "just",
2372
+ "like",
2373
+ "also",
2374
+ "very",
2375
+ "only",
2376
+ "new",
2377
+ "more",
2378
+ "most",
2379
+ "much",
2380
+ "many",
2381
+ "few",
2382
+ "own"
2383
+ ]);
2384
+ var MAX_QUERY_TERMS = 16;
2385
+ function tokenizeText(text) {
2386
+ return text.normalize("NFKC").toLocaleLowerCase().match(/[\p{L}\p{N}_]+/gu) ?? [];
2387
+ }
2388
+ function queryTerms(text) {
2389
+ const unique = [...new Set(tokenizeText(text))].slice(0, MAX_QUERY_TERMS);
2390
+ const meaningful = unique.filter((token) => !QUERY_STOP_WORDS.has(token));
2391
+ return meaningful.length > 0 ? meaningful : unique;
2392
+ }
2393
+
2259
2394
  // src/index-store/review-claims.ts
2260
2395
  var TRUNCATION_CLAIM_RES = [
2261
2396
  /truncat/i,
@@ -2790,7 +2925,7 @@ function applySchema(db, opts = {}) {
2790
2925
  // src/index-store/sqlite-driver.ts
2791
2926
  import { mkdir as mkdir4, rename as rename2 } from "fs/promises";
2792
2927
  import { createRequire as createRequire3 } from "module";
2793
- import { dirname as dirname6 } from "path";
2928
+ import { dirname as dirname7 } from "path";
2794
2929
  import { createLogger as createLogger5 } from "@bendyline/gezel";
2795
2930
  var nodeRequire = createRequire3(import.meta.url);
2796
2931
  var log5 = createLogger5("sqlite");
@@ -2813,7 +2948,7 @@ async function openIndexDatabase(dbPath) {
2813
2948
  }
2814
2949
  if (dbPath !== ":memory:") {
2815
2950
  try {
2816
- await mkdir4(dirname6(dbPath), { recursive: true });
2951
+ await mkdir4(dirname7(dbPath), { recursive: true });
2817
2952
  } catch (error) {
2818
2953
  if (isUnavailableIndexError(error)) return null;
2819
2954
  throw error;
@@ -2927,29 +3062,6 @@ var VECTOR_ARM_MIN_SIMILARITY = 0.55;
2927
3062
  function symbolId(filePath, name) {
2928
3063
  return `${filePath}#${name}`;
2929
3064
  }
2930
- var FTS_STOP_WORDS = /* @__PURE__ */ new Set([
2931
- "a",
2932
- "an",
2933
- "and",
2934
- "are",
2935
- "for",
2936
- "how",
2937
- "in",
2938
- "is",
2939
- "me",
2940
- "my",
2941
- "of",
2942
- "on",
2943
- "or",
2944
- "our",
2945
- "please",
2946
- "the",
2947
- "to",
2948
- "we",
2949
- "with",
2950
- "you",
2951
- "your"
2952
- ]);
2953
3065
  function ftsPhrase(query) {
2954
3066
  const normalized = query.normalize("NFKC");
2955
3067
  const explicitlyQuoted = normalized.match(/^\s*"([^"]+)"\s*$/u);
@@ -2957,10 +3069,7 @@ function ftsPhrase(query) {
2957
3069
  const phrase = explicitlyQuoted[1]?.match(/[\p{L}\p{N}_]+/gu)?.join(" ") ?? "";
2958
3070
  return phrase ? `"${phrase.replace(/"/g, '""')}"` : '"__gezel_no_match__"';
2959
3071
  }
2960
- const raw = normalized.match(/[\p{L}\p{N}_]+/gu) ?? [];
2961
- const unique = [...new Set(raw.map((token) => token.toLocaleLowerCase()))].slice(0, 16);
2962
- const meaningful = unique.filter((token) => !FTS_STOP_WORDS.has(token));
2963
- const tokens = meaningful.length > 0 ? meaningful : unique;
3072
+ const tokens = queryTerms(normalized);
2964
3073
  if (tokens.length === 0) return '"__gezel_no_match__"';
2965
3074
  return tokens.map((token) => `"${token.replace(/"/g, '""')}"${token.length >= 3 ? "*" : ""}`).join(" OR ");
2966
3075
  }
@@ -5296,7 +5405,7 @@ function parseBindings(raw) {
5296
5405
 
5297
5406
  // src/index-store/symbols.ts
5298
5407
  import { createRequire as createRequire4 } from "module";
5299
- import { dirname as dirname7, join as join9 } from "path";
5408
+ import { dirname as dirname8, join as join9 } from "path";
5300
5409
  var nodeRequire2 = createRequire4(import.meta.url);
5301
5410
  var SIG_CAP = 160;
5302
5411
  var GRAMMAR_FILE = {
@@ -5369,7 +5478,7 @@ async function ensureInit() {
5369
5478
  initPromise = (async () => {
5370
5479
  try {
5371
5480
  const mod = nodeRequire2("web-tree-sitter");
5372
- const wtsDir = dirname7(nodeRequire2.resolve("web-tree-sitter"));
5481
+ const wtsDir = dirname8(nodeRequire2.resolve("web-tree-sitter"));
5373
5482
  await mod.Parser.init({ locateFile: (f) => join9(wtsDir, f) });
5374
5483
  ParserCtor = mod.Parser;
5375
5484
  LanguageMod = mod.Language;
@@ -5381,7 +5490,7 @@ async function ensureInit() {
5381
5490
  return initPromise;
5382
5491
  }
5383
5492
  function grammarDir() {
5384
- return join9(dirname7(nodeRequire2.resolve("tree-sitter-wasms/package.json")), "out");
5493
+ return join9(dirname8(nodeRequire2.resolve("tree-sitter-wasms/package.json")), "out");
5385
5494
  }
5386
5495
  async function loadLanguage(langId) {
5387
5496
  const file = GRAMMAR_FILE[langId];
@@ -5832,7 +5941,7 @@ async function indexWorkspaceContent(store, workspaceDir, artifactsDir, opts = {
5832
5941
  store.upsertFile(record);
5833
5942
  if (!convertible) continue;
5834
5943
  const paths = shadowDocFilesPaths(artifactsDir, file.path);
5835
- const sidecarPresent = paths ? await stat3(paths.mdPath).then(
5944
+ const sidecarPresent = paths ? await stat4(paths.mdPath).then(
5836
5945
  (s) => s.isFile(),
5837
5946
  () => false
5838
5947
  ) : true;
@@ -5951,7 +6060,7 @@ async function indexWorkspaceContent(store, workspaceDir, artifactsDir, opts = {
5951
6060
  stats.removed++;
5952
6061
  if (isConvertibleDoc(extname3(f.path))) {
5953
6062
  const paths = shadowDocFilesPaths(artifactsDir, f.path);
5954
- if (paths) await rm4(paths.dir, { recursive: true, force: true }).catch(() => {
6063
+ if (paths) await rm5(paths.dir, { recursive: true, force: true }).catch(() => {
5955
6064
  });
5956
6065
  }
5957
6066
  }
@@ -5981,7 +6090,7 @@ async function sweepShadowOrphans(artifactsDir, seen) {
5981
6090
  if (e.name.endsWith("_files")) {
5982
6091
  const sourceRel = childRel.slice(0, -"_files".length);
5983
6092
  if (!seen.has(sourceRel)) {
5984
- await rm4(join10(shadowRoot, childRel), { recursive: true, force: true }).catch(() => {
6093
+ await rm5(join10(shadowRoot, childRel), { recursive: true, force: true }).catch(() => {
5985
6094
  });
5986
6095
  }
5987
6096
  } else {