w-dispatch-ai 1.0.7 → 1.0.8

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 +27 -1
  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 +4 -3
  5. package/docs/adapters.mjs.html +2 -2
  6. package/docs/castPintOr.mjs.html +109 -0
  7. package/docs/dfTimeoutMs.mjs.html +2 -2
  8. package/docs/dispatchAi.mjs.html +14 -13
  9. package/docs/dispatchAiFallback.mjs.html +156 -97
  10. package/docs/dispatchAiWkf.mjs.html +2 -2
  11. package/docs/dispatchAntigravity.mjs.html +10 -14
  12. package/docs/dispatchApiOpenaiCompat.mjs.html +50 -64
  13. package/docs/dispatchClaude.mjs.html +8 -13
  14. package/docs/dispatchCodex.mjs.html +8 -13
  15. package/docs/dispatchOpencode.mjs.html +8 -13
  16. package/docs/getCliArgs.mjs.html +2 -2
  17. package/docs/getErrorResult.mjs.html +12 -5
  18. package/docs/getErrorType.mjs.html +171 -0
  19. package/docs/global.html +1275 -88
  20. package/docs/index.html +2 -2
  21. package/docs/resolveProviders.mjs.html +2 -2
  22. package/docs/wkf_callAiWithFallback.mjs.html +14 -10
  23. package/docs/wkf_extractJsonLoose.mjs.html +2 -2
  24. package/docs/wkf_runFanout.mjs.html +8 -8
  25. package/docs/wkf_runFanoutPipeline.mjs.html +14 -18
  26. package/docs/wkf_runRolePipeline.mjs.html +5 -4
  27. package/package.json +1 -1
  28. package/src/WDispatchAi.mjs +2 -1
  29. package/src/castPintOr.mjs +37 -0
  30. package/src/dispatchAi.mjs +12 -11
  31. package/src/dispatchAiFallback.mjs +154 -95
  32. package/src/dispatchAntigravity.mjs +8 -12
  33. package/src/dispatchApiOpenaiCompat.mjs +48 -62
  34. package/src/dispatchClaude.mjs +6 -11
  35. package/src/dispatchCodex.mjs +6 -11
  36. package/src/dispatchOpencode.mjs +6 -11
  37. package/src/getErrorResult.mjs +10 -3
  38. package/src/getErrorType.mjs +99 -0
  39. package/src/wkf/callAiWithFallback.mjs +12 -8
  40. package/src/wkf/runFanout.mjs +6 -6
  41. package/src/wkf/runFanoutPipeline.mjs +12 -16
  42. package/src/wkf/runRolePipeline.mjs +3 -2
  43. package/test/tools/fakeServerForApiTest.mjs +4 -1
  44. package/test/unit-callAiWithFallback.test.mjs +24 -0
  45. package/test/unit-castPintOr.test.mjs +28 -0
  46. package/test/unit-dispatchAiFallback.test.mjs +137 -0
  47. package/test/unit-dispatchApiOpenaiCompat.test.mjs +39 -0
  48. package/test/unit-getErrorResult.test.mjs +13 -1
  49. package/test/unit-getErrorType.test.mjs +36 -0
  50. package/test/unit-runFanout.test.mjs +14 -0
  51. package/test/unit-runRolePipeline.test.mjs +12 -0
package/docs/index.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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -176,7 +176,7 @@ export default resolveProviders
176
176
  <br class="clear">
177
177
 
178
178
  <footer>
179
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
179
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
180
180
  </footer>
181
181
 
182
182
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -85,8 +85,9 @@ import extractJsonLoose from './extractJsonLoose.mjs'
85
85
  //本層自用之設定鍵, 其餘鍵(timeoutMs/budgetMs/minAttemptMs/maxRetries/cwd/store/onEvent/
86
86
  //retryDelayMs/maxBuffer等)一律原樣轉傳dispatchAiFallback——與各轉接器「剔除自用鍵後
87
87
  //原樣轉傳」同一約定; 曾因白名單式轉送漏掉minAttemptMs, 令README教學之工作流層
88
- //budget保護靜默失效(2026-08-14使用端實測回報), 故改採omit式轉傳杜絕同類漏鍵
89
- let OWN_KEYS = ['providers', 'spec', 'check', 'parse', 'rawText', 'promptPrefix']
88
+ //budget保護靜默失效(2026-08-14使用端實測回報), 故改採omit式轉傳杜絕同類漏鍵;
89
+ //meta為保留鍵: 呼叫端自有資訊掛此鍵保證永不轉傳(全套件同約定, 見dispatchAiFallback檔頭)
90
+ let OWN_KEYS = ['providers', 'spec', 'check', 'parse', 'rawText', 'promptPrefix', 'meta']
90
91
 
91
92
 
92
93
  //預設防寫檔前綴(禁副作用, 但豁免唯讀查閱——codex以shell讀檔, 一律禁指令等同禁讀檔)
@@ -158,8 +159,9 @@ function buildChain(providers, spec) {
158
159
  * @param {Number} [opt.maxRetries=0] 輸入同家重試次數非負整數,預設0(韌性交給遞補;端點不穩偶發空回之模型可調高令同鍵重試)
159
160
  * @param {String} [opt.cwd=process.cwd()] 輸入子進程工作目錄字串,預設process.cwd()
160
161
  * @param {Object} [opt.store=null] 輸入游標持久化物件{get,set},預設null代表用行程內記憶體
161
- * @param {Function} [opt.onEvent=null] 輸入遞補層事件回調函數,預設null。除上列外之其餘鍵(retryDelayMs、maxBuffer、onStdout等)亦一律原樣轉傳dispatchAiFallback
162
- * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否取得可用結果布林值)json(解析後物件,rawText模式下為文字)providerId(實際使用之名稱)keyIndexkeyId、ms(總耗時毫秒)、tried(遞補嘗試歷程陣列)、error(錯誤訊息字串),本函數不會reject
162
+ * @param {*} [opt.meta=undefined] 輸入呼叫端自有資訊(分類、標籤、註記),保留鍵保證永不轉傳下層,預設undefined
163
+ * @param {Function} [opt.onEvent=null] 輸入遞補層事件回調函數,預設null。除上列外之其餘鍵(retryDelayMsmaxBuffershouldStopcoolDetectcooldownMs等)亦一律原樣轉傳dispatchAiFallback
164
+ * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否取得可用結果布林值)、json(解析後物件,rawText模式下為文字)、providerId(實際使用之名稱)、keyIndex、keyId、ms(總耗時毫秒)、tried(遞補嘗試歷程陣列)、usage(api類之token用量原樣透傳,CLI類為null)、error(錯誤訊息字串)、errorType(僅失敗時,機器可讀錯誤類別字串,一覽見getErrorType.mjs檔頭),本函數不會reject
163
165
  * @example
164
166
  * //need cli in system PATH
165
167
  *
@@ -192,22 +194,22 @@ async function callAiWithFallback(prompt, opt = {}) {
192
194
  let t0 = Date.now()
193
195
 
194
196
  if (!isestr(prompt)) {
195
- return { ok: false, json: null, error: 'prompt must be a non-empty string', ms: 0, tried: [] }
197
+ return { ok: false, json: null, error: 'prompt must be a non-empty string', errorType: 'params', ms: 0, tried: [] }
196
198
  }
197
199
 
198
200
  let providers = get(opt, 'providers', null)
199
201
  let spec = get(opt, 'spec', null)
200
202
  if (!isobj(providers) || !isobj(spec)) {
201
- return { ok: false, json: null, error: `no valid provider for spec: ${JSON.stringify(spec)}`, ms: 0, tried: [] }
203
+ return { ok: false, json: null, error: `no valid provider for spec: ${JSON.stringify(spec)}`, errorType: 'params', ms: 0, tried: [] }
202
204
  }
203
205
 
204
206
  //buildChain, 名稱查無定義即回報(fail fast), 不讓打錯字的fallback靜默消失
205
207
  let { chain, missing } = buildChain(providers, spec)
206
208
  if (missing.length > 0) {
207
- return { ok: false, json: null, error: `unknown provider name(s): ${missing.join(', ')}`, ms: 0, tried: [] }
209
+ return { ok: false, json: null, error: `unknown provider name(s): ${missing.join(', ')}`, errorType: 'params', ms: 0, tried: [] }
208
210
  }
209
211
  if (chain.length === 0) {
210
- return { ok: false, json: null, error: `no valid provider for spec: ${JSON.stringify(spec)}`, ms: 0, tried: [] }
212
+ return { ok: false, json: null, error: `no valid provider for spec: ${JSON.stringify(spec)}`, errorType: 'params', ms: 0, tried: [] }
211
213
  }
212
214
 
213
215
  let rawText = get(opt, 'rawText', false) === true
@@ -264,7 +266,9 @@ async function callAiWithFallback(prompt, opt = {}) {
264
266
  keyId: (keyIndex === null) ? providerId : `${providerId}#${keyIndex}`,
265
267
  ms: Date.now() - t0,
266
268
  tried: get(r, 'tried', []),
269
+ usage: get(r, 'usage', null), //api類轉接器之token用量原樣透傳, CLI類為null(無可靠來源)
267
270
  error: r.ok ? '' : get(r, 'error', 'unknown error'),
271
+ ...(r.ok ? {} : { errorType: get(r, 'errorType', 'exec') }), //機器可讀錯誤類別, 僅失敗時
268
272
  }
269
273
  }
270
274
 
@@ -285,7 +289,7 @@ export { buildChain, NO_SIDE_EFFECT }
285
289
  <br class="clear">
286
290
 
287
291
  <footer>
288
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
292
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
289
293
  </footer>
290
294
 
291
295
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -167,7 +167,7 @@ export default extractJsonLoose
167
167
  <br class="clear">
168
168
 
169
169
  <footer>
170
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
170
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
171
171
  </footer>
172
172
 
173
173
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -97,8 +97,8 @@ ${candidates.map((c, i) => `【候選 ${i + 1}】\n${JSON.stringify(c)}`).join('
97
97
  * @param {Object} [opt={}] 輸入設定物件,預設{}
98
98
  * @param {Object} opt.providers 輸入provider定義表物件(名稱 → 條目),透傳callAiWithFallback
99
99
  * @param {String} opt.task 輸入前段各名額共用之任務提示詞字串
100
- * @param {Array} opt.agents 輸入前段名額規格陣列,各元素{ use, fallback, check?, maxRetries?, timeoutMs? }等(check可覆寫頂層檢核;除use/fallback/check外之鍵覆寫該名額呼叫設定)
101
- * @param {Object} opt.integrate 輸入整合名額規格物件{ use, fallback, prompt?, check?, ... },prompt可為(candidates)=>String自訂整合提示詞(省略用預設模板);check為終稿專屬檢核(終稿判準常與候選不同,如須含固定段落),未給則沿用頂層check
100
+ * @param {Array} opt.agents 輸入前段名額規格陣列,各元素{ use, fallback, check?, maxRetries?, timeoutMs? }等(check可覆寫頂層檢核;除use/fallback/check/meta外之鍵覆寫該名額呼叫設定;meta為保留鍵,呼叫端自有資訊掛此鍵保證永不轉傳下層)
101
+ * @param {Object} opt.integrate 輸入整合名額規格物件{ use, fallback, prompt?, check?, ... },prompt可為(candidates)=>String自訂整合提示詞(省略用預設模板);check為終稿專屬檢核(終稿判準常與候選不同,如須含固定段落),未給則沿用頂層check;meta為保留鍵同agents
102
102
  * @param {Function} [opt.check=null] 輸入檢核函數(json)=>Boolean,作為候選與終稿之共用預設,名額規格與integrate可各自帶check覆寫,預設null
103
103
  * @param {String} [opt.schema=''] 輸入輸出格式示意字串,供預設整合模板嵌入,預設''
104
104
  * @param {Number} [opt.minCandidates=2] 輸入進入整合所需之最少成功候選數正整數,未達門檻以首位候選為成果,預設2
@@ -162,9 +162,9 @@ async function runFanout(opt = {}) {
162
162
 
163
163
  //前段: 並行多開, 個別失敗不炸整輪
164
164
  //各名額可自帶check覆寫頂層(候選與終稿判準本可不同); 自spec抽出而非留在overrides,
165
- //否則會被後方明給之check靜默覆蓋(曾為死鍵)
165
+ //否則會被後方明給之check靜默覆蓋(曾為死鍵); meta為保留鍵一併抽出, 保證永不轉傳
166
166
  let rsAgents = await Promise.all(agents.map((spec) => {
167
- let { use, fallback, check: checkAgent, ...overrides } = spec
167
+ let { use, fallback, check: checkAgent, meta, ...overrides } = spec
168
168
  return callAiWithFallback(task, { ...callOpt, ...overrides, providers, spec: { use, fallback }, check: isfun(checkAgent) ? checkAgent : check })
169
169
  }))
170
170
  let candidates = rsAgents.filter((r) => r.ok).map((r) => r.json)
@@ -183,8 +183,8 @@ async function runFanout(opt = {}) {
183
183
  if (!integrate || !isestr(get(integrate, 'use', ''))) {
184
184
  return { ok: false, result: null, integrated: false, agents: rsAgents, candidates, totalMs: Date.now() - t0, error: 'integrate spec (with use) is required' }
185
185
  }
186
- //整合可帶獨立check(終稿判準常較候選嚴, 如須含固定小標題), 未給則沿用頂層check
187
- let { use, fallback, prompt: intPromptFn, check: checkInt, ...intOverrides } = integrate
186
+ //整合可帶獨立check(終稿判準常較候選嚴, 如須含固定小標題), 未給則沿用頂層check; meta為保留鍵一併抽出
187
+ let { use, fallback, prompt: intPromptFn, check: checkInt, meta, ...intOverrides } = integrate
188
188
  let intPrompt = isfun(intPromptFn) ? intPromptFn(candidates) : defaultIntegratePrompt(candidates, opt)
189
189
  let rInt = await callAiWithFallback(intPrompt, { ...callOpt, ...intOverrides, providers, spec: { use, fallback }, check: isfun(checkInt) ? checkInt : check })
190
190
 
@@ -217,7 +217,7 @@ export { defaultIntegratePrompt }
217
217
  <br class="clear">
218
218
 
219
219
  <footer>
220
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
220
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
221
221
  </footer>
222
222
 
223
223
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -45,11 +45,18 @@
45
45
 
46
46
  <section>
47
47
  <article>
48
- <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
48
+ <pre class="prettyprint source linenums"><code>import omit from 'lodash-es/omit.js'
49
49
  import runFanout from './runFanout.mjs'
50
50
  import runRolePipeline from './runRolePipeline.mjs'
51
51
 
52
52
 
53
+ //兩段各自剔除「對方專屬鍵」後原樣轉傳(providers與callOpt等共用鍵兩段皆收):
54
+ //曾因白名單式逐鍵轉送漏掉minAttemptMs令下層設定靜默失效(2026-08-14使用端實測回報),
55
+ //故一律採omit式, 任一段日後新增頂層選項時本檔無須跟改
56
+ let B_ONLY_KEYS = ['stages', 'input'] //後段專屬(input由前段成果給定, 不收外部傳入)
57
+ let A_ONLY_KEYS = ['task', 'agents', 'integrate', 'check', 'schema', 'minCandidates'] //前段專屬
58
+
59
+
53
60
  // runFanoutPipeline.mjs — FanoutPipeline工作流(Fanout+RolePipeline): 多開收斂成果接串行角色鏈
54
61
  //
55
62
  // 【結構】先跑runFanout(多開 → 整合), 其成果作為runRolePipeline的input
@@ -116,27 +123,16 @@ import runRolePipeline from './runRolePipeline.mjs'
116
123
  async function runFanoutPipeline(opt = {}) {
117
124
  let t0 = Date.now()
118
125
 
119
- //前段: Fanout(多開 → 整合)
120
- let rA = await runFanout({
121
- providers: get(opt, 'providers', null),
122
- task: get(opt, 'task', ''),
123
- agents: get(opt, 'agents', null),
124
- integrate: get(opt, 'integrate', null),
125
- check: get(opt, 'check', null),
126
- schema: get(opt, 'schema', ''),
127
- minCandidates: get(opt, 'minCandidates', null),
128
- callOpt: get(opt, 'callOpt', {}),
129
- })
126
+ //前段: Fanout(多開 → 整合), 剔除後段專屬鍵後原樣轉傳
127
+ let rA = await runFanout(omit(opt, B_ONLY_KEYS))
130
128
  if (!rA.ok) {
131
129
  return { ok: false, result: null, A: rA, B: null, totalMs: Date.now() - t0, error: `A failed: ${rA.error}` }
132
130
  }
133
131
 
134
- //後段: RolePipeline, input即前段成果
132
+ //後段: RolePipeline, 剔除前段專屬鍵後原樣轉傳, input即前段成果
135
133
  let rB = await runRolePipeline({
136
- providers: get(opt, 'providers', null),
134
+ ...omit(opt, A_ONLY_KEYS),
137
135
  input: rA.result,
138
- stages: get(opt, 'stages', null),
139
- callOpt: get(opt, 'callOpt', {}),
140
136
  })
141
137
 
142
138
  return {
@@ -165,7 +161,7 @@ export default runFanoutPipeline
165
161
  <br class="clear">
166
162
 
167
163
  <footer>
168
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
164
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
169
165
  </footer>
170
166
 
171
167
  <script>prettyPrint();</script>
@@ -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#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#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#isKeyIndependentFail">isKeyIndependentFail</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#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>
33
33
 
34
34
  </nav>
35
35
 
@@ -71,7 +71,8 @@ import callAiWithFallback from './callAiWithFallback.mjs'
71
71
 
72
72
 
73
73
  //各階段規格自用之鍵, 其餘鍵覆寫該階段之呼叫設定
74
- let STAGE_KEYS = ['id', 'use', 'fallback', 'prompt', 'check']
74
+ //meta為保留鍵: 呼叫端於階段規格掛自有資訊(如draft/audit分類)用, 保證永不轉傳下層
75
+ let STAGE_KEYS = ['id', 'use', 'fallback', 'prompt', 'check', 'meta']
75
76
 
76
77
 
77
78
  /**
@@ -86,7 +87,7 @@ let STAGE_KEYS = ['id', 'use', 'fallback', 'prompt', 'check']
86
87
  * @param {Object} [opt={}] 輸入設定物件,預設{}
87
88
  * @param {Object} opt.providers 輸入provider定義表物件(名稱 → 條目)
88
89
  * @param {*} [opt.input=null] 輸入工作流輸入(原始任務字串或前一工作流之成果物件),提供給各階段ctx.input,預設null
89
- * @param {Array} opt.stages 輸入階段規格陣列,各元素{ id, use, fallback, prompt:(ctx)=>String, check?, rawText?, maxRetries?, timeoutMs? }
90
+ * @param {Array} opt.stages 輸入階段規格陣列,各元素{ id, use, fallback, prompt:(ctx)=>String, check?, rawText?, maxRetries?, timeoutMs? }等;meta為保留鍵,呼叫端自有資訊(分類、標籤)掛此鍵保證永不轉傳下層
90
91
  * @param {Object} [opt.callOpt={}] 輸入透傳callAiWithFallback之共用設定,預設{}
91
92
  * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(布林值)、result(最末階段成果)、stages(id對階段完整呼叫結果之物件)、results(id對階段成果之物件)、order(階段id順序陣列)、failedStage(失敗階段id,無失敗為null)、totalMs(總耗時毫秒)、error(錯誤訊息字串),本函數不會reject
92
93
  * @example
@@ -182,7 +183,7 @@ export default runRolePipeline
182
183
  <br class="clear">
183
184
 
184
185
  <footer>
185
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
186
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
186
187
  </footer>
187
188
 
188
189
  <script>prettyPrint();</script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "w-dispatch-ai",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "main": "dist/w-dispatch-ai.umd.js",
5
5
  "dependencies": {
6
6
  "wsemi": "^1.8.70"
@@ -14,7 +14,8 @@ import resolveProviders from './resolveProviders.mjs'
14
14
 
15
15
  // WDispatchAi.mjs — AI供應商分派層
16
16
  //
17
- // 本套件封裝「以CLI調用各家AI」的差異,對外提供單一介面。
17
+ // 本套件封裝「以CLI或REST API調用各家AI」的差異,對外提供單一介面
18
+ // (CLI或API之選型判準見adapters.mjs檔頭)。
18
19
  // 依專案方針,不引用全域技能(dispatch-claude/dispatch-codex/dispatch-opencode),
19
20
  // 而是把其調用方式移植於各轉接器內,方便自行偵錯、修改與擴充。
20
21
 
@@ -0,0 +1,37 @@
1
+ import ispint from 'wsemi/src/ispint.mjs'
2
+ import cint from 'wsemi/src/cint.mjs'
3
+
4
+
5
+ /**
6
+ * 正整數正規化:有效正整數即轉整數回傳,否則回傳預設值
7
+ *
8
+ * 本套件各層之數值設定(timeoutMs、budgetMs、minAttemptMs、cooldownMs、retryDelayMs等)
9
+ * 皆採同一寬容策略「無效即靜默回退預設」,統一收斂於此,
10
+ * 避免同一7行判斷區塊散落各轉接器(曾重複6處)
11
+ *
12
+ * @param {*} v 輸入待正規化之值
13
+ * @param {*} df 輸入無效時之預設值(可為null代表不限)
14
+ * @returns {Number|*} 回傳正規化後之正整數,v非有效正整數時回傳df
15
+ * @example
16
+ *
17
+ * import castPintOr from './src/castPintOr.mjs'
18
+ *
19
+ * console.log(castPintOr(5000, 300000))
20
+ * // => 5000
21
+ *
22
+ * console.log(castPintOr('abc', 300000))
23
+ * // => 300000
24
+ *
25
+ * console.log(castPintOr(undefined, null))
26
+ * // => null
27
+ *
28
+ */
29
+ function castPintOr(v, df) {
30
+ if (!ispint(v)) {
31
+ return df
32
+ }
33
+ return cint(v)
34
+ }
35
+
36
+
37
+ export default castPintOr
@@ -6,18 +6,19 @@ import getErrorResult from './getErrorResult.mjs'
6
6
 
7
7
 
8
8
  /**
9
- * 依供應商種類(kind)分派至對應之CLI轉接器
9
+ * 依供應商種類(kind)分派至對應之轉接器
10
10
  *
11
- * 三種供應商的差異(2026-08-08於本機實測確認):
12
- * opencode支援逐次注入金鑰(OPENCODE_AUTH_CONTENT),故可多把金鑰輪替;
13
- * claudecodex則沿用CLI既有登入狀態,無逐次金鑰概念。
11
+ * kind清單以adapters.mjs對照表為唯一來源(目前為'opencode'、'claude'、'codex'、'antigravity'、
12
+ * 'api-openai-compat',CLI或API之選型判準見adapters.mjs檔頭)
13
+ * 各家金鑰模式不同(2026-08-08起於本機實測確認):opencodeapi-openai-compat支援逐次注入金鑰,
14
+ * 故可多把金鑰輪替;claude/codex/antigravity沿用CLI既有登入狀態,無逐次金鑰概念。
14
15
  * 故「輪替」的單位是「供應商條目」而非單純的金鑰:一個條目即一組(kind, model, 可選的key/provider),
15
- * 輪到誰就用誰的CLI與模型
16
+ * 輪到誰就用誰的轉接器與模型
16
17
  *
17
- * @param {String} kind 輸入供應商種類字串,可選'opencode'、'claude'、'codex'
18
- * @param {String} prompt 輸入提示詞字串,一律以stdin傳入子進程
19
- * @param {Object} [opt={}] 輸入設定物件,原樣轉傳對應轉接器,各轉接器可用設定詳見dispatchOpencode、dispatchClaude、dispatchCodex,預設{}
20
- * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject
18
+ * @param {String} kind 輸入供應商種類字串,須為adapters.mjs對照表之鍵名,目前可選'opencode'、'claude'、'codex'、'antigravity'、'api-openai-compat'
19
+ * @param {String} prompt 輸入提示詞字串
20
+ * @param {Object} [opt={}] 輸入設定物件,原樣轉傳對應轉接器,各轉接器可用設定詳見dispatchOpencode、dispatchClaude、dispatchCodex、dispatchAntigravity、dispatchApiOpenaiCompat,預設{}
21
+ * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject
21
22
  * @example
22
23
  * //need claude, codex or opencode cli in system PATH
23
24
  *
@@ -30,8 +31,8 @@ import getErrorResult from './getErrorResult.mjs'
30
31
  * // => true '完成'
31
32
  *
32
33
  * let re = await dispatchAi('gemini', 'abc')
33
- * console.log(re.ok, re.error)
34
- * // => false 'unknown ai kind: "gemini" (available: opencode, claude, codex)'
34
+ * console.log(re.ok, re.error.indexOf('unknown ai kind: "gemini"') === 0)
35
+ * // => false true
35
36
  *
36
37
  * }
37
38
  * await test()