diff --git a/scripts/no-telemetry-plugin.ts b/scripts/no-telemetry-plugin.ts index 910f2032..c0ad74d8 100644 --- a/scripts/no-telemetry-plugin.ts +++ b/scripts/no-telemetry-plugin.ts @@ -203,6 +203,60 @@ export async function submitTranscriptShare() { return { success: false }; } 'services/internalLogging': ` export async function logPermissionContextForAnts() {} export const getContainerId = async () => null; +`, + + // ─── Deleted Anthropic-internal modules ─────────────────────────────── + + 'services/api/dumpPrompts': ` +export function createDumpPromptsFetch() { return undefined; } +export function getDumpPromptsPath() { return ''; } +export function getLastApiRequests() { return []; } +export function clearApiRequestCache() {} +export function clearDumpState() {} +export function clearAllDumpState() {} +export function addApiRequestToCache() {} +`, + + 'utils/undercover': ` +export function isUndercover() { return false; } +export function getUndercoverInstructions() { return ''; } +export function shouldShowUndercoverAutoNotice() { return false; } +`, + + 'types/generated/events_mono/claude_code/v1/claude_code_internal_event': ` +export const ClaudeCodeInternalEvent = { + fromJSON: value => value, + toJSON: value => value, + create: value => value ?? {}, + fromPartial: value => value ?? {}, +}; +`, + + 'types/generated/events_mono/growthbook/v1/growthbook_experiment_event': ` +export const GrowthbookExperimentEvent = { + fromJSON: value => value, + toJSON: value => value, + create: value => value ?? {}, + fromPartial: value => value ?? {}, +}; +`, + + 'types/generated/events_mono/common/v1/auth': ` +export const PublicApiAuth = { + fromJSON: value => value, + toJSON: value => value, + create: value => value ?? {}, + fromPartial: value => value ?? {}, +}; +`, + + 'types/generated/google/protobuf/timestamp': ` +export const Timestamp = { + fromJSON: value => value, + toJSON: value => value, + create: value => value ?? {}, + fromPartial: value => value ?? {}, +}; `, } diff --git a/scripts/verify-no-phone-home.sh b/scripts/verify-no-phone-home.sh index 2bce48d5..79fa8b4d 100644 --- a/scripts/verify-no-phone-home.sh +++ b/scripts/verify-no-phone-home.sh @@ -19,6 +19,10 @@ BANNED=( "/var/run/secrets/kubernetes" "/proc/self/mountinfo" "tengu_internal_record_permission_context" + "anthropic-serve" + "infra.ant.dev" + "claude-code-feedback" + "C07VBSHV7EV" ) echo "Checking $DIST for banned patterns..." diff --git a/scripts/verify-no-phone-home.ts b/scripts/verify-no-phone-home.ts index c030af54..843c5f33 100644 --- a/scripts/verify-no-phone-home.ts +++ b/scripts/verify-no-phone-home.ts @@ -9,6 +9,10 @@ const BANNED_PATTERNS = [ '/var/run/secrets/kubernetes', '/proc/self/mountinfo', 'tengu_internal_record_permission_context', + 'anthropic-serve', + 'infra.ant.dev', + 'claude-code-feedback', + 'C07VBSHV7EV', ] as const if (!existsSync(DIST)) { diff --git a/src/commands/insights.ts b/src/commands/insights.ts index f66380a7..bb618fc8 100644 --- a/src/commands/insights.ts +++ b/src/commands/insights.ts @@ -3072,33 +3072,6 @@ const usageReport: Command = { let reportUrl = `file://${htmlPath}` let uploadHint = '' - if (process.env.USER_TYPE === 'ant') { - // Try to upload to S3 - const timestamp = new Date() - .toISOString() - .replace(/[-:]/g, '') - .replace('T', '_') - .slice(0, 15) - const username = process.env.SAFEUSER || process.env.USER || 'unknown' - const filename = `${username}_insights_${timestamp}.html` - const s3Path = `s3://anthropic-serve/atamkin/cc-user-reports/${filename}` - const s3Url = `https://s3-frontend.infra.ant.dev/anthropic-serve/atamkin/cc-user-reports/${filename}` - - reportUrl = s3Url - try { - execFileSync('ff', ['cp', htmlPath, s3Path], { - timeout: 60000, - stdio: 'pipe', // Suppress output - }) - } catch { - // Upload failed - fall back to local file and show upload command - reportUrl = `file://${htmlPath}` - uploadHint = `\nAutomatic upload failed. Are you on the boron namespace? Try \`use-bo\` and ensure you've run \`sso\`. -To share, run: ff cp ${htmlPath} ${s3Path} -Then access at: ${s3Url}` - } - } - // Build header with stats const sessionLabel = data.total_sessions_scanned && diff --git a/src/constants/prompts.ts b/src/constants/prompts.ts index aea13021..6d861376 100644 --- a/src/constants/prompts.ts +++ b/src/constants/prompts.ts @@ -242,7 +242,7 @@ function getSimpleDoingTasksSection(): string { : []), ...(process.env.USER_TYPE === 'ant' ? [ - `If the user reports a bug, slowness, or unexpected behavior with Claude Code itself (as opposed to asking you to fix their own code), recommend the appropriate slash command: /issue for model-related problems (odd outputs, wrong tool choices, hallucinations, refusals), or /share to upload the full session transcript for product bugs, crashes, slowness, or general issues. Only recommend these when the user is describing a problem with Claude Code. After /share produces a ccshare link, if you have a Slack MCP tool available, offer to post the link to #claude-code-feedback (channel ID C07VBSHV7EV) for the user.`, + `If the user reports a bug, slowness, or unexpected behavior with Claude Code itself (as opposed to asking you to fix their own code), recommend the appropriate slash command: /issue for model-related problems (odd outputs, wrong tool choices, hallucinations, refusals), or /share to upload the full session transcript for product bugs, crashes, slowness, or general issues. Only recommend these when the user is describing a problem with Claude Code.`, ] : []), `If the user asks for help or wants to give feedback inform them of the following:`, diff --git a/src/services/api/dumpPrompts.ts b/src/services/api/dumpPrompts.ts index a3a0e2ff..dd780be7 100644 --- a/src/services/api/dumpPrompts.ts +++ b/src/services/api/dumpPrompts.ts @@ -1,226 +1,26 @@ import type { ClientOptions } from '@anthropic-ai/sdk' -import { createHash } from 'crypto' -import { promises as fs } from 'fs' -import { dirname, join } from 'path' -import { getSessionId } from 'src/bootstrap/state.js' -import { getClaudeConfigHomeDir } from '../../utils/envUtils.js' -import { jsonParse, jsonStringify } from '../../utils/slowOperations.js' - -function hashString(str: string): string { - return createHash('sha256').update(str).digest('hex') -} - -// Cache last few API requests for ant users (e.g., for /issue command) -const MAX_CACHED_REQUESTS = 5 -const cachedApiRequests: Array<{ timestamp: string; request: unknown }> = [] - -type DumpState = { - initialized: boolean - messageCountSeen: number - lastInitDataHash: string - // Cheap proxy for change detection — skips the expensive stringify+hash - // when model/tools/system are structurally identical to the last call. - lastInitFingerprint: string -} - -// Track state per session to avoid duplicating data -const dumpState = new Map() export function getLastApiRequests(): Array<{ timestamp: string request: unknown }> { - return [...cachedApiRequests] + return [] } -export function clearApiRequestCache(): void { - cachedApiRequests.length = 0 -} +export function clearApiRequestCache(): void {} -export function clearDumpState(agentIdOrSessionId: string): void { - dumpState.delete(agentIdOrSessionId) -} +export function clearDumpState(_agentIdOrSessionId?: string): void {} -export function clearAllDumpState(): void { - dumpState.clear() -} +export function clearAllDumpState(): void {} -export function addApiRequestToCache(requestData: unknown): void { - if (process.env.USER_TYPE !== 'ant') return - cachedApiRequests.push({ - timestamp: new Date().toISOString(), - request: requestData, - }) - if (cachedApiRequests.length > MAX_CACHED_REQUESTS) { - cachedApiRequests.shift() - } -} +export function addApiRequestToCache(_requestData: unknown): void {} -export function getDumpPromptsPath(agentIdOrSessionId?: string): string { - return join( - getClaudeConfigHomeDir(), - 'dump-prompts', - `${agentIdOrSessionId ?? getSessionId()}.jsonl`, - ) -} - -function appendToFile(filePath: string, entries: string[]): void { - if (entries.length === 0) return - fs.mkdir(dirname(filePath), { recursive: true }) - .then(() => fs.appendFile(filePath, entries.join('\n') + '\n')) - .catch(() => {}) -} - -function initFingerprint(req: Record): string { - const tools = req.tools as Array<{ name?: string }> | undefined - const system = req.system as unknown[] | string | undefined - const sysLen = - typeof system === 'string' - ? system.length - : Array.isArray(system) - ? system.reduce( - (n: number, b) => n + ((b as { text?: string }).text?.length ?? 0), - 0, - ) - : 0 - const toolNames = tools?.map(t => t.name ?? '').join(',') ?? '' - return `${req.model}|${toolNames}|${sysLen}` -} - -function dumpRequest( - body: string, - ts: string, - state: DumpState, - filePath: string, -): void { - try { - const req = jsonParse(body) as Record - addApiRequestToCache(req) - - if (process.env.USER_TYPE !== 'ant') return - const entries: string[] = [] - const messages = (req.messages ?? []) as Array<{ role?: string }> - - // Write init data (system, tools, metadata) on first request, - // and a system_update entry whenever it changes. - // Cheap fingerprint first: system+tools don't change between turns, - // so skip the 300ms stringify when the shape is unchanged. - const fingerprint = initFingerprint(req) - if (!state.initialized || fingerprint !== state.lastInitFingerprint) { - const { messages: _, ...initData } = req - const initDataStr = jsonStringify(initData) - const initDataHash = hashString(initDataStr) - state.lastInitFingerprint = fingerprint - if (!state.initialized) { - state.initialized = true - state.lastInitDataHash = initDataHash - // Reuse initDataStr rather than re-serializing initData inside a wrapper. - // timestamp from toISOString() contains no chars needing JSON escaping. - entries.push( - `{"type":"init","timestamp":"${ts}","data":${initDataStr}}`, - ) - } else if (initDataHash !== state.lastInitDataHash) { - state.lastInitDataHash = initDataHash - entries.push( - `{"type":"system_update","timestamp":"${ts}","data":${initDataStr}}`, - ) - } - } - - // Write only new user messages (assistant messages captured in response) - for (const msg of messages.slice(state.messageCountSeen)) { - if (msg.role === 'user') { - entries.push( - jsonStringify({ type: 'message', timestamp: ts, data: msg }), - ) - } - } - state.messageCountSeen = messages.length - - appendToFile(filePath, entries) - } catch { - // Ignore parsing errors - } +export function getDumpPromptsPath(_agentIdOrSessionId?: string): string { + return '' } export function createDumpPromptsFetch( - agentIdOrSessionId: string, + _agentIdOrSessionId: string, ): ClientOptions['fetch'] { - const filePath = getDumpPromptsPath(agentIdOrSessionId) - - return async (input: RequestInfo | URL, init?: RequestInit) => { - const state = dumpState.get(agentIdOrSessionId) ?? { - initialized: false, - messageCountSeen: 0, - lastInitDataHash: '', - lastInitFingerprint: '', - } - dumpState.set(agentIdOrSessionId, state) - - let timestamp: string | undefined - - if (init?.method === 'POST' && init.body) { - timestamp = new Date().toISOString() - // Parsing + stringifying the request (system prompt + tool schemas = MBs) - // takes hundreds of ms. Defer so it doesn't block the actual API call — - // this is debug tooling for /issue, not on the critical path. - setImmediate(dumpRequest, init.body as string, timestamp, state, filePath) - } - - // eslint-disable-next-line eslint-plugin-n/no-unsupported-features/node-builtins - const response = await globalThis.fetch(input, init) - - // Save response async - if (timestamp && response.ok && process.env.USER_TYPE === 'ant') { - const cloned = response.clone() - void (async () => { - try { - const isStreaming = cloned.headers - .get('content-type') - ?.includes('text/event-stream') - - let data: unknown - if (isStreaming && cloned.body) { - // Parse SSE stream into chunks - const reader = cloned.body.getReader() - const decoder = new TextDecoder() - let buffer = '' - try { - while (true) { - const { done, value } = await reader.read() - if (done) break - buffer += decoder.decode(value, { stream: true }) - } - } finally { - reader.releaseLock() - } - const chunks: unknown[] = [] - for (const event of buffer.split('\n\n')) { - for (const line of event.split('\n')) { - if (line.startsWith('data: ') && line !== 'data: [DONE]') { - try { - chunks.push(jsonParse(line.slice(6))) - } catch { - // Ignore parse errors - } - } - } - } - data = { stream: true, chunks } - } else { - data = await cloned.json() - } - - await fs.appendFile( - filePath, - jsonStringify({ type: 'response', timestamp, data }) + '\n', - ) - } catch { - // Best effort - } - })() - } - - return response - } + return undefined } diff --git a/src/services/internalLogging.ts b/src/services/internalLogging.ts index c70cad73..6f8650d9 100644 --- a/src/services/internalLogging.ts +++ b/src/services/internalLogging.ts @@ -1,90 +1,9 @@ -import { readFile } from 'fs/promises' -import memoize from 'lodash-es/memoize.js' -import type { ToolPermissionContext } from '../Tool.js' -import { jsonStringify } from '../utils/slowOperations.js' -import { - type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - logEvent, -} from './analytics/index.js' +export async function logPermissionContextForAnts(): Promise {} -/** - * Get the current Kubernetes namespace: - * Returns null on laptops/local development, - * "default" for devboxes in default namespace, - * "ts" for devboxes in ts namespace, - * ... - */ -const getKubernetesNamespace = memoize(async (): Promise => { - if (process.env.USER_TYPE !== 'ant') { - return null - } - const namespacePath = - '/var/run/secrets/kubernetes.io/serviceaccount/namespace' - const namespaceNotFound = 'namespace not found' - try { - const content = await readFile(namespacePath, { encoding: 'utf8' }) - return content.trim() - } catch { - return namespaceNotFound - } -}) - -/** - * Get the OCI container ID from within a running container - */ -export const getContainerId = memoize(async (): Promise => { - if (process.env.USER_TYPE !== 'ant') { - return null - } - const containerIdPath = '/proc/self/mountinfo' - const containerIdNotFound = 'container ID not found' - const containerIdNotFoundInMountinfo = 'container ID not found in mountinfo' - try { - const mountinfo = ( - await readFile(containerIdPath, { encoding: 'utf8' }) - ).trim() - - // Pattern to match both Docker and containerd/CRI-O container IDs - // Docker: /docker/containers/[64-char-hex] - // Containerd: /sandboxes/[64-char-hex] - const containerIdPattern = - /(?:\/docker\/containers\/|\/sandboxes\/)([0-9a-f]{64})/ - - const lines = mountinfo.split('\n') - - for (const line of lines) { - const match = line.match(containerIdPattern) - if (match && match[1]) { - return match[1] - } - } - - return containerIdNotFoundInMountinfo - } catch { - return containerIdNotFound - } -}) - -/** - * Logs an event with the current namespace and tool permission context - */ -export async function logPermissionContextForAnts( - toolPermissionContext: ToolPermissionContext | null, - moment: 'summary' | 'initialization', -): Promise { - if (process.env.USER_TYPE !== 'ant') { - return - } - - void logEvent('tengu_internal_record_permission_context', { - moment: - moment as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - namespace: - (await getKubernetesNamespace()) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - toolPermissionContext: jsonStringify( - toolPermissionContext, - ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - containerId: - (await getContainerId()) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - }) +export async function getKubernetesNamespace(): Promise { + return null +} + +export async function getContainerId(): Promise { + return null } diff --git a/src/skills/bundled/index.ts b/src/skills/bundled/index.ts index fdd9dde3..53db272c 100644 --- a/src/skills/bundled/index.ts +++ b/src/skills/bundled/index.ts @@ -8,7 +8,6 @@ import { registerLoremIpsumSkill } from './loremIpsum.js' import { registerRememberSkill } from './remember.js' import { registerSimplifySkill } from './simplify.js' import { registerSkillifySkill } from './skillify.js' -import { registerStuckSkill } from './stuck.js' import { registerUpdateConfigSkill } from './updateConfig.js' import { registerVerifySkill } from './verify.js' @@ -31,7 +30,6 @@ export function initBundledSkills(): void { registerRememberSkill() registerSimplifySkill() registerBatchSkill() - registerStuckSkill() if (feature('KAIROS') || feature('KAIROS_DREAM')) { /* eslint-disable @typescript-eslint/no-require-imports */ const { registerDreamSkill } = require('./dream.js') diff --git a/src/skills/bundled/stuck.ts b/src/skills/bundled/stuck.ts index ffb57ab2..670ebd92 100644 --- a/src/skills/bundled/stuck.ts +++ b/src/skills/bundled/stuck.ts @@ -1,79 +1 @@ -import { registerBundledSkill } from '../bundledSkills.js' - -// Prompt text contains `ps` commands as instructions for Claude to run, -// not commands this file executes. -// eslint-disable-next-line custom-rules/no-direct-ps-commands -const STUCK_PROMPT = `# /stuck — diagnose frozen/slow Claude Code sessions - -The user thinks another Claude Code session on this machine is frozen, stuck, or very slow. Investigate and post a report to #claude-code-feedback. - -## What to look for - -Scan for other Claude Code processes (excluding the current one — PID is in \`process.pid\` but for shell commands just exclude the PID you see running this prompt). Process names are typically \`claude\` (installed) or \`cli\` (native dev build). - -Signs of a stuck session: -- **High CPU (≥90%) sustained** — likely an infinite loop. Sample twice, 1-2s apart, to confirm it's not a transient spike. -- **Process state \`D\` (uninterruptible sleep)** — often an I/O hang. The \`state\` column in \`ps\` output; first character matters (ignore modifiers like \`+\`, \`s\`, \`<\`). -- **Process state \`T\` (stopped)** — user probably hit Ctrl+Z by accident. -- **Process state \`Z\` (zombie)** — parent isn't reaping. -- **Very high RSS (≥4GB)** — possible memory leak making the session sluggish. -- **Stuck child process** — a hung \`git\`, \`node\`, or shell subprocess can freeze the parent. Check \`pgrep -lP \` for each session. - -## Investigation steps - -1. **List all Claude Code processes** (macOS/Linux): - \`\`\` - ps -axo pid=,pcpu=,rss=,etime=,state=,comm=,command= | grep -E '(claude|cli)' | grep -v grep - \`\`\` - Filter to rows where \`comm\` is \`claude\` or (\`cli\` AND the command path contains "claude"). - -2. **For anything suspicious**, gather more context: - - Child processes: \`pgrep -lP \` - - If high CPU: sample again after 1-2s to confirm it's sustained - - If a child looks hung (e.g., a git command), note its full command line with \`ps -p -o command=\` - - Check the session's debug log if you can infer the session ID: \`~/.claude/debug/.txt\` (the last few hundred lines often show what it was doing before hanging) - -3. **Consider a stack dump** for a truly frozen process (advanced, optional): - - macOS: \`sample 3\` gives a 3-second native stack sample - - This is big — only grab it if the process is clearly hung and you want to know *why* - -## Report - -**Only post to Slack if you actually found something stuck.** If every session looks healthy, tell the user that directly — do not post an all-clear to the channel. - -If you did find a stuck/slow session, post to **#claude-code-feedback** (channel ID: \`C07VBSHV7EV\`) using the Slack MCP tool. Use ToolSearch to find \`slack_send_message\` if it's not already loaded. - -**Use a two-message structure** to keep the channel scannable: - -1. **Top-level message** — one short line: hostname, Claude Code version, and a terse symptom (e.g. "session PID 12345 pegged at 100% CPU for 10min" or "git subprocess hung in D state"). No code blocks, no details. -2. **Thread reply** — the full diagnostic dump. Pass the top-level message's \`ts\` as \`thread_ts\`. Include: - - PID, CPU%, RSS, state, uptime, command line, child processes - - Your diagnosis of what's likely wrong - - Relevant debug log tail or \`sample\` output if you captured it - -If Slack MCP isn't available, format the report as a message the user can copy-paste into #claude-code-feedback (and let them know to thread the details themselves). - -## Notes -- Don't kill or signal any processes — this is diagnostic only. -- If the user gave an argument (e.g., a specific PID or symptom), focus there first. -` - -export function registerStuckSkill(): void { - if (process.env.USER_TYPE !== 'ant') { - return - } - - registerBundledSkill({ - name: 'stuck', - description: - '[ANT-ONLY] Investigate frozen/stuck/slow Claude Code sessions on this machine and post a diagnostic report to #claude-code-feedback.', - userInvocable: true, - async getPromptForCommand(args) { - let prompt = STUCK_PROMPT - if (args) { - prompt += `\n## User-provided context\n\n${args}\n` - } - return [{ type: 'text', text: prompt }] - }, - }) -} +export function registerStuckSkill(): void {} diff --git a/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts b/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts index 16354b43..f97b41a2 100644 --- a/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +++ b/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts @@ -1,24 +1,13 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: events_mono/claude_code/v1/claude_code_internal_event.proto - /* eslint-disable */ -import { Timestamp } from '../../../google/protobuf/timestamp.js' -import { PublicApiAuth } from '../../common/v1/auth.js' -/** GitHubActionsMetadata contains GitHub Actions-specific environment information */ +import type { PublicApiAuth } from '../../common/v1/auth.js' + export interface GitHubActionsMetadata { actor_id?: string | undefined repository_id?: string | undefined repository_owner_id?: string | undefined } -/** - * EnvironmentMetadata contains environment and runtime information - * See claude-cli-internal/src/services/statsig.ts for the source of these fields - */ export interface EnvironmentMetadata { platform?: string | undefined node_version?: string | undefined @@ -32,14 +21,11 @@ export interface EnvironmentMetadata { is_claude_code_action?: boolean | undefined is_claude_ai_auth?: boolean | undefined version?: string | undefined - /** GitHub Actions specific fields (only present when is_github_action is true) */ github_event_name?: string | undefined github_actions_runner_environment?: string | undefined github_actions_runner_os?: string | undefined github_action_ref?: string | undefined - /** WSL specific field */ wsl_version?: string | undefined - /** GitHub metadata (only present when is_github_action is true) */ github_actions_metadata?: GitHubActionsMetadata | undefined arch?: string | undefined is_claude_code_remote?: boolean | undefined @@ -60,11 +46,6 @@ export interface EnvironmentMetadata { platform_raw?: string | undefined } -/** - * SlackContext contains context fields present on every Claude-in-Slack (CIS) event. - * Event-specific fields (errorType, durationMs, httpStatus, etc.) go in - * ClaudeCodeInternalEvent.additional_metadata as JSON. - */ export interface SlackContext { slack_team_id?: string | undefined is_enterprise_install?: boolean | undefined @@ -72,56 +53,31 @@ export interface SlackContext { creation_method?: string | undefined } -/** - * ClaudeCodeInternalEvent represents events logged from Claude Code via Statsig - * This schema matches the structure in claude-cli-internal/src/services/statsig.ts - * Source table: proj-product-data-nhme.raw_statsig_internal_tools.events - */ export interface ClaudeCodeInternalEvent { - /** Event name (e.g., "tengu_binary_feedback", "tengu_api_success") */ event_name?: string | undefined - /** Event timestamp */ client_timestamp?: Date | undefined model?: string | undefined session_id?: string | undefined user_type?: string | undefined betas?: string | undefined - /** Environment and runtime information */ env?: EnvironmentMetadata | undefined entrypoint?: string | undefined agent_sdk_version?: string | undefined is_interactive?: boolean | undefined client_type?: string | undefined - /** - * Process metrics as JSON string (ant-only) - * Contains: uptime, rss, heapTotal, heapUsed, external, arrayBuffers, - * constrainedMemory, cpuUsage - */ process?: string | undefined - /** - * Additional metadata passed to logEvent (event-specific) - * This includes fields like msg_id_A, msg_id_B, gitBranch, gitHead, etc. - * that vary per event type - */ additional_metadata?: string | undefined - /** Authentication context automatically injected by the API */ auth?: PublicApiAuth | undefined - /** Server timestamp automatically injected by the API */ server_timestamp?: Date | undefined - /** Unique identifier for this event (automatically generated by API endpoint) */ event_id?: string | undefined - /** Device identifier for the client */ device_id?: string | undefined - /** SWE-bench fields */ swe_bench_run_id?: string | undefined swe_bench_instance_id?: string | undefined swe_bench_task_id?: string | undefined email?: string | undefined - /** Swarm/team agent identification for analytics attribution */ agent_id?: string | undefined parent_session_id?: string | undefined agent_type?: string | undefined - /** Claude-in-Slack context (only present for cis_* events) */ slack?: SlackContext | undefined team_name?: string | undefined skill_name?: string | undefined @@ -129,737 +85,24 @@ export interface ClaudeCodeInternalEvent { marketplace_name?: string | undefined } -function createBaseGitHubActionsMetadata(): GitHubActionsMetadata { - return { actor_id: '', repository_id: '', repository_owner_id: '' } -} - -export const GitHubActionsMetadata: MessageFns = { - fromJSON(object: any): GitHubActionsMetadata { - return { - actor_id: isSet(object.actor_id) - ? globalThis.String(object.actor_id) - : '', - repository_id: isSet(object.repository_id) - ? globalThis.String(object.repository_id) - : '', - repository_owner_id: isSet(object.repository_owner_id) - ? globalThis.String(object.repository_owner_id) - : '', - } - }, - - toJSON(message: GitHubActionsMetadata): unknown { - const obj: any = {} - if (message.actor_id !== undefined) { - obj.actor_id = message.actor_id - } - if (message.repository_id !== undefined) { - obj.repository_id = message.repository_id - } - if (message.repository_owner_id !== undefined) { - obj.repository_owner_id = message.repository_owner_id - } - return obj - }, - - create, I>>( - base?: I, - ): GitHubActionsMetadata { - return GitHubActionsMetadata.fromPartial(base ?? ({} as any)) - }, - fromPartial, I>>( - object: I, - ): GitHubActionsMetadata { - const message = createBaseGitHubActionsMetadata() - message.actor_id = object.actor_id ?? '' - message.repository_id = object.repository_id ?? '' - message.repository_owner_id = object.repository_owner_id ?? '' - return message - }, -} - -function createBaseEnvironmentMetadata(): EnvironmentMetadata { - return { - platform: '', - node_version: '', - terminal: '', - package_managers: '', - runtimes: '', - is_running_with_bun: false, - is_ci: false, - is_claubbit: false, - is_github_action: false, - is_claude_code_action: false, - is_claude_ai_auth: false, - version: '', - github_event_name: '', - github_actions_runner_environment: '', - github_actions_runner_os: '', - github_action_ref: '', - wsl_version: '', - github_actions_metadata: undefined, - arch: '', - is_claude_code_remote: false, - remote_environment_type: '', - claude_code_container_id: '', - claude_code_remote_session_id: '', - tags: [], - deployment_environment: '', - is_conductor: false, - version_base: '', - coworker_type: '', - build_time: '', - is_local_agent_mode: false, - linux_distro_id: '', - linux_distro_version: '', - linux_kernel: '', - vcs: '', - platform_raw: '', - } -} - -export const EnvironmentMetadata: MessageFns = { - fromJSON(object: any): EnvironmentMetadata { - return { - platform: isSet(object.platform) - ? globalThis.String(object.platform) - : '', - node_version: isSet(object.node_version) - ? globalThis.String(object.node_version) - : '', - terminal: isSet(object.terminal) - ? globalThis.String(object.terminal) - : '', - package_managers: isSet(object.package_managers) - ? globalThis.String(object.package_managers) - : '', - runtimes: isSet(object.runtimes) - ? globalThis.String(object.runtimes) - : '', - is_running_with_bun: isSet(object.is_running_with_bun) - ? globalThis.Boolean(object.is_running_with_bun) - : false, - is_ci: isSet(object.is_ci) ? globalThis.Boolean(object.is_ci) : false, - is_claubbit: isSet(object.is_claubbit) - ? globalThis.Boolean(object.is_claubbit) - : false, - is_github_action: isSet(object.is_github_action) - ? globalThis.Boolean(object.is_github_action) - : false, - is_claude_code_action: isSet(object.is_claude_code_action) - ? globalThis.Boolean(object.is_claude_code_action) - : false, - is_claude_ai_auth: isSet(object.is_claude_ai_auth) - ? globalThis.Boolean(object.is_claude_ai_auth) - : false, - version: isSet(object.version) ? globalThis.String(object.version) : '', - github_event_name: isSet(object.github_event_name) - ? globalThis.String(object.github_event_name) - : '', - github_actions_runner_environment: isSet( - object.github_actions_runner_environment, - ) - ? globalThis.String(object.github_actions_runner_environment) - : '', - github_actions_runner_os: isSet(object.github_actions_runner_os) - ? globalThis.String(object.github_actions_runner_os) - : '', - github_action_ref: isSet(object.github_action_ref) - ? globalThis.String(object.github_action_ref) - : '', - wsl_version: isSet(object.wsl_version) - ? globalThis.String(object.wsl_version) - : '', - github_actions_metadata: isSet(object.github_actions_metadata) - ? GitHubActionsMetadata.fromJSON(object.github_actions_metadata) - : undefined, - arch: isSet(object.arch) ? globalThis.String(object.arch) : '', - is_claude_code_remote: isSet(object.is_claude_code_remote) - ? globalThis.Boolean(object.is_claude_code_remote) - : false, - remote_environment_type: isSet(object.remote_environment_type) - ? globalThis.String(object.remote_environment_type) - : '', - claude_code_container_id: isSet(object.claude_code_container_id) - ? globalThis.String(object.claude_code_container_id) - : '', - claude_code_remote_session_id: isSet(object.claude_code_remote_session_id) - ? globalThis.String(object.claude_code_remote_session_id) - : '', - tags: globalThis.Array.isArray(object?.tags) - ? object.tags.map((e: any) => globalThis.String(e)) - : [], - deployment_environment: isSet(object.deployment_environment) - ? globalThis.String(object.deployment_environment) - : '', - is_conductor: isSet(object.is_conductor) - ? globalThis.Boolean(object.is_conductor) - : false, - version_base: isSet(object.version_base) - ? globalThis.String(object.version_base) - : '', - coworker_type: isSet(object.coworker_type) - ? globalThis.String(object.coworker_type) - : '', - build_time: isSet(object.build_time) - ? globalThis.String(object.build_time) - : '', - is_local_agent_mode: isSet(object.is_local_agent_mode) - ? globalThis.Boolean(object.is_local_agent_mode) - : false, - linux_distro_id: isSet(object.linux_distro_id) - ? globalThis.String(object.linux_distro_id) - : '', - linux_distro_version: isSet(object.linux_distro_version) - ? globalThis.String(object.linux_distro_version) - : '', - linux_kernel: isSet(object.linux_kernel) - ? globalThis.String(object.linux_kernel) - : '', - vcs: isSet(object.vcs) ? globalThis.String(object.vcs) : '', - platform_raw: isSet(object.platform_raw) - ? globalThis.String(object.platform_raw) - : '', - } - }, - - toJSON(message: EnvironmentMetadata): unknown { - const obj: any = {} - if (message.platform !== undefined) { - obj.platform = message.platform - } - if (message.node_version !== undefined) { - obj.node_version = message.node_version - } - if (message.terminal !== undefined) { - obj.terminal = message.terminal - } - if (message.package_managers !== undefined) { - obj.package_managers = message.package_managers - } - if (message.runtimes !== undefined) { - obj.runtimes = message.runtimes - } - if (message.is_running_with_bun !== undefined) { - obj.is_running_with_bun = message.is_running_with_bun - } - if (message.is_ci !== undefined) { - obj.is_ci = message.is_ci - } - if (message.is_claubbit !== undefined) { - obj.is_claubbit = message.is_claubbit - } - if (message.is_github_action !== undefined) { - obj.is_github_action = message.is_github_action - } - if (message.is_claude_code_action !== undefined) { - obj.is_claude_code_action = message.is_claude_code_action - } - if (message.is_claude_ai_auth !== undefined) { - obj.is_claude_ai_auth = message.is_claude_ai_auth - } - if (message.version !== undefined) { - obj.version = message.version - } - if (message.github_event_name !== undefined) { - obj.github_event_name = message.github_event_name - } - if (message.github_actions_runner_environment !== undefined) { - obj.github_actions_runner_environment = - message.github_actions_runner_environment - } - if (message.github_actions_runner_os !== undefined) { - obj.github_actions_runner_os = message.github_actions_runner_os - } - if (message.github_action_ref !== undefined) { - obj.github_action_ref = message.github_action_ref - } - if (message.wsl_version !== undefined) { - obj.wsl_version = message.wsl_version - } - if (message.github_actions_metadata !== undefined) { - obj.github_actions_metadata = GitHubActionsMetadata.toJSON( - message.github_actions_metadata, - ) - } - if (message.arch !== undefined) { - obj.arch = message.arch - } - if (message.is_claude_code_remote !== undefined) { - obj.is_claude_code_remote = message.is_claude_code_remote - } - if (message.remote_environment_type !== undefined) { - obj.remote_environment_type = message.remote_environment_type - } - if (message.claude_code_container_id !== undefined) { - obj.claude_code_container_id = message.claude_code_container_id - } - if (message.claude_code_remote_session_id !== undefined) { - obj.claude_code_remote_session_id = message.claude_code_remote_session_id - } - if (message.tags?.length) { - obj.tags = message.tags - } - if (message.deployment_environment !== undefined) { - obj.deployment_environment = message.deployment_environment - } - if (message.is_conductor !== undefined) { - obj.is_conductor = message.is_conductor - } - if (message.version_base !== undefined) { - obj.version_base = message.version_base - } - if (message.coworker_type !== undefined) { - obj.coworker_type = message.coworker_type - } - if (message.build_time !== undefined) { - obj.build_time = message.build_time - } - if (message.is_local_agent_mode !== undefined) { - obj.is_local_agent_mode = message.is_local_agent_mode - } - if (message.linux_distro_id !== undefined) { - obj.linux_distro_id = message.linux_distro_id - } - if (message.linux_distro_version !== undefined) { - obj.linux_distro_version = message.linux_distro_version - } - if (message.linux_kernel !== undefined) { - obj.linux_kernel = message.linux_kernel - } - if (message.vcs !== undefined) { - obj.vcs = message.vcs - } - if (message.platform_raw !== undefined) { - obj.platform_raw = message.platform_raw - } - return obj - }, - - create, I>>( - base?: I, - ): EnvironmentMetadata { - return EnvironmentMetadata.fromPartial(base ?? ({} as any)) - }, - fromPartial, I>>( - object: I, - ): EnvironmentMetadata { - const message = createBaseEnvironmentMetadata() - message.platform = object.platform ?? '' - message.node_version = object.node_version ?? '' - message.terminal = object.terminal ?? '' - message.package_managers = object.package_managers ?? '' - message.runtimes = object.runtimes ?? '' - message.is_running_with_bun = object.is_running_with_bun ?? false - message.is_ci = object.is_ci ?? false - message.is_claubbit = object.is_claubbit ?? false - message.is_github_action = object.is_github_action ?? false - message.is_claude_code_action = object.is_claude_code_action ?? false - message.is_claude_ai_auth = object.is_claude_ai_auth ?? false - message.version = object.version ?? '' - message.github_event_name = object.github_event_name ?? '' - message.github_actions_runner_environment = - object.github_actions_runner_environment ?? '' - message.github_actions_runner_os = object.github_actions_runner_os ?? '' - message.github_action_ref = object.github_action_ref ?? '' - message.wsl_version = object.wsl_version ?? '' - message.github_actions_metadata = - object.github_actions_metadata !== undefined && - object.github_actions_metadata !== null - ? GitHubActionsMetadata.fromPartial(object.github_actions_metadata) - : undefined - message.arch = object.arch ?? '' - message.is_claude_code_remote = object.is_claude_code_remote ?? false - message.remote_environment_type = object.remote_environment_type ?? '' - message.claude_code_container_id = object.claude_code_container_id ?? '' - message.claude_code_remote_session_id = - object.claude_code_remote_session_id ?? '' - message.tags = object.tags?.map(e => e) || [] - message.deployment_environment = object.deployment_environment ?? '' - message.is_conductor = object.is_conductor ?? false - message.version_base = object.version_base ?? '' - message.coworker_type = object.coworker_type ?? '' - message.build_time = object.build_time ?? '' - message.is_local_agent_mode = object.is_local_agent_mode ?? false - message.linux_distro_id = object.linux_distro_id ?? '' - message.linux_distro_version = object.linux_distro_version ?? '' - message.linux_kernel = object.linux_kernel ?? '' - message.vcs = object.vcs ?? '' - message.platform_raw = object.platform_raw ?? '' - return message - }, -} - -function createBaseSlackContext(): SlackContext { - return { - slack_team_id: '', - is_enterprise_install: false, - trigger: '', - creation_method: '', - } -} - -export const SlackContext: MessageFns = { - fromJSON(object: any): SlackContext { - return { - slack_team_id: isSet(object.slack_team_id) - ? globalThis.String(object.slack_team_id) - : '', - is_enterprise_install: isSet(object.is_enterprise_install) - ? globalThis.Boolean(object.is_enterprise_install) - : false, - trigger: isSet(object.trigger) ? globalThis.String(object.trigger) : '', - creation_method: isSet(object.creation_method) - ? globalThis.String(object.creation_method) - : '', - } - }, - - toJSON(message: SlackContext): unknown { - const obj: any = {} - if (message.slack_team_id !== undefined) { - obj.slack_team_id = message.slack_team_id - } - if (message.is_enterprise_install !== undefined) { - obj.is_enterprise_install = message.is_enterprise_install - } - if (message.trigger !== undefined) { - obj.trigger = message.trigger - } - if (message.creation_method !== undefined) { - obj.creation_method = message.creation_method - } - return obj - }, - - create, I>>( - base?: I, - ): SlackContext { - return SlackContext.fromPartial(base ?? ({} as any)) - }, - fromPartial, I>>( - object: I, - ): SlackContext { - const message = createBaseSlackContext() - message.slack_team_id = object.slack_team_id ?? '' - message.is_enterprise_install = object.is_enterprise_install ?? false - message.trigger = object.trigger ?? '' - message.creation_method = object.creation_method ?? '' - return message - }, -} - -function createBaseClaudeCodeInternalEvent(): ClaudeCodeInternalEvent { - return { - event_name: '', - client_timestamp: undefined, - model: '', - session_id: '', - user_type: '', - betas: '', - env: undefined, - entrypoint: '', - agent_sdk_version: '', - is_interactive: false, - client_type: '', - process: '', - additional_metadata: '', - auth: undefined, - server_timestamp: undefined, - event_id: '', - device_id: '', - swe_bench_run_id: '', - swe_bench_instance_id: '', - swe_bench_task_id: '', - email: '', - agent_id: '', - parent_session_id: '', - agent_type: '', - slack: undefined, - team_name: '', - skill_name: '', - plugin_name: '', - marketplace_name: '', - } -} - -export const ClaudeCodeInternalEvent: MessageFns = { +export const ClaudeCodeInternalEvent = { fromJSON(object: any): ClaudeCodeInternalEvent { - return { - event_name: isSet(object.event_name) - ? globalThis.String(object.event_name) - : '', - client_timestamp: isSet(object.client_timestamp) - ? fromJsonTimestamp(object.client_timestamp) - : undefined, - model: isSet(object.model) ? globalThis.String(object.model) : '', - session_id: isSet(object.session_id) - ? globalThis.String(object.session_id) - : '', - user_type: isSet(object.user_type) - ? globalThis.String(object.user_type) - : '', - betas: isSet(object.betas) ? globalThis.String(object.betas) : '', - env: isSet(object.env) - ? EnvironmentMetadata.fromJSON(object.env) - : undefined, - entrypoint: isSet(object.entrypoint) - ? globalThis.String(object.entrypoint) - : '', - agent_sdk_version: isSet(object.agent_sdk_version) - ? globalThis.String(object.agent_sdk_version) - : '', - is_interactive: isSet(object.is_interactive) - ? globalThis.Boolean(object.is_interactive) - : false, - client_type: isSet(object.client_type) - ? globalThis.String(object.client_type) - : '', - process: isSet(object.process) ? globalThis.String(object.process) : '', - additional_metadata: isSet(object.additional_metadata) - ? globalThis.String(object.additional_metadata) - : '', - auth: isSet(object.auth) - ? PublicApiAuth.fromJSON(object.auth) - : undefined, - server_timestamp: isSet(object.server_timestamp) - ? fromJsonTimestamp(object.server_timestamp) - : undefined, - event_id: isSet(object.event_id) - ? globalThis.String(object.event_id) - : '', - device_id: isSet(object.device_id) - ? globalThis.String(object.device_id) - : '', - swe_bench_run_id: isSet(object.swe_bench_run_id) - ? globalThis.String(object.swe_bench_run_id) - : '', - swe_bench_instance_id: isSet(object.swe_bench_instance_id) - ? globalThis.String(object.swe_bench_instance_id) - : '', - swe_bench_task_id: isSet(object.swe_bench_task_id) - ? globalThis.String(object.swe_bench_task_id) - : '', - email: isSet(object.email) ? globalThis.String(object.email) : '', - agent_id: isSet(object.agent_id) - ? globalThis.String(object.agent_id) - : '', - parent_session_id: isSet(object.parent_session_id) - ? globalThis.String(object.parent_session_id) - : '', - agent_type: isSet(object.agent_type) - ? globalThis.String(object.agent_type) - : '', - slack: isSet(object.slack) - ? SlackContext.fromJSON(object.slack) - : undefined, - team_name: isSet(object.team_name) - ? globalThis.String(object.team_name) - : '', - skill_name: isSet(object.skill_name) - ? globalThis.String(object.skill_name) - : '', - plugin_name: isSet(object.plugin_name) - ? globalThis.String(object.plugin_name) - : '', - marketplace_name: isSet(object.marketplace_name) - ? globalThis.String(object.marketplace_name) - : '', - } + return object ?? {} }, toJSON(message: ClaudeCodeInternalEvent): unknown { - const obj: any = {} - if (message.event_name !== undefined) { - obj.event_name = message.event_name - } - if (message.client_timestamp !== undefined) { - obj.client_timestamp = message.client_timestamp.toISOString() - } - if (message.model !== undefined) { - obj.model = message.model - } - if (message.session_id !== undefined) { - obj.session_id = message.session_id - } - if (message.user_type !== undefined) { - obj.user_type = message.user_type - } - if (message.betas !== undefined) { - obj.betas = message.betas - } - if (message.env !== undefined) { - obj.env = EnvironmentMetadata.toJSON(message.env) - } - if (message.entrypoint !== undefined) { - obj.entrypoint = message.entrypoint - } - if (message.agent_sdk_version !== undefined) { - obj.agent_sdk_version = message.agent_sdk_version - } - if (message.is_interactive !== undefined) { - obj.is_interactive = message.is_interactive - } - if (message.client_type !== undefined) { - obj.client_type = message.client_type - } - if (message.process !== undefined) { - obj.process = message.process - } - if (message.additional_metadata !== undefined) { - obj.additional_metadata = message.additional_metadata - } - if (message.auth !== undefined) { - obj.auth = PublicApiAuth.toJSON(message.auth) - } - if (message.server_timestamp !== undefined) { - obj.server_timestamp = message.server_timestamp.toISOString() - } - if (message.event_id !== undefined) { - obj.event_id = message.event_id - } - if (message.device_id !== undefined) { - obj.device_id = message.device_id - } - if (message.swe_bench_run_id !== undefined) { - obj.swe_bench_run_id = message.swe_bench_run_id - } - if (message.swe_bench_instance_id !== undefined) { - obj.swe_bench_instance_id = message.swe_bench_instance_id - } - if (message.swe_bench_task_id !== undefined) { - obj.swe_bench_task_id = message.swe_bench_task_id - } - if (message.email !== undefined) { - obj.email = message.email - } - if (message.agent_id !== undefined) { - obj.agent_id = message.agent_id - } - if (message.parent_session_id !== undefined) { - obj.parent_session_id = message.parent_session_id - } - if (message.agent_type !== undefined) { - obj.agent_type = message.agent_type - } - if (message.slack !== undefined) { - obj.slack = SlackContext.toJSON(message.slack) - } - if (message.team_name !== undefined) { - obj.team_name = message.team_name - } - if (message.skill_name !== undefined) { - obj.skill_name = message.skill_name - } - if (message.plugin_name !== undefined) { - obj.plugin_name = message.plugin_name - } - if (message.marketplace_name !== undefined) { - obj.marketplace_name = message.marketplace_name - } - return obj + return message ?? {} }, - create, I>>( + create( base?: I, ): ClaudeCodeInternalEvent { - return ClaudeCodeInternalEvent.fromPartial(base ?? ({} as any)) + return base ?? {} }, - fromPartial, I>>( + + fromPartial( object: I, ): ClaudeCodeInternalEvent { - const message = createBaseClaudeCodeInternalEvent() - message.event_name = object.event_name ?? '' - message.client_timestamp = object.client_timestamp ?? undefined - message.model = object.model ?? '' - message.session_id = object.session_id ?? '' - message.user_type = object.user_type ?? '' - message.betas = object.betas ?? '' - message.env = - object.env !== undefined && object.env !== null - ? EnvironmentMetadata.fromPartial(object.env) - : undefined - message.entrypoint = object.entrypoint ?? '' - message.agent_sdk_version = object.agent_sdk_version ?? '' - message.is_interactive = object.is_interactive ?? false - message.client_type = object.client_type ?? '' - message.process = object.process ?? '' - message.additional_metadata = object.additional_metadata ?? '' - message.auth = - object.auth !== undefined && object.auth !== null - ? PublicApiAuth.fromPartial(object.auth) - : undefined - message.server_timestamp = object.server_timestamp ?? undefined - message.event_id = object.event_id ?? '' - message.device_id = object.device_id ?? '' - message.swe_bench_run_id = object.swe_bench_run_id ?? '' - message.swe_bench_instance_id = object.swe_bench_instance_id ?? '' - message.swe_bench_task_id = object.swe_bench_task_id ?? '' - message.email = object.email ?? '' - message.agent_id = object.agent_id ?? '' - message.parent_session_id = object.parent_session_id ?? '' - message.agent_type = object.agent_type ?? '' - message.slack = - object.slack !== undefined && object.slack !== null - ? SlackContext.fromPartial(object.slack) - : undefined - message.team_name = object.team_name ?? '' - message.skill_name = object.skill_name ?? '' - message.plugin_name = object.plugin_name ?? '' - message.marketplace_name = object.marketplace_name ?? '' - return message + return object ?? {} }, } - -type Builtin = - | Date - | Function - | Uint8Array - | string - | number - | boolean - | undefined - -type DeepPartial = T extends Builtin - ? T - : T extends globalThis.Array - ? globalThis.Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} - ? { [K in keyof T]?: DeepPartial } - : Partial - -type KeysOfUnion = T extends T ? keyof T : never -type Exact = P extends Builtin - ? P - : P & { [K in keyof P]: Exact } & { - [K in Exclude>]: never - } - -function fromTimestamp(t: Timestamp): Date { - let millis = (t.seconds || 0) * 1_000 - millis += (t.nanos || 0) / 1_000_000 - return new globalThis.Date(millis) -} - -function fromJsonTimestamp(o: any): Date { - if (o instanceof globalThis.Date) { - return o - } else if (typeof o === 'string') { - return new globalThis.Date(o) - } else { - return fromTimestamp(Timestamp.fromJSON(o)) - } -} - -function isSet(value: any): boolean { - return value !== null && value !== undefined -} - -interface MessageFns { - fromJSON(object: any): T - toJSON(message: T): unknown - create, I>>(base?: I): T - fromPartial, I>>(object: I): T -} diff --git a/src/types/generated/events_mono/common/v1/auth.ts b/src/types/generated/events_mono/common/v1/auth.ts index cf4cb6dd..a66d0b5f 100644 --- a/src/types/generated/events_mono/common/v1/auth.ts +++ b/src/types/generated/events_mono/common/v1/auth.ts @@ -1,100 +1,25 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: events_mono/common/v1/auth.proto - /* eslint-disable */ -/** PublicApiAuth contains authentication context automatically injected by the API */ export interface PublicApiAuth { account_id?: number | undefined organization_uuid?: string | undefined account_uuid?: string | undefined } -function createBasePublicApiAuth(): PublicApiAuth { - return { account_id: 0, organization_uuid: '', account_uuid: '' } -} - -export const PublicApiAuth: MessageFns = { +export const PublicApiAuth = { fromJSON(object: any): PublicApiAuth { - return { - account_id: isSet(object.account_id) - ? globalThis.Number(object.account_id) - : 0, - organization_uuid: isSet(object.organization_uuid) - ? globalThis.String(object.organization_uuid) - : '', - account_uuid: isSet(object.account_uuid) - ? globalThis.String(object.account_uuid) - : '', - } + return object ?? {} }, toJSON(message: PublicApiAuth): unknown { - const obj: any = {} - if (message.account_id !== undefined) { - obj.account_id = Math.round(message.account_id) - } - if (message.organization_uuid !== undefined) { - obj.organization_uuid = message.organization_uuid - } - if (message.account_uuid !== undefined) { - obj.account_uuid = message.account_uuid - } - return obj + return message ?? {} }, - create, I>>( - base?: I, - ): PublicApiAuth { - return PublicApiAuth.fromPartial(base ?? ({} as any)) + create(base?: I): PublicApiAuth { + return base ?? {} }, - fromPartial, I>>( - object: I, - ): PublicApiAuth { - const message = createBasePublicApiAuth() - message.account_id = object.account_id ?? 0 - message.organization_uuid = object.organization_uuid ?? '' - message.account_uuid = object.account_uuid ?? '' - return message + + fromPartial(object: I): PublicApiAuth { + return object ?? {} }, } - -type Builtin = - | Date - | Function - | Uint8Array - | string - | number - | boolean - | undefined - -type DeepPartial = T extends Builtin - ? T - : T extends globalThis.Array - ? globalThis.Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} - ? { [K in keyof T]?: DeepPartial } - : Partial - -type KeysOfUnion = T extends T ? keyof T : never -type Exact = P extends Builtin - ? P - : P & { [K in keyof P]: Exact } & { - [K in Exclude>]: never - } - -function isSet(value: any): boolean { - return value !== null && value !== undefined -} - -interface MessageFns { - fromJSON(object: any): T - toJSON(message: T): unknown - create, I>>(base?: I): T - fromPartial, I>>(object: I): T -} diff --git a/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts b/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts index fbda5119..28cc73da 100644 --- a/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +++ b/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts @@ -1,223 +1,40 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: events_mono/growthbook/v1/growthbook_experiment_event.proto - /* eslint-disable */ -import { Timestamp } from '../../../google/protobuf/timestamp.js' -import { PublicApiAuth } from '../../common/v1/auth.js' -/** - * GrowthBook experiment assignment event - * This event tracks when a user is exposed to an experiment variant - * See: https://docs.growthbook.io/guide/bigquery - */ +import type { PublicApiAuth } from '../../common/v1/auth.js' + export interface GrowthbookExperimentEvent { - /** Unique event identifier (for deduplication) */ event_id?: string | undefined - /** When user was exposed to experiment (maps to GrowthBook's timestamp column) */ timestamp?: Date | undefined - /** Experiment tracking key (maps to GrowthBook's experiment_id column) */ experiment_id?: string | undefined - /** Variation index: 0=control, 1+=variants (maps to GrowthBook's variation_id column) */ variation_id?: number | undefined - /** Environment where assignment occurred */ environment?: string | undefined - /** User attributes at time of assignment */ user_attributes?: string | undefined - /** Experiment metadata */ experiment_metadata?: string | undefined - /** Device identifier for the client */ device_id?: string | undefined - /** Authentication context automatically injected by the API */ auth?: PublicApiAuth | undefined - /** Session identifier for tracking user sessions */ session_id?: string | undefined - /** Anonymous identifier for unauthenticated users */ anonymous_id?: string | undefined - /** Event metadata variables (automatically populated by internal-tools-common event_logging library) */ event_metadata_vars?: string | undefined } -function createBaseGrowthbookExperimentEvent(): GrowthbookExperimentEvent { - return { - event_id: '', - timestamp: undefined, - experiment_id: '', - variation_id: 0, - environment: '', - user_attributes: '', - experiment_metadata: '', - device_id: '', - auth: undefined, - session_id: '', - anonymous_id: '', - event_metadata_vars: '', - } -} - -export const GrowthbookExperimentEvent: MessageFns = - { - fromJSON(object: any): GrowthbookExperimentEvent { - return { - event_id: isSet(object.event_id) - ? globalThis.String(object.event_id) - : '', - timestamp: isSet(object.timestamp) - ? fromJsonTimestamp(object.timestamp) - : undefined, - experiment_id: isSet(object.experiment_id) - ? globalThis.String(object.experiment_id) - : '', - variation_id: isSet(object.variation_id) - ? globalThis.Number(object.variation_id) - : 0, - environment: isSet(object.environment) - ? globalThis.String(object.environment) - : '', - user_attributes: isSet(object.user_attributes) - ? globalThis.String(object.user_attributes) - : '', - experiment_metadata: isSet(object.experiment_metadata) - ? globalThis.String(object.experiment_metadata) - : '', - device_id: isSet(object.device_id) - ? globalThis.String(object.device_id) - : '', - auth: isSet(object.auth) - ? PublicApiAuth.fromJSON(object.auth) - : undefined, - session_id: isSet(object.session_id) - ? globalThis.String(object.session_id) - : '', - anonymous_id: isSet(object.anonymous_id) - ? globalThis.String(object.anonymous_id) - : '', - event_metadata_vars: isSet(object.event_metadata_vars) - ? globalThis.String(object.event_metadata_vars) - : '', - } - }, - - toJSON(message: GrowthbookExperimentEvent): unknown { - const obj: any = {} - if (message.event_id !== undefined) { - obj.event_id = message.event_id - } - if (message.timestamp !== undefined) { - obj.timestamp = message.timestamp.toISOString() - } - if (message.experiment_id !== undefined) { - obj.experiment_id = message.experiment_id - } - if (message.variation_id !== undefined) { - obj.variation_id = Math.round(message.variation_id) - } - if (message.environment !== undefined) { - obj.environment = message.environment - } - if (message.user_attributes !== undefined) { - obj.user_attributes = message.user_attributes - } - if (message.experiment_metadata !== undefined) { - obj.experiment_metadata = message.experiment_metadata - } - if (message.device_id !== undefined) { - obj.device_id = message.device_id - } - if (message.auth !== undefined) { - obj.auth = PublicApiAuth.toJSON(message.auth) - } - if (message.session_id !== undefined) { - obj.session_id = message.session_id - } - if (message.anonymous_id !== undefined) { - obj.anonymous_id = message.anonymous_id - } - if (message.event_metadata_vars !== undefined) { - obj.event_metadata_vars = message.event_metadata_vars - } - return obj - }, - - create, I>>( - base?: I, - ): GrowthbookExperimentEvent { - return GrowthbookExperimentEvent.fromPartial(base ?? ({} as any)) - }, - fromPartial, I>>( - object: I, - ): GrowthbookExperimentEvent { - const message = createBaseGrowthbookExperimentEvent() - message.event_id = object.event_id ?? '' - message.timestamp = object.timestamp ?? undefined - message.experiment_id = object.experiment_id ?? '' - message.variation_id = object.variation_id ?? 0 - message.environment = object.environment ?? '' - message.user_attributes = object.user_attributes ?? '' - message.experiment_metadata = object.experiment_metadata ?? '' - message.device_id = object.device_id ?? '' - message.auth = - object.auth !== undefined && object.auth !== null - ? PublicApiAuth.fromPartial(object.auth) - : undefined - message.session_id = object.session_id ?? '' - message.anonymous_id = object.anonymous_id ?? '' - message.event_metadata_vars = object.event_metadata_vars ?? '' - return message - }, - } - -type Builtin = - | Date - | Function - | Uint8Array - | string - | number - | boolean - | undefined - -type DeepPartial = T extends Builtin - ? T - : T extends globalThis.Array - ? globalThis.Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} - ? { [K in keyof T]?: DeepPartial } - : Partial - -type KeysOfUnion = T extends T ? keyof T : never -type Exact = P extends Builtin - ? P - : P & { [K in keyof P]: Exact } & { - [K in Exclude>]: never - } - -function fromTimestamp(t: Timestamp): Date { - let millis = (t.seconds || 0) * 1_000 - millis += (t.nanos || 0) / 1_000_000 - return new globalThis.Date(millis) -} - -function fromJsonTimestamp(o: any): Date { - if (o instanceof globalThis.Date) { - return o - } else if (typeof o === 'string') { - return new globalThis.Date(o) - } else { - return fromTimestamp(Timestamp.fromJSON(o)) - } -} - -function isSet(value: any): boolean { - return value !== null && value !== undefined -} - -interface MessageFns { - fromJSON(object: any): T - toJSON(message: T): unknown - create, I>>(base?: I): T - fromPartial, I>>(object: I): T +export const GrowthbookExperimentEvent = { + fromJSON(object: any): GrowthbookExperimentEvent { + return object ?? {} + }, + + toJSON(message: GrowthbookExperimentEvent): unknown { + return message ?? {} + }, + + create( + base?: I, + ): GrowthbookExperimentEvent { + return base ?? {} + }, + + fromPartial( + object: I, + ): GrowthbookExperimentEvent { + return object ?? {} + }, } diff --git a/src/types/generated/google/protobuf/timestamp.ts b/src/types/generated/google/protobuf/timestamp.ts index 1d8b268d..927ce64a 100644 --- a/src/types/generated/google/protobuf/timestamp.ts +++ b/src/types/generated/google/protobuf/timestamp.ts @@ -1,187 +1,19 @@ -// Code generated by protoc-gen-ts_proto. DO NOT EDIT. -// versions: -// protoc-gen-ts_proto v2.6.1 -// protoc unknown -// source: google/protobuf/timestamp.proto - /* eslint-disable */ -/** - * A Timestamp represents a point in time independent of any time zone or local - * calendar, encoded as a count of seconds and fractions of seconds at - * nanosecond resolution. The count is relative to an epoch at UTC midnight on - * January 1, 1970, in the proleptic Gregorian calendar which extends the - * Gregorian calendar backwards to year one. - * - * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap - * second table is needed for interpretation, using a [24-hour linear - * smear](https://developers.google.com/time/smear). - * - * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By - * restricting to that range, we ensure that we can convert to and from [RFC - * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. - * - * # Examples - * - * Example 1: Compute Timestamp from POSIX `time()`. - * - * Timestamp timestamp; - * timestamp.set_seconds(time(NULL)); - * timestamp.set_nanos(0); - * - * Example 2: Compute Timestamp from POSIX `gettimeofday()`. - * - * struct timeval tv; - * gettimeofday(&tv, NULL); - * - * Timestamp timestamp; - * timestamp.set_seconds(tv.tv_sec); - * timestamp.set_nanos(tv.tv_usec * 1000); - * - * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. - * - * FILETIME ft; - * GetSystemTimeAsFileTime(&ft); - * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; - * - * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z - * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. - * Timestamp timestamp; - * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); - * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); - * - * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. - * - * long millis = System.currentTimeMillis(); - * - * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) - * .setNanos((int) ((millis % 1000) * 1000000)).build(); - * - * Example 5: Compute Timestamp from Java `Instant.now()`. - * - * Instant now = Instant.now(); - * - * Timestamp timestamp = - * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) - * .setNanos(now.getNano()).build(); - * - * Example 6: Compute Timestamp from current time in Python. - * - * timestamp = Timestamp() - * timestamp.GetCurrentTime() - * - * # JSON Mapping - * - * In JSON format, the Timestamp type is encoded as a string in the - * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the - * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" - * where {year} is always expressed using four digits while {month}, {day}, - * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional - * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), - * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone - * is required. A proto3 JSON serializer should always use UTC (as indicated by - * "Z") when printing the Timestamp type and a proto3 JSON parser should be - * able to accept both UTC and other timezones (as indicated by an offset). - * - * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past - * 01:30 UTC on January 15, 2017. - * - * In JavaScript, one can convert a Date object to this format using the - * standard - * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) - * method. In Python, a standard `datetime.datetime` object can be converted - * to this format using - * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with - * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use - * the Joda Time's [`ISODateTimeFormat.dateTime()`]( - * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() - * ) to obtain a formatter capable of generating timestamps in this format. - */ -export interface Timestamp { - /** - * Represents seconds of UTC time since Unix epoch - * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - * 9999-12-31T23:59:59Z inclusive. - */ - seconds?: number | undefined - /** - * Non-negative fractions of a second at nanosecond resolution. Negative - * second values with fractions must still have non-negative nanos values - * that count forward in time. Must be from 0 to 999,999,999 - * inclusive. - */ - nanos?: number | undefined -} - -function createBaseTimestamp(): Timestamp { - return { seconds: 0, nanos: 0 } -} - -export const Timestamp: MessageFns = { - fromJSON(object: any): Timestamp { - return { - seconds: isSet(object.seconds) ? globalThis.Number(object.seconds) : 0, - nanos: isSet(object.nanos) ? globalThis.Number(object.nanos) : 0, - } +export const Timestamp = { + fromJSON(object: any): any { + return object }, - toJSON(message: Timestamp): unknown { - const obj: any = {} - if (message.seconds !== undefined) { - obj.seconds = Math.round(message.seconds) - } - if (message.nanos !== undefined) { - obj.nanos = Math.round(message.nanos) - } - return obj + toJSON(message: any): unknown { + return message ?? {} }, - create, I>>(base?: I): Timestamp { - return Timestamp.fromPartial(base ?? ({} as any)) + create(base?: T): T | {} { + return base ?? {} }, - fromPartial, I>>( - object: I, - ): Timestamp { - const message = createBaseTimestamp() - message.seconds = object.seconds ?? 0 - message.nanos = object.nanos ?? 0 - return message + + fromPartial(object: T): T { + return object }, } - -type Builtin = - | Date - | Function - | Uint8Array - | string - | number - | boolean - | undefined - -type DeepPartial = T extends Builtin - ? T - : T extends globalThis.Array - ? globalThis.Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} - ? { [K in keyof T]?: DeepPartial } - : Partial - -type KeysOfUnion = T extends T ? keyof T : never -type Exact = P extends Builtin - ? P - : P & { [K in keyof P]: Exact } & { - [K in Exclude>]: never - } - -function isSet(value: any): boolean { - return value !== null && value !== undefined -} - -interface MessageFns { - fromJSON(object: any): T - toJSON(message: T): unknown - create, I>>(base?: I): T - fromPartial, I>>(object: I): T -} diff --git a/src/utils/ide.ts b/src/utils/ide.ts index fe6d55d7..418458f8 100644 --- a/src/utils/ide.ts +++ b/src/utils/ide.ts @@ -1390,6 +1390,12 @@ const detectHostIP = memoize( ) async function installFromArtifactory(command: string): Promise { + const artifactoryBaseUrl = + process.env.CLAUDE_CODE_INTERNAL_ARTIFACTORY_BASE_URL + if (!artifactoryBaseUrl) { + throw new Error('Internal artifactory base URL is not configured') + } + const npmrcAuthPrefix = `//${artifactoryBaseUrl.replace(/^https?:\/\//, '')}/api/npm/npm-all/:_authToken=` // Read auth token from ~/.npmrc const npmrcPath = join(os.homedir(), '.npmrc') let authToken: string | null = null @@ -1402,11 +1408,8 @@ async function installFromArtifactory(command: string): Promise { const lines = npmrcContent.split('\n') for (const line of lines) { // Look for the artifactory auth token line - const match = line.match( - /\/\/artifactory\.infra\.ant\.dev\/artifactory\/api\/npm\/npm-all\/:_authToken=(.+)/, - ) - if (match && match[1]) { - authToken = match[1].trim() + if (line.startsWith(npmrcAuthPrefix)) { + authToken = line.slice(npmrcAuthPrefix.length).trim() break } } @@ -1420,8 +1423,7 @@ async function installFromArtifactory(command: string): Promise { } // Fetch the version from artifactory - const versionUrl = - 'https://artifactory.infra.ant.dev/artifactory/armorcode-claude-code-internal/claude-vscode-releases/stable' + const versionUrl = `${artifactoryBaseUrl}/armorcode-claude-code-internal/claude-vscode-releases/stable` try { const versionResponse = await axios.get(versionUrl, { @@ -1436,7 +1438,7 @@ async function installFromArtifactory(command: string): Promise { } // Download the .vsix file from artifactory - const vsixUrl = `https://artifactory.infra.ant.dev/artifactory/armorcode-claude-code-internal/claude-vscode-releases/${version}/claude-code.vsix` + const vsixUrl = `${artifactoryBaseUrl}/armorcode-claude-code-internal/claude-vscode-releases/${version}/claude-code.vsix` const tempVsixPath = join( os.tmpdir(), `claude-code-${version}-${Date.now()}.vsix`, diff --git a/src/utils/nativeInstaller/download.ts b/src/utils/nativeInstaller/download.ts index fa11e670..71316bcf 100644 --- a/src/utils/nativeInstaller/download.ts +++ b/src/utils/nativeInstaller/download.ts @@ -25,11 +25,14 @@ import { getBinaryName, getPlatform } from './installer.js' const GCS_BUCKET_URL = 'https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases' export const ARTIFACTORY_REGISTRY_URL = - 'https://artifactory.infra.ant.dev/artifactory/api/npm/npm-all/' + process.env.CLAUDE_CODE_INTERNAL_ARTIFACTORY_REGISTRY_URL ?? '' export async function getLatestVersionFromArtifactory( tag: string = 'latest', ): Promise { + if (!ARTIFACTORY_REGISTRY_URL) { + throw new Error('Internal artifactory registry URL is not configured') + } const startTime = Date.now() const { stdout, code, stderr } = await execFileNoThrowWithCwd( 'npm', @@ -152,6 +155,9 @@ export async function downloadVersionFromArtifactory( version: string, stagingPath: string, ) { + if (!ARTIFACTORY_REGISTRY_URL) { + throw new Error('Internal artifactory registry URL is not configured') + } const fs = getFsImplementation() // If we get here, we own the lock and can delete a partial download diff --git a/src/utils/permissions/permissionSetup.ts b/src/utils/permissions/permissionSetup.ts index 8520da84..3d9143b0 100644 --- a/src/utils/permissions/permissionSetup.ts +++ b/src/utils/permissions/permissionSetup.ts @@ -1059,9 +1059,7 @@ export function getAutoModeUnavailableNotification( base = 'auto mode unavailable for this model' break } - return process.env.USER_TYPE === 'ant' - ? `${base} · #claude-code-feedback` - : base + return base } /** diff --git a/src/utils/undercover.ts b/src/utils/undercover.ts index 6b04f867..bcbc89ab 100644 --- a/src/utils/undercover.ts +++ b/src/utils/undercover.ts @@ -1,89 +1,11 @@ -/** - * Undercover mode — safety utilities for contributing to public/open-source repos. - * - * When active, Claude Code adds safety instructions to commit/PR prompts and - * strips all attribution to avoid leaking internal model codenames, project - * names, or other Anthropic-internal information. The model is not told what - * model it is. - * - * Activation: - * - CLAUDE_CODE_UNDERCOVER=1 — force ON (even in internal repos) - * - Otherwise AUTO: active UNLESS the repo remote matches the internal - * allowlist (INTERNAL_MODEL_REPOS in commitAttribution.ts). Safe default - * is ON — Claude may push to public remotes from a CWD that isn't itself - * a git checkout (e.g. /tmp crash repro). - * - There is NO force-OFF. This guards against model codename leaks — if - * we're not confident we're in an internal repo, we stay undercover. - * - * All code paths are gated on process.env.USER_TYPE === 'ant'. Since USER_TYPE is - * a build-time --define, the bundler constant-folds these checks and dead-code- - * eliminates the ant-only branches from external builds. In external builds every - * function in this file reduces to a trivial return. - */ - -import { getRepoClassCached } from './commitAttribution.js' -import { getGlobalConfig } from './config.js' -import { isEnvTruthy } from './envUtils.js' - export function isUndercover(): boolean { - if (process.env.USER_TYPE === 'ant') { - if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return true - // Auto: active unless we've positively confirmed we're in an allowlisted - // internal repo. 'external', 'none', and null (check not yet run) all - // resolve to ON. The check is primed in setup.ts; only 'internal' → OFF. - return getRepoClassCached() !== 'internal' - } return false } export function getUndercoverInstructions(): string { - if (process.env.USER_TYPE === 'ant') { - return `## UNDERCOVER MODE — CRITICAL - -You are operating UNDERCOVER in a PUBLIC/OPEN-SOURCE repository. Your commit -messages, PR titles, and PR bodies MUST NOT contain ANY Anthropic-internal -information. Do not blow your cover. - -NEVER include in commit messages or PR descriptions: -- Internal model codenames (animal names like Capybara, Tengu, etc.) -- Unreleased model version numbers (e.g., opus-4-7, sonnet-4-8) -- Internal repo or project names (e.g., claude-cli-internal, anthropics/…) -- Internal tooling, Slack channels, or short links (e.g., go/cc, #claude-code-…) -- The phrase "Claude Code" or any mention that you are an AI -- Any hint of what model or version you are -- Co-Authored-By lines or any other attribution - -Write commit messages as a human developer would — describe only what the code -change does. - -GOOD: -- "Fix race condition in file watcher initialization" -- "Add support for custom key bindings" -- "Refactor parser for better error messages" - -BAD (never write these): -- "Fix bug found while testing with Claude Capybara" -- "1-shotted by claude-opus-4-6" -- "Generated with Claude Code" -- "Co-Authored-By: Claude Opus 4.6 <…>" -` - } return '' } -/** - * Check whether to show the one-time explainer dialog for auto-undercover. - * True when: undercover is active via auto-detection (not forced via env), - * and the user hasn't seen the notice before. Pure — the component marks the - * flag on mount. - */ export function shouldShowUndercoverAutoNotice(): boolean { - if (process.env.USER_TYPE === 'ant') { - // If forced via env, user already knows; don't nag. - if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return false - if (!isUndercover()) return false - if (getGlobalConfig().hasSeenUndercoverAutoNotice) return false - return true - } return false }