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
@@ -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
 
@@ -50,10 +50,10 @@ import isobj from 'wsemi/src/isobj.mjs'
50
50
  import isfun from 'wsemi/src/isfun.mjs'
51
51
  import isnum from 'wsemi/src/isnum.mjs'
52
52
  import isestr from 'wsemi/src/isestr.mjs'
53
- import ispint from 'wsemi/src/ispint.mjs'
54
53
  import isp0int from 'wsemi/src/isp0int.mjs'
55
54
  import cint from 'wsemi/src/cint.mjs'
56
55
  import delay from 'wsemi/src/delay.mjs'
56
+ import castPintOr from './castPintOr.mjs'
57
57
  import strleft from 'wsemi/src/strleft.mjs'
58
58
  import strdelleft from 'wsemi/src/strdelleft.mjs'
59
59
  import strTruncate from 'wsemi/src/strTruncate.mjs'
@@ -91,7 +91,11 @@ import dfTimeoutMs from './dfTimeoutMs.mjs'
91
91
  // 【重試語意對齊execCli】4xx(429除外)為客戶端錯誤不可重試而立即中止;
92
92
  // 429/5xx/網路錯誤/逾時依maxRetries線性退避重試(間隔retryDelayMs*次數, 上限15000ms)。
93
93
  //
94
- // 【結果結構對齊execCli】{ ok, stdout, stderr, code, error, durationMs, attempts },
94
+ // 【結果結構對齊execCli】{ ok, stdout, stderr, code, error, durationMs, attempts, usage },
95
+ // usage為原始回應之token用量原樣透傳(無則null; 驗證失敗等已耗token之失敗亦帶出),
96
+ // CLI類轉接器無可靠來源故無此欄——呼叫端可據此把「真實用量」與「只能估算」分開處理。
97
+ // 失敗結果另帶機器可讀之errorType(timeout/fetch/http/tool-unsupported/invalid-response/
98
+ // validation/params, 一覽見getErrorType.mjs檔頭), error字串保留不動, 兩者並存。
95
99
  // stdout為回覆內容、code為HTTP狀態碼(網路錯誤與逾時為null)、逾時error以TIMEOUT開頭、
96
100
  // 驗證失敗error為OUTPUT_VALIDATION_FAILED——故dispatchAiFallback之失敗分流
97
101
  // (TIMEOUT/驗證失敗跳組, 其餘換金鑰)對本轉接器同樣成立, 無須任何修改。
@@ -185,6 +189,19 @@ async function callOnce(url, headers, body, timeoutMs, validator) {
185
189
 
186
190
  let t0 = Date.now()
187
191
 
192
+ //mkResult, 結果形狀之單一來源(欄位對齊execCli, 追加errorType與usage),
193
+ //durationMs於呼叫當下計算; 失敗分支各自給errorType, 成功分支不帶(僅失敗結果有此欄)
194
+ let mkResult = (patch) => ({
195
+ ok: false,
196
+ stdout: '',
197
+ stderr: '',
198
+ code: null,
199
+ error: '',
200
+ durationMs: Date.now() - t0,
201
+ usage: null,
202
+ ...patch,
203
+ })
204
+
188
205
  //AbortController, 逾時中止(含回應本體之串流讀取)
189
206
  let controller = new AbortController()
190
207
  let timer = setTimeout(() => {
@@ -204,81 +221,65 @@ async function callOnce(url, headers, body, timeoutMs, validator) {
204
221
  }
205
222
  catch (err) {
206
223
  clearTimeout(timer)
207
- let durationMs = Date.now() - t0
208
224
 
209
225
  //逾時, error以TIMEOUT開頭令dispatchAiFallback視為與金鑰無關而跳組
210
226
  if (err.name === 'AbortError') {
211
- return {
212
- ok: false,
213
- stdout: '',
214
- stderr: '',
215
- code: null,
216
- error: `TIMEOUT after ${timeoutMs / 1000}s`,
217
- durationMs,
218
- }
227
+ return mkResult({ error: `TIMEOUT after ${timeoutMs / 1000}s`, errorType: 'timeout' })
219
228
  }
220
229
 
221
230
  //網路層錯誤(DNS/連線拒絕等)
222
231
  let cause = get(err, 'cause.code', '') || err.message
223
- return {
224
- ok: false,
225
- stdout: '',
226
- stderr: '',
227
- code: null,
228
- error: `FETCH_ERROR: ${cause}`,
229
- durationMs,
230
- }
232
+ return mkResult({ error: `FETCH_ERROR: ${cause}`, errorType: 'fetch' })
231
233
  }
232
234
  clearTimeout(timer)
233
235
 
234
- let durationMs = Date.now() - t0
235
-
236
236
  //HTTP非2xx, 原始回應本體放stderr供除錯與分類
237
237
  if (!res.ok) {
238
- return {
239
- ok: false,
240
- stdout: '',
238
+ return mkResult({
241
239
  stderr: strTruncate(txt, 1000, optTruncate),
242
240
  code: res.status,
243
241
  error: `HTTP ${res.status}`,
244
- durationMs,
245
- }
242
+ errorType: 'http',
243
+ })
246
244
  }
247
245
 
248
- //取出choices[0]
246
+ //取出choices[0]與usage(token用量, 原樣透傳; 失敗回應亦可能已耗token, 一併帶出)
249
247
  let content = null
250
248
  let finishReason = ''
251
249
  let toolCalls = null
250
+ let usage = null
252
251
  try {
253
252
  let j = JSON.parse(txt)
254
253
  content = get(j, 'choices.0.message.content', null)
255
254
  finishReason = get(j, 'choices.0.finish_reason', '')
256
255
  toolCalls = get(j, 'choices.0.message.tool_calls', null)
256
+ usage = get(j, 'usage', null)
257
+ if (!isobj(usage)) {
258
+ usage = null
259
+ }
257
260
  }
258
261
  catch {}
259
262
 
260
263
  //tool_calls, 本轉接器不支援工具迴圈(見檔頭), 明確回報而不假裝成功
261
264
  //(Agnes於tool_calls時content為"\n\n"非null, 不攔截會靜默回傳空白內容)
262
265
  if (finishReason === 'tool_calls' || (toolCalls !== null &amp;&amp; toolCalls !== undefined)) {
263
- return {
264
- ok: false,
265
- stdout: '',
266
+ return mkResult({
266
267
  stderr: strTruncate(txt, 1000, optTruncate),
267
268
  code: res.status,
268
269
  error: 'TOOL_CALLS_UNSUPPORTED: use a cli kind (opencode/claude/codex/antigravity) when tools are needed',
269
- durationMs,
270
- }
270
+ errorType: 'tool-unsupported',
271
+ usage,
272
+ })
271
273
  }
272
274
 
273
275
  if (content === null || content === undefined) {
274
- return {
275
- ok: false,
276
- stdout: '',
276
+ return mkResult({
277
277
  stderr: strTruncate(txt, 500, optTruncate),
278
278
  code: res.status,
279
279
  error: 'INVALID_RESPONSE: missing choices[0].message.content',
280
- durationMs,
281
- }
280
+ errorType: 'invalid-response',
281
+ usage,
282
+ })
282
283
  }
283
284
  if (typeof content !== 'string') {
284
285
  content = JSON.stringify(content) //少數閘道回array形態
@@ -286,24 +287,21 @@ async function callOnce(url, headers, body, timeoutMs, validator) {
286
287
 
287
288
  //validator, error與execCli一致令dispatchAiFallback可統一分流
288
289
  if (validator &amp;&amp; !validator(content)) {
289
- return {
290
- ok: false,
290
+ return mkResult({
291
291
  stdout: strTruncate(content, 500, optTruncate),
292
- stderr: '',
293
292
  code: res.status,
294
293
  error: 'OUTPUT_VALIDATION_FAILED',
295
- durationMs,
296
- }
294
+ errorType: 'validation',
295
+ usage,
296
+ })
297
297
  }
298
298
 
299
- return {
299
+ return mkResult({
300
300
  ok: true,
301
301
  stdout: content,
302
- stderr: '',
303
302
  code: res.status,
304
- error: '',
305
- durationMs,
306
- }
303
+ usage,
304
+ })
307
305
  }
308
306
 
309
307
 
@@ -334,7 +332,7 @@ async function callOnce(url, headers, body, timeoutMs, validator) {
334
332
  * @param {String|Function} [opt.validate=undefined] 輸入回覆內容驗證規則字串或自訂驗證函數,規則字串支援'nonempty'、'json'、'min:100',多規則可用逗號串接,預設undefined代表不驗證
335
333
  * @param {Number} [opt.maxRetries=0] 輸入失敗後最大重試次數非負整數,4xx(429除外)不重試,預設0
336
334
  * @param {Number} [opt.retryDelayMs=5000] 輸入重試間隔毫秒正整數,實際間隔為retryDelayMs乘以重試次數且上限15000ms,預設5000
337
- * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(回覆內容字串)、stderr(失敗時之原始回應本體)、code(HTTP狀態碼,網路錯誤與逾時為null)、error(錯誤訊息字串,成功時為空字串)、durationMs(耗時毫秒)、attempts(實際嘗試次數),本函數不會reject
335
+ * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(回覆內容字串)、stderr(失敗時之原始回應本體)、code(HTTP狀態碼,網路錯誤與逾時為null)、error(錯誤訊息字串,成功時為空字串)、errorType(僅失敗時,機器可讀錯誤類別字串,一覽見getErrorType.mjs檔頭)、durationMs(耗時毫秒)、attempts(實際嘗試次數)、usage(原始回應之token用量物件原樣透傳,無則null),本函數不會reject
338
336
  * @example
339
337
  * //need network, no cli required
340
338
  *
@@ -409,13 +407,7 @@ async function dispatchApiOpenaiCompat(prompt, opt = {}) {
409
407
  }
410
408
 
411
409
  //timeoutMs
412
- let timeoutMs = get(opt, 'timeoutMs', null)
413
- if (!ispint(timeoutMs)) {
414
- timeoutMs = DEFAULT_TIMEOUT_MS
415
- }
416
- else {
417
- timeoutMs = cint(timeoutMs)
418
- }
410
+ let timeoutMs = castPintOr(get(opt, 'timeoutMs', null), DEFAULT_TIMEOUT_MS)
419
411
 
420
412
  //maxRetries
421
413
  let maxRetries = get(opt, 'maxRetries', null)
@@ -427,13 +419,7 @@ async function dispatchApiOpenaiCompat(prompt, opt = {}) {
427
419
  }
428
420
 
429
421
  //retryDelayMs
430
- let retryDelayMs = get(opt, 'retryDelayMs', null)
431
- if (!ispint(retryDelayMs)) {
432
- retryDelayMs = DEFAULT_RETRY_DELAY_MS
433
- }
434
- else {
435
- retryDelayMs = cint(retryDelayMs)
436
- }
422
+ let retryDelayMs = castPintOr(get(opt, 'retryDelayMs', null), DEFAULT_RETRY_DELAY_MS)
437
423
 
438
424
  //validator
439
425
  let validator = buildValidator(get(opt, 'validate', null))
@@ -504,7 +490,7 @@ export default dispatchApiOpenaiCompat
504
490
  <br class="clear">
505
491
 
506
492
  <footer>
507
- 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.
493
+ 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.
508
494
  </footer>
509
495
 
510
496
  <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
 
@@ -47,13 +47,13 @@
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
49
49
  import omit from 'lodash-es/omit.js'
50
- import ispint from 'wsemi/src/ispint.mjs'
51
- import cint from 'wsemi/src/cint.mjs'
52
50
  import isbol from 'wsemi/src/isbol.mjs'
53
51
  import isestr from 'wsemi/src/isestr.mjs'
54
52
  import execCli from 'wsemi/src/execCli.mjs'
55
53
  import getCliArgs from './getCliArgs.mjs'
56
54
  import getErrorResult from './getErrorResult.mjs'
55
+ import { attachErrorType } from './getErrorType.mjs'
56
+ import castPintOr from './castPintOr.mjs'
57
57
  import dfTimeoutMs from './dfTimeoutMs.mjs'
58
58
 
59
59
 
@@ -155,23 +155,18 @@ async function dispatchClaude(prompt, opt = {}) {
155
155
  )
156
156
 
157
157
  //timeoutMs, 無效回退全套件統一預設(dfTimeoutMs=300000), 各轉接器一致令呼叫方無須記多套數字
158
- let timeoutMs = get(opt, 'timeoutMs', null)
159
- if (!ispint(timeoutMs)) {
160
- timeoutMs = dfTimeoutMs
161
- }
162
- else {
163
- timeoutMs = cint(timeoutMs)
164
- }
158
+ let timeoutMs = castPintOr(get(opt, 'timeoutMs', null), dfTimeoutMs)
165
159
 
166
160
  //optCli, 剔除本轉接器自用鍵後原樣轉傳, 令呼叫端可用execCli全部設定(例如onStdout、maxBuffer)
167
161
  let optCli = omit(opt, OWN_KEYS)
168
162
 
169
- //execCli, prompt一律走stdin
170
- return execCli(exe, args, {
163
+ //execCli, prompt一律走stdin; 失敗結果補上機器可讀之errorType(僅機械可判者, 見getErrorType.mjs)
164
+ let r = await execCli(exe, args, {
171
165
  ...optCli,
172
166
  input: prompt,
173
167
  timeoutMs,
174
168
  })
169
+ return attachErrorType(r)
175
170
  }
176
171
 
177
172
 
@@ -190,7 +185,7 @@ export default dispatchClaude
190
185
  <br class="clear">
191
186
 
192
187
  <footer>
193
- 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.
188
+ 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.
194
189
  </footer>
195
190
 
196
191
  <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
 
@@ -47,12 +47,12 @@
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
49
49
  import omit from 'lodash-es/omit.js'
50
- import ispint from 'wsemi/src/ispint.mjs'
51
- import cint from 'wsemi/src/cint.mjs'
52
50
  import isestr from 'wsemi/src/isestr.mjs'
53
51
  import execCli from 'wsemi/src/execCli.mjs'
54
52
  import getCliArgs from './getCliArgs.mjs'
55
53
  import getErrorResult from './getErrorResult.mjs'
54
+ import { attachErrorType } from './getErrorType.mjs'
55
+ import castPintOr from './castPintOr.mjs'
56
56
  import dfTimeoutMs from './dfTimeoutMs.mjs'
57
57
 
58
58
 
@@ -156,23 +156,18 @@ async function dispatchCodex(prompt, opt = {}) {
156
156
  )
157
157
 
158
158
  //timeoutMs, 無效回退全套件統一預設(dfTimeoutMs=300000), 各轉接器一致令呼叫方無須記多套數字
159
- let timeoutMs = get(opt, 'timeoutMs', null)
160
- if (!ispint(timeoutMs)) {
161
- timeoutMs = dfTimeoutMs
162
- }
163
- else {
164
- timeoutMs = cint(timeoutMs)
165
- }
159
+ let timeoutMs = castPintOr(get(opt, 'timeoutMs', null), dfTimeoutMs)
166
160
 
167
161
  //optCli, 剔除本轉接器自用鍵後原樣轉傳, 令呼叫端可用execCli全部設定(例如onStdout、maxBuffer)
168
162
  let optCli = omit(opt, OWN_KEYS)
169
163
 
170
- //execCli, prompt一律走stdin
171
- return execCli(exe, args, {
164
+ //execCli, prompt一律走stdin; 失敗結果補上機器可讀之errorType(僅機械可判者, 見getErrorType.mjs)
165
+ let r = await execCli(exe, args, {
172
166
  ...optCli,
173
167
  input: prompt,
174
168
  timeoutMs,
175
169
  })
170
+ return attachErrorType(r)
176
171
  }
177
172
 
178
173
 
@@ -191,7 +186,7 @@ export default dispatchCodex
191
186
  <br class="clear">
192
187
 
193
188
  <footer>
194
- 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.
189
+ 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.
195
190
  </footer>
196
191
 
197
192
  <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
 
@@ -47,13 +47,13 @@
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
49
49
  import omit from 'lodash-es/omit.js'
50
- import ispint from 'wsemi/src/ispint.mjs'
51
- import cint from 'wsemi/src/cint.mjs'
52
50
  import isobj from 'wsemi/src/isobj.mjs'
53
51
  import isestr from 'wsemi/src/isestr.mjs'
54
52
  import execCli from 'wsemi/src/execCli.mjs'
55
53
  import getCliArgs from './getCliArgs.mjs'
56
54
  import getErrorResult from './getErrorResult.mjs'
55
+ import { attachErrorType } from './getErrorType.mjs'
56
+ import castPintOr from './castPintOr.mjs'
57
57
  import dfTimeoutMs from './dfTimeoutMs.mjs'
58
58
 
59
59
 
@@ -224,24 +224,19 @@ async function dispatchOpencode(prompt, opt = {}) {
224
224
  }
225
225
 
226
226
  //timeoutMs, 無效回退全套件統一預設(dfTimeoutMs=300000), 各轉接器一致令呼叫方無須記多套數字
227
- let timeoutMs = get(opt, 'timeoutMs', null)
228
- if (!ispint(timeoutMs)) {
229
- timeoutMs = dfTimeoutMs
230
- }
231
- else {
232
- timeoutMs = cint(timeoutMs)
233
- }
227
+ let timeoutMs = castPintOr(get(opt, 'timeoutMs', null), dfTimeoutMs)
234
228
 
235
229
  //optCli, 剔除本轉接器自用鍵後原樣轉傳, 令呼叫端可用execCli全部設定(例如onStdout、maxBuffer)
236
230
  let optCli = omit(opt, OWN_KEYS)
237
231
 
238
- //execCli, prompt一律走stdin
239
- return execCli(exe, args, {
232
+ //execCli, prompt一律走stdin; 失敗結果補上機器可讀之errorType(僅機械可判者, 見getErrorType.mjs)
233
+ let r = await execCli(exe, args, {
240
234
  ...optCli,
241
235
  input: prompt,
242
236
  env,
243
237
  timeoutMs,
244
238
  })
239
+ return attachErrorType(r)
245
240
  }
246
241
 
247
242
 
@@ -260,7 +255,7 @@ export default dispatchOpencode
260
255
  <br class="clear">
261
256
 
262
257
  <footer>
263
- 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.
258
+ 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.
264
259
  </footer>
265
260
 
266
261
  <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
 
@@ -113,7 +113,7 @@ export default getCliArgs
113
113
  <br class="clear">
114
114
 
115
115
  <footer>
116
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Aug 14 2026 15:11:06 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
116
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 15 2026 08:45:29 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
117
117
  </footer>
118
118
 
119
119
  <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
 
@@ -56,31 +56,38 @@
56
56
  * 無須區分「參數錯誤」與「CLI執行失敗」兩種來源
57
57
  *
58
58
  * @param {String} error 輸入錯誤訊息字串
59
- * @returns {Object} 回傳結果物件,內含ok(布林值,恆為false)、stdout(空字串)、stderr(空字串)、code(null)、error(錯誤訊息字串)、durationMs(0)、attempts(0)
59
+ * @param {String} [errorType='params'] 輸入機器可讀之錯誤類別字串(一覽見getErrorType.mjs檔頭),預設'params'(參數/設定檢核失敗)
60
+ * @returns {Object} 回傳結果物件,內含ok(布林值,恆為false)、stdout(空字串)、stderr(空字串)、code(null)、error(錯誤訊息字串)、errorType(錯誤類別字串)、durationMs(0)、attempts(0)
60
61
  * @example
61
62
  *
62
63
  * import getErrorResult from './src/getErrorResult.mjs'
63
64
  *
64
65
  * console.log(getErrorResult('prompt must be a non-empty string'))
65
- * // => { ok: false, stdout: '', stderr: '', code: null, error: 'prompt must be a non-empty string', durationMs: 0, attempts: 0 }
66
+ * // => { ok: false, stdout: '', stderr: '', code: null, error: 'prompt must be a non-empty string', errorType: 'params', durationMs: 0, attempts: 0 }
66
67
  *
67
68
  * console.log(getErrorResult(null).error)
68
69
  * // => 'unknown error'
69
70
  *
70
71
  */
71
- function getErrorResult(error) {
72
+ function getErrorResult(error, errorType = 'params') {
72
73
 
73
74
  //check, 非有效字串時給予預設訊息, 確保error欄位恆為非空字串
74
75
  if (!isestr(error)) {
75
76
  error = 'unknown error'
76
77
  }
77
78
 
79
+ //check errorType, 非有效字串回退'params'
80
+ if (!isestr(errorType)) {
81
+ errorType = 'params'
82
+ }
83
+
78
84
  return {
79
85
  ok: false,
80
86
  stdout: '',
81
87
  stderr: '',
82
88
  code: null,
83
89
  error,
90
+ errorType,
84
91
  durationMs: 0,
85
92
  attempts: 0,
86
93
  }
@@ -102,7 +109,7 @@ export default getErrorResult
102
109
  <br class="clear">
103
110
 
104
111
  <footer>
105
- 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.
112
+ 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.
106
113
  </footer>
107
114
 
108
115
  <script>prettyPrint();</script>