mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 02:11:28 +00:00
style: format official channel files
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
import { spawnSync } from 'child_process';
|
||||
import type { TargetType } from '../targets/target-adapter';
|
||||
import type { ProfileType } from '../types/profile';
|
||||
import type {
|
||||
OfficialChannelId,
|
||||
OfficialChannelsConfig,
|
||||
} from '../config/unified-config-types';
|
||||
import type { OfficialChannelId, OfficialChannelsConfig } from '../config/unified-config-types';
|
||||
|
||||
export interface OfficialChannelDefinition {
|
||||
id: OfficialChannelId;
|
||||
@@ -132,7 +129,11 @@ export function buildOfficialChannelsArgs(
|
||||
channels: OfficialChannelId[],
|
||||
includePermissionBypass: boolean
|
||||
): string[] {
|
||||
const nextArgs = [...args, '--channels', ...channels.map((channel) => OFFICIAL_CHANNELS[channel].pluginSpec)];
|
||||
const nextArgs = [
|
||||
...args,
|
||||
'--channels',
|
||||
...channels.map((channel) => OFFICIAL_CHANNELS[channel].pluginSpec),
|
||||
];
|
||||
|
||||
if (includePermissionBypass) {
|
||||
nextArgs.push('--dangerously-skip-permissions');
|
||||
@@ -191,9 +192,7 @@ export function resolveOfficialChannelsLaunchPlan(
|
||||
const channel = OFFICIAL_CHANNELS[channelId];
|
||||
|
||||
if (channel.requiresMacOS && !isMacOS()) {
|
||||
skippedMessages.push(
|
||||
`${channel.displayName} auto-enable skipped because it requires macOS.`
|
||||
);
|
||||
skippedMessages.push(`${channel.displayName} auto-enable skipped because it requires macOS.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -256,7 +255,9 @@ export function getOfficialChannelSummary(channelId: OfficialChannelId): string
|
||||
return 'macOS-only. No bot token required, but Messages permissions are required.';
|
||||
}
|
||||
|
||||
export function getOfficialChannelUnavailableReason(channelId: OfficialChannelId): string | undefined {
|
||||
export function getOfficialChannelUnavailableReason(
|
||||
channelId: OfficialChannelId
|
||||
): string | undefined {
|
||||
if (channelId === 'imessage' && !isMacOS()) {
|
||||
return 'Requires macOS.';
|
||||
}
|
||||
@@ -300,7 +301,9 @@ export function isOfficialChannelSelectionValid(selection: string): boolean {
|
||||
.map((value) => value.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
|
||||
return parsed.length > 0 && parsed.every((value) => value === 'all' || isOfficialChannelId(value));
|
||||
return (
|
||||
parsed.length > 0 && parsed.every((value) => value === 'all' || isOfficialChannelId(value))
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveLegacyDiscordSelection(enabled: boolean | undefined): OfficialChannelId[] {
|
||||
@@ -369,7 +372,10 @@ export function getOfficialChannelsDocsSummary(): string {
|
||||
return 'Supported official channels are Telegram, Discord, and iMessage.';
|
||||
}
|
||||
|
||||
export function getOfficialChannelSyncFailureMessage(channelId: OfficialChannelId, targetPath: string): string {
|
||||
export function getOfficialChannelSyncFailureMessage(
|
||||
channelId: OfficialChannelId,
|
||||
targetPath: string
|
||||
): string {
|
||||
return `${getOfficialChannelDisplayName(channelId)} auto-enable skipped: failed to sync channel env to ${targetPath}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,7 @@ function parseTokenAssignment(value: string): {
|
||||
} | null {
|
||||
const separatorIndex = value.indexOf('=');
|
||||
if (separatorIndex === -1) {
|
||||
return value.trim()
|
||||
? { channelId: 'discord', token: value.trim() }
|
||||
: null;
|
||||
return value.trim() ? { channelId: 'discord', token: value.trim() } : null;
|
||||
}
|
||||
|
||||
const channelId = value.slice(0, separatorIndex).trim().toLowerCase();
|
||||
@@ -139,14 +137,20 @@ function showHelp(): void {
|
||||
console.log(` ${color('--clear', 'command')} Clear all selected channels`);
|
||||
console.log(` ${color('--enable', 'command')} Legacy alias: add Discord`);
|
||||
console.log(` ${color('--disable', 'command')} Legacy alias: remove Discord`);
|
||||
console.log(` ${color('--unattended', 'command')} Also add --dangerously-skip-permissions`);
|
||||
console.log(
|
||||
` ${color('--unattended', 'command')} Also add --dangerously-skip-permissions`
|
||||
);
|
||||
console.log(` ${color('--no-unattended', 'command')} Disable unattended runtime flag`);
|
||||
console.log(` ${color('--set-token <spec>', 'command')} ${getOfficialChannelTokenHelp()}`);
|
||||
console.log(` ${color('--clear-token [channel]', 'command')} ${getOfficialChannelClearTokenHelp()}`);
|
||||
console.log(
|
||||
` ${color('--clear-token [channel]', 'command')} ${getOfficialChannelClearTokenHelp()}`
|
||||
);
|
||||
console.log(` ${color('--help, -h', 'command')} Show this help`);
|
||||
console.log('');
|
||||
console.log(subheader('Examples:'));
|
||||
console.log(` $ ${color('ccs config channels', 'command')} ${dim('# Show status')}`);
|
||||
console.log(
|
||||
` $ ${color('ccs config channels', 'command')} ${dim('# Show status')}`
|
||||
);
|
||||
console.log(
|
||||
` $ ${color('ccs config channels --set telegram,discord', 'command')} ${dim('# Enable Telegram + Discord')}`
|
||||
);
|
||||
@@ -170,13 +174,17 @@ function showStatus(): void {
|
||||
console.log('');
|
||||
console.log(header('Official Channels Configuration'));
|
||||
console.log('');
|
||||
console.log(` Channels: ${selected.length > 0 ? ok(getChannelConfigSelectionLabel(selected)) : warn('Disabled')}`);
|
||||
console.log(
|
||||
` Channels: ${selected.length > 0 ? ok(getChannelConfigSelectionLabel(selected)) : warn('Disabled')}`
|
||||
);
|
||||
console.log(` Unattended: ${config.unattended ? warn('Enabled') : info('Disabled')}`);
|
||||
console.log(` Bun: ${bunReady ? ok('Installed') : warn('Missing')}`);
|
||||
console.log('');
|
||||
console.log(subheader('Applies To:'));
|
||||
console.log(` ${dim(getOfficialChannelsCompatibilityMessage())}`);
|
||||
console.log(` ${dim(`Supported profiles: ${getOfficialChannelsSupportedProfiles().join(', ')}`)}`);
|
||||
console.log(
|
||||
` ${dim(`Supported profiles: ${getOfficialChannelsSupportedProfiles().join(', ')}`)}`
|
||||
);
|
||||
console.log('');
|
||||
console.log(subheader('Channels:'));
|
||||
for (const channelId of expandOfficialChannelSelection('all')) {
|
||||
@@ -195,7 +203,9 @@ function showStatus(): void {
|
||||
console.log(` ${enabled ? '[x]' : '[ ]'} ${displayName}: ${status}`);
|
||||
console.log(` ${dim(getOfficialChannelSummary(channelId))}`);
|
||||
if (envKey) {
|
||||
console.log(` ${dim(`${envKey}: ${tokenConfigured ? 'configured' : 'not configured'}`)}`);
|
||||
console.log(
|
||||
` ${dim(`${envKey}: ${tokenConfigured ? 'configured' : 'not configured'}`)}`
|
||||
);
|
||||
console.log(` ${dim(getOfficialChannelEnvPath(channelId))}`);
|
||||
}
|
||||
console.log(` ${dim(getOfficialChannelReadyMessage(channelId))}`);
|
||||
@@ -242,8 +252,13 @@ export async function handleConfigChannelsCommand(args: string[]): Promise<void>
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
if (options.setSelection !== undefined && !isOfficialChannelSelectionValid(options.setSelection)) {
|
||||
console.error(fail(`Invalid --set value: ${options.setSelection} (${getOfficialChannelChoices()} or all)`));
|
||||
if (
|
||||
options.setSelection !== undefined &&
|
||||
!isOfficialChannelSelectionValid(options.setSelection)
|
||||
) {
|
||||
console.error(
|
||||
fail(`Invalid --set value: ${options.setSelection} (${getOfficialChannelChoices()} or all)`)
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
@@ -261,7 +276,9 @@ export async function handleConfigChannelsCommand(args: string[]): Promise<void>
|
||||
}
|
||||
if (options.clearTokenInvalid) {
|
||||
console.error(
|
||||
fail(`Invalid --clear-token value: ${options.clearTokenInvalid} (use ${getOfficialChannelChoices()})`)
|
||||
fail(
|
||||
`Invalid --clear-token value: ${options.clearTokenInvalid} (use ${getOfficialChannelChoices()})`
|
||||
)
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
|
||||
@@ -471,7 +471,10 @@ Run ${color('ccs config', 'command')} for web dashboard`.trim();
|
||||
|
||||
printSubSection('Official Channels (official Claude plugins)', [
|
||||
['ccs config channels', 'Show current status'],
|
||||
['ccs config channels --set telegram,discord', 'Auto-add selected channels on native Claude sessions'],
|
||||
[
|
||||
'ccs config channels --set telegram,discord',
|
||||
'Auto-add selected channels on native Claude sessions',
|
||||
],
|
||||
['ccs config channels --set all', 'Enable Telegram, Discord, and iMessage'],
|
||||
['ccs config channels --unattended', 'Also add --dangerously-skip-permissions'],
|
||||
['ccs config channels --set-token telegram=<token>', 'Save TELEGRAM_BOT_TOKEN'],
|
||||
|
||||
@@ -305,7 +305,9 @@ function normalizeOfficialChannelsConfig(
|
||||
partial: Partial<UnifiedConfig> & { discord_channels?: LegacyDiscordChannelsConfig }
|
||||
): OfficialChannelsConfig {
|
||||
const rawSelected = Array.isArray(partial.channels?.selected)
|
||||
? partial.channels.selected.filter((value): value is OfficialChannelId => isOfficialChannelId(value))
|
||||
? partial.channels.selected.filter((value): value is OfficialChannelId =>
|
||||
isOfficialChannelId(value)
|
||||
)
|
||||
: [];
|
||||
|
||||
return {
|
||||
@@ -806,16 +808,15 @@ function generateYamlWithComments(config: UnifiedConfig): string {
|
||||
lines.push('# Runtime-only: CCS injects --channels at launch for compatible Claude sessions.');
|
||||
lines.push('# Bot tokens live in Claude channel env files, not in config.yaml.');
|
||||
lines.push('# Use selected: [telegram, discord, imessage] to choose channels.');
|
||||
lines.push('# unattended adds --dangerously-skip-permissions only when channel auto-enable is active.');
|
||||
lines.push(
|
||||
'# unattended adds --dangerously-skip-permissions only when channel auto-enable is active.'
|
||||
);
|
||||
lines.push('# Compatible sessions: native Claude default/account profiles only.');
|
||||
lines.push('# Configure via: ccs config channels or the Settings > Channels dashboard tab.');
|
||||
lines.push('# ----------------------------------------------------------------------------');
|
||||
lines.push(
|
||||
yaml
|
||||
.dump(
|
||||
{ channels: config.channels },
|
||||
{ indent: 2, lineWidth: -1, quotingType: '"' }
|
||||
)
|
||||
.dump({ channels: config.channels }, { indent: 2, lineWidth: -1, quotingType: '"' })
|
||||
.trim()
|
||||
);
|
||||
lines.push('');
|
||||
|
||||
@@ -71,7 +71,8 @@ router.put('/', (req: Request, res: Response): void => {
|
||||
|
||||
if (
|
||||
selected !== undefined &&
|
||||
(!Array.isArray(selected) || selected.some((value) => typeof value !== 'string' || !isOfficialChannelId(value)))
|
||||
(!Array.isArray(selected) ||
|
||||
selected.some((value) => typeof value !== 'string' || !isOfficialChannelId(value)))
|
||||
) {
|
||||
res.status(400).json({ error: 'selected must be an array of official channel IDs' });
|
||||
return;
|
||||
@@ -84,7 +85,7 @@ router.put('/', (req: Request, res: Response): void => {
|
||||
try {
|
||||
const updated = mutateUnifiedConfig((config) => {
|
||||
config.channels = {
|
||||
selected: selected ? [...new Set(selected)] : config.channels?.selected ?? [],
|
||||
selected: selected ? [...new Set(selected)] : (config.channels?.selected ?? []),
|
||||
unattended: unattended ?? config.channels?.unattended ?? false,
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user