w-dispatch-ai 1.0.21 → 1.0.22

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 (49) hide show
  1. package/README.md +15 -3
  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 +5 -3
  5. package/docs/adapters.mjs.html +5 -3
  6. package/docs/budgetFor.mjs.html +2 -2
  7. package/docs/buildValidator.mjs.html +166 -0
  8. package/docs/castPintOr.mjs.html +2 -2
  9. package/docs/dfTimeoutMs.mjs.html +2 -2
  10. package/docs/dispatchAi.mjs.html +2 -2
  11. package/docs/dispatchAiFallback.mjs.html +2 -2
  12. package/docs/dispatchAiWkf.mjs.html +2 -2
  13. package/docs/dispatchAntigravity.mjs.html +2 -2
  14. package/docs/dispatchApiOpenaiCompat.mjs.html +4 -68
  15. package/docs/dispatchApiOpenaiResponses.mjs.html +498 -0
  16. package/docs/dispatchClaude.mjs.html +2 -2
  17. package/docs/dispatchCodex.mjs.html +2 -2
  18. package/docs/dispatchOpencode.mjs.html +2 -2
  19. package/docs/getCliArgs.mjs.html +2 -2
  20. package/docs/getErrorResult.mjs.html +2 -2
  21. package/docs/getErrorType.mjs.html +5 -3
  22. package/docs/global.html +2277 -1159
  23. package/docs/index.html +2 -2
  24. package/docs/readEnvFile.mjs.html +2 -2
  25. package/docs/resolveProviders.mjs.html +3 -3
  26. package/docs/wkf_callAiWithFallback.mjs.html +2 -2
  27. package/docs/wkf_createFileStore.mjs.html +2 -2
  28. package/docs/wkf_createUsageCounter.mjs.html +2 -2
  29. package/docs/wkf_extractJsonLoose.mjs.html +2 -2
  30. package/docs/wkf_noSideEffectPrefix.mjs.html +2 -2
  31. package/docs/wkf_runFanout.mjs.html +2 -2
  32. package/docs/wkf_runFanoutPipeline.mjs.html +2 -2
  33. package/docs/wkf_runRolePipeline.mjs.html +2 -2
  34. package/docs/wkf_salvageTruncatedArray.mjs.html +2 -2
  35. package/g.mjs +2 -2
  36. package/package.json +1 -1
  37. package/src/WDispatchAi.mjs +3 -1
  38. package/src/adapters.mjs +3 -1
  39. package/src/buildValidator.mjs +94 -0
  40. package/src/dispatchApiOpenaiCompat.mjs +2 -66
  41. package/src/dispatchApiOpenaiResponses.mjs +426 -0
  42. package/src/getErrorType.mjs +3 -1
  43. package/src/providers.mjs +303 -213
  44. package/src/resolveProviders.mjs +1 -1
  45. package/test/tools/fakeServerForApiTest.mjs +108 -3
  46. package/test/unit-WDispatchAi.test.mjs +10 -6
  47. package/test/unit-adapters.test.mjs +5 -3
  48. package/test/unit-dispatchAi.test.mjs +1 -1
  49. package/test/unit-dispatchApiOpenaiResponses.test.mjs +198 -0
package/docs/global.html CHANGED
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#NO_SIDE_EFFECT">NO_SIDE_EFFECT</a></li><li><a href="global.html#WDispatchAi">WDispatchAi</a></li><li><a href="global.html#adapters">adapters</a></li><li><a href="global.html#attachErrorType">attachErrorType</a></li><li><a href="global.html#budgetFor">budgetFor</a></li><li><a href="global.html#buildChain">buildChain</a></li><li><a href="global.html#buildValidator">buildValidator</a></li><li><a href="global.html#callAiWithFallback">callAiWithFallback</a></li><li><a href="global.html#callOnce">callOnce</a></li><li><a href="global.html#castPintOr">castPintOr</a></li><li><a href="global.html#createFileStore">createFileStore</a></li><li><a href="global.html#createUsageCounter">createUsageCounter</a></li><li><a href="global.html#defaultIntegratePrompt">defaultIntegratePrompt</a></li><li><a href="global.html#dfTimeoutMs">dfTimeoutMs</a></li><li><a href="global.html#dispatchAi">dispatchAi</a></li><li><a href="global.html#dispatchAiFallback">dispatchAiFallback</a></li><li><a href="global.html#dispatchAiWkf">dispatchAiWkf</a></li><li><a href="global.html#dispatchAntigravity">dispatchAntigravity</a></li><li><a href="global.html#dispatchApiOpenaiCompat">dispatchApiOpenaiCompat</a></li><li><a href="global.html#dispatchClaude">dispatchClaude</a></li><li><a href="global.html#dispatchCodex">dispatchCodex</a></li><li><a href="global.html#dispatchOpencode">dispatchOpencode</a></li><li><a href="global.html#extractJsonLoose">extractJsonLoose</a></li><li><a href="global.html#getCliArgs">getCliArgs</a></li><li><a href="global.html#getErrorResult">getErrorResult</a></li><li><a href="global.html#getErrorType">getErrorType</a></li><li><a href="global.html#initState">initState</a></li><li><a href="global.html#isKeyIndependentFail">isKeyIndependentFail</a></li><li><a href="global.html#readEnvFile">readEnvFile</a></li><li><a href="global.html#reorderByCooling">reorderByCooling</a></li><li><a href="global.html#resolveProviders">resolveProviders</a></li><li><a href="global.html#runFanout">runFanout</a></li><li><a href="global.html#runFanoutPipeline">runFanoutPipeline</a></li><li><a href="global.html#runRolePipeline">runRolePipeline</a></li><li><a href="global.html#salvageTruncatedArray">salvageTruncatedArray</a></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#NO_SIDE_EFFECT">NO_SIDE_EFFECT</a></li><li><a href="global.html#WDispatchAi">WDispatchAi</a></li><li><a href="global.html#adapters">adapters</a></li><li><a href="global.html#attachErrorType">attachErrorType</a></li><li><a href="global.html#budgetFor">budgetFor</a></li><li><a href="global.html#buildChain">buildChain</a></li><li><a href="global.html#buildValidator">buildValidator</a></li><li><a href="global.html#callAiWithFallback">callAiWithFallback</a></li><li><a href="global.html#callOnce">callOnce</a></li><li><a href="global.html#castPintOr">castPintOr</a></li><li><a href="global.html#createFileStore">createFileStore</a></li><li><a href="global.html#createUsageCounter">createUsageCounter</a></li><li><a href="global.html#defaultIntegratePrompt">defaultIntegratePrompt</a></li><li><a href="global.html#dfTimeoutMs">dfTimeoutMs</a></li><li><a href="global.html#dispatchAi">dispatchAi</a></li><li><a href="global.html#dispatchAiFallback">dispatchAiFallback</a></li><li><a href="global.html#dispatchAiWkf">dispatchAiWkf</a></li><li><a href="global.html#dispatchAntigravity">dispatchAntigravity</a></li><li><a href="global.html#dispatchApiOpenaiCompat">dispatchApiOpenaiCompat</a></li><li><a href="global.html#dispatchApiOpenaiResponses">dispatchApiOpenaiResponses</a></li><li><a href="global.html#dispatchClaude">dispatchClaude</a></li><li><a href="global.html#dispatchCodex">dispatchCodex</a></li><li><a href="global.html#dispatchOpencode">dispatchOpencode</a></li><li><a href="global.html#extractJsonLoose">extractJsonLoose</a></li><li><a href="global.html#extractOutputText">extractOutputText</a></li><li><a href="global.html#getCliArgs">getCliArgs</a></li><li><a href="global.html#getErrorResult">getErrorResult</a></li><li><a href="global.html#getErrorType">getErrorType</a></li><li><a href="global.html#initState">initState</a></li><li><a href="global.html#isKeyIndependentFail">isKeyIndependentFail</a></li><li><a href="global.html#readEnvFile">readEnvFile</a></li><li><a href="global.html#reorderByCooling">reorderByCooling</a></li><li><a href="global.html#resolveProviders">resolveProviders</a></li><li><a href="global.html#runFanout">runFanout</a></li><li><a href="global.html#runFanoutPipeline">runFanoutPipeline</a></li><li><a href="global.html#runRolePipeline">runRolePipeline</a></li><li><a href="global.html#salvageTruncatedArray">salvageTruncatedArray</a></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -220,7 +220,7 @@ callAiWithFallback預設自動掛上(傳promptPrefix:''關閉),
220
220
 
221
221
  <dt class="tag-source">Source:</dt>
222
222
  <dd class="tag-source"><ul class="dummy"><li>
223
- <a href="WDispatchAi.mjs.html">WDispatchAi.mjs</a>, <a href="WDispatchAi.mjs.html#line42">line 42</a>
223
+ <a href="WDispatchAi.mjs.html">WDispatchAi.mjs</a>, <a href="WDispatchAi.mjs.html#line43">line 43</a>
224
224
  </li></ul></dd>
225
225
 
226
226
 
@@ -294,7 +294,7 @@ callAiWithFallback預設自動掛上(傳promptPrefix:''關閉),
294
294
 
295
295
  <dt class="tag-source">Source:</dt>
296
296
  <dd class="tag-source"><ul class="dummy"><li>
297
- <a href="adapters.mjs.html">adapters.mjs</a>, <a href="adapters.mjs.html#line57">line 57</a>
297
+ <a href="adapters.mjs.html">adapters.mjs</a>, <a href="adapters.mjs.html#line58">line 58</a>
298
298
  </li></ul></dd>
299
299
 
300
300
 
@@ -350,7 +350,7 @@ callAiWithFallback預設自動掛上(傳promptPrefix:''關閉),
350
350
  <pre class="prettyprint"><code>import adapters from './src/adapters.mjs'
351
351
 
352
352
  console.log(Object.keys(adapters))
353
- // => ['opencode', 'claude', 'codex', 'antigravity', 'api-openai-compat']</code></pre>
353
+ // => ['opencode', 'claude', 'codex', 'antigravity', 'api-openai-compat', 'api-openai-responses']</code></pre>
354
354
 
355
355
 
356
356
 
@@ -456,7 +456,7 @@ console.log(dfTimeoutMs)
456
456
 
457
457
  <dt class="tag-source">Source:</dt>
458
458
  <dd class="tag-source"><ul class="dummy"><li>
459
- <a href="getErrorType.mjs.html">getErrorType.mjs</a>, <a href="getErrorType.mjs.html#line87">line 87</a>
459
+ <a href="getErrorType.mjs.html">getErrorType.mjs</a>, <a href="getErrorType.mjs.html#line89">line 89</a>
460
460
  </li></ul></dd>
461
461
 
462
462
 
@@ -983,13 +983,17 @@ console.log(buildChain(providers, { use: 'a', fallback: ['b', 'c'] }))
983
983
  <dl class="details">
984
984
 
985
985
  <dt class="tag-description">Description:</dt>
986
- <dd class="tag-description"><ul class="dummy"><li><p>建立驗證函式(規則語法同execCli之validate)</p></li></ul></dd>
986
+ <dd class="tag-description"><ul class="dummy"><li><p>建立驗證函式(規則語法同execCli之validate)</p>
987
+ <p>特點:
988
+ 傳入自訂函式時直接使用;
989
+ 規則字串支援'nonempty'、'json'、'min:100',多規則可用逗號串接(須全部通過);
990
+ 規則本身無效(如'min:abc')視為驗證失敗而非靜默跳過——避免打錯規則卻以為有在驗</p></li></ul></dd>
987
991
 
988
992
 
989
993
 
990
994
  <dt class="tag-source">Source:</dt>
991
995
  <dd class="tag-source"><ul class="dummy"><li>
992
- <a href="dispatchApiOpenaiCompat.mjs.html">dispatchApiOpenaiCompat.mjs</a>, <a href="dispatchApiOpenaiCompat.mjs.html#line75">line 75</a>
996
+ <a href="buildValidator.mjs.html">buildValidator.mjs</a>, <a href="buildValidator.mjs.html#line38">line 38</a>
993
997
  </li></ul></dd>
994
998
 
995
999
 
@@ -1034,6 +1038,18 @@ console.log(buildChain(providers, { use: 'a', fallback: ['b', 'c'] }))
1034
1038
 
1035
1039
 
1036
1040
 
1041
+ <h5 class="h5-examples">Example</h5>
1042
+
1043
+ <pre class="prettyprint"><code>import buildValidator from './src/buildValidator.mjs'
1044
+
1045
+ let v = buildValidator('nonempty,min:3')
1046
+ console.log(v('abcd'), v('ab'), v(''))
1047
+ // => true false false
1048
+
1049
+ console.log(buildValidator(null))
1050
+ // => null</code></pre>
1051
+
1052
+
1037
1053
 
1038
1054
 
1039
1055
  <h5 class="h5-parameters">Parameters:</h5>
@@ -1981,7 +1997,7 @@ await test()
1981
1997
 
1982
1998
  <dt class="tag-source">Source:</dt>
1983
1999
  <dd class="tag-source"><ul class="dummy"><li>
1984
- <a href="dispatchApiOpenaiCompat.mjs.html">dispatchApiOpenaiCompat.mjs</a>, <a href="dispatchApiOpenaiCompat.mjs.html#line141">line 141</a>
2000
+ <a href="dispatchApiOpenaiCompat.mjs.html">dispatchApiOpenaiCompat.mjs</a>, <a href="dispatchApiOpenaiCompat.mjs.html#line77">line 77</a>
1985
2001
  </li></ul></dd>
1986
2002
 
1987
2003
 
@@ -2222,7 +2238,7 @@ await test()
2222
2238
 
2223
2239
 
2224
2240
 
2225
- <h4 class="name" id="castPintOr"><span class="type-signature"></span>castPintOr<span class="signature">(v, df)</span><span class="type-signature"> &rarr; {Number|*}</span></h4>
2241
+ <h4 class="name" id="callOnce"><span class="type-signature type-signature-async">(async) </span>callOnce<span class="signature">(url, headers, body, timeoutMs, validator)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
2226
2242
 
2227
2243
 
2228
2244
 
@@ -2232,16 +2248,13 @@ await test()
2232
2248
  <dl class="details">
2233
2249
 
2234
2250
  <dt class="tag-description">Description:</dt>
2235
- <dd class="tag-description"><ul class="dummy"><li><p>正整數正規化:有效正整數即轉整數回傳,否則回傳預設值</p>
2236
- <p>本套件各層之數值設定(timeoutMs、budgetMs、minAttemptMs、cooldownMs、retryDelayMs等)
2237
- 皆採同一寬容策略「無效即靜默回退預設」,統一收斂於此,
2238
- 避免同一7行判斷區塊散落各轉接器(曾重複6處)</p></li></ul></dd>
2251
+ <dd class="tag-description"><ul class="dummy"><li><p>單次HTTP呼叫(內部使用, 不含重試邏輯)</p></li></ul></dd>
2239
2252
 
2240
2253
 
2241
2254
 
2242
2255
  <dt class="tag-source">Source:</dt>
2243
2256
  <dd class="tag-source"><ul class="dummy"><li>
2244
- <a href="castPintOr.mjs.html">castPintOr.mjs</a>, <a href="castPintOr.mjs.html#line29">line 29</a>
2257
+ <a href="dispatchApiOpenaiResponses.mjs.html">dispatchApiOpenaiResponses.mjs</a>, <a href="dispatchApiOpenaiResponses.mjs.html#line120">line 120</a>
2245
2258
  </li></ul></dd>
2246
2259
 
2247
2260
 
@@ -2286,20 +2299,6 @@ await test()
2286
2299
 
2287
2300
 
2288
2301
 
2289
- <h5 class="h5-examples">Example</h5>
2290
-
2291
- <pre class="prettyprint"><code>import castPintOr from './src/castPintOr.mjs'
2292
-
2293
- console.log(castPintOr(5000, 300000))
2294
- // => 5000
2295
-
2296
- console.log(castPintOr('abc', 300000))
2297
- // => 300000
2298
-
2299
- console.log(castPintOr(undefined, null))
2300
- // => null</code></pre>
2301
-
2302
-
2303
2302
 
2304
2303
 
2305
2304
  <h5 class="h5-parameters">Parameters:</h5>
@@ -2327,13 +2326,13 @@ console.log(castPintOr(undefined, null))
2327
2326
 
2328
2327
  <tr>
2329
2328
 
2330
- <td class="name"><code>v</code></td>
2329
+ <td class="name"><code>url</code></td>
2331
2330
 
2332
2331
 
2333
2332
  <td class="type">
2334
2333
 
2335
2334
 
2336
- <span class="param-type">*</span>
2335
+ <span class="param-type">String</span>
2337
2336
 
2338
2337
 
2339
2338
 
@@ -2344,20 +2343,20 @@ console.log(castPintOr(undefined, null))
2344
2343
 
2345
2344
 
2346
2345
 
2347
- <td class="description last"><p>輸入待正規化之值</p></td>
2346
+ <td class="description last"><p>輸入完整端點網址字串</p></td>
2348
2347
  </tr>
2349
2348
 
2350
2349
 
2351
2350
 
2352
2351
  <tr>
2353
2352
 
2354
- <td class="name"><code>df</code></td>
2353
+ <td class="name"><code>headers</code></td>
2355
2354
 
2356
2355
 
2357
2356
  <td class="type">
2358
2357
 
2359
2358
 
2360
- <span class="param-type">*</span>
2359
+ <span class="param-type">Object</span>
2361
2360
 
2362
2361
 
2363
2362
 
@@ -2368,7 +2367,82 @@ console.log(castPintOr(undefined, null))
2368
2367
 
2369
2368
 
2370
2369
 
2371
- <td class="description last"><p>輸入無效時之預設值(可為null代表不限)</p></td>
2370
+ <td class="description last"><p>輸入請求標頭物件</p></td>
2371
+ </tr>
2372
+
2373
+
2374
+
2375
+ <tr>
2376
+
2377
+ <td class="name"><code>body</code></td>
2378
+
2379
+
2380
+ <td class="type">
2381
+
2382
+
2383
+ <span class="param-type">Object</span>
2384
+
2385
+
2386
+
2387
+
2388
+ </td>
2389
+
2390
+
2391
+
2392
+
2393
+
2394
+ <td class="description last"><p>輸入請求本體物件</p></td>
2395
+ </tr>
2396
+
2397
+
2398
+
2399
+ <tr>
2400
+
2401
+ <td class="name"><code>timeoutMs</code></td>
2402
+
2403
+
2404
+ <td class="type">
2405
+
2406
+
2407
+ <span class="param-type">Number</span>
2408
+
2409
+
2410
+
2411
+
2412
+ </td>
2413
+
2414
+
2415
+
2416
+
2417
+
2418
+ <td class="description last"><p>輸入逾時毫秒</p></td>
2419
+ </tr>
2420
+
2421
+
2422
+
2423
+ <tr>
2424
+
2425
+ <td class="name"><code>validator</code></td>
2426
+
2427
+
2428
+ <td class="type">
2429
+
2430
+
2431
+ <span class="param-type">function</span>
2432
+ |
2433
+
2434
+ <span class="param-type">null</span>
2435
+
2436
+
2437
+
2438
+
2439
+ </td>
2440
+
2441
+
2442
+
2443
+
2444
+
2445
+ <td class="description last"><p>輸入驗證函式</p></td>
2372
2446
  </tr>
2373
2447
 
2374
2448
 
@@ -2394,7 +2468,7 @@ console.log(castPintOr(undefined, null))
2394
2468
 
2395
2469
 
2396
2470
  <div class="param-desc">
2397
- <p>回傳正規化後之正整數,v非有效正整數時回傳df</p>
2471
+ <p>回傳Promise,resolve回傳結果物件</p>
2398
2472
  </div>
2399
2473
 
2400
2474
 
@@ -2405,10 +2479,7 @@ console.log(castPintOr(undefined, null))
2405
2479
  </dt>
2406
2480
  <dd>
2407
2481
 
2408
- <span class="param-type">Number</span>
2409
- |
2410
-
2411
- <span class="param-type">*</span>
2482
+ <span class="param-type">Promise</span>
2412
2483
 
2413
2484
 
2414
2485
 
@@ -2424,7 +2495,7 @@ console.log(castPintOr(undefined, null))
2424
2495
 
2425
2496
 
2426
2497
 
2427
- <h4 class="name" id="createFileStore"><span class="type-signature"></span>createFileStore<span class="signature">(opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Object}</span></h4>
2498
+ <h4 class="name" id="castPintOr"><span class="type-signature"></span>castPintOr<span class="signature">(v, df)</span><span class="type-signature"> &rarr; {Number|*}</span></h4>
2428
2499
 
2429
2500
 
2430
2501
 
@@ -2434,18 +2505,16 @@ console.log(castPintOr(undefined, null))
2434
2505
  <dl class="details">
2435
2506
 
2436
2507
  <dt class="tag-description">Description:</dt>
2437
- <dd class="tag-description"><ul class="dummy"><li><p>建立dispatchAiFallback之store的檔案持久化(游標與冷卻跨行程有效)</p>
2438
- <p>特點:
2439
- 採排除式passthrough——state原封存還,僅剔除本層自用欄位(預設只有at:人讀的最後更新時間戳),
2440
- 日後套件擴充state欄位(如cooling)即自動相容,不需改本函數;
2441
- 檔案不存在或非法JSON時get回空物件(套件視為全新狀態);
2442
- stamp可注入時間戳函數(排程環境建議注入時區錨定者),寫入時補進at欄位供人工debug</p></li></ul></dd>
2508
+ <dd class="tag-description"><ul class="dummy"><li><p>正整數正規化:有效正整數即轉整數回傳,否則回傳預設值</p>
2509
+ <p>本套件各層之數值設定(timeoutMs、budgetMs、minAttemptMs、cooldownMs、retryDelayMs等)
2510
+ 皆採同一寬容策略「無效即靜默回退預設」,統一收斂於此,
2511
+ 避免同一7行判斷區塊散落各轉接器(曾重複6處)</p></li></ul></dd>
2443
2512
 
2444
2513
 
2445
2514
 
2446
2515
  <dt class="tag-source">Source:</dt>
2447
2516
  <dd class="tag-source"><ul class="dummy"><li>
2448
- <a href="wkf_createFileStore.mjs.html">wkf/createFileStore.mjs</a>, <a href="wkf_createFileStore.mjs.html#line56">line 56</a>
2517
+ <a href="castPintOr.mjs.html">castPintOr.mjs</a>, <a href="castPintOr.mjs.html#line29">line 29</a>
2449
2518
  </li></ul></dd>
2450
2519
 
2451
2520
 
@@ -2492,11 +2561,16 @@ stamp可注入時間戳函數(排程環境建議注入時區錨定者),寫入
2492
2561
 
2493
2562
  <h5 class="h5-examples">Example</h5>
2494
2563
 
2495
- <pre class="prettyprint"><code>import createFileStore from './src/wkf/createFileStore.mjs'
2496
- import dispatchAiFallback from './src/dispatchAiFallback.mjs'
2564
+ <pre class="prettyprint"><code>import castPintOr from './src/castPintOr.mjs'
2497
2565
 
2498
- let store = createFileStore({ dir: './state' })
2499
- //let r = await dispatchAiFallback(prompt, { providers, store, cooldownMs: 3600000 })</code></pre>
2566
+ console.log(castPintOr(5000, 300000))
2567
+ // => 5000
2568
+
2569
+ console.log(castPintOr('abc', 300000))
2570
+ // => 300000
2571
+
2572
+ console.log(castPintOr(undefined, null))
2573
+ // => null</code></pre>
2500
2574
 
2501
2575
 
2502
2576
 
@@ -2514,12 +2588,8 @@ let store = createFileStore({ dir: './state' })
2514
2588
  <th>Type</th>
2515
2589
 
2516
2590
 
2517
- <th>Attributes</th>
2518
-
2519
2591
 
2520
2592
 
2521
- <th>Default</th>
2522
-
2523
2593
 
2524
2594
  <th class="last">Description</th>
2525
2595
  </tr>
@@ -2530,13 +2600,13 @@ let store = createFileStore({ dir: './state' })
2530
2600
 
2531
2601
  <tr>
2532
2602
 
2533
- <td class="name"><code>opt</code></td>
2603
+ <td class="name"><code>v</code></td>
2534
2604
 
2535
2605
 
2536
2606
  <td class="type">
2537
2607
 
2538
2608
 
2539
- <span class="param-type">Object</span>
2609
+ <span class="param-type">*</span>
2540
2610
 
2541
2611
 
2542
2612
 
@@ -2544,62 +2614,23 @@ let store = createFileStore({ dir: './state' })
2544
2614
  </td>
2545
2615
 
2546
2616
 
2547
- <td class="attributes">
2548
-
2549
- &lt;optional><br>
2550
-
2551
-
2552
-
2553
-
2554
-
2555
- </td>
2556
-
2557
2617
 
2558
2618
 
2559
- <td class="default">
2560
-
2561
- <code>{}</code>
2562
-
2563
- </td>
2564
-
2565
-
2566
- <td class="description last"><p>輸入設定物件,預設{}</p>
2567
- <h6>Properties</h6>
2568
-
2569
-
2570
- <table class="params">
2571
- <thead>
2572
- <tr>
2573
-
2574
- <th>Name</th>
2575
-
2576
-
2577
- <th>Type</th>
2578
-
2579
-
2580
- <th>Attributes</th>
2581
-
2582
2619
 
2583
-
2584
- <th>Default</th>
2585
-
2586
-
2587
- <th class="last">Description</th>
2588
- </tr>
2589
- </thead>
2620
+ <td class="description last"><p>輸入待正規化之值</p></td>
2621
+ </tr>
2590
2622
 
2591
- <tbody>
2592
2623
 
2593
2624
 
2594
2625
  <tr>
2595
2626
 
2596
- <td class="name"><code>file</code></td>
2627
+ <td class="name"><code>df</code></td>
2597
2628
 
2598
2629
 
2599
2630
  <td class="type">
2600
2631
 
2601
2632
 
2602
- <span class="param-type">String</span>
2633
+ <span class="param-type">*</span>
2603
2634
 
2604
2635
 
2605
2636
 
@@ -2607,198 +2638,15 @@ let store = createFileStore({ dir: './state' })
2607
2638
  </td>
2608
2639
 
2609
2640
 
2610
- <td class="attributes">
2611
-
2612
- &lt;optional><br>
2613
-
2614
-
2615
-
2616
-
2617
-
2618
- </td>
2619
-
2620
2641
 
2621
2642
 
2622
- <td class="default">
2623
-
2624
- <code>null</code>
2625
-
2626
- </td>
2627
-
2628
2643
 
2629
- <td class="description last"><p>輸入狀態檔完整路徑字串,與dir/name二擇一</p></td>
2644
+ <td class="description last"><p>輸入無效時之預設值(可為null代表不限)</p></td>
2630
2645
  </tr>
2631
2646
 
2632
2647
 
2633
-
2634
- <tr>
2635
-
2636
- <td class="name"><code>dir</code></td>
2637
-
2638
-
2639
- <td class="type">
2640
-
2641
-
2642
- <span class="param-type">String</span>
2643
-
2644
-
2645
-
2646
-
2647
- </td>
2648
-
2649
-
2650
- <td class="attributes">
2651
-
2652
- &lt;optional><br>
2653
-
2654
-
2655
-
2656
-
2657
-
2658
- </td>
2659
-
2660
-
2661
-
2662
- <td class="default">
2663
-
2664
- <code>null</code>
2665
-
2666
- </td>
2667
-
2668
-
2669
- <td class="description last"><p>輸入狀態目錄字串,與name組成檔案路徑</p></td>
2670
- </tr>
2671
-
2672
-
2673
-
2674
- <tr>
2675
-
2676
- <td class="name"><code>name</code></td>
2677
-
2678
-
2679
- <td class="type">
2680
-
2681
-
2682
- <span class="param-type">String</span>
2683
-
2684
-
2685
-
2686
-
2687
- </td>
2688
-
2689
-
2690
- <td class="attributes">
2691
-
2692
- &lt;optional><br>
2693
-
2694
-
2695
-
2696
-
2697
-
2698
- </td>
2699
-
2700
-
2701
-
2702
- <td class="default">
2703
-
2704
- <code>'ai-cursor.json'</code>
2705
-
2706
- </td>
2707
-
2708
-
2709
- <td class="description last"><p>輸入狀態檔名字串,預設'ai-cursor.json'</p></td>
2710
- </tr>
2711
-
2712
-
2713
-
2714
- <tr>
2715
-
2716
- <td class="name"><code>ownKeys</code></td>
2717
-
2718
-
2719
- <td class="type">
2720
-
2721
-
2722
- <span class="param-type">Array</span>
2723
-
2724
-
2725
-
2726
-
2727
- </td>
2728
-
2729
-
2730
- <td class="attributes">
2731
-
2732
- &lt;optional><br>
2733
-
2734
-
2735
-
2736
-
2737
-
2738
- </td>
2739
-
2740
-
2741
-
2742
- <td class="default">
2743
-
2744
- <code>['at']</code>
2745
-
2746
- </td>
2747
-
2748
-
2749
- <td class="description last"><p>輸入本層自用、不屬於套件狀態之欄位名字串陣列,get時剔除set時補回,預設['at']</p></td>
2750
- </tr>
2751
-
2752
-
2753
-
2754
- <tr>
2755
-
2756
- <td class="name"><code>stamp</code></td>
2757
-
2758
-
2759
- <td class="type">
2760
-
2761
-
2762
- <span class="param-type">function</span>
2763
-
2764
-
2765
-
2766
-
2767
- </td>
2768
-
2769
-
2770
- <td class="attributes">
2771
-
2772
- &lt;optional><br>
2773
-
2774
-
2775
-
2776
-
2777
-
2778
- </td>
2779
-
2780
-
2781
-
2782
- <td class="default">
2783
-
2784
- <code>ISO時間戳</code>
2785
-
2786
- </td>
2787
-
2788
-
2789
- <td class="description last"><p>輸入時間戳函數()=&gt;String,寫入at欄位用,預設回傳new Date().toISOString()</p></td>
2790
- </tr>
2791
-
2792
-
2793
- </tbody>
2794
- </table>
2795
-
2796
- </td>
2797
- </tr>
2798
-
2799
-
2800
- </tbody>
2801
- </table>
2648
+ </tbody>
2649
+ </table>
2802
2650
 
2803
2651
 
2804
2652
 
@@ -2819,7 +2667,7 @@ let store = createFileStore({ dir: './state' })
2819
2667
 
2820
2668
 
2821
2669
  <div class="param-desc">
2822
- <p>回傳store物件,內含get、set(可直接餵dispatchAiFallback之store)與file(狀態檔路徑)</p>
2670
+ <p>回傳正規化後之正整數,v非有效正整數時回傳df</p>
2823
2671
  </div>
2824
2672
 
2825
2673
 
@@ -2830,7 +2678,10 @@ let store = createFileStore({ dir: './state' })
2830
2678
  </dt>
2831
2679
  <dd>
2832
2680
 
2833
- <span class="param-type">Object</span>
2681
+ <span class="param-type">Number</span>
2682
+ |
2683
+
2684
+ <span class="param-type">*</span>
2834
2685
 
2835
2686
 
2836
2687
 
@@ -2846,7 +2697,7 @@ let store = createFileStore({ dir: './state' })
2846
2697
 
2847
2698
 
2848
2699
 
2849
- <h4 class="name" id="createUsageCounter"><span class="type-signature"></span>createUsageCounter<span class="signature">(opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Object}</span></h4>
2700
+ <h4 class="name" id="createFileStore"><span class="type-signature"></span>createFileStore<span class="signature">(opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Object}</span></h4>
2850
2701
 
2851
2702
 
2852
2703
 
@@ -2856,19 +2707,18 @@ let store = createFileStore({ dir: './state' })
2856
2707
  <dl class="details">
2857
2708
 
2858
2709
  <dt class="tag-description">Description:</dt>
2859
- <dd class="tag-description"><ul class="dummy"><li><p>建立逐日、逐鍵之用量計數器(純觀測, 不參與任何判斷)</p>
2710
+ <dd class="tag-description"><ul class="dummy"><li><p>建立dispatchAiFallback之store的檔案持久化(游標與冷卻跨行程有效)</p>
2860
2711
  <p>特點:
2861
- onEvent可直接掛進dispatchAiFallback/dispatchAiWkf,於type為'try'時依keyOf取鍵累加——
2862
- 嘗試時即記帳,行程被外部時限中途砍掉已發出的請求仍有紀錄;
2863
- 逐日分桶並僅保留最近keepDays天,避免檔案無限成長;
2864
- getDate可注入時區錨定之日期函數——預設隨系統時區,排程session之系統時區可能為UTC+0
2865
- 而使日界錯8小時,排程環境務必注入</p></li></ul></dd>
2712
+ 採排除式passthrough——state原封存還,僅剔除本層自用欄位(預設只有at:人讀的最後更新時間戳),
2713
+ 日後套件擴充state欄位(如cooling)即自動相容,不需改本函數;
2714
+ 檔案不存在或非法JSON時get回空物件(套件視為全新狀態);
2715
+ stamp可注入時間戳函數(排程環境建議注入時區錨定者),寫入時補進at欄位供人工debug</p></li></ul></dd>
2866
2716
 
2867
2717
 
2868
2718
 
2869
2719
  <dt class="tag-source">Source:</dt>
2870
2720
  <dd class="tag-source"><ul class="dummy"><li>
2871
- <a href="wkf_createUsageCounter.mjs.html">wkf/createUsageCounter.mjs</a>, <a href="wkf_createUsageCounter.mjs.html#line59">line 59</a>
2721
+ <a href="wkf_createFileStore.mjs.html">wkf/createFileStore.mjs</a>, <a href="wkf_createFileStore.mjs.html#line56">line 56</a>
2872
2722
  </li></ul></dd>
2873
2723
 
2874
2724
 
@@ -2915,12 +2765,11 @@ getDate可注入時區錨定之日期函數——預設隨系統時區,排程s
2915
2765
 
2916
2766
  <h5 class="h5-examples">Example</h5>
2917
2767
 
2918
- <pre class="prettyprint"><code>import createUsageCounter from './src/wkf/createUsageCounter.mjs'
2768
+ <pre class="prettyprint"><code>import createFileStore from './src/wkf/createFileStore.mjs'
2769
+ import dispatchAiFallback from './src/dispatchAiFallback.mjs'
2919
2770
 
2920
- let usage = createUsageCounter({ dir: './state' })
2921
- //let r = await dispatchAiFallback(prompt, { providers, onEvent: usage.onEvent })
2922
- //console.log(usage.today())
2923
- // => { today: '2026-08-18', byKey: { 'agnes:agnes-2.5-flash#0': 3 }, total: 3 }</code></pre>
2771
+ let store = createFileStore({ dir: './state' })
2772
+ //let r = await dispatchAiFallback(prompt, { providers, store, cooldownMs: 3600000 })</code></pre>
2924
2773
 
2925
2774
 
2926
2775
 
@@ -3050,7 +2899,7 @@ let usage = createUsageCounter({ dir: './state' })
3050
2899
  </td>
3051
2900
 
3052
2901
 
3053
- <td class="description last"><p>輸入用量檔完整路徑字串,與dir/name二擇一</p></td>
2902
+ <td class="description last"><p>輸入狀態檔完整路徑字串,與dir/name二擇一</p></td>
3054
2903
  </tr>
3055
2904
 
3056
2905
 
@@ -3090,7 +2939,7 @@ let usage = createUsageCounter({ dir: './state' })
3090
2939
  </td>
3091
2940
 
3092
2941
 
3093
- <td class="description last"><p>輸入狀態目錄字串</p></td>
2942
+ <td class="description last"><p>輸入狀態目錄字串,與name組成檔案路徑</p></td>
3094
2943
  </tr>
3095
2944
 
3096
2945
 
@@ -3125,65 +2974,25 @@ let usage = createUsageCounter({ dir: './state' })
3125
2974
 
3126
2975
  <td class="default">
3127
2976
 
3128
- <code>'ai-usage.json'</code>
3129
-
3130
- </td>
3131
-
3132
-
3133
- <td class="description last"><p>輸入用量檔名字串,預設'ai-usage.json'</p></td>
3134
- </tr>
3135
-
3136
-
3137
-
3138
- <tr>
3139
-
3140
- <td class="name"><code>getDate</code></td>
3141
-
3142
-
3143
- <td class="type">
3144
-
3145
-
3146
- <span class="param-type">function</span>
3147
-
3148
-
3149
-
3150
-
3151
- </td>
3152
-
3153
-
3154
- <td class="attributes">
3155
-
3156
- &lt;optional><br>
3157
-
3158
-
3159
-
3160
-
3161
-
3162
- </td>
3163
-
3164
-
3165
-
3166
- <td class="default">
3167
-
3168
- <code>系統日期</code>
2977
+ <code>'ai-cursor.json'</code>
3169
2978
 
3170
2979
  </td>
3171
2980
 
3172
2981
 
3173
- <td class="description last"><p>輸入日期函數()=&gt;'YYYY-MM-DD',預設隨系統時區(排程環境建議注入時區錨定者)</p></td>
2982
+ <td class="description last"><p>輸入狀態檔名字串,預設'ai-cursor.json'</p></td>
3174
2983
  </tr>
3175
2984
 
3176
2985
 
3177
2986
 
3178
2987
  <tr>
3179
2988
 
3180
- <td class="name"><code>keepDays</code></td>
2989
+ <td class="name"><code>ownKeys</code></td>
3181
2990
 
3182
2991
 
3183
2992
  <td class="type">
3184
2993
 
3185
2994
 
3186
- <span class="param-type">Number</span>
2995
+ <span class="param-type">Array</span>
3187
2996
 
3188
2997
 
3189
2998
 
@@ -3205,19 +3014,19 @@ let usage = createUsageCounter({ dir: './state' })
3205
3014
 
3206
3015
  <td class="default">
3207
3016
 
3208
- <code>14</code>
3017
+ <code>['at']</code>
3209
3018
 
3210
3019
  </td>
3211
3020
 
3212
3021
 
3213
- <td class="description last"><p>輸入保留天數正整數,預設14</p></td>
3022
+ <td class="description last"><p>輸入本層自用、不屬於套件狀態之欄位名字串陣列,get時剔除set時補回,預設['at']</p></td>
3214
3023
  </tr>
3215
3024
 
3216
3025
 
3217
3026
 
3218
3027
  <tr>
3219
3028
 
3220
- <td class="name"><code>keyOf</code></td>
3029
+ <td class="name"><code>stamp</code></td>
3221
3030
 
3222
3031
 
3223
3032
  <td class="type">
@@ -3245,12 +3054,12 @@ let usage = createUsageCounter({ dir: './state' })
3245
3054
 
3246
3055
  <td class="default">
3247
3056
 
3248
- <code>(ev)=>ev.keyId||ev.providerId</code>
3057
+ <code>ISO時間戳</code>
3249
3058
 
3250
3059
  </td>
3251
3060
 
3252
3061
 
3253
- <td class="description last"><p>輸入計帳鍵函數(ev)=&gt;String,決定粒度(金鑰或條目),預設優先keyId</p></td>
3062
+ <td class="description last"><p>輸入時間戳函數()=&gt;String,寫入at欄位用,預設回傳new Date().toISOString()</p></td>
3254
3063
  </tr>
3255
3064
 
3256
3065
 
@@ -3283,7 +3092,7 @@ let usage = createUsageCounter({ dir: './state' })
3283
3092
 
3284
3093
 
3285
3094
  <div class="param-desc">
3286
- <p>回傳計數器物件,內含onEvent(可直接餵dispatchonEvent)、bump(手動累加)、today(今日統計)與file(用量檔路徑)</p>
3095
+ <p>回傳store物件,內含get、set(可直接餵dispatchAiFallbackstore)與file(狀態檔路徑)</p>
3287
3096
  </div>
3288
3097
 
3289
3098
 
@@ -3310,7 +3119,7 @@ let usage = createUsageCounter({ dir: './state' })
3310
3119
 
3311
3120
 
3312
3121
 
3313
- <h4 class="name" id="defaultIntegratePrompt"><span class="type-signature"></span>defaultIntegratePrompt<span class="signature">(candidates, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {String}</span></h4>
3122
+ <h4 class="name" id="createUsageCounter"><span class="type-signature"></span>createUsageCounter<span class="signature">(opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Object}</span></h4>
3314
3123
 
3315
3124
 
3316
3125
 
@@ -3320,13 +3129,19 @@ let usage = createUsageCounter({ dir: './state' })
3320
3129
  <dl class="details">
3321
3130
 
3322
3131
  <dt class="tag-description">Description:</dt>
3323
- <dd class="tag-description"><ul class="dummy"><li><p>預設整合提示詞模板:把成功候選JSON併入整合任務</p></li></ul></dd>
3132
+ <dd class="tag-description"><ul class="dummy"><li><p>建立逐日、逐鍵之用量計數器(純觀測, 不參與任何判斷)</p>
3133
+ <p>特點:
3134
+ onEvent可直接掛進dispatchAiFallback/dispatchAiWkf,於type為'try'時依keyOf取鍵累加——
3135
+ 嘗試時即記帳,行程被外部時限中途砍掉已發出的請求仍有紀錄;
3136
+ 逐日分桶並僅保留最近keepDays天,避免檔案無限成長;
3137
+ getDate可注入時區錨定之日期函數——預設隨系統時區,排程session之系統時區可能為UTC+0
3138
+ 而使日界錯8小時,排程環境務必注入</p></li></ul></dd>
3324
3139
 
3325
3140
 
3326
3141
 
3327
3142
  <dt class="tag-source">Source:</dt>
3328
3143
  <dd class="tag-source"><ul class="dummy"><li>
3329
- <a href="wkf_runFanout.mjs.html">wkf/runFanout.mjs</a>, <a href="wkf_runFanout.mjs.html#line31">line 31</a>
3144
+ <a href="wkf_createUsageCounter.mjs.html">wkf/createUsageCounter.mjs</a>, <a href="wkf_createUsageCounter.mjs.html#line59">line 59</a>
3330
3145
  </li></ul></dd>
3331
3146
 
3332
3147
 
@@ -3371,6 +3186,16 @@ let usage = createUsageCounter({ dir: './state' })
3371
3186
 
3372
3187
 
3373
3188
 
3189
+ <h5 class="h5-examples">Example</h5>
3190
+
3191
+ <pre class="prettyprint"><code>import createUsageCounter from './src/wkf/createUsageCounter.mjs'
3192
+
3193
+ let usage = createUsageCounter({ dir: './state' })
3194
+ //let r = await dispatchAiFallback(prompt, { providers, onEvent: usage.onEvent })
3195
+ //console.log(usage.today())
3196
+ // => { today: '2026-08-18', byKey: { 'agnes:agnes-2.5-flash#0': 3 }, total: 3 }</code></pre>
3197
+
3198
+
3374
3199
 
3375
3200
 
3376
3201
  <h5 class="h5-parameters">Parameters:</h5>
@@ -3402,13 +3227,13 @@ let usage = createUsageCounter({ dir: './state' })
3402
3227
 
3403
3228
  <tr>
3404
3229
 
3405
- <td class="name"><code>candidates</code></td>
3230
+ <td class="name"><code>opt</code></td>
3406
3231
 
3407
3232
 
3408
3233
  <td class="type">
3409
3234
 
3410
3235
 
3411
- <span class="param-type">Array</span>
3236
+ <span class="param-type">Object</span>
3412
3237
 
3413
3238
 
3414
3239
 
@@ -3418,6 +3243,8 @@ let usage = createUsageCounter({ dir: './state' })
3418
3243
 
3419
3244
  <td class="attributes">
3420
3245
 
3246
+ &lt;optional><br>
3247
+
3421
3248
 
3422
3249
 
3423
3250
 
@@ -3428,23 +3255,48 @@ let usage = createUsageCounter({ dir: './state' })
3428
3255
 
3429
3256
  <td class="default">
3430
3257
 
3258
+ <code>{}</code>
3259
+
3431
3260
  </td>
3432
3261
 
3433
3262
 
3434
- <td class="description last"><p>輸入成功候選物件陣列</p></td>
3435
- </tr>
3263
+ <td class="description last"><p>輸入設定物件,預設{}</p>
3264
+ <h6>Properties</h6>
3265
+
3266
+
3267
+ <table class="params">
3268
+ <thead>
3269
+ <tr>
3270
+
3271
+ <th>Name</th>
3272
+
3273
+
3274
+ <th>Type</th>
3275
+
3276
+
3277
+ <th>Attributes</th>
3278
+
3279
+
3280
+
3281
+ <th>Default</th>
3282
+
3283
+
3284
+ <th class="last">Description</th>
3285
+ </tr>
3286
+ </thead>
3436
3287
 
3288
+ <tbody>
3437
3289
 
3438
3290
 
3439
3291
  <tr>
3440
3292
 
3441
- <td class="name"><code>opt</code></td>
3293
+ <td class="name"><code>file</code></td>
3442
3294
 
3443
3295
 
3444
3296
  <td class="type">
3445
3297
 
3446
3298
 
3447
- <span class="param-type">Object</span>
3299
+ <span class="param-type">String</span>
3448
3300
 
3449
3301
 
3450
3302
 
@@ -3466,186 +3318,59 @@ let usage = createUsageCounter({ dir: './state' })
3466
3318
 
3467
3319
  <td class="default">
3468
3320
 
3469
- <code>{}</code>
3321
+ <code>null</code>
3470
3322
 
3471
3323
  </td>
3472
3324
 
3473
3325
 
3474
- <td class="description last"><p>輸入設定物件(取schema作為輸出格式示意),預設{}</p></td>
3326
+ <td class="description last"><p>輸入用量檔完整路徑字串,與dir/name二擇一</p></td>
3475
3327
  </tr>
3476
3328
 
3477
3329
 
3478
- </tbody>
3479
- </table>
3480
-
3481
-
3482
-
3483
-
3484
-
3485
-
3486
-
3487
-
3488
-
3489
-
3490
-
3491
-
3492
-
3493
-
3494
-
3495
-
3496
- <h5 class="h5-returns">Returns:</h5>
3497
-
3498
-
3499
- <div class="param-desc">
3500
- <p>回傳整合提示詞字串</p>
3501
- </div>
3502
-
3503
3330
 
3331
+ <tr>
3332
+
3333
+ <td class="name"><code>dir</code></td>
3334
+
3504
3335
 
3505
- <dl class="param-type">
3506
- <dt>
3507
- Type
3508
- </dt>
3509
- <dd>
3510
-
3336
+ <td class="type">
3337
+
3338
+
3511
3339
  <span class="param-type">String</span>
3512
3340
 
3513
3341
 
3514
3342
 
3515
- </dd>
3516
- </dl>
3517
-
3518
-
3519
-
3520
-
3521
-
3522
-
3523
3343
 
3344
+ </td>
3524
3345
 
3525
-
3526
-
3527
- <h4 class="name" id="dispatchAi"><span class="type-signature type-signature-async">(async) </span>dispatchAi<span class="signature">(kind, prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3528
-
3529
-
3530
-
3531
-
3532
-
3533
-
3534
- <dl class="details">
3535
-
3536
- <dt class="tag-description">Description:</dt>
3537
- <dd class="tag-description"><ul class="dummy"><li><p>依供應商種類(kind)分派至對應之轉接器</p>
3538
- <p>kind清單以adapters.mjs對照表為唯一來源(目前為'opencode'、'claude'、'codex'、'antigravity'、
3539
- 'api-openai-compat',CLI或API之選型判準見adapters.mjs檔頭)。
3540
- 各家金鑰模式不同(2026-08-08起於本機實測確認):opencode與api-openai-compat支援逐次注入金鑰,
3541
- 故可多把金鑰輪替;claude/codex/antigravity沿用CLI既有登入狀態,無逐次金鑰概念。
3542
- 故「輪替」的單位是「供應商條目」而非單純的金鑰:一個條目即一組(kind, model, 可選的key/provider),
3543
- 輪到誰就用誰的轉接器與模型</p></li></ul></dd>
3544
-
3545
-
3546
-
3547
- <dt class="tag-source">Source:</dt>
3548
- <dd class="tag-source"><ul class="dummy"><li>
3549
- <a href="dispatchAi.mjs.html">dispatchAi.mjs</a>, <a href="dispatchAi.mjs.html#line44">line 44</a>
3550
- </li></ul></dd>
3551
-
3552
-
3553
-
3554
-
3555
-
3556
-
3557
-
3558
-
3559
-
3560
-
3561
-
3562
-
3563
-
3564
-
3565
-
3566
-
3567
-
3568
-
3569
-
3570
-
3571
-
3572
-
3573
-
3574
-
3575
-
3576
-
3577
-
3578
-
3579
-
3580
-
3581
-
3582
- </dl>
3583
-
3584
-
3585
-
3586
-
3587
-
3588
-
3589
-
3590
-
3591
-
3592
-
3593
-
3594
- <h5 class="h5-examples">Example</h5>
3595
-
3596
- <pre class="prettyprint"><code>//need claude, codex or opencode cli in system PATH
3597
-
3598
- import dispatchAi from './src/dispatchAi.mjs'
3599
-
3600
- let test = async () => {
3601
-
3602
- let r = await dispatchAi('claude', '請只回覆兩個字:完成', { model: 'sonnet' })
3603
- console.log(r.ok, r.stdout.trim())
3604
- // => true '完成'
3605
-
3606
- let re = await dispatchAi('gemini', 'abc')
3607
- console.log(re.ok, re.error.indexOf('unknown ai kind: "gemini"') === 0)
3608
- // => false true
3609
-
3610
- }
3611
- await test()
3612
- .catch((err) => {
3613
- console.log(err)
3614
- })</code></pre>
3615
-
3616
-
3617
-
3618
-
3619
- <h5 class="h5-parameters">Parameters:</h5>
3620
-
3621
-
3622
- <table class="params">
3623
- <thead>
3624
- <tr>
3625
-
3626
- <th>Name</th>
3627
-
3346
+
3347
+ <td class="attributes">
3348
+
3349
+ &lt;optional><br>
3350
+
3628
3351
 
3629
- <th>Type</th>
3352
+
3630
3353
 
3631
-
3632
- <th>Attributes</th>
3633
-
3354
+
3355
+ </td>
3356
+
3634
3357
 
3635
-
3636
- <th>Default</th>
3637
-
3358
+
3359
+ <td class="default">
3360
+
3361
+ <code>null</code>
3362
+
3363
+ </td>
3364
+
3638
3365
 
3639
- <th class="last">Description</th>
3640
- </tr>
3641
- </thead>
3366
+ <td class="description last"><p>輸入狀態目錄字串</p></td>
3367
+ </tr>
3642
3368
 
3643
- <tbody>
3644
3369
 
3645
3370
 
3646
3371
  <tr>
3647
3372
 
3648
- <td class="name"><code>kind</code></td>
3373
+ <td class="name"><code>name</code></td>
3649
3374
 
3650
3375
 
3651
3376
  <td class="type">
@@ -3661,6 +3386,8 @@ await test()
3661
3386
 
3662
3387
  <td class="attributes">
3663
3388
 
3389
+ &lt;optional><br>
3390
+
3664
3391
 
3665
3392
 
3666
3393
 
@@ -3671,23 +3398,25 @@ await test()
3671
3398
 
3672
3399
  <td class="default">
3673
3400
 
3401
+ <code>'ai-usage.json'</code>
3402
+
3674
3403
  </td>
3675
3404
 
3676
3405
 
3677
- <td class="description last"><p>輸入供應商種類字串,須為adapters.mjs對照表之鍵名,目前可選'opencode'、'claude'、'codex'、'antigravity'、'api-openai-compat'</p></td>
3406
+ <td class="description last"><p>輸入用量檔名字串,預設'ai-usage.json'</p></td>
3678
3407
  </tr>
3679
3408
 
3680
3409
 
3681
3410
 
3682
3411
  <tr>
3683
3412
 
3684
- <td class="name"><code>prompt</code></td>
3413
+ <td class="name"><code>getDate</code></td>
3685
3414
 
3686
3415
 
3687
3416
  <td class="type">
3688
3417
 
3689
3418
 
3690
- <span class="param-type">String</span>
3419
+ <span class="param-type">function</span>
3691
3420
 
3692
3421
 
3693
3422
 
@@ -3697,6 +3426,8 @@ await test()
3697
3426
 
3698
3427
  <td class="attributes">
3699
3428
 
3429
+ &lt;optional><br>
3430
+
3700
3431
 
3701
3432
 
3702
3433
 
@@ -3707,23 +3438,25 @@ await test()
3707
3438
 
3708
3439
  <td class="default">
3709
3440
 
3441
+ <code>系統日期</code>
3442
+
3710
3443
  </td>
3711
3444
 
3712
3445
 
3713
- <td class="description last"><p>輸入提示詞字串</p></td>
3446
+ <td class="description last"><p>輸入日期函數()=&gt;'YYYY-MM-DD',預設隨系統時區(排程環境建議注入時區錨定者)</p></td>
3714
3447
  </tr>
3715
3448
 
3716
3449
 
3717
3450
 
3718
3451
  <tr>
3719
3452
 
3720
- <td class="name"><code>opt</code></td>
3453
+ <td class="name"><code>keepDays</code></td>
3721
3454
 
3722
3455
 
3723
3456
  <td class="type">
3724
3457
 
3725
3458
 
3726
- <span class="param-type">Object</span>
3459
+ <span class="param-type">Number</span>
3727
3460
 
3728
3461
 
3729
3462
 
@@ -3745,19 +3478,66 @@ await test()
3745
3478
 
3746
3479
  <td class="default">
3747
3480
 
3748
- <code>{}</code>
3481
+ <code>14</code>
3749
3482
 
3750
3483
  </td>
3751
3484
 
3752
3485
 
3753
- <td class="description last"><p>輸入設定物件,原樣轉傳對應轉接器,各轉接器可用設定詳見dispatchOpencode、dispatchClaude、dispatchCodex、dispatchAntigravity、dispatchApiOpenaiCompat,預設{}</p></td>
3486
+ <td class="description last"><p>輸入保留天數正整數,預設14</p></td>
3754
3487
  </tr>
3755
3488
 
3756
3489
 
3757
- </tbody>
3758
- </table>
3759
-
3760
-
3490
+
3491
+ <tr>
3492
+
3493
+ <td class="name"><code>keyOf</code></td>
3494
+
3495
+
3496
+ <td class="type">
3497
+
3498
+
3499
+ <span class="param-type">function</span>
3500
+
3501
+
3502
+
3503
+
3504
+ </td>
3505
+
3506
+
3507
+ <td class="attributes">
3508
+
3509
+ &lt;optional><br>
3510
+
3511
+
3512
+
3513
+
3514
+
3515
+ </td>
3516
+
3517
+
3518
+
3519
+ <td class="default">
3520
+
3521
+ <code>(ev)=>ev.keyId||ev.providerId</code>
3522
+
3523
+ </td>
3524
+
3525
+
3526
+ <td class="description last"><p>輸入計帳鍵函數(ev)=&gt;String,決定粒度(金鑰或條目),預設優先keyId</p></td>
3527
+ </tr>
3528
+
3529
+
3530
+ </tbody>
3531
+ </table>
3532
+
3533
+ </td>
3534
+ </tr>
3535
+
3536
+
3537
+ </tbody>
3538
+ </table>
3539
+
3540
+
3761
3541
 
3762
3542
 
3763
3543
 
@@ -3776,7 +3556,7 @@ await test()
3776
3556
 
3777
3557
 
3778
3558
  <div class="param-desc">
3779
- <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject</p>
3559
+ <p>回傳計數器物件,內含onEvent(可直接餵dispatch之onEvent)、bump(手動累加)、today(今日統計)與file(用量檔路徑)</p>
3780
3560
  </div>
3781
3561
 
3782
3562
 
@@ -3787,7 +3567,7 @@ await test()
3787
3567
  </dt>
3788
3568
  <dd>
3789
3569
 
3790
- <span class="param-type">Promise</span>
3570
+ <span class="param-type">Object</span>
3791
3571
 
3792
3572
 
3793
3573
 
@@ -3803,7 +3583,7 @@ await test()
3803
3583
 
3804
3584
 
3805
3585
 
3806
- <h4 class="name" id="dispatchAiFallback"><span class="type-signature type-signature-async">(async) </span>dispatchAiFallback<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3586
+ <h4 class="name" id="defaultIntegratePrompt"><span class="type-signature"></span>defaultIntegratePrompt<span class="signature">(candidates, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {String}</span></h4>
3807
3587
 
3808
3588
 
3809
3589
 
@@ -3813,21 +3593,13 @@ await test()
3813
3593
  <dl class="details">
3814
3594
 
3815
3595
  <dt class="tag-description">Description:</dt>
3816
- <dd class="tag-description"><ul class="dummy"><li><p>依供應商清單順序自動遞補調用AI,組內多金鑰以游標輪替</p>
3817
- <p>特點:
3818
- providers陣列順序即優先序,排前面的先用;
3819
- 條目本身即該次調用之opt(除id與keys外原樣透傳對應轉接器),與dispatchAi「條目直接當opt」同一約定;
3820
- 條目給予keys(多把金鑰)時以游標輪替,某把失敗自動換下一把,全數失敗才遞補下一組;
3821
- 與金鑰無關之失敗(逾時/執行檔不存在/參數錯誤/輸出未過驗證/未知kind)直接整組跳過,不逐把空耗;
3822
- 跨次執行僅記憶游標(經store注入持久化),不設金鑰停用清單——額度視窗形態多樣(5小時滾動/逐時/逐日),
3823
- 停用會把已恢復的金鑰閒置,而重探的代價僅一次快速失敗;
3824
- 本函數不會reject,一律以結果物件之ok與error欄位回報成敗</p></li></ul></dd>
3596
+ <dd class="tag-description"><ul class="dummy"><li><p>預設整合提示詞模板:把成功候選JSON併入整合任務</p></li></ul></dd>
3825
3597
 
3826
3598
 
3827
3599
 
3828
3600
  <dt class="tag-source">Source:</dt>
3829
3601
  <dd class="tag-source"><ul class="dummy"><li>
3830
- <a href="dispatchAiFallback.mjs.html">dispatchAiFallback.mjs</a>, <a href="dispatchAiFallback.mjs.html#line292">line 292</a>
3602
+ <a href="wkf_runFanout.mjs.html">wkf/runFanout.mjs</a>, <a href="wkf_runFanout.mjs.html#line31">line 31</a>
3831
3603
  </li></ul></dd>
3832
3604
 
3833
3605
 
@@ -3872,48 +3644,6 @@ providers陣列順序即優先序,排前面的先用;
3872
3644
 
3873
3645
 
3874
3646
 
3875
- <h5 class="h5-examples">Example</h5>
3876
-
3877
- <pre class="prettyprint"><code>//need opencode, claude, codex cli in system PATH
3878
-
3879
- import dispatchAiFallback from './src/dispatchAiFallback.mjs'
3880
-
3881
- let test = async () => {
3882
-
3883
- let r = await dispatchAiFallback('請只回覆兩個字:完成', {
3884
- providers: [
3885
- {
3886
- //id區分到模型且帶路徑: 同一模型經REST與CLI取得屬兩個供應商
3887
- id: 'zen:deepseek-v4-flash-free',
3888
- kind: 'api-openai-compat',
3889
- baseURL: 'https://opencode.ai/zen/v1',
3890
- model: 'deepseek-v4-flash-free',
3891
- keys: ['sk-aaa', 'sk-bbb'], //多把金鑰, 某把失敗自動換下一把
3892
- },
3893
- {
3894
- id: 'oc:opencode/deepseek-v4-flash-free', //同一模型之CLI版(有工具, 較慢)
3895
- kind: 'opencode',
3896
- model: 'opencode/deepseek-v4-flash-free',
3897
- provider: 'opencode',
3898
- keys: ['sk-aaa', 'sk-bbb'],
3899
- timeoutMs: 180000,
3900
- },
3901
- { id: 'claude:sonnet', kind: 'claude', model: 'sonnet' }, //以上全敗時遞補
3902
- { id: 'codex:gpt-5.6-luna', kind: 'codex', model: 'gpt-5.6-luna', sandbox: 'read-only' },
3903
- ],
3904
- budgetMs: 600000,
3905
- onEvent: (ev) => console.log(ev.type, ev.providerId, ev.keyIndex),
3906
- })
3907
- console.log(r.ok, r.providerId, r.keyIndex, r.tried.length)
3908
- // => true 'zen:deepseek-v4-flash-free' 0 1
3909
-
3910
- }
3911
- await test()
3912
- .catch((err) => {
3913
- console.log(err)
3914
- })</code></pre>
3915
-
3916
-
3917
3647
 
3918
3648
 
3919
3649
  <h5 class="h5-parameters">Parameters:</h5>
@@ -3945,13 +3675,13 @@ await test()
3945
3675
 
3946
3676
  <tr>
3947
3677
 
3948
- <td class="name"><code>prompt</code></td>
3678
+ <td class="name"><code>candidates</code></td>
3949
3679
 
3950
3680
 
3951
3681
  <td class="type">
3952
3682
 
3953
3683
 
3954
- <span class="param-type">String</span>
3684
+ <span class="param-type">Array</span>
3955
3685
 
3956
3686
 
3957
3687
 
@@ -3974,7 +3704,7 @@ await test()
3974
3704
  </td>
3975
3705
 
3976
3706
 
3977
- <td class="description last"><p>輸入提示詞字串,一律以stdin傳入子進程</p></td>
3707
+ <td class="description last"><p>輸入成功候選物件陣列</p></td>
3978
3708
  </tr>
3979
3709
 
3980
3710
 
@@ -4014,227 +3744,187 @@ await test()
4014
3744
  </td>
4015
3745
 
4016
3746
 
4017
- <td class="description last"><p>輸入設定物件,預設{}</p>
4018
- <h6>Properties</h6>
4019
-
3747
+ <td class="description last"><p>輸入設定物件(取schema作為輸出格式示意),預設{}</p></td>
3748
+ </tr>
4020
3749
 
4021
- <table class="params">
4022
- <thead>
4023
- <tr>
4024
-
4025
- <th>Name</th>
4026
-
3750
+
3751
+ </tbody>
3752
+ </table>
4027
3753
 
4028
- <th>Type</th>
4029
3754
 
4030
-
4031
- <th>Attributes</th>
4032
-
4033
3755
 
4034
-
4035
- <th>Default</th>
4036
-
4037
3756
 
4038
- <th class="last">Description</th>
4039
- </tr>
4040
- </thead>
4041
3757
 
4042
- <tbody>
4043
-
4044
3758
 
4045
- <tr>
4046
-
4047
- <td class="name"><code>providers</code></td>
4048
-
4049
3759
 
4050
- <td class="type">
4051
-
4052
-
4053
- <span class="param-type">Array</span>
4054
3760
 
4055
3761
 
4056
3762
 
4057
-
4058
- </td>
4059
3763
 
4060
-
4061
- <td class="attributes">
4062
-
4063
3764
 
4064
-
4065
3765
 
4066
-
4067
- </td>
4068
-
4069
3766
 
4070
-
4071
- <td class="default">
4072
-
4073
- </td>
4074
-
4075
3767
 
4076
- <td class="description last"><p>輸入供應商條目物件陣列,順序即優先序。各條目除下列鍵外,其餘鍵(kind、model、exe、provider、config、sandbox、timeoutMs等)即該條目之opt原樣透傳對應轉接器</p>
4077
- <h6>Properties</h6>
4078
-
4079
3768
 
4080
- <table class="params">
4081
- <thead>
4082
- <tr>
4083
-
4084
- <th>Name</th>
3769
+ <h5 class="h5-returns">Returns:</h5>
3770
+
4085
3771
 
3772
+ <div class="param-desc">
3773
+ <p>回傳整合提示詞字串</p>
3774
+ </div>
4086
3775
 
4087
- <th>Type</th>
4088
3776
 
4089
-
4090
- <th>Attributes</th>
4091
-
4092
3777
 
3778
+ <dl class="param-type">
3779
+ <dt>
3780
+ Type
3781
+ </dt>
3782
+ <dd>
4093
3783
 
4094
- <th>Default</th>
4095
-
3784
+ <span class="param-type">String</span>
4096
3785
 
4097
- <th class="last">Description</th>
4098
- </tr>
4099
- </thead>
4100
3786
 
4101
- <tbody>
4102
-
4103
3787
 
4104
- <tr>
4105
-
4106
- <td class="name"><code>id</code></td>
4107
-
3788
+ </dd>
3789
+ </dl>
4108
3790
 
4109
- <td class="type">
4110
-
4111
-
4112
- <span class="param-type">String</span>
3791
+
4113
3792
 
4114
3793
 
4115
3794
 
3795
+
4116
3796
 
4117
- </td>
4118
3797
 
4119
-
4120
- <td class="attributes">
4121
-
4122
- &lt;optional><br>
4123
-
3798
+
4124
3799
 
4125
-
3800
+ <h4 class="name" id="dispatchAi"><span class="type-signature type-signature-async">(async) </span>dispatchAi<span class="signature">(kind, prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3801
+
3802
+
4126
3803
 
4127
-
4128
- </td>
4129
-
4130
3804
 
4131
-
4132
- <td class="default">
4133
-
4134
- <code>條目索引字串</code>
4135
-
4136
- </td>
4137
-
4138
3805
 
4139
- <td class="description last"><p>輸入群組識別字串,游標以此為鍵、亦為日誌標籤,本套件不解讀其內容。須區分到「模型」而非只到「廠商」(如'claude:sonnet'而非'claude'),同一模型經不同路徑取得時須帶上路徑(如'poolside:laguna-s-2.1'與'or:poolside/laguna-s-2.1:free'),且務必唯一。省略時回退為陣列索引字串——索引是位置不是身分,日後插入條目會令後續條目繼承他人游標進度,故正式設定一律明給。詳見本檔檔頭之id設計規則</p></td>
4140
- </tr>
4141
3806
 
3807
+ <dl class="details">
3808
+
3809
+ <dt class="tag-description">Description:</dt>
3810
+ <dd class="tag-description"><ul class="dummy"><li><p>依供應商種類(kind)分派至對應之轉接器</p>
3811
+ <p>kind清單以adapters.mjs對照表為唯一來源(目前為'opencode'、'claude'、'codex'、'antigravity'、
3812
+ 'api-openai-compat',CLI或API之選型判準見adapters.mjs檔頭)。
3813
+ 各家金鑰模式不同(2026-08-08起於本機實測確認):opencode與api-openai-compat支援逐次注入金鑰,
3814
+ 故可多把金鑰輪替;claude/codex/antigravity沿用CLI既有登入狀態,無逐次金鑰概念。
3815
+ 故「輪替」的單位是「供應商條目」而非單純的金鑰:一個條目即一組(kind, model, 可選的key/provider),
3816
+ 輪到誰就用誰的轉接器與模型</p></li></ul></dd>
4142
3817
 
4143
3818
 
4144
- <tr>
4145
-
4146
- <td class="name"><code>keys</code></td>
4147
-
3819
+
3820
+ <dt class="tag-source">Source:</dt>
3821
+ <dd class="tag-source"><ul class="dummy"><li>
3822
+ <a href="dispatchAi.mjs.html">dispatchAi.mjs</a>, <a href="dispatchAi.mjs.html#line44">line 44</a>
3823
+ </li></ul></dd>
3824
+
4148
3825
 
4149
- <td class="type">
4150
-
4151
-
4152
- <span class="param-type">Array</span>
3826
+
4153
3827
 
3828
+
4154
3829
 
3830
+
4155
3831
 
4156
-
4157
- </td>
3832
+
4158
3833
 
4159
-
4160
- <td class="attributes">
4161
-
4162
- &lt;optional><br>
4163
-
3834
+
4164
3835
 
4165
-
3836
+
4166
3837
 
4167
-
4168
- </td>
4169
-
3838
+
4170
3839
 
4171
-
4172
- <td class="default">
4173
-
4174
- <code>[]</code>
4175
-
4176
- </td>
4177
-
3840
+
4178
3841
 
4179
- <td class="description last"><p>輸入同一服務之多把API key字串陣列,逐次注入輪替(kind為opencode時須同時於條目給予provider),省略代表沿用CLI既有登入狀態之單一虛擬金鑰</p></td>
4180
- </tr>
3842
+
4181
3843
 
4182
3844
 
4183
3845
 
4184
- <tr>
4185
-
4186
- <td class="name"><code>meta</code></td>
4187
-
3846
+
4188
3847
 
4189
- <td class="type">
4190
-
4191
-
4192
- <span class="param-type">*</span>
3848
+
4193
3849
 
3850
+
4194
3851
 
3852
+
3853
+
3854
+
3855
+ </dl>
4195
3856
 
4196
-
4197
- </td>
4198
3857
 
4199
-
4200
- <td class="attributes">
4201
-
4202
- &lt;optional><br>
4203
-
4204
3858
 
4205
-
4206
3859
 
4207
-
4208
- </td>
4209
-
4210
3860
 
4211
-
4212
- <td class="default">
4213
-
4214
- </td>
4215
-
4216
3861
 
4217
- <td class="description last"><p>輸入呼叫端自有資訊(分類、標籤、註記),保留鍵保證永不轉傳對應轉接器——條目其餘鍵一律原樣轉傳,自有欄位放此鍵可與轉傳機制永久絕緣,預設undefined</p></td>
4218
- </tr>
4219
3862
 
3863
+
3864
+
3865
+
3866
+
3867
+ <h5 class="h5-examples">Example</h5>
4220
3868
 
4221
- </tbody>
4222
- </table>
3869
+ <pre class="prettyprint"><code>//need claude, codex or opencode cli in system PATH
4223
3870
 
4224
- </td>
4225
- </tr>
3871
+ import dispatchAi from './src/dispatchAi.mjs'
3872
+
3873
+ let test = async () => {
3874
+
3875
+ let r = await dispatchAi('claude', '請只回覆兩個字:完成', { model: 'sonnet' })
3876
+ console.log(r.ok, r.stdout.trim())
3877
+ // => true '完成'
3878
+
3879
+ let re = await dispatchAi('gemini', 'abc')
3880
+ console.log(re.ok, re.error.indexOf('unknown ai kind: "gemini"') === 0)
3881
+ // => false true
3882
+
3883
+ }
3884
+ await test()
3885
+ .catch((err) => {
3886
+ console.log(err)
3887
+ })</code></pre>
3888
+
3889
+
3890
+
3891
+
3892
+ <h5 class="h5-parameters">Parameters:</h5>
3893
+
3894
+
3895
+ <table class="params">
3896
+ <thead>
3897
+ <tr>
3898
+
3899
+ <th>Name</th>
3900
+
4226
3901
 
3902
+ <th>Type</th>
3903
+
3904
+
3905
+ <th>Attributes</th>
3906
+
3907
+
3908
+
3909
+ <th>Default</th>
3910
+
3911
+
3912
+ <th class="last">Description</th>
3913
+ </tr>
3914
+ </thead>
3915
+
3916
+ <tbody>
4227
3917
 
4228
3918
 
4229
3919
  <tr>
4230
3920
 
4231
- <td class="name"><code>budgetMs</code></td>
3921
+ <td class="name"><code>kind</code></td>
4232
3922
 
4233
3923
 
4234
3924
  <td class="type">
4235
3925
 
4236
3926
 
4237
- <span class="param-type">Number</span>
3927
+ <span class="param-type">String</span>
4238
3928
 
4239
3929
 
4240
3930
 
@@ -4244,8 +3934,6 @@ await test()
4244
3934
 
4245
3935
  <td class="attributes">
4246
3936
 
4247
- &lt;optional><br>
4248
-
4249
3937
 
4250
3938
 
4251
3939
 
@@ -4256,25 +3944,23 @@ await test()
4256
3944
 
4257
3945
  <td class="default">
4258
3946
 
4259
- <code>null</code>
4260
-
4261
3947
  </td>
4262
3948
 
4263
3949
 
4264
- <td class="description last"><p>輸入整輪遞補之時間上限毫秒正整數,剩餘預算會壓進每次呼叫之timeoutMs,預設null代表不限</p></td>
3950
+ <td class="description last"><p>輸入供應商種類字串,須為adapters.mjs對照表之鍵名,目前可選'opencode'、'claude'、'codex'、'antigravity'、'api-openai-compat'</p></td>
4265
3951
  </tr>
4266
3952
 
4267
3953
 
4268
3954
 
4269
3955
  <tr>
4270
3956
 
4271
- <td class="name"><code>minAttemptMs</code></td>
3957
+ <td class="name"><code>prompt</code></td>
4272
3958
 
4273
3959
 
4274
3960
  <td class="type">
4275
3961
 
4276
3962
 
4277
- <span class="param-type">Number</span>
3963
+ <span class="param-type">String</span>
4278
3964
 
4279
3965
 
4280
3966
 
@@ -4284,8 +3970,6 @@ await test()
4284
3970
 
4285
3971
  <td class="attributes">
4286
3972
 
4287
- &lt;optional><br>
4288
-
4289
3973
 
4290
3974
 
4291
3975
 
@@ -4296,19 +3980,17 @@ await test()
4296
3980
 
4297
3981
  <td class="default">
4298
3982
 
4299
- <code>20000</code>
4300
-
4301
3983
  </td>
4302
3984
 
4303
3985
 
4304
- <td class="description last"><p>輸入單次嘗試之最低剩餘預算毫秒正整數,剩餘低於此值即停止嘗試回報budget exhausted,預設20000</p></td>
3986
+ <td class="description last"><p>輸入提示詞字串</p></td>
4305
3987
  </tr>
4306
3988
 
4307
3989
 
4308
3990
 
4309
3991
  <tr>
4310
3992
 
4311
- <td class="name"><code>store</code></td>
3993
+ <td class="name"><code>opt</code></td>
4312
3994
 
4313
3995
 
4314
3996
  <td class="type">
@@ -4336,65 +4018,1433 @@ await test()
4336
4018
 
4337
4019
  <td class="default">
4338
4020
 
4339
- <code>null</code>
4021
+ <code>{}</code>
4340
4022
 
4341
4023
  </td>
4342
4024
 
4343
4025
 
4344
- <td class="description last"><p>輸入狀態持久化物件{get:()=&gt;state,set:(state)=&gt;{}},state內含cursors(逐群組游標)與cooling(供應商冷卻時間戳,僅cooldownMs&gt;0時使用),省略代表用行程內記憶體(跨呼叫有效,重啟歸零)。假定單行程序列調用,並行請自行加鎖</p></td>
4026
+ <td class="description last"><p>輸入設定物件,原樣轉傳對應轉接器,各轉接器可用設定詳見dispatchOpencode、dispatchClaude、dispatchCodex、dispatchAntigravity、dispatchApiOpenaiCompat,預設{}</p></td>
4345
4027
  </tr>
4346
4028
 
4347
4029
 
4030
+ </tbody>
4031
+ </table>
4348
4032
 
4349
- <tr>
4350
-
4351
- <td class="name"><code>cooldownMs</code></td>
4352
-
4353
4033
 
4354
- <td class="type">
4355
-
4356
-
4357
- <span class="param-type">Number</span>
4358
4034
 
4359
4035
 
4360
4036
 
4361
-
4362
- </td>
4363
4037
 
4364
-
4365
- <td class="attributes">
4366
-
4367
- &lt;optional><br>
4368
-
4369
4038
 
4370
-
4371
4039
 
4372
-
4373
- </td>
4374
-
4375
4040
 
4376
-
4377
- <td class="default">
4378
-
4379
- <code>0</code>
4380
-
4381
- </td>
4382
-
4383
4041
 
4384
- <td class="description last"><p>輸入供應商冷卻視窗毫秒非負整數,&gt;0啟用:條目(限有明給id者)遭遇限流(HTTP 429,僅api類可偵測;CLI類可經coolDetect注入判定)或逾時(TIMEOUT開頭)後,於冷卻視窗內之後續呼叫中被移至鏈尾——只降序不移除,前面全敗時仍會被嘗試,任一次成功立即解除;注意啟用時「providers順序即優先序」會被暫時重排,此即本機制之目的;預設0代表不啟用</p></td>
4385
- </tr>
4042
+
4043
+
4044
+
4045
+
4046
+
4047
+
4048
+ <h5 class="h5-returns">Returns:</h5>
4049
+
4050
+
4051
+ <div class="param-desc">
4052
+ <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject</p>
4053
+ </div>
4054
+
4055
+
4056
+
4057
+ <dl class="param-type">
4058
+ <dt>
4059
+ Type
4060
+ </dt>
4061
+ <dd>
4062
+
4063
+ <span class="param-type">Promise</span>
4064
+
4065
+
4066
+
4067
+ </dd>
4068
+ </dl>
4386
4069
 
4387
4070
 
4388
4071
 
4389
- <tr>
4390
-
4391
- <td class="name"><code>coolDetect</code></td>
4392
-
4393
4072
 
4394
- <td class="type">
4073
+
4074
+
4395
4075
 
4396
-
4397
- <span class="param-type">function</span>
4076
+
4077
+
4078
+
4079
+ <h4 class="name" id="dispatchAiFallback"><span class="type-signature type-signature-async">(async) </span>dispatchAiFallback<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
4080
+
4081
+
4082
+
4083
+
4084
+
4085
+
4086
+ <dl class="details">
4087
+
4088
+ <dt class="tag-description">Description:</dt>
4089
+ <dd class="tag-description"><ul class="dummy"><li><p>依供應商清單順序自動遞補調用AI,組內多金鑰以游標輪替</p>
4090
+ <p>特點:
4091
+ providers陣列順序即優先序,排前面的先用;
4092
+ 條目本身即該次調用之opt(除id與keys外原樣透傳對應轉接器),與dispatchAi「條目直接當opt」同一約定;
4093
+ 條目給予keys(多把金鑰)時以游標輪替,某把失敗自動換下一把,全數失敗才遞補下一組;
4094
+ 與金鑰無關之失敗(逾時/執行檔不存在/參數錯誤/輸出未過驗證/未知kind)直接整組跳過,不逐把空耗;
4095
+ 跨次執行僅記憶游標(經store注入持久化),不設金鑰停用清單——額度視窗形態多樣(5小時滾動/逐時/逐日),
4096
+ 停用會把已恢復的金鑰閒置,而重探的代價僅一次快速失敗;
4097
+ 本函數不會reject,一律以結果物件之ok與error欄位回報成敗</p></li></ul></dd>
4098
+
4099
+
4100
+
4101
+ <dt class="tag-source">Source:</dt>
4102
+ <dd class="tag-source"><ul class="dummy"><li>
4103
+ <a href="dispatchAiFallback.mjs.html">dispatchAiFallback.mjs</a>, <a href="dispatchAiFallback.mjs.html#line292">line 292</a>
4104
+ </li></ul></dd>
4105
+
4106
+
4107
+
4108
+
4109
+
4110
+
4111
+
4112
+
4113
+
4114
+
4115
+
4116
+
4117
+
4118
+
4119
+
4120
+
4121
+
4122
+
4123
+
4124
+
4125
+
4126
+
4127
+
4128
+
4129
+
4130
+
4131
+
4132
+
4133
+
4134
+
4135
+
4136
+ </dl>
4137
+
4138
+
4139
+
4140
+
4141
+
4142
+
4143
+
4144
+
4145
+
4146
+
4147
+
4148
+ <h5 class="h5-examples">Example</h5>
4149
+
4150
+ <pre class="prettyprint"><code>//need opencode, claude, codex cli in system PATH
4151
+
4152
+ import dispatchAiFallback from './src/dispatchAiFallback.mjs'
4153
+
4154
+ let test = async () => {
4155
+
4156
+ let r = await dispatchAiFallback('請只回覆兩個字:完成', {
4157
+ providers: [
4158
+ {
4159
+ //id區分到模型且帶路徑: 同一模型經REST與CLI取得屬兩個供應商
4160
+ id: 'zen:deepseek-v4-flash-free',
4161
+ kind: 'api-openai-compat',
4162
+ baseURL: 'https://opencode.ai/zen/v1',
4163
+ model: 'deepseek-v4-flash-free',
4164
+ keys: ['sk-aaa', 'sk-bbb'], //多把金鑰, 某把失敗自動換下一把
4165
+ },
4166
+ {
4167
+ id: 'oc:opencode/deepseek-v4-flash-free', //同一模型之CLI版(有工具, 較慢)
4168
+ kind: 'opencode',
4169
+ model: 'opencode/deepseek-v4-flash-free',
4170
+ provider: 'opencode',
4171
+ keys: ['sk-aaa', 'sk-bbb'],
4172
+ timeoutMs: 180000,
4173
+ },
4174
+ { id: 'claude:sonnet', kind: 'claude', model: 'sonnet' }, //以上全敗時遞補
4175
+ { id: 'codex:gpt-5.6-luna', kind: 'codex', model: 'gpt-5.6-luna', sandbox: 'read-only' },
4176
+ ],
4177
+ budgetMs: 600000,
4178
+ onEvent: (ev) => console.log(ev.type, ev.providerId, ev.keyIndex),
4179
+ })
4180
+ console.log(r.ok, r.providerId, r.keyIndex, r.tried.length)
4181
+ // => true 'zen:deepseek-v4-flash-free' 0 1
4182
+
4183
+ }
4184
+ await test()
4185
+ .catch((err) => {
4186
+ console.log(err)
4187
+ })</code></pre>
4188
+
4189
+
4190
+
4191
+
4192
+ <h5 class="h5-parameters">Parameters:</h5>
4193
+
4194
+
4195
+ <table class="params">
4196
+ <thead>
4197
+ <tr>
4198
+
4199
+ <th>Name</th>
4200
+
4201
+
4202
+ <th>Type</th>
4203
+
4204
+
4205
+ <th>Attributes</th>
4206
+
4207
+
4208
+
4209
+ <th>Default</th>
4210
+
4211
+
4212
+ <th class="last">Description</th>
4213
+ </tr>
4214
+ </thead>
4215
+
4216
+ <tbody>
4217
+
4218
+
4219
+ <tr>
4220
+
4221
+ <td class="name"><code>prompt</code></td>
4222
+
4223
+
4224
+ <td class="type">
4225
+
4226
+
4227
+ <span class="param-type">String</span>
4228
+
4229
+
4230
+
4231
+
4232
+ </td>
4233
+
4234
+
4235
+ <td class="attributes">
4236
+
4237
+
4238
+
4239
+
4240
+
4241
+ </td>
4242
+
4243
+
4244
+
4245
+ <td class="default">
4246
+
4247
+ </td>
4248
+
4249
+
4250
+ <td class="description last"><p>輸入提示詞字串,一律以stdin傳入子進程</p></td>
4251
+ </tr>
4252
+
4253
+
4254
+
4255
+ <tr>
4256
+
4257
+ <td class="name"><code>opt</code></td>
4258
+
4259
+
4260
+ <td class="type">
4261
+
4262
+
4263
+ <span class="param-type">Object</span>
4264
+
4265
+
4266
+
4267
+
4268
+ </td>
4269
+
4270
+
4271
+ <td class="attributes">
4272
+
4273
+ &lt;optional><br>
4274
+
4275
+
4276
+
4277
+
4278
+
4279
+ </td>
4280
+
4281
+
4282
+
4283
+ <td class="default">
4284
+
4285
+ <code>{}</code>
4286
+
4287
+ </td>
4288
+
4289
+
4290
+ <td class="description last"><p>輸入設定物件,預設{}</p>
4291
+ <h6>Properties</h6>
4292
+
4293
+
4294
+ <table class="params">
4295
+ <thead>
4296
+ <tr>
4297
+
4298
+ <th>Name</th>
4299
+
4300
+
4301
+ <th>Type</th>
4302
+
4303
+
4304
+ <th>Attributes</th>
4305
+
4306
+
4307
+
4308
+ <th>Default</th>
4309
+
4310
+
4311
+ <th class="last">Description</th>
4312
+ </tr>
4313
+ </thead>
4314
+
4315
+ <tbody>
4316
+
4317
+
4318
+ <tr>
4319
+
4320
+ <td class="name"><code>providers</code></td>
4321
+
4322
+
4323
+ <td class="type">
4324
+
4325
+
4326
+ <span class="param-type">Array</span>
4327
+
4328
+
4329
+
4330
+
4331
+ </td>
4332
+
4333
+
4334
+ <td class="attributes">
4335
+
4336
+
4337
+
4338
+
4339
+
4340
+ </td>
4341
+
4342
+
4343
+
4344
+ <td class="default">
4345
+
4346
+ </td>
4347
+
4348
+
4349
+ <td class="description last"><p>輸入供應商條目物件陣列,順序即優先序。各條目除下列鍵外,其餘鍵(kind、model、exe、provider、config、sandbox、timeoutMs等)即該條目之opt原樣透傳對應轉接器</p>
4350
+ <h6>Properties</h6>
4351
+
4352
+
4353
+ <table class="params">
4354
+ <thead>
4355
+ <tr>
4356
+
4357
+ <th>Name</th>
4358
+
4359
+
4360
+ <th>Type</th>
4361
+
4362
+
4363
+ <th>Attributes</th>
4364
+
4365
+
4366
+
4367
+ <th>Default</th>
4368
+
4369
+
4370
+ <th class="last">Description</th>
4371
+ </tr>
4372
+ </thead>
4373
+
4374
+ <tbody>
4375
+
4376
+
4377
+ <tr>
4378
+
4379
+ <td class="name"><code>id</code></td>
4380
+
4381
+
4382
+ <td class="type">
4383
+
4384
+
4385
+ <span class="param-type">String</span>
4386
+
4387
+
4388
+
4389
+
4390
+ </td>
4391
+
4392
+
4393
+ <td class="attributes">
4394
+
4395
+ &lt;optional><br>
4396
+
4397
+
4398
+
4399
+
4400
+
4401
+ </td>
4402
+
4403
+
4404
+
4405
+ <td class="default">
4406
+
4407
+ <code>條目索引字串</code>
4408
+
4409
+ </td>
4410
+
4411
+
4412
+ <td class="description last"><p>輸入群組識別字串,游標以此為鍵、亦為日誌標籤,本套件不解讀其內容。須區分到「模型」而非只到「廠商」(如'claude:sonnet'而非'claude'),同一模型經不同路徑取得時須帶上路徑(如'poolside:laguna-s-2.1'與'or:poolside/laguna-s-2.1:free'),且務必唯一。省略時回退為陣列索引字串——索引是位置不是身分,日後插入條目會令後續條目繼承他人游標進度,故正式設定一律明給。詳見本檔檔頭之id設計規則</p></td>
4413
+ </tr>
4414
+
4415
+
4416
+
4417
+ <tr>
4418
+
4419
+ <td class="name"><code>keys</code></td>
4420
+
4421
+
4422
+ <td class="type">
4423
+
4424
+
4425
+ <span class="param-type">Array</span>
4426
+
4427
+
4428
+
4429
+
4430
+ </td>
4431
+
4432
+
4433
+ <td class="attributes">
4434
+
4435
+ &lt;optional><br>
4436
+
4437
+
4438
+
4439
+
4440
+
4441
+ </td>
4442
+
4443
+
4444
+
4445
+ <td class="default">
4446
+
4447
+ <code>[]</code>
4448
+
4449
+ </td>
4450
+
4451
+
4452
+ <td class="description last"><p>輸入同一服務之多把API key字串陣列,逐次注入輪替(kind為opencode時須同時於條目給予provider),省略代表沿用CLI既有登入狀態之單一虛擬金鑰</p></td>
4453
+ </tr>
4454
+
4455
+
4456
+
4457
+ <tr>
4458
+
4459
+ <td class="name"><code>meta</code></td>
4460
+
4461
+
4462
+ <td class="type">
4463
+
4464
+
4465
+ <span class="param-type">*</span>
4466
+
4467
+
4468
+
4469
+
4470
+ </td>
4471
+
4472
+
4473
+ <td class="attributes">
4474
+
4475
+ &lt;optional><br>
4476
+
4477
+
4478
+
4479
+
4480
+
4481
+ </td>
4482
+
4483
+
4484
+
4485
+ <td class="default">
4486
+
4487
+ </td>
4488
+
4489
+
4490
+ <td class="description last"><p>輸入呼叫端自有資訊(分類、標籤、註記),保留鍵保證永不轉傳對應轉接器——條目其餘鍵一律原樣轉傳,自有欄位放此鍵可與轉傳機制永久絕緣,預設undefined</p></td>
4491
+ </tr>
4492
+
4493
+
4494
+ </tbody>
4495
+ </table>
4496
+
4497
+ </td>
4498
+ </tr>
4499
+
4500
+
4501
+
4502
+ <tr>
4503
+
4504
+ <td class="name"><code>budgetMs</code></td>
4505
+
4506
+
4507
+ <td class="type">
4508
+
4509
+
4510
+ <span class="param-type">Number</span>
4511
+
4512
+
4513
+
4514
+
4515
+ </td>
4516
+
4517
+
4518
+ <td class="attributes">
4519
+
4520
+ &lt;optional><br>
4521
+
4522
+
4523
+
4524
+
4525
+
4526
+ </td>
4527
+
4528
+
4529
+
4530
+ <td class="default">
4531
+
4532
+ <code>null</code>
4533
+
4534
+ </td>
4535
+
4536
+
4537
+ <td class="description last"><p>輸入整輪遞補之時間上限毫秒正整數,剩餘預算會壓進每次呼叫之timeoutMs,預設null代表不限</p></td>
4538
+ </tr>
4539
+
4540
+
4541
+
4542
+ <tr>
4543
+
4544
+ <td class="name"><code>minAttemptMs</code></td>
4545
+
4546
+
4547
+ <td class="type">
4548
+
4549
+
4550
+ <span class="param-type">Number</span>
4551
+
4552
+
4553
+
4554
+
4555
+ </td>
4556
+
4557
+
4558
+ <td class="attributes">
4559
+
4560
+ &lt;optional><br>
4561
+
4562
+
4563
+
4564
+
4565
+
4566
+ </td>
4567
+
4568
+
4569
+
4570
+ <td class="default">
4571
+
4572
+ <code>20000</code>
4573
+
4574
+ </td>
4575
+
4576
+
4577
+ <td class="description last"><p>輸入單次嘗試之最低剩餘預算毫秒正整數,剩餘低於此值即停止嘗試回報budget exhausted,預設20000</p></td>
4578
+ </tr>
4579
+
4580
+
4581
+
4582
+ <tr>
4583
+
4584
+ <td class="name"><code>store</code></td>
4585
+
4586
+
4587
+ <td class="type">
4588
+
4589
+
4590
+ <span class="param-type">Object</span>
4591
+
4592
+
4593
+
4594
+
4595
+ </td>
4596
+
4597
+
4598
+ <td class="attributes">
4599
+
4600
+ &lt;optional><br>
4601
+
4602
+
4603
+
4604
+
4605
+
4606
+ </td>
4607
+
4608
+
4609
+
4610
+ <td class="default">
4611
+
4612
+ <code>null</code>
4613
+
4614
+ </td>
4615
+
4616
+
4617
+ <td class="description last"><p>輸入狀態持久化物件{get:()=&gt;state,set:(state)=&gt;{}},state內含cursors(逐群組游標)與cooling(供應商冷卻時間戳,僅cooldownMs&gt;0時使用),省略代表用行程內記憶體(跨呼叫有效,重啟歸零)。假定單行程序列調用,並行請自行加鎖</p></td>
4618
+ </tr>
4619
+
4620
+
4621
+
4622
+ <tr>
4623
+
4624
+ <td class="name"><code>cooldownMs</code></td>
4625
+
4626
+
4627
+ <td class="type">
4628
+
4629
+
4630
+ <span class="param-type">Number</span>
4631
+
4632
+
4633
+
4634
+
4635
+ </td>
4636
+
4637
+
4638
+ <td class="attributes">
4639
+
4640
+ &lt;optional><br>
4641
+
4642
+
4643
+
4644
+
4645
+
4646
+ </td>
4647
+
4648
+
4649
+
4650
+ <td class="default">
4651
+
4652
+ <code>0</code>
4653
+
4654
+ </td>
4655
+
4656
+
4657
+ <td class="description last"><p>輸入供應商冷卻視窗毫秒非負整數,&gt;0啟用:條目(限有明給id者)遭遇限流(HTTP 429,僅api類可偵測;CLI類可經coolDetect注入判定)或逾時(TIMEOUT開頭)後,於冷卻視窗內之後續呼叫中被移至鏈尾——只降序不移除,前面全敗時仍會被嘗試,任一次成功立即解除;注意啟用時「providers順序即優先序」會被暫時重排,此即本機制之目的;預設0代表不啟用</p></td>
4658
+ </tr>
4659
+
4660
+
4661
+
4662
+ <tr>
4663
+
4664
+ <td class="name"><code>coolDetect</code></td>
4665
+
4666
+
4667
+ <td class="type">
4668
+
4669
+
4670
+ <span class="param-type">function</span>
4671
+
4672
+
4673
+
4674
+
4675
+ </td>
4676
+
4677
+
4678
+ <td class="attributes">
4679
+
4680
+ &lt;optional><br>
4681
+
4682
+
4683
+
4684
+
4685
+
4686
+ </td>
4687
+
4688
+
4689
+
4690
+ <td class="default">
4691
+
4692
+ <code>null</code>
4693
+
4694
+ </td>
4695
+
4696
+
4697
+ <td class="description last"><p>輸入冷卻觸發判定函數(r)=&gt;Boolean,收完整失敗結果物件(含stdout、stderr、code、error),回傳true即視同冷卻觸發(內建429/TIMEOUT觸發不受影響)——CLI類限流埋在stderr且各家字樣不同,簽章表由觀察到字樣的呼叫端維護,如(r)=&gt;/FreeUsageLimitError/i.test(r.stderr||'');僅cooldownMs&gt;0時有效,回調拋出例外視同false,預設null</p></td>
4698
+ </tr>
4699
+
4700
+
4701
+
4702
+ <tr>
4703
+
4704
+ <td class="name"><code>shouldStop</code></td>
4705
+
4706
+
4707
+ <td class="type">
4708
+
4709
+
4710
+ <span class="param-type">function</span>
4711
+
4712
+
4713
+
4714
+
4715
+ </td>
4716
+
4717
+
4718
+ <td class="attributes">
4719
+
4720
+ &lt;optional><br>
4721
+
4722
+
4723
+
4724
+
4725
+
4726
+ </td>
4727
+
4728
+
4729
+
4730
+ <td class="default">
4731
+
4732
+ <code>null</code>
4733
+
4734
+ </td>
4735
+
4736
+
4737
+ <td class="description last"><p>輸入中止判定函數()=&gt;Boolean,於每次嘗試之間檢查,回傳true即停止遞補回報ABORTED(不中止進行中之嘗試)——供呼叫端於成果已無人接收時(如客戶端斷線)止損;經工作流層原樣轉傳,中止後各後續呼叫進門即回ABORTED令整條工作流快速收束;回調拋出例外視同false,預設null</p></td>
4738
+ </tr>
4739
+
4740
+
4741
+
4742
+ <tr>
4743
+
4744
+ <td class="name"><code>meta</code></td>
4745
+
4746
+
4747
+ <td class="type">
4748
+
4749
+
4750
+ <span class="param-type">*</span>
4751
+
4752
+
4753
+
4754
+
4755
+ </td>
4756
+
4757
+
4758
+ <td class="attributes">
4759
+
4760
+ &lt;optional><br>
4761
+
4762
+
4763
+
4764
+
4765
+
4766
+ </td>
4767
+
4768
+
4769
+
4770
+ <td class="default">
4771
+
4772
+ </td>
4773
+
4774
+
4775
+ <td class="description last"><p>輸入呼叫端自有資訊,保留鍵保證永不轉傳各轉接器,預設undefined</p></td>
4776
+ </tr>
4777
+
4778
+
4779
+
4780
+ <tr>
4781
+
4782
+ <td class="name"><code>onEvent</code></td>
4783
+
4784
+
4785
+ <td class="type">
4786
+
4787
+
4788
+ <span class="param-type">function</span>
4789
+
4790
+
4791
+
4792
+
4793
+ </td>
4794
+
4795
+
4796
+ <td class="attributes">
4797
+
4798
+ &lt;optional><br>
4799
+
4800
+
4801
+
4802
+
4803
+
4804
+ </td>
4805
+
4806
+
4807
+
4808
+ <td class="default">
4809
+
4810
+ <code>null</code>
4811
+
4812
+ </td>
4813
+
4814
+
4815
+ <td class="description last"><p>輸入事件回調函數(ev)=&gt;{},ev.type可為'try'、'ok'、'next-key'、'skip-group'、'budget-out'、'aborted'、'cooled'(冷卻觸發,帶error與cooldownMs,僅cooldownMs&gt;0時出現);失敗事件(next-key/skip-group)另帶errorType、stdout(被拒回覆)與stderr(錯誤輸出)供診斷,後兩者於失敗路徑已由轉接器截斷;回調拋出例外不影響主流程,預設null</p></td>
4816
+ </tr>
4817
+
4818
+
4819
+
4820
+ <tr>
4821
+
4822
+ <td class="name"><code>timeoutMs</code></td>
4823
+
4824
+
4825
+ <td class="type">
4826
+
4827
+
4828
+ <span class="param-type">Number</span>
4829
+
4830
+
4831
+
4832
+
4833
+ </td>
4834
+
4835
+
4836
+ <td class="attributes">
4837
+
4838
+ &lt;optional><br>
4839
+
4840
+
4841
+
4842
+
4843
+
4844
+ </td>
4845
+
4846
+
4847
+
4848
+ <td class="default">
4849
+
4850
+ <code>300000</code>
4851
+
4852
+ </td>
4853
+
4854
+
4855
+ <td class="description last"><p>輸入各attempt共用之逾時毫秒正整數,條目可覆寫,全套件統一預設300000</p></td>
4856
+ </tr>
4857
+
4858
+
4859
+
4860
+ <tr>
4861
+
4862
+ <td class="name"><code>validate</code></td>
4863
+
4864
+
4865
+ <td class="type">
4866
+
4867
+
4868
+ <span class="param-type">String</span>
4869
+ |
4870
+
4871
+ <span class="param-type">function</span>
4872
+
4873
+
4874
+
4875
+
4876
+ </td>
4877
+
4878
+
4879
+ <td class="attributes">
4880
+
4881
+ &lt;optional><br>
4882
+
4883
+
4884
+
4885
+
4886
+
4887
+ </td>
4888
+
4889
+
4890
+
4891
+ <td class="default">
4892
+
4893
+ </td>
4894
+
4895
+
4896
+ <td class="description last"><p>輸入各attempt共用之stdout驗證規則,條目可覆寫,預設undefined</p></td>
4897
+ </tr>
4898
+
4899
+
4900
+
4901
+ <tr>
4902
+
4903
+ <td class="name"><code>maxRetries</code></td>
4904
+
4905
+
4906
+ <td class="type">
4907
+
4908
+
4909
+ <span class="param-type">Number</span>
4910
+
4911
+
4912
+
4913
+
4914
+ </td>
4915
+
4916
+
4917
+ <td class="attributes">
4918
+
4919
+ &lt;optional><br>
4920
+
4921
+
4922
+
4923
+
4924
+
4925
+ </td>
4926
+
4927
+
4928
+
4929
+ <td class="default">
4930
+
4931
+ <code>0</code>
4932
+
4933
+ </td>
4934
+
4935
+
4936
+ <td class="description last"><p>輸入各attempt共用之同家重試次數非負整數,韌性建議交給換家而非重試同一家,預設0</p></td>
4937
+ </tr>
4938
+
4939
+
4940
+ </tbody>
4941
+ </table>
4942
+
4943
+ </td>
4944
+ </tr>
4945
+
4946
+
4947
+ </tbody>
4948
+ </table>
4949
+
4950
+
4951
+
4952
+
4953
+
4954
+
4955
+
4956
+
4957
+
4958
+
4959
+
4960
+
4961
+
4962
+
4963
+
4964
+
4965
+ <h5 class="h5-returns">Returns:</h5>
4966
+
4967
+
4968
+ <div class="param-desc">
4969
+ <p>回傳Promise,resolve回傳結果物件,除execCli既有欄位(ok、stdout、stderr、code、error、durationMs、attempts、pid)外,追加providerId(實際使用之群組)、keyIndex(實際使用之金鑰索引,無keys時為null)、kind、model、tried(全部嘗試歷程陣列,成功時亦回傳;失敗項含errorType、stdout與stderr供診斷被拒原因);失敗結果帶機器可讀之errorType(一覽見getErrorType.mjs檔頭);api類轉接器提供usage(token用量)時原樣流出於結果與tried各項,CLI類無此欄;本函數不會reject</p>
4970
+ </div>
4971
+
4972
+
4973
+
4974
+ <dl class="param-type">
4975
+ <dt>
4976
+ Type
4977
+ </dt>
4978
+ <dd>
4979
+
4980
+ <span class="param-type">Promise</span>
4981
+
4982
+
4983
+
4984
+ </dd>
4985
+ </dl>
4986
+
4987
+
4988
+
4989
+
4990
+
4991
+
4992
+
4993
+
4994
+
4995
+
4996
+ <h4 class="name" id="dispatchAiWkf"><span class="type-signature"></span>dispatchAiWkf<span class="signature">(opt)</span><span class="type-signature"> &rarr; {Object}</span></h4>
4997
+
4998
+
4999
+
5000
+
5001
+
5002
+
5003
+ <dl class="details">
5004
+
5005
+ <dt class="tag-description">Description:</dt>
5006
+ <dd class="tag-description"><ul class="dummy"><li><p>建立AI工作流執行環境(工廠),注入provider定義表與共用預設後回傳綁定版API</p>
5007
+ <p>特點:
5008
+ providers為名稱對dispatchAiFallback條目之定義表,之後各工作流以名稱宣告主模型與遞補鏈;
5009
+ defaults為共用呼叫設定,各工作流之callOpt與名額規格可逐項覆寫;
5010
+ 回傳之各函數皆不reject;本工廠為同步函數,providers無效時throw(設定錯誤應於啟動期即失敗)</p></li></ul></dd>
5011
+
5012
+
5013
+
5014
+ <dt class="tag-source">Source:</dt>
5015
+ <dd class="tag-source"><ul class="dummy"><li>
5016
+ <a href="dispatchAiWkf.mjs.html">dispatchAiWkf.mjs</a>, <a href="dispatchAiWkf.mjs.html#line106">line 106</a>
5017
+ </li></ul></dd>
5018
+
5019
+
5020
+
5021
+
5022
+
5023
+
5024
+
5025
+
5026
+
5027
+
5028
+
5029
+
5030
+
5031
+
5032
+
5033
+
5034
+
5035
+
5036
+
5037
+
5038
+
5039
+
5040
+
5041
+
5042
+
5043
+
5044
+
5045
+
5046
+
5047
+
5048
+
5049
+ </dl>
5050
+
5051
+
5052
+
5053
+
5054
+
5055
+
5056
+
5057
+
5058
+
5059
+
5060
+
5061
+ <h5 class="h5-examples">Example</h5>
5062
+
5063
+ <pre class="prettyprint"><code>//need cli in system PATH
5064
+
5065
+ import dispatchAiWkf from './src/dispatchAiWkf.mjs'
5066
+
5067
+ //定義表之鍵名即dispatchAiFallback之條目id, 須區分到模型而非只到廠商,
5068
+ //同一模型經不同路徑取得時須帶上路徑(REST與CLI屬兩個供應商, 能力與速度皆不同)
5069
+ let wkf = dispatchAiWkf({
5070
+ providers: {
5071
+ 'zen:deepseek-v4-flash-free': { kind: 'api-openai-compat', baseURL: 'https://opencode.ai/zen/v1', model: 'deepseek-v4-flash-free', keys: ['sk-xxx'] },
5072
+ 'oc:opencode/deepseek-v4-flash-free': { kind: 'opencode', model: 'opencode/deepseek-v4-flash-free', provider: 'opencode', keys: ['sk-xxx'] },
5073
+ 'claude:sonnet': { kind: 'claude', model: 'sonnet' },
5074
+ 'claude:opus': { kind: 'claude', model: 'opus' },
5075
+ 'codex:gpt-5.6-luna': { kind: 'codex', model: 'gpt-5.6-luna' },
5076
+ },
5077
+ defaults: { timeoutMs: 300000 },
5078
+ })
5079
+
5080
+ let test = async () => {
5081
+
5082
+ //單一名額: 主模型+遞補鏈
5083
+ let r1 = await wkf.callAi('只回覆JSON: {"a":1}', { spec: { use: 'zen:deepseek-v4-flash-free', fallback: ['claude:sonnet'] }, check: (j) => j.a === 1 })
5084
+ console.log(r1.ok, r1.json)
5085
+ // => true { a: 1 }
5086
+
5087
+ //Fanout工作流: 多開執行+單點整合
5088
+ //純文字階段用REST(快), 需要讀專案檔案之階段才用CLI(有工具)
5089
+ let r2 = await wkf.runFanout({
5090
+ task: '分析並只回覆JSON: {"essence":"..."}',
5091
+ agents: [
5092
+ { use: 'zen:deepseek-v4-flash-free', fallback: ['claude:sonnet'] },
5093
+ { use: 'claude:sonnet' },
5094
+ ],
5095
+ integrate: { use: 'codex:gpt-5.6-luna' },
5096
+ check: (j) => !!j.essence,
5097
+ })
5098
+ console.log(r2.ok, r2.integrated)
5099
+ // => true true
5100
+
5101
+ }
5102
+ await test()
5103
+ .catch((err) => {
5104
+ console.log(err)
5105
+ })</code></pre>
5106
+
5107
+
5108
+
5109
+
5110
+ <h5 class="h5-parameters">Parameters:</h5>
5111
+
5112
+
5113
+ <table class="params">
5114
+ <thead>
5115
+ <tr>
5116
+
5117
+ <th>Name</th>
5118
+
5119
+
5120
+ <th>Type</th>
5121
+
5122
+
5123
+
5124
+
5125
+
5126
+ <th class="last">Description</th>
5127
+ </tr>
5128
+ </thead>
5129
+
5130
+ <tbody>
5131
+
5132
+
5133
+ <tr>
5134
+
5135
+ <td class="name"><code>opt</code></td>
5136
+
5137
+
5138
+ <td class="type">
5139
+
5140
+
5141
+ <span class="param-type">Object</span>
5142
+
5143
+
5144
+
5145
+
5146
+ </td>
5147
+
5148
+
5149
+
5150
+
5151
+
5152
+ <td class="description last"><p>輸入設定物件</p>
5153
+ <h6>Properties</h6>
5154
+
5155
+
5156
+ <table class="params">
5157
+ <thead>
5158
+ <tr>
5159
+
5160
+ <th>Name</th>
5161
+
5162
+
5163
+ <th>Type</th>
5164
+
5165
+
5166
+ <th>Attributes</th>
5167
+
5168
+
5169
+
5170
+ <th>Default</th>
5171
+
5172
+
5173
+ <th class="last">Description</th>
5174
+ </tr>
5175
+ </thead>
5176
+
5177
+ <tbody>
5178
+
5179
+
5180
+ <tr>
5181
+
5182
+ <td class="name"><code>providers</code></td>
5183
+
5184
+
5185
+ <td class="type">
5186
+
5187
+
5188
+ <span class="param-type">Object</span>
5189
+
5190
+
5191
+
5192
+
5193
+ </td>
5194
+
5195
+
5196
+ <td class="attributes">
5197
+
5198
+
5199
+
5200
+
5201
+
5202
+ </td>
5203
+
5204
+
5205
+
5206
+ <td class="default">
5207
+
5208
+ </td>
5209
+
5210
+
5211
+ <td class="description last"><p>輸入provider定義表物件(名稱 → dispatchAiFallback條目:{ kind, model, keys, exe, provider, config, sandbox, extraArgs... })</p></td>
5212
+ </tr>
5213
+
5214
+
5215
+
5216
+ <tr>
5217
+
5218
+ <td class="name"><code>defaults</code></td>
5219
+
5220
+
5221
+ <td class="type">
5222
+
5223
+
5224
+ <span class="param-type">Object</span>
5225
+
5226
+
5227
+
5228
+
5229
+ </td>
5230
+
5231
+
5232
+ <td class="attributes">
5233
+
5234
+ &lt;optional><br>
5235
+
5236
+
5237
+
5238
+
5239
+
5240
+ </td>
5241
+
5242
+
5243
+
5244
+ <td class="default">
5245
+
5246
+ <code>{}</code>
5247
+
5248
+ </td>
5249
+
5250
+
5251
+ <td class="description last"><p>輸入共用呼叫設定物件(cwd、store、onEvent、timeoutMs、budgetMs、maxRetries、promptPrefix、parse等),預設{}</p></td>
5252
+ </tr>
5253
+
5254
+
5255
+ </tbody>
5256
+ </table>
5257
+
5258
+ </td>
5259
+ </tr>
5260
+
5261
+
5262
+ </tbody>
5263
+ </table>
5264
+
5265
+
5266
+
5267
+
5268
+
5269
+
5270
+
5271
+
5272
+
5273
+
5274
+
5275
+
5276
+
5277
+
5278
+
5279
+
5280
+ <h5 class="h5-returns">Returns:</h5>
5281
+
5282
+
5283
+ <div class="param-desc">
5284
+ <p>回傳綁定版API物件,內含callAi(單一名額呼叫)、runFanout(多開+整合)、runRolePipeline(串行角色鏈)、runFanoutPipeline(多開+整合+角色鏈)、providers(定義表原樣)</p>
5285
+ </div>
5286
+
5287
+
5288
+
5289
+ <dl class="param-type">
5290
+ <dt>
5291
+ Type
5292
+ </dt>
5293
+ <dd>
5294
+
5295
+ <span class="param-type">Object</span>
5296
+
5297
+
5298
+
5299
+ </dd>
5300
+ </dl>
5301
+
5302
+
5303
+
5304
+
5305
+
5306
+
5307
+
5308
+
5309
+
5310
+
5311
+ <h4 class="name" id="dispatchAntigravity"><span class="type-signature type-signature-async">(async) </span>dispatchAntigravity<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
5312
+
5313
+
5314
+
5315
+
5316
+
5317
+
5318
+ <dl class="details">
5319
+
5320
+ <dt class="tag-description">Description:</dt>
5321
+ <dd class="tag-description"><ul class="dummy"><li><p>以Google Antigravity CLI(agy)呼叫AI模型</p>
5322
+ <p>特點:
5323
+ prompt作為<code>--print</code>旗標之值傳遞而非stdin(agy介面如此,塞stdin會進互動模式卡住),
5324
+ 故prompt受命令列長度上限約束,超過30000字元回傳錯誤結果物件;
5325
+ model須為<code>agy models</code>第一欄之slug(如gemini-3.6-flash-low),注意agy錯誤訊息列出的是顯示名稱而非slug;
5326
+ 帶檔位之slug(-high/-medium/-low結尾)與effort同時給定且檔位不一致時agy回conflicts錯誤(一致則放行),
5327
+ effort需agy&gt;=1.1.11,建議搭配不帶檔位之基礎slug(如gemini-3.1-pro)使用;
5328
+ 預設帶<code>--dangerously-skip-permissions</code>令非互動print模式不卡權限確認,可給予skipPermissions為false保留權限閘門;
5329
+ agy自身之--print-timeout未給時由timeoutMs推導並預留30秒緩衝,令CLI先於外層逾時;
5330
+ 沿用agy既有OAuth登入狀態(首次須於桌面互動模式完成登入);
5331
+ 本函數不會reject,一律以結果物件之ok與error欄位回報成敗</p></li></ul></dd>
5332
+
5333
+
5334
+
5335
+ <dt class="tag-source">Source:</dt>
5336
+ <dd class="tag-source"><ul class="dummy"><li>
5337
+ <a href="dispatchAntigravity.mjs.html">dispatchAntigravity.mjs</a>, <a href="dispatchAntigravity.mjs.html#line106">line 106</a>
5338
+ </li></ul></dd>
5339
+
5340
+
5341
+
5342
+
5343
+
5344
+
5345
+
5346
+
5347
+
5348
+
5349
+
5350
+
5351
+
5352
+
5353
+
5354
+
5355
+
5356
+
5357
+
5358
+
5359
+
5360
+
5361
+
5362
+
5363
+
5364
+
5365
+
5366
+
5367
+
5368
+
5369
+
5370
+ </dl>
5371
+
5372
+
5373
+
5374
+
5375
+
5376
+
5377
+
5378
+
5379
+
5380
+
5381
+
5382
+ <h5 class="h5-examples">Example</h5>
5383
+
5384
+ <pre class="prettyprint"><code>//need agy cli in system PATH, and OAuth login completed
5385
+
5386
+ import dispatchAntigravity from './src/dispatchAntigravity.mjs'
5387
+
5388
+ let test = async () => {
5389
+
5390
+ let r = await dispatchAntigravity('請只回覆兩個字:完成', { model: 'gemini-3.6-flash-low' })
5391
+ console.log(r.ok, r.stdout.trim())
5392
+ // => true 完成
5393
+
5394
+ //基礎slug搭配effort(不可用帶檔位之slug併用effort)
5395
+ let r2 = await dispatchAntigravity('請只回覆兩個字:完成', { model: 'gemini-3.1-pro', effort: 'low' })
5396
+ console.log(r2.ok)
5397
+ // => true
5398
+
5399
+ let re = await dispatchAntigravity('')
5400
+ console.log(re.ok, re.error)
5401
+ // => false 'prompt must be a non-empty string'
5402
+
5403
+ }
5404
+ await test()
5405
+ .catch((err) => {
5406
+ console.log(err)
5407
+ })</code></pre>
5408
+
5409
+
5410
+
5411
+
5412
+ <h5 class="h5-parameters">Parameters:</h5>
5413
+
5414
+
5415
+ <table class="params">
5416
+ <thead>
5417
+ <tr>
5418
+
5419
+ <th>Name</th>
5420
+
5421
+
5422
+ <th>Type</th>
5423
+
5424
+
5425
+ <th>Attributes</th>
5426
+
5427
+
5428
+
5429
+ <th>Default</th>
5430
+
5431
+
5432
+ <th class="last">Description</th>
5433
+ </tr>
5434
+ </thead>
5435
+
5436
+ <tbody>
5437
+
5438
+
5439
+ <tr>
5440
+
5441
+ <td class="name"><code>prompt</code></td>
5442
+
5443
+
5444
+ <td class="type">
5445
+
5446
+
5447
+ <span class="param-type">String</span>
4398
5448
 
4399
5449
 
4400
5450
 
@@ -4404,8 +5454,6 @@ await test()
4404
5454
 
4405
5455
  <td class="attributes">
4406
5456
 
4407
- &lt;optional><br>
4408
-
4409
5457
 
4410
5458
 
4411
5459
 
@@ -4416,25 +5464,23 @@ await test()
4416
5464
 
4417
5465
  <td class="default">
4418
5466
 
4419
- <code>null</code>
4420
-
4421
5467
  </td>
4422
5468
 
4423
5469
 
4424
- <td class="description last"><p>輸入冷卻觸發判定函數(r)=&gt;Boolean,收完整失敗結果物件(含stdout、stderr、code、error),回傳true即視同冷卻觸發(內建429/TIMEOUT觸發不受影響)——CLI類限流埋在stderr且各家字樣不同,簽章表由觀察到字樣的呼叫端維護,如(r)=&gt;/FreeUsageLimitError/i.test(r.stderr||'');僅cooldownMs&gt;0時有效,回調拋出例外視同false,預設null</p></td>
5470
+ <td class="description last"><p>輸入提示詞字串,作為<code>--print</code>旗標之值傳遞,長度上限30000字元</p></td>
4425
5471
  </tr>
4426
5472
 
4427
5473
 
4428
5474
 
4429
5475
  <tr>
4430
5476
 
4431
- <td class="name"><code>shouldStop</code></td>
5477
+ <td class="name"><code>opt</code></td>
4432
5478
 
4433
5479
 
4434
5480
  <td class="type">
4435
5481
 
4436
5482
 
4437
- <span class="param-type">function</span>
5483
+ <span class="param-type">Object</span>
4438
5484
 
4439
5485
 
4440
5486
 
@@ -4456,25 +5502,48 @@ await test()
4456
5502
 
4457
5503
  <td class="default">
4458
5504
 
4459
- <code>null</code>
5505
+ <code>{}</code>
4460
5506
 
4461
5507
  </td>
4462
5508
 
4463
5509
 
4464
- <td class="description last"><p>輸入中止判定函數()=&gt;Boolean,於每次嘗試之間檢查,回傳true即停止遞補回報ABORTED(不中止進行中之嘗試)——供呼叫端於成果已無人接收時(如客戶端斷線)止損;經工作流層原樣轉傳,中止後各後續呼叫進門即回ABORTED令整條工作流快速收束;回調拋出例外視同false,預設null</p></td>
4465
- </tr>
5510
+ <td class="description last"><p>輸入設定物件,預設{}</p>
5511
+ <h6>Properties</h6>
5512
+
5513
+
5514
+ <table class="params">
5515
+ <thead>
5516
+ <tr>
5517
+
5518
+ <th>Name</th>
5519
+
5520
+
5521
+ <th>Type</th>
5522
+
5523
+
5524
+ <th>Attributes</th>
5525
+
5526
+
5527
+
5528
+ <th>Default</th>
5529
+
5530
+
5531
+ <th class="last">Description</th>
5532
+ </tr>
5533
+ </thead>
4466
5534
 
5535
+ <tbody>
4467
5536
 
4468
5537
 
4469
5538
  <tr>
4470
5539
 
4471
- <td class="name"><code>meta</code></td>
5540
+ <td class="name"><code>exe</code></td>
4472
5541
 
4473
5542
 
4474
5543
  <td class="type">
4475
5544
 
4476
5545
 
4477
- <span class="param-type">*</span>
5546
+ <span class="param-type">String</span>
4478
5547
 
4479
5548
 
4480
5549
 
@@ -4496,23 +5565,25 @@ await test()
4496
5565
 
4497
5566
  <td class="default">
4498
5567
 
5568
+ <code>'agy'</code>
5569
+
4499
5570
  </td>
4500
5571
 
4501
5572
 
4502
- <td class="description last"><p>輸入呼叫端自有資訊,保留鍵保證永不轉傳各轉接器,預設undefined</p></td>
5573
+ <td class="description last"><p>輸入agy執行檔名稱或絕對路徑字串,命令名為agy非antigravity,給予名稱時由execCli自系統PATH解析,預設'agy'</p></td>
4503
5574
  </tr>
4504
5575
 
4505
5576
 
4506
5577
 
4507
5578
  <tr>
4508
5579
 
4509
- <td class="name"><code>onEvent</code></td>
5580
+ <td class="name"><code>model</code></td>
4510
5581
 
4511
5582
 
4512
5583
  <td class="type">
4513
5584
 
4514
5585
 
4515
- <span class="param-type">function</span>
5586
+ <span class="param-type">String</span>
4516
5587
 
4517
5588
 
4518
5589
 
@@ -4534,25 +5605,25 @@ await test()
4534
5605
 
4535
5606
  <td class="default">
4536
5607
 
4537
- <code>null</code>
5608
+ <code>''</code>
4538
5609
 
4539
5610
  </td>
4540
5611
 
4541
5612
 
4542
- <td class="description last"><p>輸入事件回調函數(ev)=&gt;{},ev.type可為'try'、'ok'、'next-key'、'skip-group'、'budget-out''aborted'、'cooled'(冷卻觸發,帶error與cooldownMs,僅cooldownMs&gt;0時出現);失敗事件(next-key/skip-group)另帶errorType、stdout(被拒回覆)與stderr(錯誤輸出)供診斷,後兩者於失敗路徑已由轉接器截斷;回調拋出例外不影響主流程,預設null</p></td>
5613
+ <td class="description last"><p>輸入模型slug字串,須為<code>agy models</code>第一欄之slug,例如'gemini-3.6-flash-low'、'gemini-3.1-pro-high',預設''代表不帶<code>--model</code>旗標由agy自行決定</p></td>
4543
5614
  </tr>
4544
5615
 
4545
5616
 
4546
5617
 
4547
5618
  <tr>
4548
5619
 
4549
- <td class="name"><code>timeoutMs</code></td>
5620
+ <td class="name"><code>effort</code></td>
4550
5621
 
4551
5622
 
4552
5623
  <td class="type">
4553
5624
 
4554
5625
 
4555
- <span class="param-type">Number</span>
5626
+ <span class="param-type">String</span>
4556
5627
 
4557
5628
 
4558
5629
 
@@ -4574,28 +5645,25 @@ await test()
4574
5645
 
4575
5646
  <td class="default">
4576
5647
 
4577
- <code>300000</code>
5648
+ <code>''</code>
4578
5649
 
4579
5650
  </td>
4580
5651
 
4581
5652
 
4582
- <td class="description last"><p>輸入各attempt共用之逾時毫秒正整數,條目可覆寫,全套件統一預設300000</p></td>
5653
+ <td class="description last"><p>輸入推理深度字串,可選'low'、'medium'、'high',需agy&gt;=1.1.11,建議搭配不帶檔位之基礎slug;與帶檔位slug併用且檔位不一致時agy回conflicts錯誤,預設''代表不帶</p></td>
4583
5654
  </tr>
4584
5655
 
4585
5656
 
4586
5657
 
4587
5658
  <tr>
4588
5659
 
4589
- <td class="name"><code>validate</code></td>
5660
+ <td class="name"><code>skipPermissions</code></td>
4590
5661
 
4591
5662
 
4592
5663
  <td class="type">
4593
5664
 
4594
5665
 
4595
- <span class="param-type">String</span>
4596
- |
4597
-
4598
- <span class="param-type">function</span>
5666
+ <span class="param-type">Boolean</span>
4599
5667
 
4600
5668
 
4601
5669
 
@@ -4617,23 +5685,25 @@ await test()
4617
5685
 
4618
5686
  <td class="default">
4619
5687
 
5688
+ <code>true</code>
5689
+
4620
5690
  </td>
4621
5691
 
4622
5692
 
4623
- <td class="description last"><p>輸入各attempt共用之stdout驗證規則,條目可覆寫,預設undefined</p></td>
5693
+ <td class="description last"><p>輸入是否帶<code>--dangerously-skip-permissions</code>旗標布林值,false代表保留CLI權限閘門,預設true</p></td>
4624
5694
  </tr>
4625
5695
 
4626
5696
 
4627
5697
 
4628
5698
  <tr>
4629
5699
 
4630
- <td class="name"><code>maxRetries</code></td>
5700
+ <td class="name"><code>printTimeout</code></td>
4631
5701
 
4632
5702
 
4633
5703
  <td class="type">
4634
5704
 
4635
5705
 
4636
- <span class="param-type">Number</span>
5706
+ <span class="param-type">String</span>
4637
5707
 
4638
5708
 
4639
5709
 
@@ -4655,217 +5725,105 @@ await test()
4655
5725
 
4656
5726
  <td class="default">
4657
5727
 
4658
- <code>0</code>
5728
+ <code>''</code>
4659
5729
 
4660
5730
  </td>
4661
5731
 
4662
5732
 
4663
- <td class="description last"><p>輸入各attempt共用之同家重試次數非負整數,韌性建議交給換家而非重試同一家,預設0</p></td>
4664
- </tr>
4665
-
4666
-
4667
- </tbody>
4668
- </table>
4669
-
4670
- </td>
5733
+ <td class="description last"><p>輸入agy自身等待上限字串(如'10m'、'570s'),預設''代表由timeoutMs推導(扣30秒緩衝,下限30秒)</p></td>
4671
5734
  </tr>
4672
5735
 
4673
5736
 
4674
- </tbody>
4675
- </table>
4676
-
4677
-
4678
-
4679
-
4680
-
4681
-
4682
-
4683
-
4684
-
4685
-
4686
-
4687
-
4688
-
4689
-
4690
-
4691
-
4692
- <h5 class="h5-returns">Returns:</h5>
4693
-
4694
-
4695
- <div class="param-desc">
4696
- <p>回傳Promise,resolve回傳結果物件,除execCli既有欄位(ok、stdout、stderr、code、error、durationMs、attempts、pid)外,追加providerId(實際使用之群組)、keyIndex(實際使用之金鑰索引,無keys時為null)、kind、model、tried(全部嘗試歷程陣列,成功時亦回傳;失敗項含errorType、stdout與stderr供診斷被拒原因);失敗結果帶機器可讀之errorType(一覽見getErrorType.mjs檔頭);api類轉接器提供usage(token用量)時原樣流出於結果與tried各項,CLI類無此欄;本函數不會reject</p>
4697
- </div>
4698
-
4699
-
4700
-
4701
- <dl class="param-type">
4702
- <dt>
4703
- Type
4704
- </dt>
4705
- <dd>
4706
-
4707
- <span class="param-type">Promise</span>
4708
-
4709
-
4710
-
4711
- </dd>
4712
- </dl>
4713
-
4714
-
4715
-
4716
5737
 
4717
-
4718
-
5738
+ <tr>
5739
+
5740
+ <td class="name"><code>addDirs</code></td>
4719
5741
 
4720
5742
 
4721
-
4722
-
4723
- <h4 class="name" id="dispatchAiWkf"><span class="type-signature"></span>dispatchAiWkf<span class="signature">(opt)</span><span class="type-signature"> &rarr; {Object}</span></h4>
4724
-
4725
-
4726
-
4727
-
4728
-
4729
-
4730
- <dl class="details">
4731
-
4732
- <dt class="tag-description">Description:</dt>
4733
- <dd class="tag-description"><ul class="dummy"><li><p>建立AI工作流執行環境(工廠),注入provider定義表與共用預設後回傳綁定版API</p>
4734
- <p>特點:
4735
- providers為名稱對dispatchAiFallback條目之定義表,之後各工作流以名稱宣告主模型與遞補鏈;
4736
- defaults為共用呼叫設定,各工作流之callOpt與名額規格可逐項覆寫;
4737
- 回傳之各函數皆不reject;本工廠為同步函數,providers無效時throw(設定錯誤應於啟動期即失敗)</p></li></ul></dd>
4738
-
4739
-
4740
-
4741
- <dt class="tag-source">Source:</dt>
4742
- <dd class="tag-source"><ul class="dummy"><li>
4743
- <a href="dispatchAiWkf.mjs.html">dispatchAiWkf.mjs</a>, <a href="dispatchAiWkf.mjs.html#line106">line 106</a>
4744
- </li></ul></dd>
4745
-
4746
-
4747
-
4748
-
4749
-
4750
-
4751
-
4752
-
4753
-
4754
-
4755
-
4756
-
4757
-
4758
-
4759
-
4760
-
4761
-
4762
-
4763
-
4764
-
4765
-
4766
-
4767
-
4768
-
4769
-
4770
-
4771
-
4772
-
4773
-
4774
-
4775
-
4776
- </dl>
4777
-
4778
-
4779
-
4780
-
4781
-
4782
-
4783
-
4784
-
4785
-
4786
-
4787
-
4788
- <h5 class="h5-examples">Example</h5>
4789
-
4790
- <pre class="prettyprint"><code>//need cli in system PATH
4791
-
4792
- import dispatchAiWkf from './src/dispatchAiWkf.mjs'
5743
+ <td class="type">
5744
+
5745
+
5746
+ <span class="param-type">Array</span>
4793
5747
 
4794
- //定義表之鍵名即dispatchAiFallback之條目id, 須區分到模型而非只到廠商,
4795
- //同一模型經不同路徑取得時須帶上路徑(REST與CLI屬兩個供應商, 能力與速度皆不同)
4796
- let wkf = dispatchAiWkf({
4797
- providers: {
4798
- 'zen:deepseek-v4-flash-free': { kind: 'api-openai-compat', baseURL: 'https://opencode.ai/zen/v1', model: 'deepseek-v4-flash-free', keys: ['sk-xxx'] },
4799
- 'oc:opencode/deepseek-v4-flash-free': { kind: 'opencode', model: 'opencode/deepseek-v4-flash-free', provider: 'opencode', keys: ['sk-xxx'] },
4800
- 'claude:sonnet': { kind: 'claude', model: 'sonnet' },
4801
- 'claude:opus': { kind: 'claude', model: 'opus' },
4802
- 'codex:gpt-5.6-luna': { kind: 'codex', model: 'gpt-5.6-luna' },
4803
- },
4804
- defaults: { timeoutMs: 300000 },
4805
- })
4806
5748
 
4807
- let test = async () => {
4808
5749
 
4809
- //單一名額: 主模型+遞補鏈
4810
- let r1 = await wkf.callAi('只回覆JSON: {"a":1}', { spec: { use: 'zen:deepseek-v4-flash-free', fallback: ['claude:sonnet'] }, check: (j) => j.a === 1 })
4811
- console.log(r1.ok, r1.json)
4812
- // => true { a: 1 }
5750
+
5751
+ </td>
4813
5752
 
4814
- //Fanout工作流: 多開執行+單點整合
4815
- //純文字階段用REST(快), 需要讀專案檔案之階段才用CLI(有工具)
4816
- let r2 = await wkf.runFanout({
4817
- task: '分析並只回覆JSON: {"essence":"..."}',
4818
- agents: [
4819
- { use: 'zen:deepseek-v4-flash-free', fallback: ['claude:sonnet'] },
4820
- { use: 'claude:sonnet' },
4821
- ],
4822
- integrate: { use: 'codex:gpt-5.6-luna' },
4823
- check: (j) => !!j.essence,
4824
- })
4825
- console.log(r2.ok, r2.integrated)
4826
- // => true true
5753
+
5754
+ <td class="attributes">
5755
+
5756
+ &lt;optional><br>
5757
+
4827
5758
 
4828
- }
4829
- await test()
4830
- .catch((err) => {
4831
- console.log(err)
4832
- })</code></pre>
5759
+
4833
5760
 
5761
+
5762
+ </td>
5763
+
4834
5764
 
5765
+
5766
+ <td class="default">
5767
+
5768
+ <code>自動納入cwd</code>
5769
+
5770
+ </td>
5771
+
4835
5772
 
5773
+ <td class="description last"><p>輸入加入workspace之目錄字串陣列,逐項展開為<code>--add-dir</code>。agy以自身scratch目錄為工作區而不採子進程cwd,故未給本參數時自動納入有效cwd令檔案可視範圍與其他CLI轉接器一致;明示給陣列(含空陣列[]代表不揭露任何目錄)則完全尊重呼叫端</p></td>
5774
+ </tr>
4836
5775
 
4837
- <h5 class="h5-parameters">Parameters:</h5>
4838
5776
 
4839
5777
 
4840
- <table class="params">
4841
- <thead>
4842
- <tr>
4843
-
4844
- <th>Name</th>
4845
-
5778
+ <tr>
5779
+
5780
+ <td class="name"><code>extraArgs</code></td>
5781
+
4846
5782
 
4847
- <th>Type</th>
5783
+ <td class="type">
5784
+
5785
+
5786
+ <span class="param-type">Array</span>
4848
5787
 
4849
-
4850
5788
 
4851
-
4852
5789
 
4853
- <th class="last">Description</th>
4854
- </tr>
4855
- </thead>
5790
+
5791
+ </td>
5792
+
5793
+
5794
+ <td class="attributes">
5795
+
5796
+ &lt;optional><br>
5797
+
5798
+
5799
+
5800
+
5801
+
5802
+ </td>
5803
+
5804
+
5805
+
5806
+ <td class="default">
5807
+
5808
+ <code>[]</code>
5809
+
5810
+ </td>
5811
+
5812
+
5813
+ <td class="description last"><p>輸入額外命令列旗標字串陣列(如--output-format、--json-schema、--mode),將接於固定旗標之後、<code>--print</code>之前,預設[]</p></td>
5814
+ </tr>
4856
5815
 
4857
- <tbody>
4858
5816
 
4859
5817
 
4860
5818
  <tr>
4861
5819
 
4862
- <td class="name"><code>opt</code></td>
5820
+ <td class="name"><code>timeoutMs</code></td>
4863
5821
 
4864
5822
 
4865
5823
  <td class="type">
4866
5824
 
4867
5825
 
4868
- <span class="param-type">Object</span>
5826
+ <span class="param-type">Number</span>
4869
5827
 
4870
5828
 
4871
5829
 
@@ -4873,46 +5831,82 @@ await test()
4873
5831
  </td>
4874
5832
 
4875
5833
 
5834
+ <td class="attributes">
5835
+
5836
+ &lt;optional><br>
5837
+
5838
+
5839
+
5840
+
5841
+
5842
+ </td>
5843
+
4876
5844
 
4877
5845
 
5846
+ <td class="default">
5847
+
5848
+ <code>300000</code>
5849
+
5850
+ </td>
5851
+
4878
5852
 
4879
- <td class="description last"><p>輸入設定物件</p>
4880
- <h6>Properties</h6>
5853
+ <td class="description last"><p>輸入逾時毫秒正整數,逾時將強制關閉子進程及其子孫程序,全套件統一預設300000(恰對齊agy自身print-timeout預設5m0s)</p></td>
5854
+ </tr>
5855
+
5856
+
5857
+
5858
+ <tr>
5859
+
5860
+ <td class="name"><code>cwd</code></td>
5861
+
5862
+
5863
+ <td class="type">
5864
+
4881
5865
 
5866
+ <span class="param-type">String</span>
4882
5867
 
4883
- <table class="params">
4884
- <thead>
4885
- <tr>
4886
-
4887
- <th>Name</th>
4888
-
4889
5868
 
4890
- <th>Type</th>
4891
5869
 
4892
-
4893
- <th>Attributes</th>
4894
-
5870
+
5871
+ </td>
4895
5872
 
4896
-
4897
- <th>Default</th>
4898
-
5873
+
5874
+ <td class="attributes">
5875
+
5876
+ &lt;optional><br>
5877
+
4899
5878
 
4900
- <th class="last">Description</th>
4901
- </tr>
4902
- </thead>
5879
+
5880
+
5881
+
5882
+ </td>
5883
+
5884
+
5885
+
5886
+ <td class="default">
5887
+
5888
+ <code>process.cwd()</code>
5889
+
5890
+ </td>
5891
+
5892
+
5893
+ <td class="description last"><p>輸入子進程工作目錄字串,預設process.cwd()。注意本參數不影響agy之檔案可視範圍(agy以自身scratch目錄為工作區),可視範圍由addDirs決定(未給addDirs時自動納入本目錄)</p></td>
5894
+ </tr>
4903
5895
 
4904
- <tbody>
4905
5896
 
4906
5897
 
4907
5898
  <tr>
4908
5899
 
4909
- <td class="name"><code>providers</code></td>
5900
+ <td class="name"><code>validate</code></td>
4910
5901
 
4911
5902
 
4912
5903
  <td class="type">
4913
5904
 
4914
5905
 
4915
- <span class="param-type">Object</span>
5906
+ <span class="param-type">String</span>
5907
+ |
5908
+
5909
+ <span class="param-type">function</span>
4916
5910
 
4917
5911
 
4918
5912
 
@@ -4922,6 +5916,8 @@ await test()
4922
5916
 
4923
5917
  <td class="attributes">
4924
5918
 
5919
+ &lt;optional><br>
5920
+
4925
5921
 
4926
5922
 
4927
5923
 
@@ -4935,20 +5931,20 @@ await test()
4935
5931
  </td>
4936
5932
 
4937
5933
 
4938
- <td class="description last"><p>輸入provider定義表物件(名稱 → dispatchAiFallback條目:{ kind, model, keys, exe, provider, config, sandbox, extraArgs... })</p></td>
5934
+ <td class="description last"><p>輸入stdout驗證規則字串或自訂驗證函數,規則字串支援'nonempty'、'json'、'min:100',多規則可用逗號串接,預設undefined代表不驗證</p></td>
4939
5935
  </tr>
4940
5936
 
4941
5937
 
4942
5938
 
4943
5939
  <tr>
4944
5940
 
4945
- <td class="name"><code>defaults</code></td>
5941
+ <td class="name"><code>maxRetries</code></td>
4946
5942
 
4947
5943
 
4948
5944
  <td class="type">
4949
5945
 
4950
5946
 
4951
- <span class="param-type">Object</span>
5947
+ <span class="param-type">Number</span>
4952
5948
 
4953
5949
 
4954
5950
 
@@ -4970,12 +5966,12 @@ await test()
4970
5966
 
4971
5967
  <td class="default">
4972
5968
 
4973
- <code>{}</code>
5969
+ <code>0</code>
4974
5970
 
4975
5971
  </td>
4976
5972
 
4977
5973
 
4978
- <td class="description last"><p>輸入共用呼叫設定物件(cwd、store、onEvent、timeoutMs、budgetMs、maxRetries、promptPrefix、parse等),預設{}</p></td>
5974
+ <td class="description last"><p>輸入失敗後最大重試次數非負整數,預設0</p></td>
4979
5975
  </tr>
4980
5976
 
4981
5977
 
@@ -5008,7 +6004,7 @@ await test()
5008
6004
 
5009
6005
 
5010
6006
  <div class="param-desc">
5011
- <p>回傳綁定版API物件,內含callAi(單一名額呼叫)、runFanout(多開+整合)、runRolePipeline(串行角色鏈)、runFanoutPipeline(多開+整合+角色鏈)、providers(定義表原樣)</p>
6007
+ <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject</p>
5012
6008
  </div>
5013
6009
 
5014
6010
 
@@ -5019,7 +6015,7 @@ await test()
5019
6015
  </dt>
5020
6016
  <dd>
5021
6017
 
5022
- <span class="param-type">Object</span>
6018
+ <span class="param-type">Promise</span>
5023
6019
 
5024
6020
 
5025
6021
 
@@ -5035,7 +6031,7 @@ await test()
5035
6031
 
5036
6032
 
5037
6033
 
5038
- <h4 class="name" id="dispatchAntigravity"><span class="type-signature type-signature-async">(async) </span>dispatchAntigravity<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
6034
+ <h4 class="name" id="dispatchApiOpenaiCompat"><span class="type-signature type-signature-async">(async) </span>dispatchApiOpenaiCompat<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
5039
6035
 
5040
6036
 
5041
6037
 
@@ -5045,23 +6041,21 @@ await test()
5045
6041
  <dl class="details">
5046
6042
 
5047
6043
  <dt class="tag-description">Description:</dt>
5048
- <dd class="tag-description"><ul class="dummy"><li><p>以Google Antigravity CLI(agy)呼叫AI模型</p>
6044
+ <dd class="tag-description"><ul class="dummy"><li><p>以fetch直呼OpenAI相容API(chat/completions)呼叫AI模型</p>
5049
6045
  <p>特點:
5050
- prompt作為<code>--print</code>旗標之值傳遞而非stdin(agy介面如此,塞stdin會進互動模式卡住)
5051
- prompt受命令列長度上限約束,超過30000字元回傳錯誤結果物件;
5052
- model須為<code>agy models</code>第一欄之slug(如gemini-3.6-flash-low),注意agy錯誤訊息列出的是顯示名稱而非slug
5053
- 帶檔位之slug(-high/-medium/-low結尾)與effort同時給定且檔位不一致時agy回conflicts錯誤(一致則放行),
5054
- effort需agy&gt;=1.1.11,建議搭配不帶檔位之基礎slug(如gemini-3.1-pro)使用;
5055
- 預設帶<code>--dangerously-skip-permissions</code>令非互動print模式不卡權限確認,可給予skipPermissions為false保留權限閘門;
5056
- agy自身之--print-timeout未給時由timeoutMs推導並預留30秒緩衝,令CLI先於外層逾時;
5057
- 沿用agy既有OAuth登入狀態(首次須於桌面互動模式完成登入);
6046
+ 免安裝CLI、免預先登入,給baseURL+key+model即可呼叫(如OpenCode Zen、Agnes等OpenAI相容閘道)
6047
+ 僅供純文字生成(摘要、分析、改寫、產出JSON等素材已在prompt內之任務)——
6048
+ 需要讀本機檔案、grep、執行指令、抓網頁等工具能力時,請改用CLI類kind(opencode/claude/codex/antigravity);
6049
+ prompt走HTTP body,無命令列長度限制;
6050
+ 錯誤依HTTP狀態碼分流:4xx(429除外)為客戶端錯誤不重試,429/5xx/網路錯誤/逾時依maxRetries線性退避重試;
6051
+ 結果結構與逾時/驗證失敗之error字樣對齊execCli,可直接作為dispatchAi與dispatchAiFallback之kind('api-openai-compat')使用;
5058
6052
  本函數不會reject,一律以結果物件之ok與error欄位回報成敗</p></li></ul></dd>
5059
6053
 
5060
6054
 
5061
6055
 
5062
6056
  <dt class="tag-source">Source:</dt>
5063
6057
  <dd class="tag-source"><ul class="dummy"><li>
5064
- <a href="dispatchAntigravity.mjs.html">dispatchAntigravity.mjs</a>, <a href="dispatchAntigravity.mjs.html#line106">line 106</a>
6058
+ <a href="dispatchApiOpenaiCompat.mjs.html">dispatchApiOpenaiCompat.mjs</a>, <a href="dispatchApiOpenaiCompat.mjs.html#line261">line 261</a>
5065
6059
  </li></ul></dd>
5066
6060
 
5067
6061
 
@@ -5108,24 +6102,33 @@ agy自身之--print-timeout未給時由timeoutMs推導並預留30秒緩衝,令
5108
6102
 
5109
6103
  <h5 class="h5-examples">Example</h5>
5110
6104
 
5111
- <pre class="prettyprint"><code>//need agy cli in system PATH, and OAuth login completed
6105
+ <pre class="prettyprint"><code>//need network, no cli required
5112
6106
 
5113
- import dispatchAntigravity from './src/dispatchAntigravity.mjs'
6107
+ import dispatchApiOpenaiCompat from './src/dispatchApiOpenaiCompat.mjs'
5114
6108
 
5115
6109
  let test = async () => {
5116
6110
 
5117
- let r = await dispatchAntigravity('請只回覆兩個字:完成', { model: 'gemini-3.6-flash-low' })
5118
- console.log(r.ok, r.stdout.trim())
6111
+ //OpenCode Zen(即opencode CLI之自家閘道), 模型名不帶opencode/前綴
6112
+ let r1 = await dispatchApiOpenaiCompat('請只回覆兩個字:完成', {
6113
+ baseURL: 'https://opencode.ai/zen/v1',
6114
+ key: 'sk-xxxxxx',
6115
+ model: 'deepseek-v4-flash-free',
6116
+ })
6117
+ console.log(r1.ok, r1.stdout.trim())
5119
6118
  // => true 完成
5120
6119
 
5121
- //基礎slug搭配effort(不可用帶檔位之slug併用effort)
5122
- let r2 = await dispatchAntigravity('請只回覆兩個字:完成', { model: 'gemini-3.1-pro', effort: 'low' })
5123
- console.log(r2.ok)
5124
- // => true
6120
+ //Agnes
6121
+ let r2 = await dispatchApiOpenaiCompat('請只回覆兩個字:完成', {
6122
+ baseURL: 'https://apihub.agnes-ai.com/v1',
6123
+ key: 'sk-xxxxxx',
6124
+ model: 'agnes-2.0-flash',
6125
+ })
6126
+ console.log(r2.ok, r2.stdout.trim())
6127
+ // => true 完成
5125
6128
 
5126
- let re = await dispatchAntigravity('')
5127
- console.log(re.ok, re.error)
5128
- // => false 'prompt must be a non-empty string'
6129
+ let re = await dispatchApiOpenaiCompat('abc', { baseURL: 'https://opencode.ai/zen/v1', key: 'sk-bad', model: 'deepseek-v4-flash-free' })
6130
+ console.log(re.ok, re.code, re.error)
6131
+ // => false 401 HTTP 401
5129
6132
 
5130
6133
  }
5131
6134
  await test()
@@ -5194,7 +6197,7 @@ await test()
5194
6197
  </td>
5195
6198
 
5196
6199
 
5197
- <td class="description last"><p>輸入提示詞字串,作為<code>--print</code>旗標之值傳遞,長度上限30000字元</p></td>
6200
+ <td class="description last"><p>輸入提示詞字串,作為user訊息置於HTTP body</p></td>
5198
6201
  </tr>
5199
6202
 
5200
6203
 
@@ -5264,47 +6267,7 @@ await test()
5264
6267
 
5265
6268
  <tr>
5266
6269
 
5267
- <td class="name"><code>exe</code></td>
5268
-
5269
-
5270
- <td class="type">
5271
-
5272
-
5273
- <span class="param-type">String</span>
5274
-
5275
-
5276
-
5277
-
5278
- </td>
5279
-
5280
-
5281
- <td class="attributes">
5282
-
5283
- &lt;optional><br>
5284
-
5285
-
5286
-
5287
-
5288
-
5289
- </td>
5290
-
5291
-
5292
-
5293
- <td class="default">
5294
-
5295
- <code>'agy'</code>
5296
-
5297
- </td>
5298
-
5299
-
5300
- <td class="description last"><p>輸入agy執行檔名稱或絕對路徑字串,命令名為agy非antigravity,給予名稱時由execCli自系統PATH解析,預設'agy'</p></td>
5301
- </tr>
5302
-
5303
-
5304
-
5305
- <tr>
5306
-
5307
- <td class="name"><code>model</code></td>
6270
+ <td class="name"><code>baseURL</code></td>
5308
6271
 
5309
6272
 
5310
6273
  <td class="type">
@@ -5320,8 +6283,6 @@ await test()
5320
6283
 
5321
6284
  <td class="attributes">
5322
6285
 
5323
- &lt;optional><br>
5324
-
5325
6286
 
5326
6287
 
5327
6288
 
@@ -5332,19 +6293,17 @@ await test()
5332
6293
 
5333
6294
  <td class="default">
5334
6295
 
5335
- <code>''</code>
5336
-
5337
6296
  </td>
5338
6297
 
5339
6298
 
5340
- <td class="description last"><p>輸入模型slug字串,須為<code>agy models</code>第一欄之slug,例如'gemini-3.6-flash-low'、'gemini-3.1-pro-high',預設''代表不帶<code>--model</code>旗標由agy自行決定</p></td>
6299
+ <td class="description last"><p>輸入API基底網址字串,例如'https://opencode.ai/zen/v1'、'https://apihub.agnes-ai.com/v1',將於尾端接上/chat/completions</p></td>
5341
6300
  </tr>
5342
6301
 
5343
6302
 
5344
6303
 
5345
6304
  <tr>
5346
6305
 
5347
- <td class="name"><code>effort</code></td>
6306
+ <td class="name"><code>model</code></td>
5348
6307
 
5349
6308
 
5350
6309
  <td class="type">
@@ -5360,8 +6319,6 @@ await test()
5360
6319
 
5361
6320
  <td class="attributes">
5362
6321
 
5363
- &lt;optional><br>
5364
-
5365
6322
 
5366
6323
 
5367
6324
 
@@ -5372,25 +6329,23 @@ await test()
5372
6329
 
5373
6330
  <td class="default">
5374
6331
 
5375
- <code>''</code>
5376
-
5377
6332
  </td>
5378
6333
 
5379
6334
 
5380
- <td class="description last"><p>輸入推理深度字串,可選'low'、'medium'、'high',需agy&gt;=1.1.11,建議搭配不帶檔位之基礎slug;與帶檔位slug併用且檔位不一致時agy回conflicts錯誤,預設''代表不帶</p></td>
6335
+ <td class="description last"><p>輸入模型ID字串,例如'deepseek-v4-flash-free'(Zen之模型名不帶opencode/前綴)、'agnes-2.0-flash'</p></td>
5381
6336
  </tr>
5382
6337
 
5383
6338
 
5384
6339
 
5385
6340
  <tr>
5386
6341
 
5387
- <td class="name"><code>skipPermissions</code></td>
6342
+ <td class="name"><code>key</code></td>
5388
6343
 
5389
6344
 
5390
6345
  <td class="type">
5391
6346
 
5392
6347
 
5393
- <span class="param-type">Boolean</span>
6348
+ <span class="param-type">String</span>
5394
6349
 
5395
6350
 
5396
6351
 
@@ -5412,19 +6367,19 @@ await test()
5412
6367
 
5413
6368
  <td class="default">
5414
6369
 
5415
- <code>true</code>
6370
+ <code>''</code>
5416
6371
 
5417
6372
  </td>
5418
6373
 
5419
6374
 
5420
- <td class="description last"><p>輸入是否帶<code>--dangerously-skip-permissions</code>旗標布林值,false代表保留CLI權限閘門,預設true</p></td>
6375
+ <td class="description last"><p>輸入API key字串,以Bearer置於Authorization標頭,預設''代表不帶認證標頭</p></td>
5421
6376
  </tr>
5422
6377
 
5423
6378
 
5424
6379
 
5425
6380
  <tr>
5426
6381
 
5427
- <td class="name"><code>printTimeout</code></td>
6382
+ <td class="name"><code>system</code></td>
5428
6383
 
5429
6384
 
5430
6385
  <td class="type">
@@ -5457,20 +6412,20 @@ await test()
5457
6412
  </td>
5458
6413
 
5459
6414
 
5460
- <td class="description last"><p>輸入agy自身等待上限字串(如'10m'、'570s'),預設''代表由timeoutMs推導(扣30秒緩衝,下限30秒)</p></td>
6415
+ <td class="description last"><p>輸入system提示詞字串,將以system角色置於messages首位,預設''代表不帶</p></td>
5461
6416
  </tr>
5462
6417
 
5463
6418
 
5464
6419
 
5465
6420
  <tr>
5466
6421
 
5467
- <td class="name"><code>addDirs</code></td>
6422
+ <td class="name"><code>body</code></td>
5468
6423
 
5469
6424
 
5470
6425
  <td class="type">
5471
6426
 
5472
6427
 
5473
- <span class="param-type">Array</span>
6428
+ <span class="param-type">Object</span>
5474
6429
 
5475
6430
 
5476
6431
 
@@ -5492,25 +6447,25 @@ await test()
5492
6447
 
5493
6448
  <td class="default">
5494
6449
 
5495
- <code>自動納入cwd</code>
6450
+ <code>{}</code>
5496
6451
 
5497
6452
  </td>
5498
6453
 
5499
6454
 
5500
- <td class="description last"><p>輸入加入workspace之目錄字串陣列,逐項展開為<code>--add-dir</code>。agy以自身scratch目錄為工作區而不採子進程cwd,故未給本參數時自動納入有效cwd令檔案可視範圍與其他CLI轉接器一致;明示給陣列(含空陣列[]代表不揭露任何目錄)則完全尊重呼叫端</p></td>
6455
+ <td class="description last"><p>輸入額外請求本體物件(如temperature、max_tokens、response_format),將併入預設body(同名鍵以此為準),預設{}。注意本轉接器不支援工具,帶入tools而模型回tool_calls時一律以TOOL_CALLS_UNSUPPORTED回報失敗,需要工具請改用CLI類kind</p></td>
5501
6456
  </tr>
5502
6457
 
5503
6458
 
5504
6459
 
5505
6460
  <tr>
5506
6461
 
5507
- <td class="name"><code>extraArgs</code></td>
6462
+ <td class="name"><code>headers</code></td>
5508
6463
 
5509
6464
 
5510
6465
  <td class="type">
5511
6466
 
5512
6467
 
5513
- <span class="param-type">Array</span>
6468
+ <span class="param-type">Object</span>
5514
6469
 
5515
6470
 
5516
6471
 
@@ -5532,12 +6487,12 @@ await test()
5532
6487
 
5533
6488
  <td class="default">
5534
6489
 
5535
- <code>[]</code>
6490
+ <code>{}</code>
5536
6491
 
5537
6492
  </td>
5538
6493
 
5539
6494
 
5540
- <td class="description last"><p>輸入額外命令列旗標字串陣列(如--output-format、--json-schema、--mode),將接於固定旗標之後、<code>--print</code>之前,預設[]</p></td>
6495
+ <td class="description last"><p>輸入額外請求標頭物件,預設{}</p></td>
5541
6496
  </tr>
5542
6497
 
5543
6498
 
@@ -5577,20 +6532,23 @@ await test()
5577
6532
  </td>
5578
6533
 
5579
6534
 
5580
- <td class="description last"><p>輸入逾時毫秒正整數,逾時將強制關閉子進程及其子孫程序,全套件統一預設300000(恰對齊agy自身print-timeout預設5m0s)</p></td>
6535
+ <td class="description last"><p>輸入逾時毫秒正整數,逾時將中止請求(含回應串流讀取),全套件統一預設300000</p></td>
5581
6536
  </tr>
5582
6537
 
5583
6538
 
5584
6539
 
5585
6540
  <tr>
5586
6541
 
5587
- <td class="name"><code>cwd</code></td>
6542
+ <td class="name"><code>validate</code></td>
5588
6543
 
5589
6544
 
5590
6545
  <td class="type">
5591
6546
 
5592
6547
 
5593
6548
  <span class="param-type">String</span>
6549
+ |
6550
+
6551
+ <span class="param-type">function</span>
5594
6552
 
5595
6553
 
5596
6554
 
@@ -5612,28 +6570,23 @@ await test()
5612
6570
 
5613
6571
  <td class="default">
5614
6572
 
5615
- <code>process.cwd()</code>
5616
-
5617
6573
  </td>
5618
6574
 
5619
6575
 
5620
- <td class="description last"><p>輸入子進程工作目錄字串,預設process.cwd()。注意本參數不影響agy之檔案可視範圍(agy以自身scratch目錄為工作區),可視範圍由addDirs決定(未給addDirs時自動納入本目錄)</p></td>
6576
+ <td class="description last"><p>輸入回覆內容驗證規則字串或自訂驗證函數,規則字串支援'nonempty'、'json'、'min:100',多規則可用逗號串接,預設undefined代表不驗證</p></td>
5621
6577
  </tr>
5622
6578
 
5623
6579
 
5624
6580
 
5625
6581
  <tr>
5626
6582
 
5627
- <td class="name"><code>validate</code></td>
6583
+ <td class="name"><code>maxRetries</code></td>
5628
6584
 
5629
6585
 
5630
6586
  <td class="type">
5631
6587
 
5632
6588
 
5633
- <span class="param-type">String</span>
5634
- |
5635
-
5636
- <span class="param-type">function</span>
6589
+ <span class="param-type">Number</span>
5637
6590
 
5638
6591
 
5639
6592
 
@@ -5655,17 +6608,19 @@ await test()
5655
6608
 
5656
6609
  <td class="default">
5657
6610
 
6611
+ <code>0</code>
6612
+
5658
6613
  </td>
5659
6614
 
5660
6615
 
5661
- <td class="description last"><p>輸入stdout驗證規則字串或自訂驗證函數,規則字串支援'nonempty'、'json'、'min:100',多規則可用逗號串接,預設undefined代表不驗證</p></td>
6616
+ <td class="description last"><p>輸入失敗後最大重試次數非負整數,4xx(429除外)不重試,預設0</p></td>
5662
6617
  </tr>
5663
6618
 
5664
6619
 
5665
6620
 
5666
6621
  <tr>
5667
6622
 
5668
- <td class="name"><code>maxRetries</code></td>
6623
+ <td class="name"><code>retryDelayMs</code></td>
5669
6624
 
5670
6625
 
5671
6626
  <td class="type">
@@ -5693,12 +6648,12 @@ await test()
5693
6648
 
5694
6649
  <td class="default">
5695
6650
 
5696
- <code>0</code>
6651
+ <code>5000</code>
5697
6652
 
5698
6653
  </td>
5699
6654
 
5700
6655
 
5701
- <td class="description last"><p>輸入失敗後最大重試次數非負整數,預設0</p></td>
6656
+ <td class="description last"><p>輸入重試間隔毫秒正整數,實際間隔為retryDelayMs乘以重試次數且上限15000ms,預設5000</p></td>
5702
6657
  </tr>
5703
6658
 
5704
6659
 
@@ -5731,7 +6686,7 @@ await test()
5731
6686
 
5732
6687
 
5733
6688
  <div class="param-desc">
5734
- <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject</p>
6689
+ <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(回覆內容字串)、stderr(失敗時之原始回應本體)、code(HTTP狀態碼,網路錯誤與逾時為null)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串,一覽見getErrorType.mjs檔頭)、durationMs(耗時毫秒)、attempts(實際嘗試次數)、usage(原始回應之token用量物件原樣透傳,無則null),本函數不會reject</p>
5735
6690
  </div>
5736
6691
 
5737
6692
 
@@ -5758,7 +6713,7 @@ await test()
5758
6713
 
5759
6714
 
5760
6715
 
5761
- <h4 class="name" id="dispatchApiOpenaiCompat"><span class="type-signature type-signature-async">(async) </span>dispatchApiOpenaiCompat<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
6716
+ <h4 class="name" id="dispatchApiOpenaiResponses"><span class="type-signature type-signature-async">(async) </span>dispatchApiOpenaiResponses<span class="signature">(prompt, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
5762
6717
 
5763
6718
 
5764
6719
 
@@ -5768,21 +6723,21 @@ await test()
5768
6723
  <dl class="details">
5769
6724
 
5770
6725
  <dt class="tag-description">Description:</dt>
5771
- <dd class="tag-description"><ul class="dummy"><li><p>以fetch直呼OpenAI相容API(chat/completions)呼叫AI模型</p>
6726
+ <dd class="tag-description"><ul class="dummy"><li><p>以fetch直呼OpenAI Responses API(/responses)呼叫AI模型</p>
5772
6727
  <p>特點:
5773
- 免安裝CLI、免預先登入,給baseURL+key+model即可呼叫(如OpenCode Zen、Agnes等OpenAI相容閘道);
5774
- 僅供純文字生成(摘要、分析、改寫、產出JSON等素材已在prompt內之任務)——
5775
- 需要讀本機檔案、grep、執行指令、抓網頁等工具能力時,請改用CLI類kind(opencode/claude/codex/antigravity)
5776
- prompt走HTTP body,無命令列長度限制;
5777
- 錯誤依HTTP狀態碼分流:4xx(429除外)為客戶端錯誤不重試,429/5xx/網路錯誤/逾時依maxRetries線性退避重試;
5778
- 結果結構與逾時/驗證失敗之error字樣對齊execCli,可直接作為dispatchAi與dispatchAiFallback之kind('api-openai-compat')使用;
6728
+ 免安裝CLI、免預先登入,給baseURL+key+model即可呼叫(如OpenCode Zen之muse-spark系與GPT系);
6729
+ 端點型別與dispatchApiOpenaiCompat不同——Zen之端點依模型家族而異,收錄前須查官方文件端點欄
6730
+ (https://opencode.ai/docs/zh-tw/zen/),打錯端點會得到HTTP 500而非404,詳見providers.mjs檔頭;
6731
+ 僅供純文字生成,需要工具能力請改用CLI類kind(opencode/claude/codex/antigravity);
6732
+ status非completed(如max_output_tokens耗盡)一律以INCOMPLETE_RESPONSE回報,不回半截內容;
6733
+ 結果結構與dispatchApiOpenaiCompat完全一致,可直接作為dispatchAi與dispatchAiFallback之kind('api-openai-responses')使用;
5779
6734
  本函數不會reject,一律以結果物件之ok與error欄位回報成敗</p></li></ul></dd>
5780
6735
 
5781
6736
 
5782
6737
 
5783
6738
  <dt class="tag-source">Source:</dt>
5784
6739
  <dd class="tag-source"><ul class="dummy"><li>
5785
- <a href="dispatchApiOpenaiCompat.mjs.html">dispatchApiOpenaiCompat.mjs</a>, <a href="dispatchApiOpenaiCompat.mjs.html#line325">line 325</a>
6740
+ <a href="dispatchApiOpenaiResponses.mjs.html">dispatchApiOpenaiResponses.mjs</a>, <a href="dispatchApiOpenaiResponses.mjs.html#line322">line 322</a>
5786
6741
  </li></ul></dd>
5787
6742
 
5788
6743
 
@@ -5831,31 +6786,22 @@ prompt走HTTP body,無命令列長度限制;
5831
6786
 
5832
6787
  <pre class="prettyprint"><code>//need network, no cli required
5833
6788
 
5834
- import dispatchApiOpenaiCompat from './src/dispatchApiOpenaiCompat.mjs'
6789
+ import dispatchApiOpenaiResponses from './src/dispatchApiOpenaiResponses.mjs'
5835
6790
 
5836
6791
  let test = async () => {
5837
6792
 
5838
- //OpenCode Zen(即opencode CLI之自家閘道), 模型名不帶opencode/前綴
5839
- let r1 = await dispatchApiOpenaiCompat('請只回覆兩個字:完成', {
6793
+ //OpenCode Zen之muse-spark系走/responses(非chat/completions), 詳見providers.mjs檔頭
6794
+ let r = await dispatchApiOpenaiResponses('請只回覆兩個字:完成', {
5840
6795
  baseURL: 'https://opencode.ai/zen/v1',
5841
6796
  key: 'sk-xxxxxx',
5842
- model: 'deepseek-v4-flash-free',
5843
- })
5844
- console.log(r1.ok, r1.stdout.trim())
5845
- // => true 完成
5846
-
5847
- //Agnes
5848
- let r2 = await dispatchApiOpenaiCompat('請只回覆兩個字:完成', {
5849
- baseURL: 'https://apihub.agnes-ai.com/v1',
5850
- key: 'sk-xxxxxx',
5851
- model: 'agnes-2.0-flash',
6797
+ model: 'muse-spark-1.3-contributor-free',
5852
6798
  })
5853
- console.log(r2.ok, r2.stdout.trim())
6799
+ console.log(r.ok, r.stdout.trim())
5854
6800
  // => true 完成
5855
6801
 
5856
- let re = await dispatchApiOpenaiCompat('abc', { baseURL: 'https://opencode.ai/zen/v1', key: 'sk-bad', model: 'deepseek-v4-flash-free' })
5857
- console.log(re.ok, re.code, re.error)
5858
- // => false 401 HTTP 401
6802
+ let re = await dispatchApiOpenaiResponses('abc', { baseURL: 'https://opencode.ai/zen/v1', key: 'sk-bad', model: 'muse-spark-1.3-contributor-free' })
6803
+ console.log(re.ok, re.code, re.errorType)
6804
+ // => false 401 http
5859
6805
 
5860
6806
  }
5861
6807
  await test()
@@ -5924,7 +6870,7 @@ await test()
5924
6870
  </td>
5925
6871
 
5926
6872
 
5927
- <td class="description last"><p>輸入提示詞字串,作為user訊息置於HTTP body</p></td>
6873
+ <td class="description last"><p>輸入提示詞字串,作為input置於HTTP body</p></td>
5928
6874
  </tr>
5929
6875
 
5930
6876
 
@@ -6023,7 +6969,7 @@ await test()
6023
6969
  </td>
6024
6970
 
6025
6971
 
6026
- <td class="description last"><p>輸入API基底網址字串,例如'https://opencode.ai/zen/v1'、'https://apihub.agnes-ai.com/v1',將於尾端接上/chat/completions</p></td>
6972
+ <td class="description last"><p>輸入API基底網址字串,例如'https://opencode.ai/zen/v1',將於尾端接上/responses</p></td>
6027
6973
  </tr>
6028
6974
 
6029
6975
 
@@ -6059,7 +7005,7 @@ await test()
6059
7005
  </td>
6060
7006
 
6061
7007
 
6062
- <td class="description last"><p>輸入模型ID字串,例如'deepseek-v4-flash-free'(Zen之模型名不帶opencode/前綴)、'agnes-2.0-flash'</p></td>
7008
+ <td class="description last"><p>輸入模型ID字串,例如'muse-spark-1.3-contributor-free'</p></td>
6063
7009
  </tr>
6064
7010
 
6065
7011
 
@@ -6139,7 +7085,7 @@ await test()
6139
7085
  </td>
6140
7086
 
6141
7087
 
6142
- <td class="description last"><p>輸入system提示詞字串,將以system角色置於messages首位,預設''代表不帶</p></td>
7088
+ <td class="description last"><p>輸入system提示詞字串,將置於instructions欄位(Responses API之system管道),預設''代表不帶</p></td>
6143
7089
  </tr>
6144
7090
 
6145
7091
 
@@ -6179,7 +7125,7 @@ await test()
6179
7125
  </td>
6180
7126
 
6181
7127
 
6182
- <td class="description last"><p>輸入額外請求本體物件(如temperature、max_tokensresponse_format),將併入預設body(同名鍵以此為準),預設{}。注意本轉接器不支援工具,帶入tools而模型回tool_calls時一律以TOOL_CALLS_UNSUPPORTED回報失敗,需要工具請改用CLI類kind</p></td>
7128
+ <td class="description last"><p>輸入額外請求本體物件(如temperature、max_output_tokensreasoning),將併入預設body(同名鍵以此為準),預設{}。注意輸出上限欄位名為max_output_tokens而非max_tokens;本轉接器不支援工具,帶入tools而模型回function_call時一律以TOOL_CALLS_UNSUPPORTED回報失敗</p></td>
6183
7129
  </tr>
6184
7130
 
6185
7131
 
@@ -6413,7 +7359,7 @@ await test()
6413
7359
 
6414
7360
 
6415
7361
  <div class="param-desc">
6416
- <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(回覆內容字串)、stderr(失敗時之原始回應本體)、code(HTTP狀態碼,網路錯誤與逾時為null)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串,一覽見getErrorType.mjs檔頭)、durationMs(耗時毫秒)、attempts(實際嘗試次數)、usage(原始回應之token用量物件原樣透傳,無則null),本函數不會reject</p>
7362
+ <p>回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(回覆內容字串)、stderr(失敗時之原始回應本體)、code(HTTP狀態碼,網路錯誤與逾時為null)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串,一覽見getErrorType.mjs檔頭)、durationMs(耗時毫秒)、attempts(實際嘗試次數)、usage(原始回應之token用量物件原樣透傳,欄位名為input_tokens/output_tokens/total_tokens,無則null),本函數不會reject</p>
6417
7363
  </div>
6418
7364
 
6419
7365
 
@@ -8598,6 +9544,178 @@ console.log(extractJsonLoose('純文字回覆'))
8598
9544
 
8599
9545
 
8600
9546
 
9547
+ <h4 class="name" id="extractOutputText"><span class="type-signature"></span>extractOutputText<span class="signature">(output)</span><span class="type-signature"> &rarr; {String}</span></h4>
9548
+
9549
+
9550
+
9551
+
9552
+
9553
+
9554
+ <dl class="details">
9555
+
9556
+ <dt class="tag-description">Description:</dt>
9557
+ <dd class="tag-description"><ul class="dummy"><li><p>自Responses API之output陣列取出文字內容(僅取message型元素之output_text)</p>
9558
+ <p>reasoning型元素為模型思考過程(Zen實測其content為空陣列),不屬回覆內容故略過;
9559
+ 多個message元素依序串接</p></li></ul></dd>
9560
+
9561
+
9562
+
9563
+ <dt class="tag-source">Source:</dt>
9564
+ <dd class="tag-source"><ul class="dummy"><li>
9565
+ <a href="dispatchApiOpenaiResponses.mjs.html">dispatchApiOpenaiResponses.mjs</a>, <a href="dispatchApiOpenaiResponses.mjs.html#line86">line 86</a>
9566
+ </li></ul></dd>
9567
+
9568
+
9569
+
9570
+
9571
+
9572
+
9573
+
9574
+
9575
+
9576
+
9577
+
9578
+
9579
+
9580
+
9581
+
9582
+
9583
+
9584
+
9585
+
9586
+
9587
+
9588
+
9589
+
9590
+
9591
+
9592
+
9593
+
9594
+
9595
+
9596
+
9597
+
9598
+ </dl>
9599
+
9600
+
9601
+
9602
+
9603
+
9604
+
9605
+
9606
+
9607
+
9608
+
9609
+
9610
+ <h5 class="h5-examples">Example</h5>
9611
+
9612
+ <pre class="prettyprint"><code>import { extractOutputText } from './src/dispatchApiOpenaiResponses.mjs'
9613
+
9614
+ let output = [
9615
+ { type: 'reasoning', content: [] },
9616
+ { type: 'message', content: [{ type: 'output_text', text: '完成' }] },
9617
+ ]
9618
+ console.log(extractOutputText(output))
9619
+ // => '完成'</code></pre>
9620
+
9621
+
9622
+
9623
+
9624
+ <h5 class="h5-parameters">Parameters:</h5>
9625
+
9626
+
9627
+ <table class="params">
9628
+ <thead>
9629
+ <tr>
9630
+
9631
+ <th>Name</th>
9632
+
9633
+
9634
+ <th>Type</th>
9635
+
9636
+
9637
+
9638
+
9639
+
9640
+ <th class="last">Description</th>
9641
+ </tr>
9642
+ </thead>
9643
+
9644
+ <tbody>
9645
+
9646
+
9647
+ <tr>
9648
+
9649
+ <td class="name"><code>output</code></td>
9650
+
9651
+
9652
+ <td class="type">
9653
+
9654
+
9655
+ <span class="param-type">Array</span>
9656
+
9657
+
9658
+
9659
+
9660
+ </td>
9661
+
9662
+
9663
+
9664
+
9665
+
9666
+ <td class="description last"><p>輸入回應之output陣列</p></td>
9667
+ </tr>
9668
+
9669
+
9670
+ </tbody>
9671
+ </table>
9672
+
9673
+
9674
+
9675
+
9676
+
9677
+
9678
+
9679
+
9680
+
9681
+
9682
+
9683
+
9684
+
9685
+
9686
+
9687
+
9688
+ <h5 class="h5-returns">Returns:</h5>
9689
+
9690
+
9691
+ <div class="param-desc">
9692
+ <p>回傳串接後之文字內容,無有效內容回傳空字串</p>
9693
+ </div>
9694
+
9695
+
9696
+
9697
+ <dl class="param-type">
9698
+ <dt>
9699
+ Type
9700
+ </dt>
9701
+ <dd>
9702
+
9703
+ <span class="param-type">String</span>
9704
+
9705
+
9706
+
9707
+ </dd>
9708
+ </dl>
9709
+
9710
+
9711
+
9712
+
9713
+
9714
+
9715
+
9716
+
9717
+
9718
+
8601
9719
  <h4 class="name" id="getCliArgs"><span class="type-signature"></span>getCliArgs<span class="signature">(&hellip;args)</span><span class="type-signature"> &rarr; {Array}</span></h4>
8602
9720
 
8603
9721
 
@@ -9034,7 +10152,7 @@ console.log(getErrorResult(null).error)
9034
10152
 
9035
10153
  <dt class="tag-source">Source:</dt>
9036
10154
  <dd class="tag-source"><ul class="dummy"><li>
9037
- <a href="getErrorType.mjs.html">getErrorType.mjs</a>, <a href="getErrorType.mjs.html#line53">line 53</a>
10155
+ <a href="getErrorType.mjs.html">getErrorType.mjs</a>, <a href="getErrorType.mjs.html#line55">line 55</a>
9038
10156
  </li></ul></dd>
9039
10157
 
9040
10158
 
@@ -9992,7 +11110,7 @@ let env = readEnvFile('./.env')
9992
11110
  //全取: envVar展開為keys, 缺環境變數者列入skipped
9993
11111
  let { providers, table, skipped } = resolveProviders(providersAll, { env })
9994
11112
  console.log(providers.length, skipped)
9995
- // => 16 []
11113
+ // => 17 []
9996
11114
 
9997
11115
  //pick打錯字時, missing附拼寫提示hints(最接近之可用id)
9998
11116
  let rm = resolveProviders(providersAll, { env, pick: ['poolside/laguna-s-2.1'] })
@@ -12085,7 +13203,7 @@ console.log(salvageTruncatedArray('[{"a":1}]')) //有閉合=非截斷, 不在
12085
13203
  <br class="clear">
12086
13204
 
12087
13205
  <footer>
12088
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Sep 02 2026 18:01:49 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
13206
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Sep 03 2026 11:40:21 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
12089
13207
  </footer>
12090
13208
 
12091
13209
  <script>prettyPrint();</script>