@tyhld/conductor 0.12.63 → 0.12.64
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.
- package/dist/headless.js +53 -2
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -268,8 +268,51 @@ export function streamEventToCommandEvent(parsed, attempt) {
|
|
|
268
268
|
}
|
|
269
269
|
return null;
|
|
270
270
|
}
|
|
271
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* stream-json の1行から認証エラーを検出する。
|
|
273
|
+
*
|
|
274
|
+
* 実物(2026-10-01 メインPC Fshima・ログイン切れ):
|
|
275
|
+
* assistant 行: error="authentication_failed", text="Not logged in · Please run /login"
|
|
276
|
+
* result 行: subtype="success", is_error=true, result="Not logged in · Please run /login"
|
|
277
|
+
* stderr: 空。exit code: 1。
|
|
278
|
+
*
|
|
279
|
+
* ★stderr には何も出ない。stdout の stream-json でだけ分かる。
|
|
280
|
+
*/
|
|
281
|
+
export function detectStreamAuthError(parsed) {
|
|
282
|
+
// assistant 行の error フィールド(最も確実な判定)
|
|
283
|
+
if (parsed.type === 'assistant') {
|
|
284
|
+
const msg = parsed.message;
|
|
285
|
+
if (msg) {
|
|
286
|
+
// assistant 直下にも error がある場合がある(実物で確認)
|
|
287
|
+
}
|
|
288
|
+
if (parsed.error === 'authentication_failed')
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
// assistant.message.content[].text or parsed.error on assistant envelope
|
|
292
|
+
if (parsed.type === 'assistant' && typeof parsed.message === 'object' && parsed.message !== null) {
|
|
293
|
+
const msg = parsed.message;
|
|
294
|
+
if (msg.error === 'authentication_failed')
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
// result 行: is_error=true かつ result テキストにログイン切れの文言
|
|
298
|
+
if (parsed.type === 'result' && parsed.is_error === true) {
|
|
299
|
+
const result = String(parsed.result ?? '').toLowerCase();
|
|
300
|
+
if (result.includes('not logged in') ||
|
|
301
|
+
result.includes('please run /login') ||
|
|
302
|
+
result.includes('login required') ||
|
|
303
|
+
result.includes('session expired') ||
|
|
304
|
+
result.includes('token expired')) {
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
/** 子プロセスの stderr と stream-json の両方から認証エラーを検出する。 */
|
|
272
311
|
export function isAuthError(job) {
|
|
312
|
+
// ★stream-json(stdout)で検出済み
|
|
313
|
+
if (job.authErrorDetected)
|
|
314
|
+
return true;
|
|
315
|
+
// stderr からも検出(従来の判定。API キーの認証エラーなど)
|
|
273
316
|
const s = job.stderrBuf.toLowerCase();
|
|
274
317
|
return (s.includes('401') ||
|
|
275
318
|
s.includes('unauthorized') ||
|
|
@@ -387,6 +430,7 @@ export function spawnClaudeProcess(cfg, cmd, sessionId, attempt, isResume) {
|
|
|
387
430
|
lastFlushAt: Date.now(),
|
|
388
431
|
lastStopCheckAt: Date.now(),
|
|
389
432
|
stderrBuf: '',
|
|
433
|
+
authErrorDetected: false,
|
|
390
434
|
stdoutLog: logs?.stdoutLog ?? null,
|
|
391
435
|
stderrLog: logs?.stderrLog ?? null,
|
|
392
436
|
durationMs: 0,
|
|
@@ -421,6 +465,10 @@ export function spawnClaudeProcess(cfg, cmd, sessionId, attempt, isResume) {
|
|
|
421
465
|
job.stdoutLog?.write(line + '\n');
|
|
422
466
|
try {
|
|
423
467
|
const parsed = JSON.parse(line);
|
|
468
|
+
// ★stream-json から認証エラーを検出(stderr に出ない実物に対応)
|
|
469
|
+
if (!job.authErrorDetected && detectStreamAuthError(parsed)) {
|
|
470
|
+
job.authErrorDetected = true;
|
|
471
|
+
}
|
|
424
472
|
const event = streamEventToCommandEvent(parsed, attempt);
|
|
425
473
|
if (event)
|
|
426
474
|
job.eventBuffer.push(event);
|
|
@@ -548,7 +596,10 @@ async function checkRunningJob(cfg, state) {
|
|
|
548
596
|
}
|
|
549
597
|
if (isAuthError(job)) {
|
|
550
598
|
// 認証エラー → 再試行しない
|
|
551
|
-
const
|
|
599
|
+
const detail = job.authErrorDetected
|
|
600
|
+
? 'ログイン切れ(stream-json で検出)'
|
|
601
|
+
: job.stderrBuf.slice(0, 300);
|
|
602
|
+
const authMsg = maskSecrets(`認証エラー (exit=${job.exitCode}): ${detail}`).slice(0, EVENT_TEXT_MAX);
|
|
552
603
|
await sendCommandEvents(cfg, job.commandId, [{
|
|
553
604
|
type: 'auth_error',
|
|
554
605
|
text: authMsg,
|