@modular-prompt/driver 0.15.0 → 0.17.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 (198) hide show
  1. package/README.md +124 -9
  2. package/dist/cache-controller.d.ts +4 -0
  3. package/dist/cache-controller.d.ts.map +1 -1
  4. package/dist/driver-registry/config-based-factory.d.ts.map +1 -1
  5. package/dist/driver-registry/config-based-factory.js +10 -3
  6. package/dist/driver-registry/config-based-factory.js.map +1 -1
  7. package/dist/driver-registry/factory-helper.d.ts.map +1 -1
  8. package/dist/driver-registry/factory-helper.js +10 -2
  9. package/dist/driver-registry/factory-helper.js.map +1 -1
  10. package/dist/driver-registry/index.d.ts +1 -1
  11. package/dist/driver-registry/index.d.ts.map +1 -1
  12. package/dist/driver-registry/types.d.ts +18 -1
  13. package/dist/driver-registry/types.d.ts.map +1 -1
  14. package/dist/formatter/converter.d.ts.map +1 -1
  15. package/dist/formatter/converter.js +31 -2
  16. package/dist/formatter/converter.js.map +1 -1
  17. package/dist/index.d.ts +5 -3
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +5 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/local-inference/adapters.d.ts +6 -0
  22. package/dist/local-inference/adapters.d.ts.map +1 -1
  23. package/dist/local-inference/driver.d.ts.map +1 -1
  24. package/dist/local-inference/driver.js +45 -24
  25. package/dist/local-inference/driver.js.map +1 -1
  26. package/dist/local-inference/process-client.d.ts +4 -2
  27. package/dist/local-inference/process-client.d.ts.map +1 -1
  28. package/dist/local-inference/process-client.js +24 -8
  29. package/dist/local-inference/process-client.js.map +1 -1
  30. package/dist/local-inference/process-communication.d.ts +9 -2
  31. package/dist/local-inference/process-communication.d.ts.map +1 -1
  32. package/dist/local-inference/process-communication.js +37 -5
  33. package/dist/local-inference/process-communication.js.map +1 -1
  34. package/dist/local-inference/protocol.d.ts +4 -0
  35. package/dist/local-inference/protocol.d.ts.map +1 -1
  36. package/dist/local-inference/request-queue.d.ts +1 -1
  37. package/dist/local-inference/request-queue.d.ts.map +1 -1
  38. package/dist/local-inference/request-queue.js +26 -7
  39. package/dist/local-inference/request-queue.js.map +1 -1
  40. package/dist/local-inference/stream-utils.d.ts +6 -0
  41. package/dist/local-inference/stream-utils.d.ts.map +1 -1
  42. package/dist/local-inference/stream-utils.js.map +1 -1
  43. package/dist/mlx-ml/mlx-cache-controller.d.ts +9 -0
  44. package/dist/mlx-ml/mlx-cache-controller.d.ts.map +1 -1
  45. package/dist/mlx-ml/mlx-cache-controller.js +158 -32
  46. package/dist/mlx-ml/mlx-cache-controller.js.map +1 -1
  47. package/dist/mlx-ml/mlx-cache-support.d.ts +2 -2
  48. package/dist/mlx-ml/mlx-cache-support.d.ts.map +1 -1
  49. package/dist/mlx-ml/mlx-cache-support.js +8 -3
  50. package/dist/mlx-ml/mlx-cache-support.js.map +1 -1
  51. package/dist/mlx-ml/mlx-driver.d.ts +0 -1
  52. package/dist/mlx-ml/mlx-driver.d.ts.map +1 -1
  53. package/dist/mlx-ml/mlx-driver.js +1 -8
  54. package/dist/mlx-ml/mlx-driver.js.map +1 -1
  55. package/dist/mlx-ml/process/index.d.ts +1 -1
  56. package/dist/mlx-ml/process/index.d.ts.map +1 -1
  57. package/dist/mlx-ml/process/index.js +2 -2
  58. package/dist/mlx-ml/process/index.js.map +1 -1
  59. package/dist/models-config/index.d.ts +2 -2
  60. package/dist/models-config/index.d.ts.map +1 -1
  61. package/dist/models-config/index.js +2 -2
  62. package/dist/models-config/index.js.map +1 -1
  63. package/dist/models-config/paths.d.ts +8 -0
  64. package/dist/models-config/paths.d.ts.map +1 -1
  65. package/dist/models-config/paths.js +16 -1
  66. package/dist/models-config/paths.js.map +1 -1
  67. package/dist/models-config/resolve.d.ts +10 -2
  68. package/dist/models-config/resolve.d.ts.map +1 -1
  69. package/dist/models-config/resolve.js +119 -6
  70. package/dist/models-config/resolve.js.map +1 -1
  71. package/dist/models-config/types.d.ts +5 -1
  72. package/dist/models-config/types.d.ts.map +1 -1
  73. package/dist/pytorch/process/index.d.ts +4 -2
  74. package/dist/pytorch/process/index.d.ts.map +1 -1
  75. package/dist/pytorch/process/index.js +24 -7
  76. package/dist/pytorch/process/index.js.map +1 -1
  77. package/dist/pytorch/pytorch-cache-controller.d.ts +84 -0
  78. package/dist/pytorch/pytorch-cache-controller.d.ts.map +1 -0
  79. package/dist/pytorch/pytorch-cache-controller.js +742 -0
  80. package/dist/pytorch/pytorch-cache-controller.js.map +1 -0
  81. package/dist/pytorch/pytorch-cache-support.d.ts +23 -0
  82. package/dist/pytorch/pytorch-cache-support.d.ts.map +1 -0
  83. package/dist/pytorch/pytorch-cache-support.js +47 -0
  84. package/dist/pytorch/pytorch-cache-support.js.map +1 -0
  85. package/dist/pytorch/pytorch-driver.d.ts +8 -1
  86. package/dist/pytorch/pytorch-driver.d.ts.map +1 -1
  87. package/dist/pytorch/pytorch-driver.js +40 -0
  88. package/dist/pytorch/pytorch-driver.js.map +1 -1
  89. package/dist/runtime/check.d.ts.map +1 -1
  90. package/dist/runtime/check.js +9 -6
  91. package/dist/runtime/check.js.map +1 -1
  92. package/dist/runtime/index.d.ts +2 -1
  93. package/dist/runtime/index.d.ts.map +1 -1
  94. package/dist/runtime/index.js +2 -1
  95. package/dist/runtime/index.js.map +1 -1
  96. package/dist/runtime/manifest-core.d.mts +1 -0
  97. package/dist/runtime/manifest-core.mjs +1 -0
  98. package/dist/runtime/manifest-core.mjs.map +1 -1
  99. package/dist/runtime/manifest.d.ts +2 -0
  100. package/dist/runtime/manifest.d.ts.map +1 -1
  101. package/dist/runtime/manifest.js.map +1 -1
  102. package/dist/runtime/paths-core.d.mts +15 -1
  103. package/dist/runtime/paths-core.d.mts.map +1 -1
  104. package/dist/runtime/paths-core.mjs +50 -5
  105. package/dist/runtime/paths-core.mjs.map +1 -1
  106. package/dist/runtime/paths.d.ts +2 -2
  107. package/dist/runtime/paths.d.ts.map +1 -1
  108. package/dist/runtime/paths.js +2 -2
  109. package/dist/runtime/paths.js.map +1 -1
  110. package/dist/runtime/pytorch-template-core.d.mts +11 -0
  111. package/dist/runtime/pytorch-template-core.d.mts.map +1 -0
  112. package/dist/runtime/pytorch-template-core.mjs +54 -0
  113. package/dist/runtime/pytorch-template-core.mjs.map +1 -0
  114. package/dist/runtime/setup-commands-core.d.mts +16 -0
  115. package/dist/runtime/setup-commands-core.d.mts.map +1 -0
  116. package/dist/runtime/setup-commands-core.mjs +18 -0
  117. package/dist/runtime/setup-commands-core.mjs.map +1 -0
  118. package/dist/runtime/setup-commands.d.ts +2 -0
  119. package/dist/runtime/setup-commands.d.ts.map +1 -0
  120. package/dist/runtime/setup-commands.js +2 -0
  121. package/dist/runtime/setup-commands.js.map +1 -0
  122. package/docs/DRIVER_API.md +455 -0
  123. package/docs/LOCAL_MODEL_SETUP.md +765 -0
  124. package/docs/mlx-api-selection.md +301 -0
  125. package/package.json +12 -5
  126. package/scripts/download-model.js +3 -2
  127. package/scripts/runtime-cli.bin.test.ts +142 -0
  128. package/scripts/runtime-cli.js +322 -47
  129. package/scripts/runtime-cli.test.ts +163 -0
  130. package/src/mlx-ml/python/__main__.py +1 -1
  131. package/src/mlx-ml/python/backends/base.py +88 -18
  132. package/src/mlx-ml/python/backends/cache_archive.py +41 -0
  133. package/src/mlx-ml/python/backends/mlx_lm.py +45 -4
  134. package/src/mlx-ml/python/backends/mlx_vlm.py +679 -2
  135. package/src/mlx-ml/python/handlers/cache.py +4 -0
  136. package/src/mlx-ml/python/handlers/generate.py +33 -10
  137. package/src/mlx-ml/python/handlers/tokenize.py +1 -4
  138. package/src/mlx-ml/python/pyproject.toml +9 -3
  139. package/src/mlx-ml/python/server.py +2 -0
  140. package/src/mlx-ml/python/uv.lock +193 -433
  141. package/src/pytorch/templates/cpu-minimal/backends/base.py +139 -0
  142. package/src/pytorch/templates/cpu-minimal/backends/transformers_lm.py +1167 -0
  143. package/src/pytorch/{python → templates/cpu-minimal}/handlers/__init__.py +1 -0
  144. package/src/pytorch/templates/cpu-minimal/handlers/cache.py +88 -0
  145. package/src/pytorch/templates/cpu-minimal/handlers/generate.py +157 -0
  146. package/src/pytorch/{python → templates/cpu-minimal}/pyproject.toml +2 -2
  147. package/src/pytorch/{python → templates/cpu-minimal}/server.py +20 -2
  148. package/src/pytorch/templates/cpu-minimal/tests/test_cache_handler.py +284 -0
  149. package/src/pytorch/templates/cpu-minimal/tests/test_capabilities.py +14 -0
  150. package/src/pytorch/templates/cpu-minimal/tests/test_server.py +141 -0
  151. package/src/pytorch/templates/cpu-minimal/tests/test_transformers_errors.py +89 -0
  152. package/src/pytorch/templates/cpu-minimal/tests/test_transformers_lm_cache.py +554 -0
  153. package/src/pytorch/templates/cpu-minimal/utils/__init__.py +0 -0
  154. package/src/pytorch/{python → templates/cpu-minimal}/utils/token_utils.py +2 -2
  155. package/src/pytorch/templates/cpu-minimal/utils/transformers_errors.py +54 -0
  156. package/src/pytorch/{python → templates/cpu-minimal}/uv.lock +149 -109
  157. package/src/pytorch/templates/cuda/__main__.py +19 -0
  158. package/src/pytorch/templates/cuda/backends/__init__.py +3 -0
  159. package/src/pytorch/{python → templates/cuda}/backends/base.py +54 -6
  160. package/src/pytorch/templates/cuda/backends/transformers_lm.py +379 -0
  161. package/src/pytorch/templates/cuda/handlers/__init__.py +7 -0
  162. package/src/pytorch/templates/cuda/handlers/cache.py +93 -0
  163. package/src/pytorch/templates/cuda/handlers/cancel.py +53 -0
  164. package/src/pytorch/templates/cuda/handlers/capabilities.py +6 -0
  165. package/src/pytorch/templates/cuda/handlers/completion.py +15 -0
  166. package/src/pytorch/templates/cuda/handlers/format_test.py +70 -0
  167. package/src/pytorch/templates/cuda/handlers/generate.py +152 -0
  168. package/src/pytorch/templates/cuda/handlers/render.py +40 -0
  169. package/src/pytorch/templates/cuda/handlers/tokenize.py +63 -0
  170. package/src/pytorch/templates/cuda/pyproject.toml +37 -0
  171. package/src/pytorch/templates/cuda/server.py +158 -0
  172. package/src/pytorch/templates/cuda/tests/__init__.py +0 -0
  173. package/src/pytorch/templates/cuda/tests/test_cache_handler.py +207 -0
  174. package/src/pytorch/templates/cuda/tests/test_capabilities.py +14 -0
  175. package/src/pytorch/templates/cuda/tests/test_server.py +145 -0
  176. package/src/pytorch/templates/cuda/tests/test_transformers_errors.py +89 -0
  177. package/src/pytorch/templates/cuda/tests/test_transformers_lm_cache.py +288 -0
  178. package/src/pytorch/templates/cuda/utils/__init__.py +0 -0
  179. package/src/pytorch/templates/cuda/utils/chat_template_constraints.py +164 -0
  180. package/src/pytorch/templates/cuda/utils/prompt_builder.py +54 -0
  181. package/src/pytorch/templates/cuda/utils/template_render.py +80 -0
  182. package/src/pytorch/templates/cuda/utils/token_utils.py +376 -0
  183. package/src/pytorch/templates/cuda/utils/transformers_errors.py +54 -0
  184. package/src/pytorch/templates/cuda/uv.lock +734 -0
  185. package/src/pytorch/python/backends/transformers_lm.py +0 -127
  186. package/src/pytorch/python/handlers/generate.py +0 -68
  187. /package/src/pytorch/{python → templates/cpu-minimal}/__main__.py +0 -0
  188. /package/src/pytorch/{python → templates/cpu-minimal}/backends/__init__.py +0 -0
  189. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/cancel.py +0 -0
  190. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/capabilities.py +0 -0
  191. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/completion.py +0 -0
  192. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/format_test.py +0 -0
  193. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/render.py +0 -0
  194. /package/src/pytorch/{python → templates/cpu-minimal}/handlers/tokenize.py +0 -0
  195. /package/src/pytorch/{python/utils → templates/cpu-minimal/tests}/__init__.py +0 -0
  196. /package/src/pytorch/{python → templates/cpu-minimal}/utils/chat_template_constraints.py +0 -0
  197. /package/src/pytorch/{python → templates/cpu-minimal}/utils/prompt_builder.py +0 -0
  198. /package/src/pytorch/{python → templates/cpu-minimal}/utils/template_render.py +0 -0
@@ -0,0 +1,301 @@
1
+ # MLX Driver API Selection
2
+
3
+ MLX Driverは、chat APIとcompletion APIの2つのAPIを提供しています。このドキュメントでは、どちらのAPIを使用するかを決定するロジックと、カスタマイズ方法について説明します。
4
+
5
+ ## デフォルトのAPI選択ロジック
6
+
7
+ `ModelSpecManager.determineApi()`は、以下の順序でAPIを選択します:
8
+
9
+ ### 1. カスタムロジック(最優先)
10
+
11
+ `customProcessor.determineApi()`が提供されている場合、それが最優先されます。
12
+
13
+ ```typescript
14
+ const driver = new MlxDriver({
15
+ model: 'some-model',
16
+ modelSpec: {
17
+ customProcessor: {
18
+ determineApi: (context) => {
19
+ // カスタムロジック
20
+ if (/* 特定の条件 */) {
21
+ return 'completion';
22
+ }
23
+ // デフォルトロジックに委譲
24
+ return undefined;
25
+ }
26
+ }
27
+ }
28
+ });
29
+ ```
30
+
31
+ ### 2. 強制モード
32
+
33
+ `apiStrategy`が`'force-chat'`または`'force-completion'`の場合、その設定が優先されます。
34
+
35
+ ```typescript
36
+ modelSpec: {
37
+ apiStrategy: 'force-completion' // 常にcompletion APIを使用
38
+ }
39
+ ```
40
+
41
+ ### 3. 機能チェック
42
+
43
+ - `hasApplyChatTemplate: false`の場合: completion APIを使用
44
+ - `supportsCompletion: false`の場合: chat APIを使用
45
+
46
+ ### 4. 優先モード
47
+
48
+ #### `prefer-chat`
49
+
50
+ 1. メッセージを検証
51
+ 2. 有効な場合: chat APIを使用
52
+ 3. 無効な場合: completion APIにフォールバック
53
+
54
+ ```typescript
55
+ modelSpec: {
56
+ apiStrategy: 'prefer-chat',
57
+ chatRestrictions: {
58
+ singleSystemAtStart: true,
59
+ requiresUserLast: true
60
+ }
61
+ }
62
+ ```
63
+
64
+ #### `prefer-completion`
65
+
66
+ 常にcompletion APIを使用します。
67
+
68
+ ### 5. `auto`モード(デフォルト)
69
+
70
+ 1. メッセージを検証
71
+ 2. chat制限に違反している場合: completion APIを使用
72
+ 3. chat制限が3個以上の場合: completion APIを使用
73
+ 4. それ以外: chat APIを使用
74
+
75
+ ---
76
+
77
+ ## カスタムAPI選択ロジック
78
+
79
+ `customProcessor.determineApi()`を使用して、独自のロジックを実装できます。
80
+
81
+ ### ApiSelectionContext
82
+
83
+ カスタムロジックには、以下の情報が提供されます:
84
+
85
+ ```typescript
86
+ interface ApiSelectionContext {
87
+ messages: MlxMessage[]; // 処理対象のメッセージ
88
+ validation: ValidationResult; // メッセージの検証結果
89
+ capabilities: { // モデルの機能情報
90
+ hasApplyChatTemplate?: boolean;
91
+ supportsCompletion?: boolean;
92
+ };
93
+ chatRestrictions?: ChatRestrictions; // チャット制限
94
+ apiStrategy: ApiStrategy; // 設定されたapiStrategy
95
+ }
96
+ ```
97
+
98
+ ### 戻り値
99
+
100
+ - `'chat'`: chat APIを使用
101
+ - `'completion'`: completion APIを使用
102
+ - `undefined`: デフォルトロジックに委譲
103
+
104
+ ---
105
+
106
+ ## ヘルパー関数
107
+
108
+ ### createModulerPromptApiSelector()
109
+
110
+ modular-promptの典型的なパターン(system → user → system(cue))に最適化されたセレクター。
111
+
112
+ #### 検出するパターン
113
+
114
+ ```typescript
115
+ [
116
+ { role: 'system', content: 'instructions...' },
117
+ { role: 'user', content: 'input data...' },
118
+ { role: 'system', content: 'Please output in JSON format' } // cue
119
+ ]
120
+ ```
121
+
122
+ #### 問題となる制限
123
+
124
+ - `singleSystemAtStart: true` - systemメッセージは先頭1つのみ
125
+ - `maxSystemMessages: 1` - システムメッセージは1個まで
126
+
127
+ 上記パターンと制限の組み合わせでは、cueメッセージを配置できないため、completion APIを強制します。
128
+
129
+ #### 使用例
130
+
131
+ ```typescript
132
+ import { createModulerPromptApiSelector } from '@modular-prompt/driver/mlx-ml/model-spec';
133
+
134
+ const driver = new MlxDriver({
135
+ model: 'gemma-2-2b-it-4bit',
136
+ modelSpec: {
137
+ customProcessor: {
138
+ determineApi: createModulerPromptApiSelector()
139
+ }
140
+ }
141
+ });
142
+ ```
143
+
144
+ ### createSystemMessageBasedSelector(minSystemMessages)
145
+
146
+ システムメッセージの数に基づくセレクター。
147
+
148
+ #### パラメータ
149
+
150
+ - `minSystemMessages`: この数以上のsystemメッセージがある場合に判定(デフォルト: 2)
151
+
152
+ #### 使用例
153
+
154
+ ```typescript
155
+ import { createSystemMessageBasedSelector } from '@modular-prompt/driver/mlx-ml/model-spec';
156
+
157
+ const driver = new MlxDriver({
158
+ model: 'some-model',
159
+ modelSpec: {
160
+ customProcessor: {
161
+ determineApi: createSystemMessageBasedSelector(3)
162
+ }
163
+ }
164
+ });
165
+ ```
166
+
167
+ ### combineSelectors(selectors)
168
+
169
+ 複数のセレクターを組み合わせるコンビネーター。
170
+
171
+ #### 動作
172
+
173
+ セレクターを順番に実行し、最初に`undefined`以外を返したセレクターの結果を使用します。
174
+
175
+ #### 使用例
176
+
177
+ ```typescript
178
+ import {
179
+ combineSelectors,
180
+ createModulerPromptApiSelector,
181
+ createSystemMessageBasedSelector
182
+ } from '@modular-prompt/driver/mlx-ml/model-spec';
183
+
184
+ const driver = new MlxDriver({
185
+ model: 'some-model',
186
+ modelSpec: {
187
+ customProcessor: {
188
+ determineApi: combineSelectors([
189
+ // 1. modular-promptパターンをチェック
190
+ createModulerPromptApiSelector(),
191
+ // 2. システムメッセージ数をチェック
192
+ createSystemMessageBasedSelector(3),
193
+ // 3. カスタムロジック
194
+ (context) => {
195
+ if (context.messages.length > 100) {
196
+ return 'completion';
197
+ }
198
+ return undefined;
199
+ }
200
+ ])
201
+ }
202
+ }
203
+ });
204
+ ```
205
+
206
+ ---
207
+
208
+ ## ユースケース別の推奨設定
209
+
210
+ ### 1. modular-promptで使用する場合
211
+
212
+ ```typescript
213
+ import { createModulerPromptApiSelector } from '@modular-prompt/driver/mlx-ml/model-spec';
214
+
215
+ const driver = new MlxDriver({
216
+ model: 'gemma-2-2b-it-4bit',
217
+ modelSpec: {
218
+ customProcessor: {
219
+ determineApi: createModulerPromptApiSelector()
220
+ }
221
+ }
222
+ });
223
+ ```
224
+
225
+ ### 2. chat APIを優先したいが、制限違反時はフォールバック
226
+
227
+ ```typescript
228
+ const driver = new MlxDriver({
229
+ model: 'some-model',
230
+ modelSpec: {
231
+ apiStrategy: 'prefer-chat'
232
+ }
233
+ });
234
+ ```
235
+
236
+ ### 3. 常にcompletion APIを使用
237
+
238
+ ```typescript
239
+ const driver = new MlxDriver({
240
+ model: 'some-model',
241
+ modelSpec: {
242
+ apiStrategy: 'force-completion'
243
+ }
244
+ });
245
+ ```
246
+
247
+ ### 4. 完全カスタムロジック
248
+
249
+ ```typescript
250
+ const driver = new MlxDriver({
251
+ model: 'some-model',
252
+ modelSpec: {
253
+ customProcessor: {
254
+ determineApi: (context) => {
255
+ // 独自のロジック
256
+ const systemMessages = context.messages.filter(m => m.role === 'system');
257
+ const hasComplexPattern = systemMessages.length > 2;
258
+
259
+ if (hasComplexPattern && context.chatRestrictions?.singleSystemAtStart) {
260
+ return 'completion';
261
+ }
262
+
263
+ // デフォルトロジックに委譲
264
+ return undefined;
265
+ }
266
+ }
267
+ }
268
+ });
269
+ ```
270
+
271
+ ---
272
+
273
+ ## トラブルシューティング
274
+
275
+ ### chat APIでエラーが発生する
276
+
277
+ **症状**: 「システムメッセージが複数ある」などのエラー
278
+
279
+ **原因**: chat制限に違反している
280
+
281
+ **解決策**:
282
+ 1. `apiStrategy: 'force-completion'`を設定
283
+ 2. または`createModulerPromptApiSelector()`を使用
284
+
285
+ ### completion APIしか使われない
286
+
287
+ **症状**: chat APIを使いたいのにcompletion APIが選択される
288
+
289
+ **原因**: デフォルトロジックがchat制限を厳しいと判断
290
+
291
+ **解決策**:
292
+ 1. `apiStrategy: 'prefer-chat'`を設定
293
+ 2. または`chatRestrictions: undefined`で制限をクリア
294
+
295
+ ---
296
+
297
+ ## 関連ドキュメント
298
+
299
+ - [型定義](../src/mlx-ml/model-spec/types.ts)
300
+ - [ヘルパー関数](../src/mlx-ml/model-spec/helpers.ts)
301
+ - [ModelSpecManager](../src/mlx-ml/model-spec/manager.ts)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modular-prompt/driver",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -15,8 +15,13 @@
15
15
  "scripts",
16
16
  "skills",
17
17
  "src/mlx-ml/python",
18
- "src/pytorch/python"
18
+ "src/pytorch/templates",
19
+ "docs"
19
20
  ],
21
+ "bin": {
22
+ "modular-prompt-runtime": "./scripts/runtime-cli.js",
23
+ "modular-runtime": "./scripts/runtime-cli.js"
24
+ },
20
25
  "dependencies": {
21
26
  "@anthropic-ai/sdk": "0.61.0",
22
27
  "@anthropic-ai/vertex-sdk": "0.14.4",
@@ -54,7 +59,7 @@
54
59
  "directory": "packages/driver"
55
60
  },
56
61
  "scripts": {
57
- "build": "tsc -b --force && cp src/runtime/paths-core.mjs src/runtime/manifest-core.mjs dist/runtime/",
62
+ "build": "tsc -b --force && cp src/runtime/paths-core.mjs src/runtime/manifest-core.mjs src/runtime/setup-commands-core.mjs src/runtime/pytorch-template-core.mjs dist/runtime/",
58
63
  "test": "vitest",
59
64
  "test:run": "vitest run",
60
65
  "test:system": "vitest run --config vitest.config.system.ts",
@@ -63,10 +68,12 @@
63
68
  "lint": "eslint src/**/*.ts",
64
69
  "typecheck": "tsc --noEmit",
65
70
  "copy-skills": "mkdir -p skills/driver-usage && cp ../../skills/driver-usage/SKILL.md skills/driver-usage/SKILL.md",
66
- "clean": "rm -rf dist skills tsconfig.tsbuildinfo",
71
+ "clean": "rm -rf dist skills docs tsconfig.tsbuildinfo",
67
72
  "setup-mlx": "node scripts/runtime-cli.js setup mlx",
68
73
  "setup-pytorch": "node scripts/runtime-cli.js setup pytorch",
69
74
  "runtime:status": "node scripts/runtime-cli.js setup --status",
70
- "runtime:cleanup": "node scripts/runtime-cli.js cleanup"
75
+ "runtime:sync-pytorch": "node scripts/runtime-cli.js sync pytorch",
76
+ "runtime:cleanup": "node scripts/runtime-cli.js cleanup",
77
+ "copy-docs": "node ../../scripts/copy-package-docs.mjs driver"
71
78
  }
72
79
  }
@@ -15,19 +15,20 @@ function runtimeModuleUrl(name) {
15
15
  }
16
16
 
17
17
  const { getMlxPythonDir, getVenvPath } = await import(runtimeModuleUrl('paths-core.mjs'));
18
+ const { SETUP_MLX_MONOREPO } = await import(runtimeModuleUrl('setup-commands-core.mjs'));
18
19
 
19
20
  const targetDir = getMlxPythonDir(packageRoot);
20
21
  const venvPath = getVenvPath('mlx');
21
22
 
22
23
  if (!existsSync(targetDir)) {
23
24
  console.error('❌ MLX Python directory not found.');
24
- console.error(' Please run "pnpm run setup-mlx -w @modular-prompt/driver" first.');
25
+ console.error(` Please run "${SETUP_MLX_MONOREPO}" first.`);
25
26
  process.exit(1);
26
27
  }
27
28
 
28
29
  if (!existsSync(join(venvPath, 'bin', 'python'))) {
29
30
  console.error('❌ MLX runtime is not set up.');
30
- console.error(' Please run "pnpm run setup-mlx -w @modular-prompt/driver" first.');
31
+ console.error(` Please run "${SETUP_MLX_MONOREPO}" first.`);
31
32
  process.exit(1);
32
33
  }
33
34
 
@@ -0,0 +1,142 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import {
3
+ chmodSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ mkdtempSync,
7
+ readdirSync,
8
+ readFileSync,
9
+ rmSync,
10
+ writeFileSync,
11
+ } from 'node:fs';
12
+ import { dirname, join, resolve } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+ import { tmpdir } from 'node:os';
15
+ import { afterEach, describe, expect, it } from 'vitest';
16
+
17
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
18
+ const temporaryDirectories: string[] = [];
19
+
20
+ afterEach(() => {
21
+ for (const directory of temporaryDirectories.splice(0)) {
22
+ rmSync(directory, { recursive: true, force: true });
23
+ }
24
+ });
25
+
26
+ describe('runtime CLI bin', () => {
27
+ it('publishes modular-prompt-runtime in npm pack', () => {
28
+ const temporaryDirectory = mkdtempSync(
29
+ join(tmpdir(), 'modular-prompt-driver-pack-'),
30
+ );
31
+ temporaryDirectories.push(temporaryDirectory);
32
+
33
+ execFileSync(
34
+ 'npm',
35
+ ['pack', '--ignore-scripts', '--pack-destination', temporaryDirectory],
36
+ {
37
+ cwd: packageRoot,
38
+ encoding: 'utf8',
39
+ env: {
40
+ ...process.env,
41
+ COREPACK_ENABLE_PROJECT_SPEC: '0',
42
+ npm_config_cache: join(temporaryDirectory, 'npm-cache'),
43
+ },
44
+ },
45
+ );
46
+
47
+ const tarballName = readdirSync(temporaryDirectory).find((name) =>
48
+ name.endsWith('.tgz'),
49
+ );
50
+ if (!tarballName) {
51
+ throw new Error('npm pack did not create a tarball');
52
+ }
53
+
54
+ const packedPackageJson = execFileSync(
55
+ 'tar',
56
+ ['-xOf', join(temporaryDirectory, tarballName), 'package/package.json'],
57
+ { encoding: 'utf8' },
58
+ );
59
+ const { bin } = JSON.parse(packedPackageJson) as { bin: Record<string, string> };
60
+
61
+ expect(bin['modular-prompt-runtime']).toBe('./scripts/runtime-cli.js');
62
+
63
+ const archiveEntries = execFileSync(
64
+ 'tar',
65
+ ['-tzf', join(temporaryDirectory, tarballName)],
66
+ { encoding: 'utf8' },
67
+ );
68
+ expect(archiveEntries).toContain('package/src/pytorch/templates/cpu-minimal/pyproject.toml');
69
+ expect(archiveEntries).toContain('package/src/pytorch/templates/cuda/pyproject.toml');
70
+ expect(archiveEntries).not.toContain('package/src/pytorch/python/');
71
+ });
72
+
73
+ it('documents modular-prompt-runtime in package.json', () => {
74
+ const packageJson = JSON.parse(
75
+ readFileSync(join(packageRoot, 'package.json'), 'utf8'),
76
+ ) as { bin: Record<string, string> };
77
+
78
+ expect(packageJson.bin['modular-prompt-runtime']).toBe('./scripts/runtime-cli.js');
79
+ });
80
+
81
+ it('smokes torch CUDA availability and reports runtime status details', () => {
82
+ const temporaryDirectory = mkdtempSync(
83
+ join(tmpdir(), 'modular-prompt-driver-status-'),
84
+ );
85
+ temporaryDirectories.push(temporaryDirectory);
86
+
87
+ const runtimeDir = join(temporaryDirectory, 'runtimes', 'pytorch');
88
+ const venvPythonDir = process.platform === 'win32' ? 'Scripts' : 'bin';
89
+ const venvPython = join(
90
+ runtimeDir,
91
+ '.venv',
92
+ venvPythonDir,
93
+ 'python' + (process.platform === 'win32' ? '.exe' : ''),
94
+ );
95
+ mkdirSync(join(runtimeDir, '.venv', venvPythonDir), { recursive: true });
96
+ mkdirSync(join(runtimeDir, 'python'), { recursive: true });
97
+ if (process.platform === 'win32') {
98
+ writeFileSync(venvPython, '');
99
+ } else {
100
+ writeFileSync(
101
+ venvPython,
102
+ '#!/usr/bin/env node\n' +
103
+ 'if (process.argv[2] !== "-c" || !process.argv[3].includes("import torch")) process.exit(2);\n' +
104
+ 'console.log("false");\n',
105
+ );
106
+ chmodSync(venvPython, 0o755);
107
+ }
108
+ writeFileSync(join(runtimeDir, 'python', 'pyproject.toml'), '[project]\nname = "test"\n');
109
+ writeFileSync(join(runtimeDir, 'python', '__main__.py'), '');
110
+ writeFileSync(
111
+ join(runtimeDir, 'manifest.json'),
112
+ JSON.stringify({
113
+ profile: 'pytorch',
114
+ variant: 'cuda',
115
+ cudaVersion: '12.4',
116
+ driverVersion: '0.0.0',
117
+ platform: process.platform,
118
+ pythonVersion: '3.12',
119
+ createdAt: new Date().toISOString(),
120
+ }),
121
+ );
122
+
123
+ const output = execFileSync(
124
+ process.execPath,
125
+ [join(packageRoot, 'scripts', 'runtime-cli.js'), 'setup', '--status'],
126
+ {
127
+ encoding: 'utf8',
128
+ env: { ...process.env, MODULAR_PROMPT_HOME: temporaryDirectory },
129
+ },
130
+ );
131
+
132
+ expect(output).toContain('pytorch: ready');
133
+ expect(output).toContain('variant cuda');
134
+ expect(output).toContain('CUDA 12.4');
135
+ expect(output).toContain(
136
+ `CUDA: ${process.platform === 'win32' ? 'unknown' : 'unavailable'}`,
137
+ );
138
+ expect(output).toContain('driver version differs');
139
+ expect(output).toContain('modular-prompt-runtime sync pytorch');
140
+ expect(existsSync(join(runtimeDir, 'python', 'pyproject.toml'))).toBe(true);
141
+ });
142
+ });