spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / mods / telemetry / hooks / telemetry-of / telemetry-of.ts
80 lines · 2.2 KBRaw
1import Entries from '../entries'
2import { isAnalyticsOff } from '../is-analytics-off'
3import type { TelemetryDeps } from '../telemetry-deps'
4import type TelemetryTypes from '../telemetry-types'
5
6/**
7 * Builds `$.telemetry`: `log` and `mark` check the entry, authorize once, build
8 * the first-party row and POST it to the ingest.
9 *
10 * One POST per call, none batched, one attempt; a session with no credential to
11 * authorize, or an ingest that refuses, rejects the caller's promise. A failed
12 * authorize or environment read is not memoized, so a later call retries it.
13 *
14 * @param deps the calls on the nouns beneath
15 * @returns the `$.telemetry` interface, `log` and `mark`, each authorizing once
16 * (memoized) before it posts
17 */
18export function telemetryOf(deps: TelemetryDeps): TelemetryTypes.Telemetry {
19 let held: ReturnType<TelemetryDeps['authorize']> | undefined
20 let read: ReturnType<TelemetryDeps['environment']> | undefined
21
22 async function post(
23 fields: Entries.Fields,
24 method: TelemetryTypes.Method,
25 ): Promise<void> {
26 read ??= deps.environment().catch((error: unknown) => {
27 read = undefined
28
29 throw error
30 })
31 const environment = await read
32
33 if (isAnalyticsOff(environment)) {
34 return
35 }
36
37 if (!held) {
38 held = deps.authorize().catch((error: unknown) => {
39 held = undefined
40
41 throw error
42 })
43 }
44
45 const auth = await held
46
47 if (!auth) {
48 held = undefined
49
50 throw Entries.refusal(
51 'this session has no first-party credential to authorize',
52 method,
53 )
54 }
55
56 const body = Entries.batchOf(fields, {
57 sessionId: await deps.id(),
58 model: await deps.model(),
59 userType: environment.userType === 'ant' ? 'ant' : 'external',
60 })
61 const response = await deps.fetch(Entries.INGEST_URL, {
62 method: 'POST',
63 headers: {
64 'Content-Type': 'application/json',
65 'x-service-name': 'claude-code',
66 },
67 auth: auth.handle,
68 body,
69 })
70
71 if (!response.ok) {
72 throw Entries.refusal(`the ingest answered ${response.status}`, method)
73 }
74 }
75
76 return {
77 log: async entry => post(Entries.checkedFields(entry), 'log'),
78 mark: async entry => post(Entries.checkedMark(entry), 'mark'),
79 }
80}