w-dispatch-ai 1.0.16 → 1.0.18

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 (37) hide show
  1. package/README.md +20 -2
  2. package/dist/w-dispatch-ai.umd.js +2 -2
  3. package/dist/w-dispatch-ai.umd.js.map +1 -1
  4. package/docs/WDispatchAi.mjs.html +1 -1
  5. package/docs/adapters.mjs.html +1 -1
  6. package/docs/budgetFor.mjs.html +1 -1
  7. package/docs/castPintOr.mjs.html +1 -1
  8. package/docs/dfTimeoutMs.mjs.html +1 -1
  9. package/docs/dispatchAi.mjs.html +1 -1
  10. package/docs/dispatchAiFallback.mjs.html +1 -1
  11. package/docs/dispatchAiWkf.mjs.html +1 -1
  12. package/docs/dispatchAntigravity.mjs.html +1 -1
  13. package/docs/dispatchApiOpenaiCompat.mjs.html +1 -1
  14. package/docs/dispatchClaude.mjs.html +1 -1
  15. package/docs/dispatchCodex.mjs.html +1 -1
  16. package/docs/dispatchOpencode.mjs.html +1 -1
  17. package/docs/getCliArgs.mjs.html +1 -1
  18. package/docs/getErrorResult.mjs.html +1 -1
  19. package/docs/getErrorType.mjs.html +1 -1
  20. package/docs/global.html +9 -4
  21. package/docs/index.html +1 -1
  22. package/docs/readEnvFile.mjs.html +1 -1
  23. package/docs/resolveProviders.mjs.html +20 -4
  24. package/docs/wkf_callAiWithFallback.mjs.html +1 -1
  25. package/docs/wkf_createFileStore.mjs.html +1 -1
  26. package/docs/wkf_createUsageCounter.mjs.html +1 -1
  27. package/docs/wkf_extractJsonLoose.mjs.html +1 -1
  28. package/docs/wkf_noSideEffectPrefix.mjs.html +1 -1
  29. package/docs/wkf_runFanout.mjs.html +1 -1
  30. package/docs/wkf_runFanoutPipeline.mjs.html +1 -1
  31. package/docs/wkf_runRolePipeline.mjs.html +1 -1
  32. package/docs/wkf_salvageTruncatedArray.mjs.html +1 -1
  33. package/package.json +2 -2
  34. package/src/providers.mjs +74 -0
  35. package/src/resolveProviders.mjs +19 -3
  36. package/test/unit-WDispatchAi.test.mjs +2 -2
  37. package/test/unit-resolveProviders.test.mjs +26 -0
@@ -490,7 +490,7 @@ export default dispatchApiOpenaiCompat
490
490
  <br class="clear">
491
491
 
492
492
  <footer>
493
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
493
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
494
494
  </footer>
495
495
 
496
496
  <script>prettyPrint();</script>
@@ -185,7 +185,7 @@ export default dispatchClaude
185
185
  <br class="clear">
186
186
 
187
187
  <footer>
188
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
188
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
189
189
  </footer>
190
190
 
191
191
  <script>prettyPrint();</script>
@@ -186,7 +186,7 @@ export default dispatchCodex
186
186
  <br class="clear">
187
187
 
188
188
  <footer>
189
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
189
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
190
190
  </footer>
191
191
 
192
192
  <script>prettyPrint();</script>
@@ -255,7 +255,7 @@ export default dispatchOpencode
255
255
  <br class="clear">
256
256
 
257
257
  <footer>
258
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
258
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
259
259
  </footer>
260
260
 
261
261
  <script>prettyPrint();</script>
@@ -113,7 +113,7 @@ export default getCliArgs
113
113
  <br class="clear">
114
114
 
115
115
  <footer>
116
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
116
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
117
117
  </footer>
118
118
 
119
119
  <script>prettyPrint();</script>
@@ -109,7 +109,7 @@ export default getErrorResult
109
109
  <br class="clear">
110
110
 
111
111
  <footer>
112
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
112
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
113
113
  </footer>
114
114
 
115
115
  <script>prettyPrint();</script>
@@ -158,7 +158,7 @@ export { attachErrorType }
158
158
  <br class="clear">
159
159
 
160
160
  <footer>
161
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
161
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
162
162
  </footer>
163
163
 
164
164
  <script>prettyPrint();</script>
package/docs/global.html CHANGED
@@ -9935,7 +9935,7 @@ providers與table同源產出故必然一致;
9935
9935
 
9936
9936
  <dt class="tag-source">Source:</dt>
9937
9937
  <dd class="tag-source"><ul class="dummy"><li>
9938
- <a href="resolveProviders.mjs.html">resolveProviders.mjs</a>, <a href="resolveProviders.mjs.html#line80">line 80</a>
9938
+ <a href="resolveProviders.mjs.html">resolveProviders.mjs</a>, <a href="resolveProviders.mjs.html#line86">line 86</a>
9939
9939
  </li></ul></dd>
9940
9940
 
9941
9941
 
@@ -9992,7 +9992,12 @@ let env = readEnvFile('./.env')
9992
9992
  //全取: envVar展開為keys, 缺環境變數者列入skipped
9993
9993
  let { providers, table, skipped } = resolveProviders(providersAll, { env })
9994
9994
  console.log(providers.length, skipped)
9995
- // => 10 []
9995
+ // => 16 []
9996
+
9997
+ //pick打錯字時, missing附拼寫提示hints(最接近之可用id)
9998
+ let rm = resolveProviders(providersAll, { env, pick: ['poolside/laguna-s-2.1'] })
9999
+ console.log(rm.missing, rm.hints)
10000
+ // => [ 'poolside/laguna-s-2.1' ] { 'poolside/laguna-s-2.1': 'poolside:laguna-s-2.1' }
9996
10001
 
9997
10002
  //自選: 依pick順序回傳(順序即遞補優先序), 可直接餵dispatchAiFallback
9998
10003
  let r2 = resolveProviders(providersAll, { env, pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'] })
@@ -10329,7 +10334,7 @@ console.log(r3.table['claude:sonnet'].exe, r3.table['claude:sonnet'].timeoutMs)
10329
10334
 
10330
10335
 
10331
10336
  <div class="param-desc">
10332
- <p>回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)</p>
10337
+ <p>回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)、hints(missing id對最接近可用id之拼寫提示物件,pick查無多半是打錯字,附最接近id供直接定位;僅為相似度最高者非保證正解,無missing時為空物件)</p>
10333
10338
  </div>
10334
10339
 
10335
10340
 
@@ -12080,7 +12085,7 @@ console.log(salvageTruncatedArray('[{"a":1}]')) //有閉合=非截斷, 不在
12080
12085
  <br class="clear">
12081
12086
 
12082
12087
  <footer>
12083
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
12088
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
12084
12089
  </footer>
12085
12090
 
12086
12091
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
@@ -119,7 +119,7 @@ export default readEnvFile
119
119
  <br class="clear">
120
120
 
121
121
  <footer>
122
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
122
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
123
123
  </footer>
124
124
 
125
125
  <script>prettyPrint();</script>
@@ -51,6 +51,7 @@ import isarr from 'wsemi/src/isarr.mjs'
51
51
  import isobj from 'wsemi/src/isobj.mjs'
52
52
  import isestr from 'wsemi/src/isestr.mjs'
53
53
  import isearr from 'wsemi/src/isearr.mjs'
54
+ import strFindSimilar from 'wsemi/src/strFindSimilar.mjs'
54
55
 
55
56
 
56
57
  // resolveProviders.mjs — 把providers定義檔展開為可直接使用的條目
@@ -90,7 +91,7 @@ import isearr from 'wsemi/src/isearr.mjs'
90
91
  * @param {Array} [opt.pick=null] 輸入自選id字串陣列,依此順序回傳對應條目,查無之id列入missing,預設null代表全取(依原順序)
91
92
  * @param {Object} [opt.exes=null] 輸入kind對執行檔絕對路徑之物件(如{claude:'C:/.../claude.exe'}),命中kind之條目補上exe欄位(條目已自帶exe者不覆寫——條目層設定優先),預設null代表不注入
92
93
  * @param {Object} [opt.patch=null] 輸入id對部分欄位之物件(如{'claude:sonnet':{timeoutMs:360000}}),命中id之條目淺合併覆寫,於exes之後施作故可覆寫exe,預設null代表不覆寫
93
- * @returns {Object} 回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)
94
+ * @returns {Object} 回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)、hints(missing id對最接近可用id之拼寫提示物件,pick查無多半是打錯字,附最接近id供直接定位;僅為相似度最高者非保證正解,無missing時為空物件)
94
95
  * @example
95
96
  *
96
97
  * import resolveProviders from './src/resolveProviders.mjs'
@@ -103,7 +104,12 @@ import isearr from 'wsemi/src/isearr.mjs'
103
104
  * //全取: envVar展開為keys, 缺環境變數者列入skipped
104
105
  * let { providers, table, skipped } = resolveProviders(providersAll, { env })
105
106
  * console.log(providers.length, skipped)
106
- * // => 10 []
107
+ * // => 16 []
108
+ *
109
+ * //pick打錯字時, missing附拼寫提示hints(最接近之可用id)
110
+ * let rm = resolveProviders(providersAll, { env, pick: ['poolside/laguna-s-2.1'] })
111
+ * console.log(rm.missing, rm.hints)
112
+ * // => [ 'poolside/laguna-s-2.1' ] { 'poolside/laguna-s-2.1': 'poolside:laguna-s-2.1' }
107
113
  *
108
114
  * //自選: 依pick順序回傳(順序即遞補優先序), 可直接餵dispatchAiFallback
109
115
  * let r2 = resolveProviders(providersAll, { env, pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'] })
@@ -152,6 +158,16 @@ function resolveProviders(providers, opt = {}) {
152
158
  }
153
159
  }
154
160
 
161
+ //hints, missing之拼寫提示: 自全部條目id中找最接近者——實務上pick查無多半是打錯字
162
+ //(如'poolside/laguna'誤作分隔符), 附上最接近id可直接定位; 僅為相似度最高者, 非保證正解
163
+ let hints = {}
164
+ if (missing.length > 0) {
165
+ let ids = providersRaw.map((p) => get(p, 'id', null)).filter(isestr)
166
+ for (let mid of missing) {
167
+ hints[mid] = (ids.length > 0) ? get(strFindSimilar(mid, ids), 'bestMatch.target', null) : null
168
+ }
169
+ }
170
+
155
171
  //展開envVar → keys
156
172
  let out = []
157
173
  let skipped = []
@@ -205,7 +221,7 @@ function resolveProviders(providers, opt = {}) {
205
221
  table[entry.id] = entry
206
222
  }
207
223
 
208
- return { providers: out, table, skipped, missing }
224
+ return { providers: out, table, skipped, missing, hints }
209
225
  }
210
226
 
211
227
 
@@ -224,7 +240,7 @@ export default resolveProviders
224
240
  <br class="clear">
225
241
 
226
242
  <footer>
227
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
243
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
228
244
  </footer>
229
245
 
230
246
  <script>prettyPrint();</script>
@@ -274,7 +274,7 @@ export { buildChain, NO_SIDE_EFFECT }
274
274
  <br class="clear">
275
275
 
276
276
  <footer>
277
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
277
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
278
278
  </footer>
279
279
 
280
280
  <script>prettyPrint();</script>
@@ -162,7 +162,7 @@ export default createFileStore
162
162
  <br class="clear">
163
163
 
164
164
  <footer>
165
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
165
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
166
166
  </footer>
167
167
 
168
168
  <script>prettyPrint();</script>
@@ -200,7 +200,7 @@ export default createUsageCounter
200
200
  <br class="clear">
201
201
 
202
202
  <footer>
203
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
203
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
204
204
  </footer>
205
205
 
206
206
  <script>prettyPrint();</script>
@@ -167,7 +167,7 @@ export default extractJsonLoose
167
167
  <br class="clear">
168
168
 
169
169
  <footer>
170
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
170
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
171
171
  </footer>
172
172
 
173
173
  <script>prettyPrint();</script>
@@ -108,7 +108,7 @@ export default NO_SIDE_EFFECT
108
108
  <br class="clear">
109
109
 
110
110
  <footer>
111
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
111
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
112
112
  </footer>
113
113
 
114
114
  <script>prettyPrint();</script>
@@ -217,7 +217,7 @@ export { defaultIntegratePrompt }
217
217
  <br class="clear">
218
218
 
219
219
  <footer>
220
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
220
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
221
221
  </footer>
222
222
 
223
223
  <script>prettyPrint();</script>
@@ -161,7 +161,7 @@ export default runFanoutPipeline
161
161
  <br class="clear">
162
162
 
163
163
  <footer>
164
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
164
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
165
165
  </footer>
166
166
 
167
167
  <script>prettyPrint();</script>
@@ -183,7 +183,7 @@ export default runRolePipeline
183
183
  <br class="clear">
184
184
 
185
185
  <footer>
186
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
186
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
187
187
  </footer>
188
188
 
189
189
  <script>prettyPrint();</script>
@@ -154,7 +154,7 @@ export default salvageTruncatedArray
154
154
  <br class="clear">
155
155
 
156
156
  <footer>
157
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 21 2026 10:53:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
157
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 26 2026 16:22:12 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
158
158
  </footer>
159
159
 
160
160
  <script>prettyPrint();</script>
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "w-dispatch-ai",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "main": "dist/w-dispatch-ai.umd.js",
5
5
  "dependencies": {
6
- "wsemi": "^1.8.79"
6
+ "wsemi": "^1.8.80"
7
7
  },
8
8
  "devDependencies": {
9
9
  "w-package-tools": "^1.1.15"
package/src/providers.mjs CHANGED
@@ -9,6 +9,13 @@
9
9
  // zen:/agnes:/poolside:=REST直呼(免CLI免登入、快, 純文字生成)
10
10
  // 同一模型之CLI版與REST版屬不同供應商(能力與額度池皆不同), 故各為一條。
11
11
  //
12
+ // 【zen免費模型清單為「更新日快照」, 不保證即為當前狀態】zen:系收錄截至2026-08-21
13
+ // 經GET https://opencode.ai/zen/v1/models 查得之「全部」免費模型(*-free), 不做好用篩選——
14
+ // 新模型會上線、舊模型可能下架或限流, 且各模型能力/速度/輸出習慣差異極大
15
+ // (各條目註解記錄已測特性), 由呼叫端自行評估選用; 要查當前清單, 以OPENCODE_KEYS
16
+ // 打上述/models端點即可。暫時打不通的條目(限流/額度)依本套件哲學保留不移除:
17
+ // 恢復的偵測就是下次再打一次, 代價僅一次快速失敗(fallback/cooldownMs即為此而生)。
18
+ //
12
19
  // 【使用方式】
13
20
  // import providers from 'w-dispatch-ai/src/providers.mjs'
14
21
  // import resolveProviders from 'w-dispatch-ai/src/resolveProviders.mjs'
@@ -43,6 +50,7 @@ let providers = [
43
50
  config: {
44
51
  permission: { edit: 'deny', write: 'deny', bash: 'deny' },
45
52
  },
53
+ //2026-08-21實測失敗(UnknownError, 與zen:deepseek同日之401同源); 保留理由見該條註記
46
54
  },
47
55
  {
48
56
  id: 'oc:agnes-ai/agnes-2.5-flash',
@@ -105,6 +113,7 @@ let providers = [
105
113
  },
106
114
 
107
115
  //api版
116
+ //zen:系為2026-08-21快照(檔頭聲明), 各條註記當日以「請只回覆兩個字:完成」實測之結果
108
117
  {
109
118
  id: 'zen:deepseek-v4-flash-free',
110
119
  model: 'deepseek-v4-flash-free',
@@ -112,6 +121,71 @@ let providers = [
112
121
  envVar: 'OPENCODE_KEYS',
113
122
  baseURL: 'https://opencode.ai/zen/v1',
114
123
  body: { max_tokens: 8192 },
124
+ //2026-08-21實測回401(官方訊息: Free promotion has ended); opencode方案端仍列此模型,
125
+ //判讀為用量壓力下之暫時狀態而保留, 恢復之偵測即下次再打
126
+ },
127
+ {
128
+ id: 'zen:laguna-s-2.1-free',
129
+ model: 'laguna-s-2.1-free',
130
+ kind: 'api-openai-compat',
131
+ envVar: 'OPENCODE_KEYS',
132
+ baseURL: 'https://opencode.ai/zen/v1',
133
+ body: { max_tokens: 8192 },
134
+ //2026-08-21實測4.0s; 同一laguna之第三條路(Poolside官方REST/oc CLI/zen), 三者故障域獨立
135
+ },
136
+ {
137
+ id: 'zen:x-preview-f-free',
138
+ model: 'x-preview-f-free', //官方顯示名Ox Alpha Free
139
+ kind: 'api-openai-compat',
140
+ envVar: 'OPENCODE_KEYS',
141
+ baseURL: 'https://opencode.ai/zen/v1',
142
+ body: { max_tokens: 8192 },
143
+ //2026-08-21實測2.4s; 使用端回報批次涵蓋率偏低(3篇輸入常只回1~2篇), 批次任務慎用
144
+ },
145
+ {
146
+ id: 'zen:muse-spark-1.2-contributor-free',
147
+ model: 'muse-spark-1.2-contributor-free',
148
+ kind: 'api-openai-compat',
149
+ envVar: 'OPENCODE_KEYS',
150
+ baseURL: 'https://opencode.ai/zen/v1',
151
+ body: { max_tokens: 8192 },
152
+ //2026-08-21實測3.9s; 使用端回報批次涵蓋率100%、術語標準、內容密度高
153
+ },
154
+ {
155
+ id: 'zen:mimo-v2.5-free',
156
+ model: 'mimo-v2.5-free',
157
+ kind: 'api-openai-compat',
158
+ envVar: 'OPENCODE_KEYS',
159
+ baseURL: 'https://opencode.ai/zen/v1',
160
+ body: { max_tokens: 8192 },
161
+ //2026-08-21實測連續429(FreeUsageLimitError, 容量型)——429證明閘道認得此id(寫錯會回其他4xx)
162
+ },
163
+ {
164
+ id: 'zen:hy3-free',
165
+ model: 'hy3-free',
166
+ kind: 'api-openai-compat',
167
+ envVar: 'OPENCODE_KEYS',
168
+ baseURL: 'https://opencode.ai/zen/v1',
169
+ body: { max_tokens: 8192 },
170
+ //2026-08-21實測3.2s
171
+ },
172
+ {
173
+ id: 'zen:nemotron-3-ultra-free',
174
+ model: 'nemotron-3-ultra-free',
175
+ kind: 'api-openai-compat',
176
+ envVar: 'OPENCODE_KEYS',
177
+ baseURL: 'https://opencode.ai/zen/v1',
178
+ body: { max_tokens: 8192 },
179
+ //2026-08-21實測2.2s; function calling協定實測可用(tool_calls格式標準, 但本套件api類不支援工具)
180
+ },
181
+ {
182
+ id: 'zen:nemotron-3.5-lightning-free',
183
+ model: 'nemotron-3.5-lightning-free',
184
+ kind: 'api-openai-compat',
185
+ envVar: 'OPENCODE_KEYS',
186
+ baseURL: 'https://opencode.ai/zen/v1',
187
+ body: { max_tokens: 8192 },
188
+ //2026-08-21實測27.4s——名為lightning實測卻最慢, timeout與批量規劃須留意
115
189
  },
116
190
  {
117
191
  id: 'agnes:agnes-2.5-flash',
@@ -4,6 +4,7 @@ import isarr from 'wsemi/src/isarr.mjs'
4
4
  import isobj from 'wsemi/src/isobj.mjs'
5
5
  import isestr from 'wsemi/src/isestr.mjs'
6
6
  import isearr from 'wsemi/src/isearr.mjs'
7
+ import strFindSimilar from 'wsemi/src/strFindSimilar.mjs'
7
8
 
8
9
 
9
10
  // resolveProviders.mjs — 把providers定義檔展開為可直接使用的條目
@@ -43,7 +44,7 @@ import isearr from 'wsemi/src/isearr.mjs'
43
44
  * @param {Array} [opt.pick=null] 輸入自選id字串陣列,依此順序回傳對應條目,查無之id列入missing,預設null代表全取(依原順序)
44
45
  * @param {Object} [opt.exes=null] 輸入kind對執行檔絕對路徑之物件(如{claude:'C:/.../claude.exe'}),命中kind之條目補上exe欄位(條目已自帶exe者不覆寫——條目層設定優先),預設null代表不注入
45
46
  * @param {Object} [opt.patch=null] 輸入id對部分欄位之物件(如{'claude:sonnet':{timeoutMs:360000}}),命中id之條目淺合併覆寫,於exes之後施作故可覆寫exe,預設null代表不覆寫
46
- * @returns {Object} 回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)
47
+ * @returns {Object} 回傳物件,內含providers(可直接餵dispatchAiFallback之條目陣列)、table(id對條目之物件,可直接餵dispatchAiWkf)、skipped(缺環境變數而停用之{id,envVar}陣列)、missing(pick查無之id字串陣列)、hints(missing id對最接近可用id之拼寫提示物件,pick查無多半是打錯字,附最接近id供直接定位;僅為相似度最高者非保證正解,無missing時為空物件)
47
48
  * @example
48
49
  *
49
50
  * import resolveProviders from './src/resolveProviders.mjs'
@@ -56,7 +57,12 @@ import isearr from 'wsemi/src/isearr.mjs'
56
57
  * //全取: envVar展開為keys, 缺環境變數者列入skipped
57
58
  * let { providers, table, skipped } = resolveProviders(providersAll, { env })
58
59
  * console.log(providers.length, skipped)
59
- * // => 10 []
60
+ * // => 16 []
61
+ *
62
+ * //pick打錯字時, missing附拼寫提示hints(最接近之可用id)
63
+ * let rm = resolveProviders(providersAll, { env, pick: ['poolside/laguna-s-2.1'] })
64
+ * console.log(rm.missing, rm.hints)
65
+ * // => [ 'poolside/laguna-s-2.1' ] { 'poolside/laguna-s-2.1': 'poolside:laguna-s-2.1' }
60
66
  *
61
67
  * //自選: 依pick順序回傳(順序即遞補優先序), 可直接餵dispatchAiFallback
62
68
  * let r2 = resolveProviders(providersAll, { env, pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'] })
@@ -105,6 +111,16 @@ function resolveProviders(providers, opt = {}) {
105
111
  }
106
112
  }
107
113
 
114
+ //hints, missing之拼寫提示: 自全部條目id中找最接近者——實務上pick查無多半是打錯字
115
+ //(如'poolside/laguna'誤作分隔符), 附上最接近id可直接定位; 僅為相似度最高者, 非保證正解
116
+ let hints = {}
117
+ if (missing.length > 0) {
118
+ let ids = providersRaw.map((p) => get(p, 'id', null)).filter(isestr)
119
+ for (let mid of missing) {
120
+ hints[mid] = (ids.length > 0) ? get(strFindSimilar(mid, ids), 'bestMatch.target', null) : null
121
+ }
122
+ }
123
+
108
124
  //展開envVar → keys
109
125
  let out = []
110
126
  let skipped = []
@@ -158,7 +174,7 @@ function resolveProviders(providers, opt = {}) {
158
174
  table[entry.id] = entry
159
175
  }
160
176
 
161
- return { providers: out, table, skipped, missing }
177
+ return { providers: out, table, skipped, missing, hints }
162
178
  }
163
179
 
164
180
 
@@ -20,6 +20,7 @@ describe('WDispatchAi', function() {
20
20
  let r = keys(wi)
21
21
  let rr = [
22
22
  'KINDS',
23
+ 'NO_SIDE_EFFECT',
23
24
  'dispatchAi',
24
25
  'dispatchAiFallback',
25
26
  'dispatchAiWkf',
@@ -35,7 +36,6 @@ describe('WDispatchAi', function() {
35
36
  'createFileStore',
36
37
  'createUsageCounter',
37
38
  'salvageTruncatedArray',
38
- 'NO_SIDE_EFFECT',
39
39
  ]
40
40
  assert.strict.deepEqual(r, rr)
41
41
  })
@@ -48,7 +48,7 @@ describe('WDispatchAi', function() {
48
48
 
49
49
  it('各鍵值型別正確(KINDS與providers為物件, NO_SIDE_EFFECT為字串, 其餘為函數)', function() {
50
50
  let r = map(keys(wi), (k) => typeof wi[k])
51
- let rr = ['object', 'function', 'function', 'function', 'function', 'function', 'function', 'function', 'function', 'object', 'function', 'function', 'function', 'function', 'function', 'function', 'string']
51
+ let rr = ['object', 'string', 'function', 'function', 'function', 'function', 'function', 'function', 'function', 'function', 'object', 'function', 'function', 'function', 'function', 'function', 'function']
52
52
  assert.strict.deepEqual(r, rr)
53
53
  })
54
54
 
@@ -120,6 +120,32 @@ describe('resolveProviders', function() {
120
120
  assert.strict.deepEqual(r, rr)
121
121
  })
122
122
 
123
+ it('pick查無時missing附拼寫提示hints(最接近之可用id), 無missing時hints為空物件', function() {
124
+ let defs = [
125
+ { id: 'poolside:laguna-s-2.1', kind: 'api-openai-compat', model: 'm' },
126
+ { id: 'claude:sonnet', kind: 'claude', model: 'sonnet' },
127
+ ]
128
+ //實務上pick查無多半是打錯字(如分隔符「/」誤替「:」), hints直接定位
129
+ let t1 = resolveProviders(defs, { env: {}, pick: ['poolside/laguna-s-2.1', 'claude:sonnet'] })
130
+ let t2 = resolveProviders(defs, { env: {} })
131
+ let r = [t1.missing, t1.hints, t1.providers.map((p) => p.id), t2.missing, t2.hints]
132
+ let rr = [
133
+ ['poolside/laguna-s-2.1'],
134
+ { 'poolside/laguna-s-2.1': 'poolside:laguna-s-2.1' },
135
+ ['claude:sonnet'], //查無者不影響其餘pick
136
+ [],
137
+ {},
138
+ ]
139
+ assert.strict.deepEqual(r, rr)
140
+ })
141
+
142
+ it('providers為空而pick有值時hints值為null(無可比對之id), 不throw', function() {
143
+ let t = resolveProviders([], { env: {}, pick: ['x'] })
144
+ let r = [t.missing, t.hints]
145
+ let rr = [['x'], { x: null }]
146
+ assert.strict.deepEqual(r, rr)
147
+ })
148
+
123
149
  it('exes與patch皆省略時行為與原版完全相同(向後相容), 且不改動輸入條目', function() {
124
150
  let defs = [{ id: 'a:m', kind: 'claude', model: 'm' }]
125
151
  let before = JSON.stringify(defs)