mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 12:14:19 +00:00
Merge pull request #128 from kaitranntt/dev
fix(release): v6.2.0-dev.2 - WebSearch native passthrough and UI improvements
This commit is contained in:
6 files changed
+73
-16
No files matched your search
@@ -116,6 +116,24 @@ const DEFAULT_TIMEOUT_SEC = 55;
|
||||
// HOOK LOGIC - Generally no need to edit below
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Determine if hook should skip and pass through to native WebSearch.
|
||||
* Returns true for native Claude accounts where WebSearch works server-side.
|
||||
*/
|
||||
function shouldSkipHook() {
|
||||
// Explicit skip signal (set by CCS for account profiles)
|
||||
if (process.env.CCS_WEBSEARCH_SKIP === '1') return true;
|
||||
|
||||
// Account/default profiles - use native WebSearch
|
||||
const profileType = process.env.CCS_PROFILE_TYPE;
|
||||
if (profileType === 'account' || profileType === 'default') return true;
|
||||
|
||||
// Explicit disable
|
||||
if (process.env.CCS_WEBSEARCH_ENABLED === '0') return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read input from stdin
|
||||
let input = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
@@ -164,13 +182,8 @@ function isProviderEnabled(provider) {
|
||||
*/
|
||||
async function processHook() {
|
||||
try {
|
||||
// Skip if disabled (for official Claude subscriptions)
|
||||
if (process.env.CCS_WEBSEARCH_SKIP === '1') {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Check if enabled (default: enabled)
|
||||
if (process.env.CCS_WEBSEARCH_ENABLED === '0') {
|
||||
// Skip for native accounts (account, default profiles) or explicit disable
|
||||
if (shouldSkipHook()) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -238,7 +251,9 @@ async function processHook() {
|
||||
|
||||
// All providers failed or none enabled
|
||||
if (enabledProviders.length === 0) {
|
||||
outputNoProvidersEnabled(query);
|
||||
// No providers enabled - pass through to native WebSearch
|
||||
// This allows native Claude accounts to use server-side WebSearch
|
||||
process.exit(0);
|
||||
} else {
|
||||
outputAllFailedMessage(query, errors);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kaitranntt/ccs",
|
||||
"version": "6.2.0",
|
||||
"version": "6.2.0-dev.2",
|
||||
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
||||
"keywords": [
|
||||
"cli",
|
||||
|
||||
+24
-4
@@ -154,7 +154,12 @@ async function execClaudeWithProxy(
|
||||
const isWindows = process.platform === 'win32';
|
||||
const needsShell = isWindows && /\.(cmd|bat|ps1)$/i.test(claudeCli);
|
||||
const webSearchEnv = getWebSearchHookEnv();
|
||||
const env = { ...process.env, ...envVars, ...webSearchEnv };
|
||||
const env = {
|
||||
...process.env,
|
||||
...envVars,
|
||||
...webSearchEnv,
|
||||
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
|
||||
};
|
||||
|
||||
let claude: ChildProcess;
|
||||
if (needsShell) {
|
||||
@@ -401,7 +406,12 @@ async function main(): Promise<void> {
|
||||
// EXISTING FLOW: Settings-based profile (glm, kimi)
|
||||
// Use --settings flag (backward compatible)
|
||||
const expandedSettingsPath = getSettingsPath(profileInfo.name);
|
||||
execClaude(claudeCli, ['--settings', expandedSettingsPath, ...remainingArgs]);
|
||||
const webSearchEnv = getWebSearchHookEnv();
|
||||
const envVars: NodeJS.ProcessEnv = {
|
||||
...webSearchEnv,
|
||||
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
|
||||
};
|
||||
execClaude(claudeCli, ['--settings', expandedSettingsPath, ...remainingArgs], envVars);
|
||||
}
|
||||
} else if (profileInfo.type === 'account') {
|
||||
// NEW FLOW: Account-based profile (work, personal)
|
||||
@@ -420,11 +430,21 @@ async function main(): Promise<void> {
|
||||
}
|
||||
|
||||
// Execute Claude with instance isolation
|
||||
const envVars: NodeJS.ProcessEnv = { CLAUDE_CONFIG_DIR: instancePath };
|
||||
// Skip WebSearch hook - account profiles use native server-side WebSearch
|
||||
const envVars: NodeJS.ProcessEnv = {
|
||||
CLAUDE_CONFIG_DIR: instancePath,
|
||||
CCS_PROFILE_TYPE: 'account',
|
||||
CCS_WEBSEARCH_SKIP: '1',
|
||||
};
|
||||
execClaude(claudeCli, remainingArgs, envVars);
|
||||
} else {
|
||||
// DEFAULT: No profile configured, use Claude's own defaults
|
||||
execClaude(claudeCli, remainingArgs);
|
||||
// Skip WebSearch hook - native Claude has server-side WebSearch
|
||||
const envVars: NodeJS.ProcessEnv = {
|
||||
CCS_PROFILE_TYPE: 'default',
|
||||
CCS_WEBSEARCH_SKIP: '1',
|
||||
};
|
||||
execClaude(claudeCli, remainingArgs, envVars);
|
||||
}
|
||||
} catch (error) {
|
||||
const err = error as ProfileError;
|
||||
|
||||
@@ -426,7 +426,12 @@ export async function execClaudeWithCLIProxy(
|
||||
// Uses custom settings path (for variants), user settings, or bundled defaults
|
||||
const envVars = getEffectiveEnvVars(provider, cfg.port, cfg.customSettingsPath);
|
||||
const webSearchEnv = getWebSearchHookEnv();
|
||||
const env = { ...process.env, ...envVars, ...webSearchEnv };
|
||||
const env = {
|
||||
...process.env,
|
||||
...envVars,
|
||||
...webSearchEnv,
|
||||
CCS_PROFILE_TYPE: 'cliproxy', // Signal to WebSearch hook this is a third-party provider
|
||||
};
|
||||
|
||||
log(`Claude env: ANTHROPIC_BASE_URL=${envVars.ANTHROPIC_BASE_URL}`);
|
||||
log(`Claude env: ANTHROPIC_MODEL=${envVars.ANTHROPIC_MODEL}`);
|
||||
|
||||
+18
-1
@@ -19,6 +19,7 @@ import {
|
||||
Server,
|
||||
ExternalLink,
|
||||
FileJson,
|
||||
RefreshCw,
|
||||
} from 'lucide-react';
|
||||
import { ProfileEditor } from '@/components/profile-editor';
|
||||
import { ProfileCreateDialog } from '@/components/profile-create-dialog';
|
||||
@@ -29,7 +30,7 @@ import { cn } from '@/lib/utils';
|
||||
import { CopyButton } from '@/components/ui/copy-button';
|
||||
|
||||
export function ApiPage() {
|
||||
const { data, isLoading } = useProfiles();
|
||||
const { data, isLoading, isError, refetch } = useProfiles();
|
||||
const deleteMutation = useDeleteProfile();
|
||||
const [selectedProfile, setSelectedProfile] = useState<string | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -111,6 +112,22 @@ export function ApiPage() {
|
||||
<ScrollArea className="flex-1">
|
||||
{isLoading ? (
|
||||
<div className="p-4 text-sm text-muted-foreground">Loading profiles...</div>
|
||||
) : isError ? (
|
||||
<div className="p-4 text-center">
|
||||
<div className="space-y-3 py-8">
|
||||
<AlertCircle className="w-12 h-12 mx-auto text-destructive/50" />
|
||||
<div>
|
||||
<p className="text-sm font-medium">Failed to load profiles</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Unable to fetch API profiles. Please try again.
|
||||
</p>
|
||||
</div>
|
||||
<Button size="sm" variant="outline" onClick={() => refetch()}>
|
||||
<RefreshCw className="w-4 h-4 mr-1" />
|
||||
Retry
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : filteredProfiles.length === 0 ? (
|
||||
<div className="p-4 text-center">
|
||||
{profiles.length === 0 ? (
|
||||
|
||||
Reference in new issue
Block a user