source dump of claude code
at main 90 lines 2.8 kB view raw
1import { readFile } from 'fs/promises' 2import memoize from 'lodash-es/memoize.js' 3import type { ToolPermissionContext } from '../Tool.js' 4import { jsonStringify } from '../utils/slowOperations.js' 5import { 6 type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 7 logEvent, 8} from './analytics/index.js' 9 10/** 11 * Get the current Kubernetes namespace: 12 * Returns null on laptops/local development, 13 * "default" for devboxes in default namespace, 14 * "ts" for devboxes in ts namespace, 15 * ... 16 */ 17const getKubernetesNamespace = memoize(async (): Promise<string | null> => { 18 if (process.env.USER_TYPE !== 'ant') { 19 return null 20 } 21 const namespacePath = 22 '/var/run/secrets/kubernetes.io/serviceaccount/namespace' 23 const namespaceNotFound = 'namespace not found' 24 try { 25 const content = await readFile(namespacePath, { encoding: 'utf8' }) 26 return content.trim() 27 } catch { 28 return namespaceNotFound 29 } 30}) 31 32/** 33 * Get the OCI container ID from within a running container 34 */ 35export const getContainerId = memoize(async (): Promise<string | null> => { 36 if (process.env.USER_TYPE !== 'ant') { 37 return null 38 } 39 const containerIdPath = '/proc/self/mountinfo' 40 const containerIdNotFound = 'container ID not found' 41 const containerIdNotFoundInMountinfo = 'container ID not found in mountinfo' 42 try { 43 const mountinfo = ( 44 await readFile(containerIdPath, { encoding: 'utf8' }) 45 ).trim() 46 47 // Pattern to match both Docker and containerd/CRI-O container IDs 48 // Docker: /docker/containers/[64-char-hex] 49 // Containerd: /sandboxes/[64-char-hex] 50 const containerIdPattern = 51 /(?:\/docker\/containers\/|\/sandboxes\/)([0-9a-f]{64})/ 52 53 const lines = mountinfo.split('\n') 54 55 for (const line of lines) { 56 const match = line.match(containerIdPattern) 57 if (match && match[1]) { 58 return match[1] 59 } 60 } 61 62 return containerIdNotFoundInMountinfo 63 } catch { 64 return containerIdNotFound 65 } 66}) 67 68/** 69 * Logs an event with the current namespace and tool permission context 70 */ 71export async function logPermissionContextForAnts( 72 toolPermissionContext: ToolPermissionContext | null, 73 moment: 'summary' | 'initialization', 74): Promise<void> { 75 if (process.env.USER_TYPE !== 'ant') { 76 return 77 } 78 79 void logEvent('tengu_internal_record_permission_context', { 80 moment: 81 moment as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 82 namespace: 83 (await getKubernetesNamespace()) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 84 toolPermissionContext: jsonStringify( 85 toolPermissionContext, 86 ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 87 containerId: 88 (await getContainerId()) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 89 }) 90}