w-dispatch-ai 1.0.11 → 1.0.13

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 (51) hide show
  1. package/README.md +33 -5
  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 +15 -3
  5. package/docs/adapters.mjs.html +2 -2
  6. package/docs/budgetFor.mjs.html +124 -0
  7. package/docs/castPintOr.mjs.html +2 -2
  8. package/docs/dfTimeoutMs.mjs.html +2 -2
  9. package/docs/dispatchAi.mjs.html +2 -2
  10. package/docs/dispatchAiFallback.mjs.html +2 -2
  11. package/docs/dispatchAiWkf.mjs.html +2 -2
  12. package/docs/dispatchAntigravity.mjs.html +2 -2
  13. package/docs/dispatchApiOpenaiCompat.mjs.html +2 -2
  14. package/docs/dispatchClaude.mjs.html +2 -2
  15. package/docs/dispatchCodex.mjs.html +2 -2
  16. package/docs/dispatchOpencode.mjs.html +2 -2
  17. package/docs/getCliArgs.mjs.html +2 -2
  18. package/docs/getErrorResult.mjs.html +2 -2
  19. package/docs/getErrorType.mjs.html +2 -2
  20. package/docs/global.html +1632 -49
  21. package/docs/index.html +2 -2
  22. package/docs/readEnvFile.mjs.html +132 -0
  23. package/docs/resolveProviders.mjs.html +54 -6
  24. package/docs/wkf_callAiWithFallback.mjs.html +7 -22
  25. package/docs/wkf_createFileStore.mjs.html +175 -0
  26. package/docs/wkf_createUsageCounter.mjs.html +213 -0
  27. package/docs/wkf_extractJsonLoose.mjs.html +2 -2
  28. package/docs/wkf_noSideEffectPrefix.mjs.html +121 -0
  29. package/docs/wkf_runFanout.mjs.html +2 -2
  30. package/docs/wkf_runFanoutPipeline.mjs.html +2 -2
  31. package/docs/wkf_runRolePipeline.mjs.html +2 -2
  32. package/docs/wkf_salvageTruncatedArray.mjs.html +167 -0
  33. package/package.json +2 -2
  34. package/src/WDispatchAi.mjs +13 -1
  35. package/src/budgetFor.mjs +52 -0
  36. package/src/providers.mjs +4 -3
  37. package/src/readEnvFile.mjs +60 -0
  38. package/src/resolveProviders.mjs +52 -4
  39. package/src/wkf/callAiWithFallback.mjs +5 -20
  40. package/src/wkf/createFileStore.mjs +103 -0
  41. package/src/wkf/createUsageCounter.mjs +141 -0
  42. package/src/wkf/noSideEffectPrefix.mjs +49 -0
  43. package/src/wkf/salvageTruncatedArray.mjs +95 -0
  44. package/test/unit-WDispatchAi.test.mjs +9 -3
  45. package/test/unit-budgetFor.test.mjs +26 -0
  46. package/test/unit-callAiWithFallback.test.mjs +8 -0
  47. package/test/unit-createFileStore.test.mjs +66 -0
  48. package/test/unit-createUsageCounter.test.mjs +76 -0
  49. package/test/unit-readEnvFile.test.mjs +52 -0
  50. package/test/unit-resolveProviders.test.mjs +49 -0
  51. package/test/unit-salvageTruncatedArray.test.mjs +39 -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#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#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#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#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></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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -125,6 +125,86 @@
125
125
 
126
126
 
127
127
 
128
+ <h4 class="name" id="NO_SIDE_EFFECT"><span class="type-signature"></span>NO_SIDE_EFFECT<span class="type-signature"></span></h4>
129
+
130
+
131
+
132
+
133
+
134
+ <dl class="details">
135
+
136
+ <dt class="tag-description">Description:</dt>
137
+ <dd class="tag-description"><ul class="dummy"><li><p>防副作用prompt前綴:禁止寫入類副作用、豁免唯讀查閱</p>
138
+ <p>用法:<code>NO_SIDE_EFFECT + prompt</code>後交dispatchAiFallback;
139
+ callAiWithFallback預設自動掛上(傳promptPrefix:''關閉),
140
+ 直接呼叫dispatchAiFallback的呼叫端自行前綴</p></li></ul></dd>
141
+
142
+
143
+
144
+ <dt class="tag-source">Source:</dt>
145
+ <dd class="tag-source"><ul class="dummy"><li>
146
+ <a href="wkf_noSideEffectPrefix.mjs.html">wkf/noSideEffectPrefix.mjs</a>, <a href="wkf_noSideEffectPrefix.mjs.html#line40">line 40</a>
147
+ </li></ul></dd>
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+ </dl>
180
+
181
+
182
+
183
+
184
+
185
+ <div class="description usertext">
186
+ <p>防副作用prompt前綴:禁止寫入類副作用、豁免唯讀查閱</p>
187
+ <p>用法:<code>NO_SIDE_EFFECT + prompt</code>後交dispatchAiFallback;
188
+ callAiWithFallback預設自動掛上(傳promptPrefix:''關閉),
189
+ 直接呼叫dispatchAiFallback的呼叫端自行前綴</p>
190
+ </div>
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+ <h5 class="h5-examples">Example</h5>
199
+
200
+ <pre class="prettyprint"><code>import NO_SIDE_EFFECT from './src/wkf/noSideEffectPrefix.mjs'
201
+
202
+ //let r = await dispatchAiFallback(NO_SIDE_EFFECT + prompt, { providers })</code></pre>
203
+
204
+
205
+
206
+
207
+
128
208
  <h4 class="name" id="WDispatchAi"><span class="type-signature"></span>WDispatchAi<span class="type-signature"></span></h4>
129
209
 
130
210
 
@@ -140,7 +220,7 @@
140
220
 
141
221
  <dt class="tag-source">Source:</dt>
142
222
  <dd class="tag-source"><ul class="dummy"><li>
143
- <a href="WDispatchAi.mjs.html">WDispatchAi.mjs</a>, <a href="WDispatchAi.mjs.html#line36">line 36</a>
223
+ <a href="WDispatchAi.mjs.html">WDispatchAi.mjs</a>, <a href="WDispatchAi.mjs.html#line42">line 42</a>
144
224
  </li></ul></dd>
145
225
 
146
226
 
@@ -529,6 +609,179 @@ console.log(attachErrorType({ ok: true, stdout: 'abc' }).errorType)
529
609
 
530
610
 
531
611
 
612
+ <h4 class="name" id="budgetFor"><span class="type-signature"></span>budgetFor<span class="signature">(providers)</span><span class="type-signature"> &rarr; {Number}</span></h4>
613
+
614
+
615
+
616
+
617
+
618
+
619
+ <dl class="details">
620
+
621
+ <dt class="tag-description">Description:</dt>
622
+ <dd class="tag-description"><ul class="dummy"><li><p>計算遞補鏈走滿所需之時間預算(=各條目timeoutMs之總和, 未帶者以套件統一預設計)</p>
623
+ <p>特點:
624
+ 條目timeoutMs取正整數者計入,未帶或無效者以dfTimeoutMs(全套件統一預設300000)計——
625
+ 與dispatchAiFallback執行時之實際取值一致,故總和即為走滿全鏈之上限;
626
+ 輸入非陣列回傳0</p></li></ul></dd>
627
+
628
+
629
+
630
+ <dt class="tag-source">Source:</dt>
631
+ <dd class="tag-source"><ul class="dummy"><li>
632
+ <a href="budgetFor.mjs.html">budgetFor.mjs</a>, <a href="budgetFor.mjs.html#line40">line 40</a>
633
+ </li></ul></dd>
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+ </dl>
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+ <h5 class="h5-examples">Example</h5>
678
+
679
+ <pre class="prettyprint"><code>import budgetFor from './src/budgetFor.mjs'
680
+
681
+ console.log(budgetFor([{ timeoutMs: 180000 }, { timeoutMs: 240000 }]))
682
+ // => 420000
683
+
684
+ console.log(budgetFor([{ timeoutMs: 180000 }, {}])) //未帶者以套件統一預設300000計
685
+ // => 480000</code></pre>
686
+
687
+
688
+
689
+
690
+ <h5 class="h5-parameters">Parameters:</h5>
691
+
692
+
693
+ <table class="params">
694
+ <thead>
695
+ <tr>
696
+
697
+ <th>Name</th>
698
+
699
+
700
+ <th>Type</th>
701
+
702
+
703
+
704
+
705
+
706
+ <th class="last">Description</th>
707
+ </tr>
708
+ </thead>
709
+
710
+ <tbody>
711
+
712
+
713
+ <tr>
714
+
715
+ <td class="name"><code>providers</code></td>
716
+
717
+
718
+ <td class="type">
719
+
720
+
721
+ <span class="param-type">Array</span>
722
+
723
+
724
+
725
+
726
+ </td>
727
+
728
+
729
+
730
+
731
+
732
+ <td class="description last"><p>輸入供應商條目物件陣列(dispatchAiFallback之providers)</p></td>
733
+ </tr>
734
+
735
+
736
+ </tbody>
737
+ </table>
738
+
739
+
740
+
741
+
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+
752
+
753
+
754
+ <h5 class="h5-returns">Returns:</h5>
755
+
756
+
757
+ <div class="param-desc">
758
+ <p>回傳時間預算毫秒整數</p>
759
+ </div>
760
+
761
+
762
+
763
+ <dl class="param-type">
764
+ <dt>
765
+ Type
766
+ </dt>
767
+ <dd>
768
+
769
+ <span class="param-type">Number</span>
770
+
771
+
772
+
773
+ </dd>
774
+ </dl>
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+
532
785
  <h4 class="name" id="buildChain"><span class="type-signature"></span>buildChain<span class="signature">(providers, spec)</span><span class="type-signature"> &rarr; {Object}</span></h4>
533
786
 
534
787
 
@@ -545,7 +798,7 @@ console.log(attachErrorType({ ok: true, stdout: 'abc' }).errorType)
545
798
 
546
799
  <dt class="tag-source">Source:</dt>
547
800
  <dd class="tag-source"><ul class="dummy"><li>
548
- <a href="wkf_callAiWithFallback.mjs.html">wkf/callAiWithFallback.mjs</a>, <a href="wkf_callAiWithFallback.mjs.html#line71">line 71</a>
801
+ <a href="wkf_callAiWithFallback.mjs.html">wkf/callAiWithFallback.mjs</a>, <a href="wkf_callAiWithFallback.mjs.html#line56">line 56</a>
549
802
  </li></ul></dd>
550
803
 
551
804
 
@@ -905,7 +1158,7 @@ parse+check接進遞補層之validate——非法回覆視為該家失敗而
905
1158
 
906
1159
  <dt class="tag-source">Source:</dt>
907
1160
  <dd class="tag-source"><ul class="dummy"><li>
908
- <a href="wkf_callAiWithFallback.mjs.html">wkf/callAiWithFallback.mjs</a>, <a href="wkf_callAiWithFallback.mjs.html#line146">line 146</a>
1161
+ <a href="wkf_callAiWithFallback.mjs.html">wkf/callAiWithFallback.mjs</a>, <a href="wkf_callAiWithFallback.mjs.html#line131">line 131</a>
909
1162
  </li></ul></dd>
910
1163
 
911
1164
 
@@ -1334,7 +1587,7 @@ await test()
1334
1587
  </td>
1335
1588
 
1336
1589
 
1337
- <td class="description last"><p>輸入prompt前綴字串,預設為防寫檔約束,傳''關閉</p></td>
1590
+ <td class="description last"><p>輸入prompt前綴字串,預設為防寫檔約束(見wkf/noSideEffectPrefix.mjs),傳''關閉</p></td>
1338
1591
  </tr>
1339
1592
 
1340
1593
 
@@ -2037,50 +2290,900 @@ await test()
2037
2290
 
2038
2291
  <pre class="prettyprint"><code>import castPintOr from './src/castPintOr.mjs'
2039
2292
 
2040
- console.log(castPintOr(5000, 300000))
2041
- // => 5000
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
+
2304
+
2305
+ <h5 class="h5-parameters">Parameters:</h5>
2306
+
2307
+
2308
+ <table class="params">
2309
+ <thead>
2310
+ <tr>
2311
+
2312
+ <th>Name</th>
2313
+
2314
+
2315
+ <th>Type</th>
2316
+
2317
+
2318
+
2319
+
2320
+
2321
+ <th class="last">Description</th>
2322
+ </tr>
2323
+ </thead>
2324
+
2325
+ <tbody>
2326
+
2327
+
2328
+ <tr>
2329
+
2330
+ <td class="name"><code>v</code></td>
2331
+
2332
+
2333
+ <td class="type">
2334
+
2335
+
2336
+ <span class="param-type">*</span>
2337
+
2338
+
2339
+
2340
+
2341
+ </td>
2342
+
2343
+
2344
+
2345
+
2346
+
2347
+ <td class="description last"><p>輸入待正規化之值</p></td>
2348
+ </tr>
2349
+
2350
+
2351
+
2352
+ <tr>
2353
+
2354
+ <td class="name"><code>df</code></td>
2355
+
2356
+
2357
+ <td class="type">
2358
+
2359
+
2360
+ <span class="param-type">*</span>
2361
+
2362
+
2363
+
2364
+
2365
+ </td>
2366
+
2367
+
2368
+
2369
+
2370
+
2371
+ <td class="description last"><p>輸入無效時之預設值(可為null代表不限)</p></td>
2372
+ </tr>
2373
+
2374
+
2375
+ </tbody>
2376
+ </table>
2377
+
2378
+
2379
+
2380
+
2381
+
2382
+
2383
+
2384
+
2385
+
2386
+
2387
+
2388
+
2389
+
2390
+
2391
+
2392
+
2393
+ <h5 class="h5-returns">Returns:</h5>
2394
+
2395
+
2396
+ <div class="param-desc">
2397
+ <p>回傳正規化後之正整數,v非有效正整數時回傳df</p>
2398
+ </div>
2399
+
2400
+
2401
+
2402
+ <dl class="param-type">
2403
+ <dt>
2404
+ Type
2405
+ </dt>
2406
+ <dd>
2407
+
2408
+ <span class="param-type">Number</span>
2409
+ |
2410
+
2411
+ <span class="param-type">*</span>
2412
+
2413
+
2414
+
2415
+ </dd>
2416
+ </dl>
2417
+
2418
+
2419
+
2420
+
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+
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>
2428
+
2429
+
2430
+
2431
+
2432
+
2433
+
2434
+ <dl class="details">
2435
+
2436
+ <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>
2443
+
2444
+
2445
+
2446
+ <dt class="tag-source">Source:</dt>
2447
+ <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>
2449
+ </li></ul></dd>
2450
+
2451
+
2452
+
2453
+
2454
+
2455
+
2456
+
2457
+
2458
+
2459
+
2460
+
2461
+
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+
2469
+
2470
+
2471
+
2472
+
2473
+
2474
+
2475
+
2476
+
2477
+
2478
+
2479
+
2480
+
2481
+ </dl>
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+
2491
+
2492
+
2493
+ <h5 class="h5-examples">Example</h5>
2494
+
2495
+ <pre class="prettyprint"><code>import createFileStore from './src/wkf/createFileStore.mjs'
2496
+ import dispatchAiFallback from './src/dispatchAiFallback.mjs'
2497
+
2498
+ let store = createFileStore({ dir: './state' })
2499
+ //let r = await dispatchAiFallback(prompt, { providers, store, cooldownMs: 3600000 })</code></pre>
2500
+
2501
+
2502
+
2503
+
2504
+ <h5 class="h5-parameters">Parameters:</h5>
2505
+
2506
+
2507
+ <table class="params">
2508
+ <thead>
2509
+ <tr>
2510
+
2511
+ <th>Name</th>
2512
+
2513
+
2514
+ <th>Type</th>
2515
+
2516
+
2517
+ <th>Attributes</th>
2518
+
2519
+
2520
+
2521
+ <th>Default</th>
2522
+
2523
+
2524
+ <th class="last">Description</th>
2525
+ </tr>
2526
+ </thead>
2527
+
2528
+ <tbody>
2529
+
2530
+
2531
+ <tr>
2532
+
2533
+ <td class="name"><code>opt</code></td>
2534
+
2535
+
2536
+ <td class="type">
2537
+
2538
+
2539
+ <span class="param-type">Object</span>
2540
+
2541
+
2542
+
2543
+
2544
+ </td>
2545
+
2546
+
2547
+ <td class="attributes">
2548
+
2549
+ &lt;optional><br>
2550
+
2551
+
2552
+
2553
+
2554
+
2555
+ </td>
2556
+
2557
+
2558
+
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
+
2583
+
2584
+ <th>Default</th>
2585
+
2586
+
2587
+ <th class="last">Description</th>
2588
+ </tr>
2589
+ </thead>
2590
+
2591
+ <tbody>
2592
+
2593
+
2594
+ <tr>
2595
+
2596
+ <td class="name"><code>file</code></td>
2597
+
2598
+
2599
+ <td class="type">
2600
+
2601
+
2602
+ <span class="param-type">String</span>
2603
+
2604
+
2605
+
2606
+
2607
+ </td>
2608
+
2609
+
2610
+ <td class="attributes">
2611
+
2612
+ &lt;optional><br>
2613
+
2614
+
2615
+
2616
+
2617
+
2618
+ </td>
2619
+
2620
+
2621
+
2622
+ <td class="default">
2623
+
2624
+ <code>null</code>
2625
+
2626
+ </td>
2627
+
2628
+
2629
+ <td class="description last"><p>輸入狀態檔完整路徑字串,與dir/name二擇一</p></td>
2630
+ </tr>
2631
+
2632
+
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>
2802
+
2803
+
2804
+
2805
+
2806
+
2807
+
2808
+
2809
+
2810
+
2811
+
2812
+
2813
+
2814
+
2815
+
2816
+
2817
+
2818
+ <h5 class="h5-returns">Returns:</h5>
2819
+
2820
+
2821
+ <div class="param-desc">
2822
+ <p>回傳store物件,內含get、set(可直接餵dispatchAiFallback之store)與file(狀態檔路徑)</p>
2823
+ </div>
2824
+
2825
+
2826
+
2827
+ <dl class="param-type">
2828
+ <dt>
2829
+ Type
2830
+ </dt>
2831
+ <dd>
2832
+
2833
+ <span class="param-type">Object</span>
2834
+
2835
+
2836
+
2837
+ </dd>
2838
+ </dl>
2839
+
2840
+
2841
+
2842
+
2843
+
2844
+
2845
+
2846
+
2847
+
2848
+
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>
2850
+
2851
+
2852
+
2853
+
2854
+
2855
+
2856
+ <dl class="details">
2857
+
2858
+ <dt class="tag-description">Description:</dt>
2859
+ <dd class="tag-description"><ul class="dummy"><li><p>建立逐日、逐鍵之用量計數器(純觀測, 不參與任何判斷)</p>
2860
+ <p>特點:
2861
+ onEvent可直接掛進dispatchAiFallback/dispatchAiWkf,於type為'try'時依keyOf取鍵累加——
2862
+ 嘗試時即記帳,行程被外部時限中途砍掉已發出的請求仍有紀錄;
2863
+ 逐日分桶並僅保留最近keepDays天,避免檔案無限成長;
2864
+ getDate可注入時區錨定之日期函數——預設隨系統時區,排程session之系統時區可能為UTC+0
2865
+ 而使日界錯8小時,排程環境務必注入</p></li></ul></dd>
2866
+
2867
+
2868
+
2869
+ <dt class="tag-source">Source:</dt>
2870
+ <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>
2872
+ </li></ul></dd>
2873
+
2874
+
2875
+
2876
+
2877
+
2878
+
2879
+
2880
+
2881
+
2882
+
2883
+
2884
+
2885
+
2886
+
2887
+
2888
+
2889
+
2890
+
2891
+
2892
+
2893
+
2894
+
2895
+
2896
+
2897
+
2898
+
2899
+
2900
+
2901
+
2902
+
2903
+
2904
+ </dl>
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+
2911
+
2912
+
2913
+
2914
+
2915
+
2916
+ <h5 class="h5-examples">Example</h5>
2917
+
2918
+ <pre class="prettyprint"><code>import createUsageCounter from './src/wkf/createUsageCounter.mjs'
2919
+
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>
2924
+
2925
+
2926
+
2927
+
2928
+ <h5 class="h5-parameters">Parameters:</h5>
2929
+
2930
+
2931
+ <table class="params">
2932
+ <thead>
2933
+ <tr>
2934
+
2935
+ <th>Name</th>
2936
+
2937
+
2938
+ <th>Type</th>
2939
+
2940
+
2941
+ <th>Attributes</th>
2942
+
2943
+
2944
+
2945
+ <th>Default</th>
2946
+
2947
+
2948
+ <th class="last">Description</th>
2949
+ </tr>
2950
+ </thead>
2951
+
2952
+ <tbody>
2953
+
2954
+
2955
+ <tr>
2956
+
2957
+ <td class="name"><code>opt</code></td>
2958
+
2959
+
2960
+ <td class="type">
2961
+
2962
+
2963
+ <span class="param-type">Object</span>
2964
+
2965
+
2966
+
2967
+
2968
+ </td>
2969
+
2970
+
2971
+ <td class="attributes">
2972
+
2973
+ &lt;optional><br>
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+ </td>
2980
+
2981
+
2982
+
2983
+ <td class="default">
2984
+
2985
+ <code>{}</code>
2986
+
2987
+ </td>
2988
+
2989
+
2990
+ <td class="description last"><p>輸入設定物件,預設{}</p>
2991
+ <h6>Properties</h6>
2992
+
2993
+
2994
+ <table class="params">
2995
+ <thead>
2996
+ <tr>
2997
+
2998
+ <th>Name</th>
2999
+
3000
+
3001
+ <th>Type</th>
3002
+
3003
+
3004
+ <th>Attributes</th>
3005
+
3006
+
3007
+
3008
+ <th>Default</th>
3009
+
3010
+
3011
+ <th class="last">Description</th>
3012
+ </tr>
3013
+ </thead>
3014
+
3015
+ <tbody>
3016
+
3017
+
3018
+ <tr>
3019
+
3020
+ <td class="name"><code>file</code></td>
3021
+
3022
+
3023
+ <td class="type">
3024
+
3025
+
3026
+ <span class="param-type">String</span>
3027
+
3028
+
3029
+
3030
+
3031
+ </td>
3032
+
3033
+
3034
+ <td class="attributes">
3035
+
3036
+ &lt;optional><br>
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+ </td>
3043
+
3044
+
3045
+
3046
+ <td class="default">
3047
+
3048
+ <code>null</code>
3049
+
3050
+ </td>
3051
+
3052
+
3053
+ <td class="description last"><p>輸入用量檔完整路徑字串,與dir/name二擇一</p></td>
3054
+ </tr>
3055
+
3056
+
3057
+
3058
+ <tr>
3059
+
3060
+ <td class="name"><code>dir</code></td>
3061
+
3062
+
3063
+ <td class="type">
3064
+
3065
+
3066
+ <span class="param-type">String</span>
3067
+
3068
+
3069
+
3070
+
3071
+ </td>
3072
+
3073
+
3074
+ <td class="attributes">
3075
+
3076
+ &lt;optional><br>
3077
+
3078
+
3079
+
3080
+
3081
+
3082
+ </td>
3083
+
3084
+
3085
+
3086
+ <td class="default">
3087
+
3088
+ <code>null</code>
3089
+
3090
+ </td>
3091
+
3092
+
3093
+ <td class="description last"><p>輸入狀態目錄字串</p></td>
3094
+ </tr>
3095
+
3096
+
3097
+
3098
+ <tr>
3099
+
3100
+ <td class="name"><code>name</code></td>
3101
+
3102
+
3103
+ <td class="type">
3104
+
3105
+
3106
+ <span class="param-type">String</span>
3107
+
3108
+
3109
+
3110
+
3111
+ </td>
3112
+
3113
+
3114
+ <td class="attributes">
3115
+
3116
+ &lt;optional><br>
3117
+
3118
+
3119
+
3120
+
3121
+
3122
+ </td>
3123
+
3124
+
3125
+
3126
+ <td class="default">
3127
+
3128
+ <code>'ai-usage.json'</code>
3129
+
3130
+ </td>
3131
+
3132
+
3133
+ <td class="description last"><p>輸入用量檔名字串,預設'ai-usage.json'</p></td>
3134
+ </tr>
2042
3135
 
2043
- console.log(castPintOr('abc', 300000))
2044
- // => 300000
3136
+
2045
3137
 
2046
- console.log(castPintOr(undefined, null))
2047
- // => null</code></pre>
3138
+ <tr>
3139
+
3140
+ <td class="name"><code>getDate</code></td>
3141
+
2048
3142
 
3143
+ <td class="type">
3144
+
3145
+
3146
+ <span class="param-type">function</span>
2049
3147
 
2050
3148
 
2051
3149
 
2052
- <h5 class="h5-parameters">Parameters:</h5>
2053
-
3150
+
3151
+ </td>
2054
3152
 
2055
- <table class="params">
2056
- <thead>
2057
- <tr>
2058
-
2059
- <th>Name</th>
2060
-
3153
+
3154
+ <td class="attributes">
3155
+
3156
+ &lt;optional><br>
3157
+
2061
3158
 
2062
- <th>Type</th>
3159
+
2063
3160
 
2064
-
3161
+
3162
+ </td>
3163
+
2065
3164
 
2066
-
3165
+
3166
+ <td class="default">
3167
+
3168
+ <code>系統日期</code>
3169
+
3170
+ </td>
3171
+
2067
3172
 
2068
- <th class="last">Description</th>
2069
- </tr>
2070
- </thead>
3173
+ <td class="description last"><p>輸入日期函數()=&gt;'YYYY-MM-DD',預設隨系統時區(排程環境建議注入時區錨定者)</p></td>
3174
+ </tr>
2071
3175
 
2072
- <tbody>
2073
3176
 
2074
3177
 
2075
3178
  <tr>
2076
3179
 
2077
- <td class="name"><code>v</code></td>
3180
+ <td class="name"><code>keepDays</code></td>
2078
3181
 
2079
3182
 
2080
3183
  <td class="type">
2081
3184
 
2082
3185
 
2083
- <span class="param-type">*</span>
3186
+ <span class="param-type">Number</span>
2084
3187
 
2085
3188
 
2086
3189
 
@@ -2088,23 +3191,39 @@ console.log(castPintOr(undefined, null))
2088
3191
  </td>
2089
3192
 
2090
3193
 
3194
+ <td class="attributes">
3195
+
3196
+ &lt;optional><br>
3197
+
3198
+
3199
+
2091
3200
 
3201
+
3202
+ </td>
2092
3203
 
2093
3204
 
2094
- <td class="description last"><p>輸入待正規化之值</p></td>
3205
+
3206
+ <td class="default">
3207
+
3208
+ <code>14</code>
3209
+
3210
+ </td>
3211
+
3212
+
3213
+ <td class="description last"><p>輸入保留天數正整數,預設14</p></td>
2095
3214
  </tr>
2096
3215
 
2097
3216
 
2098
3217
 
2099
3218
  <tr>
2100
3219
 
2101
- <td class="name"><code>df</code></td>
3220
+ <td class="name"><code>keyOf</code></td>
2102
3221
 
2103
3222
 
2104
3223
  <td class="type">
2105
3224
 
2106
3225
 
2107
- <span class="param-type">*</span>
3226
+ <span class="param-type">function</span>
2108
3227
 
2109
3228
 
2110
3229
 
@@ -2112,10 +3231,33 @@ console.log(castPintOr(undefined, null))
2112
3231
  </td>
2113
3232
 
2114
3233
 
3234
+ <td class="attributes">
3235
+
3236
+ &lt;optional><br>
3237
+
3238
+
3239
+
2115
3240
 
3241
+
3242
+ </td>
2116
3243
 
2117
3244
 
2118
- <td class="description last"><p>輸入無效時之預設值(可為null代表不限)</p></td>
3245
+
3246
+ <td class="default">
3247
+
3248
+ <code>(ev)=>ev.keyId||ev.providerId</code>
3249
+
3250
+ </td>
3251
+
3252
+
3253
+ <td class="description last"><p>輸入計帳鍵函數(ev)=&gt;String,決定粒度(金鑰或條目),預設優先keyId</p></td>
3254
+ </tr>
3255
+
3256
+
3257
+ </tbody>
3258
+ </table>
3259
+
3260
+ </td>
2119
3261
  </tr>
2120
3262
 
2121
3263
 
@@ -2141,7 +3283,7 @@ console.log(castPintOr(undefined, null))
2141
3283
 
2142
3284
 
2143
3285
  <div class="param-desc">
2144
- <p>回傳正規化後之正整數,v非有效正整數時回傳df</p>
3286
+ <p>回傳計數器物件,內含onEvent(可直接餵dispatch之onEvent)、bump(手動累加)、today(今日統計)與file(用量檔路徑)</p>
2145
3287
  </div>
2146
3288
 
2147
3289
 
@@ -2152,10 +3294,7 @@ console.log(castPintOr(undefined, null))
2152
3294
  </dt>
2153
3295
  <dd>
2154
3296
 
2155
- <span class="param-type">Number</span>
2156
- |
2157
-
2158
- <span class="param-type">*</span>
3297
+ <span class="param-type">Object</span>
2159
3298
 
2160
3299
 
2161
3300
 
@@ -8225,7 +9364,169 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8225
9364
 
8226
9365
  <dt class="tag-source">Source:</dt>
8227
9366
  <dd class="tag-source"><ul class="dummy"><li>
8228
- <a href="dispatchAiFallback.mjs.html">dispatchAiFallback.mjs</a>, <a href="dispatchAiFallback.mjs.html#line183">line 183</a>
9367
+ <a href="dispatchAiFallback.mjs.html">dispatchAiFallback.mjs</a>, <a href="dispatchAiFallback.mjs.html#line183">line 183</a>
9368
+ </li></ul></dd>
9369
+
9370
+
9371
+
9372
+
9373
+
9374
+
9375
+
9376
+
9377
+
9378
+
9379
+
9380
+
9381
+
9382
+
9383
+
9384
+
9385
+
9386
+
9387
+
9388
+
9389
+
9390
+
9391
+
9392
+
9393
+
9394
+
9395
+
9396
+
9397
+
9398
+
9399
+
9400
+ </dl>
9401
+
9402
+
9403
+
9404
+
9405
+
9406
+
9407
+
9408
+
9409
+
9410
+
9411
+
9412
+
9413
+
9414
+ <h5 class="h5-parameters">Parameters:</h5>
9415
+
9416
+
9417
+ <table class="params">
9418
+ <thead>
9419
+ <tr>
9420
+
9421
+ <th>Name</th>
9422
+
9423
+
9424
+ <th>Type</th>
9425
+
9426
+
9427
+
9428
+
9429
+
9430
+ <th class="last">Description</th>
9431
+ </tr>
9432
+ </thead>
9433
+
9434
+ <tbody>
9435
+
9436
+
9437
+ <tr>
9438
+
9439
+ <td class="name"><code>r</code></td>
9440
+
9441
+
9442
+ <td class="type">
9443
+
9444
+
9445
+ <span class="param-type">Object</span>
9446
+
9447
+
9448
+
9449
+
9450
+ </td>
9451
+
9452
+
9453
+
9454
+
9455
+
9456
+ <td class="description last"><p>輸入dispatchAi失敗結果物件</p></td>
9457
+ </tr>
9458
+
9459
+
9460
+ </tbody>
9461
+ </table>
9462
+
9463
+
9464
+
9465
+
9466
+
9467
+
9468
+
9469
+
9470
+
9471
+
9472
+
9473
+
9474
+
9475
+
9476
+
9477
+
9478
+ <h5 class="h5-returns">Returns:</h5>
9479
+
9480
+
9481
+ <div class="param-desc">
9482
+ <p>回傳是否應整組跳過之布林值</p>
9483
+ </div>
9484
+
9485
+
9486
+
9487
+ <dl class="param-type">
9488
+ <dt>
9489
+ Type
9490
+ </dt>
9491
+ <dd>
9492
+
9493
+ <span class="param-type">Boolean</span>
9494
+
9495
+
9496
+
9497
+ </dd>
9498
+ </dl>
9499
+
9500
+
9501
+
9502
+
9503
+
9504
+
9505
+
9506
+
9507
+
9508
+
9509
+ <h4 class="name" id="readEnvFile"><span class="type-signature"></span>readEnvFile<span class="signature">(file)</span><span class="type-signature"> &rarr; {Object}</span></h4>
9510
+
9511
+
9512
+
9513
+
9514
+
9515
+
9516
+ <dl class="details">
9517
+
9518
+ <dt class="tag-description">Description:</dt>
9519
+ <dd class="tag-description"><ul class="dummy"><li><p>讀取.env檔為鍵值物件(金鑰來源, 不寫入process.env)</p>
9520
+ <p>特點:
9521
+ 只解析<code>KEY=value</code>形式(KEY限英數底線),忽略空行、註解與無效行;
9522
+ value修剪空白並剝除成對之首尾引號(單雙引號皆可);
9523
+ 檔案不存在或不可讀一律回空物件不throw(金鑰缺失交由resolveProviders之skipped回報)</p></li></ul></dd>
9524
+
9525
+
9526
+
9527
+ <dt class="tag-source">Source:</dt>
9528
+ <dd class="tag-source"><ul class="dummy"><li>
9529
+ <a href="readEnvFile.mjs.html">readEnvFile.mjs</a>, <a href="readEnvFile.mjs.html#line40">line 40</a>
8229
9530
  </li></ul></dd>
8230
9531
 
8231
9532
 
@@ -8270,6 +9571,17 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8270
9571
 
8271
9572
 
8272
9573
 
9574
+ <h5 class="h5-examples">Example</h5>
9575
+
9576
+ <pre class="prettyprint"><code>import readEnvFile from './src/readEnvFile.mjs'
9577
+ import resolveProviders from './src/resolveProviders.mjs'
9578
+ import providersAll from './src/providers.mjs'
9579
+
9580
+ //金鑰放.env(變數值以逗號分隔多把), 讀成物件交resolveProviders, 不污染process.env
9581
+ let env = readEnvFile('./.env')
9582
+ let { providers, skipped } = resolveProviders(providersAll, { env, pick: ['agnes:agnes-2.5-flash'] })</code></pre>
9583
+
9584
+
8273
9585
 
8274
9586
 
8275
9587
  <h5 class="h5-parameters">Parameters:</h5>
@@ -8297,13 +9609,13 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8297
9609
 
8298
9610
  <tr>
8299
9611
 
8300
- <td class="name"><code>r</code></td>
9612
+ <td class="name"><code>file</code></td>
8301
9613
 
8302
9614
 
8303
9615
  <td class="type">
8304
9616
 
8305
9617
 
8306
- <span class="param-type">Object</span>
9618
+ <span class="param-type">String</span>
8307
9619
 
8308
9620
 
8309
9621
 
@@ -8314,7 +9626,7 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8314
9626
 
8315
9627
 
8316
9628
 
8317
- <td class="description last"><p>輸入dispatchAi失敗結果物件</p></td>
9629
+ <td class="description last"><p>輸入.env檔案路徑字串</p></td>
8318
9630
  </tr>
8319
9631
 
8320
9632
 
@@ -8340,7 +9652,7 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8340
9652
 
8341
9653
 
8342
9654
  <div class="param-desc">
8343
- <p>回傳是否應整組跳過之布林值</p>
9655
+ <p>回傳鍵值物件(變數名 → 字串值),讀取失敗回空物件</p>
8344
9656
  </div>
8345
9657
 
8346
9658
 
@@ -8351,7 +9663,7 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8351
9663
  </dt>
8352
9664
  <dd>
8353
9665
 
8354
- <span class="param-type">Boolean</span>
9666
+ <span class="param-type">Object</span>
8355
9667
 
8356
9668
 
8357
9669
 
@@ -8615,13 +9927,15 @@ console.log(getErrorType({ error: 'Exit code 1' }))
8615
9927
  缺對應環境變數(或值為空)之條目停用並列入skipped,不中斷不throw;
8616
9928
  無envVar之條目(訂閱登入態CLI)原樣通過;條目已自帶有效keys者以keys為準;
8617
9929
  opt.pick可依id自選子集並以pick順序回傳(順序即遞補優先序);
9930
+ opt.exes依kind注入CLI執行檔路徑、opt.patch依id淺合併覆寫欄位——皆於展開後施作,
9931
+ providers與table同源產出故必然一致;
8618
9932
  輸入陣列與條目皆不被改動(輸出為淺拷貝)</p></li></ul></dd>
8619
9933
 
8620
9934
 
8621
9935
 
8622
9936
  <dt class="tag-source">Source:</dt>
8623
9937
  <dd class="tag-source"><ul class="dummy"><li>
8624
- <a href="resolveProviders.mjs.html">resolveProviders.mjs</a>, <a href="resolveProviders.mjs.html#line56">line 56</a>
9938
+ <a href="resolveProviders.mjs.html">resolveProviders.mjs</a>, <a href="resolveProviders.mjs.html#line80">line 80</a>
8625
9939
  </li></ul></dd>
8626
9940
 
8627
9941
 
@@ -8669,20 +9983,32 @@ opt.pick可依id自選子集並以pick順序回傳(順序即遞補優先序);
8669
9983
  <h5 class="h5-examples">Example</h5>
8670
9984
 
8671
9985
  <pre class="prettyprint"><code>import resolveProviders from './src/resolveProviders.mjs'
9986
+ import readEnvFile from './src/readEnvFile.mjs'
8672
9987
  import providersAll from './src/providers.mjs'
8673
9988
 
8674
- process.loadEnvFile('./.env') //金鑰放.env, 變數值以逗號分隔多把
9989
+ //金鑰放.env(變數值以逗號分隔多把), 以readEnvFile讀成物件, 不污染process.env
9990
+ let env = readEnvFile('./.env')
8675
9991
 
8676
9992
  //全取: envVar展開為keys, 缺環境變數者列入skipped
8677
- let { providers, table, skipped } = resolveProviders(providersAll)
9993
+ let { providers, table, skipped } = resolveProviders(providersAll, { env })
8678
9994
  console.log(providers.length, skipped)
8679
9995
  // => 10 []
8680
9996
 
8681
9997
  //自選: 依pick順序回傳(順序即遞補優先序), 可直接餵dispatchAiFallback
8682
- let r2 = resolveProviders(providersAll, { pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'] })
9998
+ let r2 = resolveProviders(providersAll, { env, pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'] })
8683
9999
  console.log(r2.providers.map((p) => p.id))
8684
10000
  // => [ 'agnes:agnes-2.5-flash', 'claude:sonnet' ]
8685
10001
 
10002
+ //後處理: exes逐kind注入執行檔、patch逐id覆寫欄位, 陣列與table同步生效
10003
+ let r3 = resolveProviders(providersAll, {
10004
+ env,
10005
+ pick: ['agnes:agnes-2.5-flash', 'claude:sonnet'],
10006
+ exes: { claude: 'C:/Users/x/.local/bin/claude.exe' },
10007
+ patch: { 'claude:sonnet': { timeoutMs: 360000 } },
10008
+ })
10009
+ console.log(r3.table['claude:sonnet'].exe, r3.table['claude:sonnet'].timeoutMs)
10010
+ // => 'C:/Users/x/.local/bin/claude.exe' 360000
10011
+
8686
10012
  //table可直接餵dispatchAiWkf之providers定義表
8687
10013
  //let wkf = dispatchAiWkf({ providers: r2.table, defaults: { timeoutMs: 1200000 } })</code></pre>
8688
10014
 
@@ -8850,7 +10176,7 @@ console.log(r2.providers.map((p) => p.id))
8850
10176
  </td>
8851
10177
 
8852
10178
 
8853
- <td class="description last"><p>輸入金鑰來源物件(變數名 → 逗號分隔之金鑰字串),預設process.env</p></td>
10179
+ <td class="description last"><p>輸入金鑰來源物件(變數名 → 逗號分隔之金鑰字串),預設process.env。建議以readEnvFile('./.env')讀成物件傳入,不污染process.env</p></td>
8854
10180
  </tr>
8855
10181
 
8856
10182
 
@@ -8894,6 +10220,86 @@ console.log(r2.providers.map((p) => p.id))
8894
10220
  </tr>
8895
10221
 
8896
10222
 
10223
+
10224
+ <tr>
10225
+
10226
+ <td class="name"><code>exes</code></td>
10227
+
10228
+
10229
+ <td class="type">
10230
+
10231
+
10232
+ <span class="param-type">Object</span>
10233
+
10234
+
10235
+
10236
+
10237
+ </td>
10238
+
10239
+
10240
+ <td class="attributes">
10241
+
10242
+ &lt;optional><br>
10243
+
10244
+
10245
+
10246
+
10247
+
10248
+ </td>
10249
+
10250
+
10251
+
10252
+ <td class="default">
10253
+
10254
+ <code>null</code>
10255
+
10256
+ </td>
10257
+
10258
+
10259
+ <td class="description last"><p>輸入kind對執行檔絕對路徑之物件(如{claude:'C:/.../claude.exe'}),命中kind之條目補上exe欄位(條目已自帶exe者不覆寫——條目層設定優先),預設null代表不注入</p></td>
10260
+ </tr>
10261
+
10262
+
10263
+
10264
+ <tr>
10265
+
10266
+ <td class="name"><code>patch</code></td>
10267
+
10268
+
10269
+ <td class="type">
10270
+
10271
+
10272
+ <span class="param-type">Object</span>
10273
+
10274
+
10275
+
10276
+
10277
+ </td>
10278
+
10279
+
10280
+ <td class="attributes">
10281
+
10282
+ &lt;optional><br>
10283
+
10284
+
10285
+
10286
+
10287
+
10288
+ </td>
10289
+
10290
+
10291
+
10292
+ <td class="default">
10293
+
10294
+ <code>null</code>
10295
+
10296
+ </td>
10297
+
10298
+
10299
+ <td class="description last"><p>輸入id對部分欄位之物件(如{'claude:sonnet':{timeoutMs:360000}}),命中id之條目淺合併覆寫,於exes之後施作故可覆寫exe,預設null代表不覆寫</p></td>
10300
+ </tr>
10301
+
10302
+
8897
10303
  </tbody>
8898
10304
  </table>
8899
10305
 
@@ -10478,6 +11884,183 @@ await test()
10478
11884
 
10479
11885
 
10480
11886
 
11887
+
11888
+
11889
+
11890
+
11891
+ <h4 class="name" id="salvageTruncatedArray"><span class="type-signature"></span>salvageTruncatedArray<span class="signature">(text)</span><span class="type-signature"> &rarr; {Array|null}</span></h4>
11892
+
11893
+
11894
+
11895
+
11896
+
11897
+
11898
+ <dl class="details">
11899
+
11900
+ <dt class="tag-description">Description:</dt>
11901
+ <dd class="tag-description"><ul class="dummy"><li><p>自截斷的JSON陣列文字搶救出前段完整元素(頂層元素須為物件)</p>
11902
+ <p>特點:
11903
+ 自第一個<code>[</code>起逐字元掃描(字串與跳脫感知),追蹤「最後一個完整結束的頂層物件元素」,
11904
+ 補上<code>]</code>重新解析——回傳的每個元素皆完整合法,不是半成品;
11905
+ 陣列有正常閉合(=非截斷)、無<code>[</code>、或救回後為空陣列,一律回null不硬救;
11906
+ 典型用法:extractJsonLoose回null時之後備,或組成自訂parse注入callAiWithFallback</p></li></ul></dd>
11907
+
11908
+
11909
+
11910
+ <dt class="tag-source">Source:</dt>
11911
+ <dd class="tag-source"><ul class="dummy"><li>
11912
+ <a href="wkf_salvageTruncatedArray.mjs.html">wkf/salvageTruncatedArray.mjs</a>, <a href="wkf_salvageTruncatedArray.mjs.html#line40">line 40</a>
11913
+ </li></ul></dd>
11914
+
11915
+
11916
+
11917
+
11918
+
11919
+
11920
+
11921
+
11922
+
11923
+
11924
+
11925
+
11926
+
11927
+
11928
+
11929
+
11930
+
11931
+
11932
+
11933
+
11934
+
11935
+
11936
+
11937
+
11938
+
11939
+
11940
+
11941
+
11942
+
11943
+
11944
+
11945
+ </dl>
11946
+
11947
+
11948
+
11949
+
11950
+
11951
+
11952
+
11953
+
11954
+
11955
+
11956
+
11957
+ <h5 class="h5-examples">Example</h5>
11958
+
11959
+ <pre class="prettyprint"><code>import salvageTruncatedArray from './src/wkf/salvageTruncatedArray.mjs'
11960
+
11961
+ console.log(salvageTruncatedArray('[{"a":1},{"b":2},{"c":'))
11962
+ // => [ { a: 1 }, { b: 2 } ]
11963
+
11964
+ console.log(salvageTruncatedArray('[{"a":1}]')) //有閉合=非截斷, 不在搶救範圍
11965
+ // => null</code></pre>
11966
+
11967
+
11968
+
11969
+
11970
+ <h5 class="h5-parameters">Parameters:</h5>
11971
+
11972
+
11973
+ <table class="params">
11974
+ <thead>
11975
+ <tr>
11976
+
11977
+ <th>Name</th>
11978
+
11979
+
11980
+ <th>Type</th>
11981
+
11982
+
11983
+
11984
+
11985
+
11986
+ <th class="last">Description</th>
11987
+ </tr>
11988
+ </thead>
11989
+
11990
+ <tbody>
11991
+
11992
+
11993
+ <tr>
11994
+
11995
+ <td class="name"><code>text</code></td>
11996
+
11997
+
11998
+ <td class="type">
11999
+
12000
+
12001
+ <span class="param-type">String</span>
12002
+
12003
+
12004
+
12005
+
12006
+ </td>
12007
+
12008
+
12009
+
12010
+
12011
+
12012
+ <td class="description last"><p>輸入模型輸出文字字串</p></td>
12013
+ </tr>
12014
+
12015
+
12016
+ </tbody>
12017
+ </table>
12018
+
12019
+
12020
+
12021
+
12022
+
12023
+
12024
+
12025
+
12026
+
12027
+
12028
+
12029
+
12030
+
12031
+
12032
+
12033
+
12034
+ <h5 class="h5-returns">Returns:</h5>
12035
+
12036
+
12037
+ <div class="param-desc">
12038
+ <p>回傳搶救出之非空陣列,無法搶救回null</p>
12039
+ </div>
12040
+
12041
+
12042
+
12043
+ <dl class="param-type">
12044
+ <dt>
12045
+ Type
12046
+ </dt>
12047
+ <dd>
12048
+
12049
+ <span class="param-type">Array</span>
12050
+ |
12051
+
12052
+ <span class="param-type">null</span>
12053
+
12054
+
12055
+
12056
+ </dd>
12057
+ </dl>
12058
+
12059
+
12060
+
12061
+
12062
+
12063
+
10481
12064
 
10482
12065
 
10483
12066
 
@@ -10497,7 +12080,7 @@ await test()
10497
12080
  <br class="clear">
10498
12081
 
10499
12082
  <footer>
10500
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 18 2026 13:42:39 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
12083
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 18 2026 15:44:01 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
10501
12084
  </footer>
10502
12085
 
10503
12086
  <script>prettyPrint();</script>