cc-viewer 1.6.270 → 1.6.271
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/README.md +3 -17
- package/cli.js +13 -2
- package/dist/assets/{App-BlL1FIJJ.js → App-LEYaH-CM.js} +1 -1
- package/dist/assets/{MdxEditorPanel-DxMKSSN2.js → MdxEditorPanel-B7oOvR3k.js} +1 -1
- package/dist/assets/{Mobile-CXv8o6bc.js → Mobile-Cwf21Pmq.js} +1 -1
- package/dist/assets/{index-CCAOHnbk.js → index-CLfbZzwF.js} +2 -2
- package/dist/assets/seqResourceLoaders-CmFg0jyW.js +2 -0
- package/dist/index.html +1 -1
- package/dist/voice-packs/default/A_choice_for_your_consideration_sir.MP3 +0 -0
- package/dist/voice-packs/default/It_is_done_sir.MP3 +0 -0
- package/dist/voice-packs/default/The_plan_awaits_your_approval_sir.MP3 +0 -0
- package/dist/voice-packs/default/pack.json +13 -13
- package/dist/voice-packs/sanguo/ask.MP3 +0 -0
- package/dist/voice-packs/sanguo/end.MP3 +0 -0
- package/dist/voice-packs/sanguo/pack.json +24 -0
- package/dist/voice-packs/sanguo/plan.MP3 +0 -0
- package/lib/voice-pack-events.js +47 -1
- package/lib/voice-pack-manager.js +135 -38
- package/package.json +1 -1
- package/pty-manager.js +2 -2
- package/server.js +227 -29
- package/dist/assets/seqResourceLoaders-ZhPI6y_m.js +0 -2
- package/dist/voice-packs/default/askQuestion.wav +0 -0
- package/dist/voice-packs/default/planApproval.wav +0 -0
- package/dist/voice-packs/default/turnEnd.wav +0 -0
package/dist/index.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
if (pick) document.documentElement.setAttribute('data-theme', pick);
|
|
20
20
|
} catch {}
|
|
21
21
|
</script>
|
|
22
|
-
<script type="module" crossorigin src="/assets/index-
|
|
22
|
+
<script type="module" crossorigin src="/assets/index-CLfbZzwF.js"></script>
|
|
23
23
|
<link rel="modulepreload" crossorigin href="/assets/vendor-antd-BG1SvzuN.js">
|
|
24
24
|
<link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-8NDhydlF.js">
|
|
25
25
|
<link rel="modulepreload" crossorigin href="/assets/vendor-mdxeditor-BB4hhpxM.js">
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "default-
|
|
3
|
-
"displayName": "
|
|
2
|
+
"name": "default-butler",
|
|
3
|
+
"displayName": "Butler · 皇上系列 (默认)",
|
|
4
4
|
"placeholder": false,
|
|
5
5
|
"events": {
|
|
6
6
|
"planApproval": {
|
|
7
|
-
"file": "
|
|
8
|
-
"size":
|
|
7
|
+
"file": "The_plan_awaits_your_approval_sir.MP3",
|
|
8
|
+
"size": 52712
|
|
9
9
|
},
|
|
10
10
|
"askQuestion": {
|
|
11
|
-
"file": "
|
|
12
|
-
"size":
|
|
11
|
+
"file": "A_choice_for_your_consideration_sir.MP3",
|
|
12
|
+
"size": 60236
|
|
13
13
|
},
|
|
14
14
|
"turnEnd": {
|
|
15
|
-
"file": "
|
|
16
|
-
"size":
|
|
15
|
+
"file": "It_is_done_sir.MP3",
|
|
16
|
+
"size": 45816
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
-
"
|
|
20
|
-
"planApproval": "
|
|
21
|
-
"askQuestion": "
|
|
22
|
-
"turnEnd": "
|
|
19
|
+
"voiceLines": {
|
|
20
|
+
"planApproval": "The plan awaits your approval, sir.",
|
|
21
|
+
"askQuestion": "A choice for your consideration, sir.",
|
|
22
|
+
"turnEnd": "It is done, sir."
|
|
23
23
|
}
|
|
24
|
-
}
|
|
24
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sanguo",
|
|
3
|
+
"displayName": "三国 (Sanguo)",
|
|
4
|
+
"placeholder": false,
|
|
5
|
+
"events": {
|
|
6
|
+
"planApproval": {
|
|
7
|
+
"file": "plan.MP3",
|
|
8
|
+
"size": 67759
|
|
9
|
+
},
|
|
10
|
+
"askQuestion": {
|
|
11
|
+
"file": "ask.MP3",
|
|
12
|
+
"size": 75282
|
|
13
|
+
},
|
|
14
|
+
"turnEnd": {
|
|
15
|
+
"file": "end.MP3",
|
|
16
|
+
"size": 70894
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"voiceLines": {
|
|
20
|
+
"planApproval": "请陛下御览。",
|
|
21
|
+
"askQuestion": "请陛下圣裁。",
|
|
22
|
+
"turnEnd": "臣已办妥。"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
Binary file
|
package/lib/voice-pack-events.js
CHANGED
|
@@ -21,7 +21,8 @@ export const EVENT_KEYS = [
|
|
|
21
21
|
];
|
|
22
22
|
|
|
23
23
|
// Per-event default binding when no user override is set:
|
|
24
|
-
// - 'default' → play the bundled default-pack audio
|
|
24
|
+
// - 'default' → play the bundled default-pack (butler) audio
|
|
25
|
+
// - 'sanguo' → play the bundled sanguo (三国) audio — initial seed for zh/zh-TW
|
|
25
26
|
// - null → event is OFF by default (user must opt in)
|
|
26
27
|
// turnEnd defaults to null because firing on every Claude reply is noisy
|
|
27
28
|
//( — frequency overload mitigation).
|
|
@@ -30,3 +31,48 @@ export const DEFAULT_BINDINGS = Object.freeze({
|
|
|
30
31
|
askQuestion: 'default',
|
|
31
32
|
turnEnd: null,
|
|
32
33
|
});
|
|
34
|
+
|
|
35
|
+
// Bundled packs that ship inside the npm tarball under public/voice-packs/<id>/.
|
|
36
|
+
// Used as a value whitelist in reconcile (manager.js) and a dispatch table in the
|
|
37
|
+
// audio route (server.js) + URL builder (voicePackPlayer.js). Adding a third
|
|
38
|
+
// pack means appending its id here and dropping a public/voice-packs/<id>/
|
|
39
|
+
// directory + pack.json — no other code path needs editing.
|
|
40
|
+
export const BUNDLED_PACK_IDS = Object.freeze(['default', 'sanguo']);
|
|
41
|
+
|
|
42
|
+
// Locale → preferred bundled pack for initial seed of new users. Declarative
|
|
43
|
+
// map (not control flow) so adding a third pack that wants to capture some
|
|
44
|
+
// locale is a one-line table edit — never a new `if` branch.
|
|
45
|
+
// Match strategy: exact-match locale → pack; missing locale → fall through to
|
|
46
|
+
// DEFAULT_BINDINGS (butler).
|
|
47
|
+
// Locale strings are normalised lowercase before lookup (i18n.js LANG_MAP
|
|
48
|
+
// already folds variants like zh-Hans → zh, zh-HK → zh-TW; this map only
|
|
49
|
+
// needs the canonical forms produced by getLang()).
|
|
50
|
+
const LOCALE_DEFAULT_SEEDS = Object.freeze({
|
|
51
|
+
zh: 'sanguo',
|
|
52
|
+
'zh-tw': 'sanguo',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Per-event default bindings for a given locale pack. Event keys that should
|
|
56
|
+
// stay off-by-default (turnEnd is noisy on every reply) keep null regardless
|
|
57
|
+
// of which pack the locale prefers.
|
|
58
|
+
function bindingsForPack(packId) {
|
|
59
|
+
return Object.freeze({
|
|
60
|
+
planApproval: packId,
|
|
61
|
+
askQuestion: packId,
|
|
62
|
+
turnEnd: null,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Initial-seed bindings for a fresh user, parameterised by detected locale.
|
|
67
|
+
// Locale is read **once** at first-launch in AppBase — runtime lang changes
|
|
68
|
+
// do NOT re-seed (that would silently mutate the user's persisted choice
|
|
69
|
+
// — "no silent migration" P0 rule).
|
|
70
|
+
// Pure function — safe to unit-test without mounting React.
|
|
71
|
+
export function getDefaultBindingsForLocale(locale) {
|
|
72
|
+
const normalized = typeof locale === 'string' ? locale.toLowerCase() : '';
|
|
73
|
+
const packId = LOCALE_DEFAULT_SEEDS[normalized];
|
|
74
|
+
if (packId && BUNDLED_PACK_IDS.includes(packId)) {
|
|
75
|
+
return bindingsForPack(packId);
|
|
76
|
+
}
|
|
77
|
+
return DEFAULT_BINDINGS;
|
|
78
|
+
}
|
|
@@ -13,26 +13,30 @@ import { join, extname } from 'node:path';
|
|
|
13
13
|
import { randomUUID } from 'node:crypto';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { dirname } from 'node:path';
|
|
16
|
-
import { EVENT_KEYS, DEFAULT_BINDINGS } from './voice-pack-events.js';
|
|
16
|
+
import { EVENT_KEYS, DEFAULT_BINDINGS, BUNDLED_PACK_IDS } from './voice-pack-events.js';
|
|
17
17
|
|
|
18
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
19
|
const __dirname = dirname(__filename);
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
// 1. <repo>/dist/voice-packs
|
|
23
|
-
// 2. <repo>/public/voice-packs
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
// Bundled pack lookup order, per packId:
|
|
22
|
+
// 1. <repo>/dist/voice-packs/<packId>/ — production (Vite copies public/* into dist/, npm ships dist/ only)
|
|
23
|
+
// 2. <repo>/public/voice-packs/<packId>/ — dev (source tree, before `npm run build`)
|
|
24
|
+
// Adding a new pack: append id to BUNDLED_PACK_IDS in voice-pack-events.js +
|
|
25
|
+
// drop public/voice-packs/<id>/ with pack.json. No code path here needs editing.
|
|
26
|
+
function bundledPackDirs(packId) {
|
|
27
|
+
return [
|
|
28
|
+
join(__dirname, '..', 'dist', 'voice-packs', packId),
|
|
29
|
+
join(__dirname, '..', 'public', 'voice-packs', packId),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Surface a packaging-regression warning at module load when any declared bundled
|
|
34
|
+
// pack is missing — keeps a future relocation of this file or a broken
|
|
33
35
|
// `npm pack` from silently shipping a feature without its bundled audio.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
for (const packId of BUNDLED_PACK_IDS) {
|
|
37
|
+
if (!bundledPackDirs(packId).some(d => existsSync(d))) {
|
|
38
|
+
console.warn(`[voice-pack] no bundled-pack directory found for "${packId}" — bundled audio will 404, frontend falls back to chime`);
|
|
39
|
+
}
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
export { EVENT_KEYS } from './voice-pack-events.js';
|
|
@@ -172,17 +176,63 @@ export function deleteUserAudio(logDir, id) {
|
|
|
172
176
|
return removed;
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
+
// Read pack.json from the given dir; returns parsed object or null. Per-dir so
|
|
180
|
+
// a dist/ pack and a public/ pack can describe different files (dev iteration).
|
|
181
|
+
// Parse failures emit a single console.warn so a broken manifest doesn't make
|
|
182
|
+
// the entire bundled pack silently disappear from the Settings UI (the pack
|
|
183
|
+
// would fall back to literal `<eventKey>.<ext>` lookup, which fails for
|
|
184
|
+
// descriptive filenames like ask.MP3 → empty pack → not listed).
|
|
185
|
+
function readPackManifest(dir) {
|
|
186
|
+
const p = join(dir, 'pack.json');
|
|
187
|
+
if (!existsSync(p)) return null;
|
|
188
|
+
try { return JSON.parse(readFileSync(p, 'utf-8')); }
|
|
189
|
+
catch (err) {
|
|
190
|
+
try { console.warn(`[voice-pack] failed to parse pack.json at ${p}:`, err?.message || err); } catch { /* ignore */ }
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Validate a pack.json events[eventKey].file value and resolve it inside `dir`.
|
|
196
|
+
// Returns { path, format } when safe + existing, null otherwise. The file field
|
|
197
|
+
// is descriptive (e.g. "The_plan_awaits_your_approval_sir.MP3") so we have to
|
|
198
|
+
// allow non-eventKey filenames while still rejecting traversal / symlink games.
|
|
199
|
+
// Exported as _resolveBundledPackManifestFile for unit-testing the rejection
|
|
200
|
+
// rules without standing up the bundled pack dir.
|
|
201
|
+
export function _resolveBundledPackManifestFile(dir, file) {
|
|
202
|
+
if (typeof file !== 'string' || file.length === 0 || file.length > 200) return null;
|
|
203
|
+
if (file.includes('/') || file.includes('\\') || file.includes('\0')) return null;
|
|
204
|
+
if (file === '.' || file === '..' || file.startsWith('.')) return null;
|
|
205
|
+
const ext = extname(file).toLowerCase();
|
|
206
|
+
if (!ALLOWED_EXTS.has(ext)) return null;
|
|
207
|
+
const p = join(dir, file);
|
|
208
|
+
if (!existsSync(p)) return null;
|
|
209
|
+
try { if (lstatSync(p).isSymbolicLink()) return null; } catch { return null; }
|
|
210
|
+
return { path: p, format: ext.slice(1) };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Bundled-pack lookup — (packId, eventKey) → file inside bundledPackDirs(packId).
|
|
214
|
+
// Resolution order per dir:
|
|
215
|
+
// 1. pack.json events[eventKey].file (descriptive filename, e.g. butler voice line)
|
|
216
|
+
// 2. literal `<eventKey>.<ext>` (legacy / placeholder-generator convention)
|
|
217
|
+
// Returns null when neither exists, letting the API 404 and the front-end fall
|
|
218
|
+
// back to its Web Audio chime.
|
|
219
|
+
// packId is whitelisted against BUNDLED_PACK_IDS to neutralise a malformed
|
|
220
|
+
// route segment (e.g. '../etc') reaching the FS layer.
|
|
221
|
+
export function getBundledPackPath(packId, eventKey) {
|
|
222
|
+
if (!BUNDLED_PACK_IDS.includes(packId)) return null;
|
|
179
223
|
if (!EVENT_KEYS.includes(eventKey)) return null;
|
|
180
|
-
for (const dir of
|
|
224
|
+
for (const dir of bundledPackDirs(packId)) {
|
|
225
|
+
const manifest = readPackManifest(dir);
|
|
226
|
+
const manifestFile = manifest?.events?.[eventKey]?.file;
|
|
227
|
+
if (manifestFile) {
|
|
228
|
+
const hit = _resolveBundledPackManifestFile(dir, manifestFile);
|
|
229
|
+
if (hit) return hit;
|
|
230
|
+
}
|
|
181
231
|
for (const ext of ALLOWED_EXTS) {
|
|
182
232
|
const p = join(dir, `${eventKey}${ext}`);
|
|
183
233
|
if (!existsSync(p)) continue;
|
|
184
234
|
// Symlink hardening — same threat model as getUserAudioPath above. The
|
|
185
|
-
//
|
|
235
|
+
// bundled-pack directories live inside the package install, so a tampered
|
|
186
236
|
// install could ship symlinks; skip rather than dereference.
|
|
187
237
|
try { if (lstatSync(p).isSymbolicLink()) continue; } catch { continue; }
|
|
188
238
|
return { path: p, format: ext.slice(1) };
|
|
@@ -191,12 +241,21 @@ export function getDefaultPackPath(eventKey) {
|
|
|
191
241
|
return null;
|
|
192
242
|
}
|
|
193
243
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
244
|
+
// Back-compat thin wrapper. External callers that imported the original name
|
|
245
|
+
// keep working; new code should use getBundledPackPath directly.
|
|
246
|
+
export function getDefaultPackPath(eventKey) {
|
|
247
|
+
return getBundledPackPath('default', eventKey);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Per-pack event listing — used by /api/voice-pack/list to surface every
|
|
251
|
+
// bundled pack to the Settings UI.
|
|
252
|
+
export function listBundledPack(packId) {
|
|
253
|
+
if (!BUNDLED_PACK_IDS.includes(packId)) return [];
|
|
254
|
+
const dirs = bundledPackDirs(packId);
|
|
255
|
+
if (!dirs.some(d => existsSync(d))) return [];
|
|
197
256
|
const out = [];
|
|
198
257
|
for (const eventKey of EVENT_KEYS) {
|
|
199
|
-
const hit =
|
|
258
|
+
const hit = getBundledPackPath(packId, eventKey);
|
|
200
259
|
if (hit) {
|
|
201
260
|
let size = 0;
|
|
202
261
|
try { size = statSync(hit.path).size; } catch { /* ignore */ }
|
|
@@ -206,32 +265,70 @@ export function listDefaultPack() {
|
|
|
206
265
|
return out;
|
|
207
266
|
}
|
|
208
267
|
|
|
209
|
-
//
|
|
210
|
-
//
|
|
268
|
+
// Read pack.json manifest metadata for the Settings UI — displayName,
|
|
269
|
+
// placeholder flag, voiceLines. Returns null when no manifest exists.
|
|
270
|
+
function readBundledPackMeta(packId) {
|
|
271
|
+
for (const dir of bundledPackDirs(packId)) {
|
|
272
|
+
const meta = readPackManifest(dir);
|
|
273
|
+
if (meta) return meta;
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Returns every bundled pack with enough metadata for Settings UI to render
|
|
279
|
+
// a dropdown row: id, displayName (falls back to id), placeholder flag, and
|
|
280
|
+
// the per-event file listing. Empty packs (no files on disk) are skipped so
|
|
281
|
+
// a partial install doesn't show an unusable option.
|
|
282
|
+
export function listBundledPacks() {
|
|
283
|
+
const out = [];
|
|
284
|
+
for (const packId of BUNDLED_PACK_IDS) {
|
|
285
|
+
const events = listBundledPack(packId);
|
|
286
|
+
if (events.length === 0) continue;
|
|
287
|
+
const meta = readBundledPackMeta(packId);
|
|
288
|
+
out.push({
|
|
289
|
+
id: packId,
|
|
290
|
+
displayName: meta?.displayName || packId,
|
|
291
|
+
placeholder: !!meta?.placeholder,
|
|
292
|
+
events,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return out;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Legacy listing — kept so callers that haven't migrated to listBundledPacks()
|
|
299
|
+
// continue to get the default pack's events.
|
|
300
|
+
export function listDefaultPack() {
|
|
301
|
+
return listBundledPack('default');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Surfaces the pack.json `placeholder` flag so the Settings UI can label
|
|
305
|
+
// a bundled pack as a placeholder (— discoverability of the
|
|
211
306
|
// placeholder→real-recording replacement path). Returns false when no manifest
|
|
212
307
|
// is present (treats absence as "not flagged" rather than guessing).
|
|
308
|
+
export function isBundledPackPlaceholder(packId) {
|
|
309
|
+
if (!BUNDLED_PACK_IDS.includes(packId)) return false;
|
|
310
|
+
const meta = readBundledPackMeta(packId);
|
|
311
|
+
return !!meta?.placeholder;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Back-compat thin wrapper.
|
|
213
315
|
export function isDefaultPackPlaceholder() {
|
|
214
|
-
|
|
215
|
-
const p = join(dir, 'pack.json');
|
|
216
|
-
if (!existsSync(p)) continue;
|
|
217
|
-
try {
|
|
218
|
-
const meta = JSON.parse(readFileSync(p, 'utf-8'));
|
|
219
|
-
return !!meta?.placeholder;
|
|
220
|
-
} catch { /* keep looking */ }
|
|
221
|
-
}
|
|
222
|
-
return false;
|
|
316
|
+
return isBundledPackPlaceholder('default');
|
|
223
317
|
}
|
|
224
318
|
|
|
225
319
|
// Reconcile a voice-pack settings blob against on-disk state. Any event whose
|
|
226
320
|
// bound id no longer exists is silently reset to null — surfaces in the next
|
|
227
321
|
// GET /api/preferences without the client doing anything. Returns the reconciled
|
|
228
322
|
// object (caller decides whether to persist it).
|
|
323
|
+
// Literal strings in BUNDLED_PACK_IDS (currently 'default' and 'sanguo') are
|
|
324
|
+
// passed through verbatim — they're checked against the bundled-pack route
|
|
325
|
+
// at playback time, not against logDir/voice-packs/.
|
|
229
326
|
export function reconcileVoicePackPrefs(logDir, vp) {
|
|
230
327
|
if (!vp || typeof vp !== 'object') return vp;
|
|
231
328
|
const events = vp.events && typeof vp.events === 'object' ? { ...vp.events } : {};
|
|
232
329
|
for (const key of EVENT_KEYS) {
|
|
233
330
|
const val = events[key];
|
|
234
|
-
if (val == null || val
|
|
331
|
+
if (val == null || BUNDLED_PACK_IDS.includes(val)) continue;
|
|
235
332
|
if (typeof val !== 'string' || !isValidId(val)) { events[key] = null; continue; }
|
|
236
333
|
if (!getUserAudioPath(logDir, val)) events[key] = null;
|
|
237
334
|
}
|
|
@@ -239,7 +336,7 @@ export function reconcileVoicePackPrefs(logDir, vp) {
|
|
|
239
336
|
}
|
|
240
337
|
|
|
241
338
|
// Re-export shared defaults so consumers can pull everything from one module.
|
|
242
|
-
export { DEFAULT_BINDINGS };
|
|
339
|
+
export { DEFAULT_BINDINGS, BUNDLED_PACK_IDS };
|
|
243
340
|
|
|
244
341
|
// mergeApprovalModalPrefs / mergeVoicePackInto moved to lib/approval-modal-prefs.js
|
|
245
342
|
//( — merge logic isn't voice-pack-specific). Import from
|
package/package.json
CHANGED
package/pty-manager.js
CHANGED
|
@@ -248,7 +248,7 @@ export async function spawnClaude(proxyPort, cwd, extraArgs = [], claudePath = n
|
|
|
248
248
|
if (hasContinue && exitCode !== 0 && outputBuffer.includes('No conversation found')) {
|
|
249
249
|
console.error('[CC Viewer] -c failed (no conversation), retrying without -c');
|
|
250
250
|
const retryArgs = extraArgs.filter(a => a !== '-c' && a !== '--continue');
|
|
251
|
-
spawnClaude(proxyPort, cwd, retryArgs, claudePath, isNpmVersion, serverPort, serverProtocol);
|
|
251
|
+
spawnClaude(proxyPort, cwd, retryArgs, claudePath, isNpmVersion, serverPort, serverProtocol, internalToken);
|
|
252
252
|
return;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -264,7 +264,7 @@ export async function spawnClaude(proxyPort, cwd, extraArgs = [], claudePath = n
|
|
|
264
264
|
if (flagRejected) {
|
|
265
265
|
console.error('[CC Viewer] claude rejected --thinking-display, marking as unsupported and retrying without flag');
|
|
266
266
|
_thinkingDisplayRejectedPaths.add(claudePath);
|
|
267
|
-
spawnClaude(proxyPort, cwd, extraArgs, claudePath, isNpmVersion, serverPort, serverProtocol);
|
|
267
|
+
spawnClaude(proxyPort, cwd, extraArgs, claudePath, isNpmVersion, serverPort, serverProtocol, internalToken);
|
|
268
268
|
return;
|
|
269
269
|
}
|
|
270
270
|
|