ummaya 0.2.9 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/npm-shrinkwrap.json +2 -2
  2. package/package.json +1 -1
  3. package/pyproject.toml +2 -2
  4. package/tui/package.json +1 -1
  5. package/tui/src/bridge/bridgeEnabled.ts +1 -1
  6. package/tui/src/commands/chrome/chrome.tsx +3 -4
  7. package/tui/src/commands/createMovedToPluginCommand.ts +1 -1
  8. package/tui/src/commands/extra-usage/extra-usage-core.ts +2 -4
  9. package/tui/src/commands/insights.ts +5 -4
  10. package/tui/src/commands/install-github-app/ApiKeyStep.tsx +1 -2
  11. package/tui/src/commands/install-github-app/CheckExistingSecretStep.tsx +3 -3
  12. package/tui/src/commands/install-github-app/ExistingWorkflowStep.tsx +3 -3
  13. package/tui/src/commands/install-github-app/InstallAppStep.tsx +1 -1
  14. package/tui/src/commands/install-github-app/SuccessStep.tsx +2 -10
  15. package/tui/src/commands/install-github-app/install-github-app.tsx +21 -22
  16. package/tui/src/commands/install-github-app/setupGitHubActions.ts +21 -27
  17. package/tui/src/commands/install-slack-app/install-slack-app.ts +1 -1
  18. package/tui/src/commands/mobile/mobile.tsx +3 -3
  19. package/tui/src/commands/stickers/stickers.ts +1 -1
  20. package/tui/src/commands/upgrade/upgrade.tsx +3 -4
  21. package/tui/src/components/ClaudeInChromeOnboarding.tsx +2 -3
  22. package/tui/src/components/Feedback.tsx +8 -2
  23. package/tui/src/components/FeedbackSurvey/submitTranscriptShare.ts +7 -2
  24. package/tui/src/components/Passes/Passes.tsx +1 -1
  25. package/tui/src/components/WorkflowMultiselectDialog.tsx +3 -3
  26. package/tui/src/components/messages/AssistantTextMessage.tsx +1 -2
  27. package/tui/src/constants/github-app.ts +26 -38
  28. package/tui/src/constants/oauth.ts +28 -59
  29. package/tui/src/constants/product.ts +6 -6
  30. package/tui/src/entrypoints/sdk/coreSchemas.ts +1 -1
  31. package/tui/src/services/analytics/firstPartyEventLogger.ts +0 -3
  32. package/tui/src/services/analytics/firstPartyEventLoggingExporter.ts +34 -12
  33. package/tui/src/services/analytics/growthbook.ts +17 -16
  34. package/tui/src/services/api/filesApi.ts +4 -14
  35. package/tui/src/services/api/metricsOptOut.ts +20 -1
  36. package/tui/src/services/mcp/channelNotification.ts +1 -1
  37. package/tui/src/services/mcp/officialRegistry.ts +5 -1
  38. package/tui/src/services/mcp/useManageMCPConnections.ts +1 -1
  39. package/tui/src/services/mcp/utils.ts +2 -2
  40. package/tui/src/services/tokenEstimation.ts +0 -1
  41. package/tui/src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts +6 -6
  42. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +1 -1
  43. package/tui/src/tools/RemoteTriggerTool/RemoteTriggerTool.ts +1 -1
  44. package/tui/src/tools/RemoteTriggerTool/prompt.ts +2 -2
  45. package/tui/src/tools/WebFetchTool/preapproved.ts +0 -4
  46. package/tui/src/tools/WebFetchTool/utils.ts +15 -11
  47. package/tui/src/upstreamproxy/upstreamproxy.ts +9 -15
  48. package/tui/src/utils/autoUpdater.ts +4 -1
  49. package/tui/src/utils/claudeInChrome/mcpServer.ts +1 -1
  50. package/tui/src/utils/claudeInChrome/setup.ts +1 -1
  51. package/tui/src/utils/claudeInChrome/toolRendering.tsx +1 -2
  52. package/tui/src/utils/desktopDeepLink.ts +18 -18
  53. package/tui/src/utils/fastMode.ts +1 -1
  54. package/tui/src/utils/http.ts +1 -6
  55. package/tui/src/utils/ide.ts +6 -5
  56. package/tui/src/utils/model/providers.ts +6 -10
  57. package/tui/src/utils/modelCost.ts +0 -2
  58. package/tui/src/utils/nativeInstaller/download.ts +15 -17
  59. package/tui/src/utils/plugins/installCounts.ts +4 -11
  60. package/tui/src/utils/plugins/officialMarketplaceGcs.ts +5 -18
  61. package/tui/src/utils/releaseNotes.ts +2 -2
  62. package/tui/src/utils/settings/types.ts +1 -1
  63. package/tui/src/utils/statusNoticeDefinitions.tsx +3 -3
  64. package/tui/src/utils/telemetry/bigqueryExporter.ts +20 -13
  65. package/uv.lock +1 -1
@@ -28,12 +28,12 @@ function isDevMode(): boolean {
28
28
  }
29
29
 
30
30
  /**
31
- * Builds a deep link URL for Claude Desktop to resume a CLI session.
32
- * Format: claude://resume?session={sessionId}&cwd={cwd}
33
- * In dev mode: claude-dev://resume?session={sessionId}&cwd={cwd}
31
+ * Builds a deep link URL for UMMAYA Desktop to resume a CLI session.
32
+ * Format: ummaya://resume?session={sessionId}&cwd={cwd}
33
+ * In dev mode: ummaya-dev://resume?session={sessionId}&cwd={cwd}
34
34
  */
35
35
  function buildDesktopDeepLink(sessionId: string): string {
36
- const protocol = isDevMode() ? 'claude-dev' : 'claude'
36
+ const protocol = isDevMode() ? 'ummaya-dev' : 'ummaya'
37
37
  const url = new URL(`${protocol}://resume`)
38
38
  url.searchParams.set('session', sessionId)
39
39
  url.searchParams.set('cwd', getCwd())
@@ -41,9 +41,9 @@ function buildDesktopDeepLink(sessionId: string): string {
41
41
  }
42
42
 
43
43
  /**
44
- * Check if Claude Desktop app is installed.
45
- * On macOS, checks for /Applications/Claude.app.
46
- * On Linux, checks if xdg-open can handle claude:// protocol.
44
+ * Check if UMMAYA Desktop app is installed.
45
+ * On macOS, checks for /Applications/UMMAYA.app.
46
+ * On Linux, checks if xdg-open can handle ummaya:// protocol.
47
47
  * On Windows, checks if the protocol handler exists.
48
48
  * In dev mode, always returns true (assumes dev Desktop is running).
49
49
  */
@@ -56,22 +56,22 @@ async function isDesktopInstalled(): Promise<boolean> {
56
56
  const platform = process.platform
57
57
 
58
58
  if (platform === 'darwin') {
59
- // Check for Claude.app in /Applications
60
- return pathExists('/Applications/Claude.app')
59
+ // Check for UMMAYA.app in /Applications
60
+ return pathExists('/Applications/UMMAYA.app')
61
61
  } else if (platform === 'linux') {
62
- // Check if xdg-mime can find a handler for claude://
62
+ // Check if xdg-mime can find a handler for ummaya://
63
63
  // Note: xdg-mime returns exit code 0 even with no handler, so check stdout too
64
64
  const { code, stdout } = await execFileNoThrow('xdg-mime', [
65
65
  'query',
66
66
  'default',
67
- 'x-scheme-handler/claude',
67
+ 'x-scheme-handler/ummaya',
68
68
  ])
69
69
  return code === 0 && stdout.trim().length > 0
70
70
  } else if (platform === 'win32') {
71
71
  // On Windows, try to query the registry for the protocol handler
72
72
  const { code } = await execFileNoThrow('reg', [
73
73
  'query',
74
- 'HKEY_CLASSES_ROOT\\claude',
74
+ 'HKEY_CLASSES_ROOT\\ummaya',
75
75
  '/ve',
76
76
  ])
77
77
  return code === 0
@@ -81,7 +81,7 @@ async function isDesktopInstalled(): Promise<boolean> {
81
81
  }
82
82
 
83
83
  /**
84
- * Detect the installed Claude Desktop version.
84
+ * Detect the installed UMMAYA Desktop version.
85
85
  * On macOS, reads CFBundleShortVersionString from the app plist.
86
86
  * On Windows, finds the highest app-X.Y.Z directory in the Squirrel install.
87
87
  * Returns null if version cannot be determined.
@@ -92,7 +92,7 @@ async function getDesktopVersion(): Promise<string | null> {
92
92
  if (platform === 'darwin') {
93
93
  const { code, stdout } = await execFileNoThrow('defaults', [
94
94
  'read',
95
- '/Applications/Claude.app/Contents/Info.plist',
95
+ '/Applications/UMMAYA.app/Contents/Info.plist',
96
96
  'CFBundleShortVersionString',
97
97
  ])
98
98
  if (code !== 0) {
@@ -105,7 +105,7 @@ async function getDesktopVersion(): Promise<string | null> {
105
105
  if (!localAppData) {
106
106
  return null
107
107
  }
108
- const installDir = join(localAppData, 'AnthropicClaude')
108
+ const installDir = join(localAppData, 'UMMAYA')
109
109
  try {
110
110
  const entries = await readdir(installDir)
111
111
  const versions = entries
@@ -200,7 +200,7 @@ async function openDeepLink(deepLinkUrl: string): Promise<boolean> {
200
200
  }
201
201
 
202
202
  /**
203
- * Build and open a deep link to resume the current session in Claude Desktop.
203
+ * Build and open a deep link to resume the current session in UMMAYA Desktop.
204
204
  * Returns an object with success status and any error message.
205
205
  */
206
206
  export async function openCurrentSessionInDesktop(): Promise<{
@@ -216,7 +216,7 @@ export async function openCurrentSessionInDesktop(): Promise<{
216
216
  return {
217
217
  success: false,
218
218
  error:
219
- 'Claude Desktop is not installed. Install it from https://claude.ai/download',
219
+ 'UMMAYA Desktop is not installed. See https://ummaya-docs.pages.dev/ for setup instructions.',
220
220
  }
221
221
  }
222
222
 
@@ -227,7 +227,7 @@ export async function openCurrentSessionInDesktop(): Promise<{
227
227
  if (!opened) {
228
228
  return {
229
229
  success: false,
230
- error: 'Failed to open Claude Desktop. Please try opening it manually.',
230
+ error: 'Failed to open UMMAYA Desktop. Please try opening it manually.',
231
231
  deepLinkUrl,
232
232
  }
233
233
  }
@@ -90,7 +90,7 @@ export function getFastModeUnavailableReason(): string | null {
90
90
  !isInBundledMode() &&
91
91
  getFeatureValue_CACHED_MAY_BE_STALE('tengu_marble_sandcastle', false)
92
92
  ) {
93
- return 'Fast mode requires the native binary · Install from: https://claude.com/product/claude-code'
93
+ return 'Fast mode requires the native UMMAYA binary · Install from: https://ummaya-docs.pages.dev/'
94
94
  }
95
95
 
96
96
  // Not available in the SDK unless explicitly opted in via --settings.
@@ -10,7 +10,6 @@ import {
10
10
  handleOAuth401Error,
11
11
  isClaudeAISubscriber,
12
12
  } from './auth.js'
13
- import { getClaudeCodeUserAgent } from './userAgent.js'
14
13
  import { getWorkload } from './workloadContext.js'
15
14
 
16
15
  // WARNING: We rely on `claude-cli` in the user agent for log filtering.
@@ -49,12 +48,8 @@ export function getMCPUserAgent(): string {
49
48
  return `claude-code/${MACRO.VERSION}${suffix}`
50
49
  }
51
50
 
52
- // User-Agent for WebFetch requests to arbitrary sites. `Claude-User` is
53
- // Anthropic's publicly documented agent for user-initiated fetches (what site
54
- // operators match in robots.txt); the claude-code suffix lets them distinguish
55
- // local CLI traffic from claude.ai server-side fetches.
56
51
  export function getWebFetchUserAgent(): string {
57
- return `Claude-User (${getClaudeCodeUserAgent()}; +https://support.anthropic.com/)`
52
+ return `UMMAYA-User (ummaya/${MACRO.VERSION}; +https://ummaya-docs.pages.dev/)`
58
53
  }
59
54
 
60
55
  export type AuthHeaders = {
@@ -1419,9 +1419,11 @@ async function installFromArtifactory(command: string): Promise<string> {
1419
1419
  throw new Error('No artifactory auth token found in ~/.npmrc')
1420
1420
  }
1421
1421
 
1422
- // Fetch the version from artifactory
1423
- const versionUrl =
1424
- 'https://artifactory.infra.ant.dev/artifactory/armorcode-claude-code-internal/claude-vscode-releases/stable'
1422
+ const vsixBaseUrl = process.env.UMMAYA_VSCODE_EXTENSION_BASE_URL?.trim()
1423
+ if (!vsixBaseUrl) {
1424
+ throw new Error('UMMAYA_VSCODE_EXTENSION_BASE_URL is not configured')
1425
+ }
1426
+ const versionUrl = `${vsixBaseUrl}/stable`
1425
1427
 
1426
1428
  try {
1427
1429
  const versionResponse = await axios.get(versionUrl, {
@@ -1435,8 +1437,7 @@ async function installFromArtifactory(command: string): Promise<string> {
1435
1437
  throw new Error('No version found in artifactory response')
1436
1438
  }
1437
1439
 
1438
- // Download the .vsix file from artifactory
1439
- const vsixUrl = `https://artifactory.infra.ant.dev/artifactory/armorcode-claude-code-internal/claude-vscode-releases/${version}/claude-code.vsix`
1440
+ const vsixUrl = `${vsixBaseUrl}/${version}/ummaya.vsix`
1440
1441
  const tempVsixPath = join(
1441
1442
  os.tmpdir(),
1442
1443
  `claude-code-${version}-${Date.now()}.vsix`,
@@ -17,22 +17,18 @@ export function getAPIProviderForStatsig(): AnalyticsMetadata_I_VERIFIED_THIS_IS
17
17
  return getAPIProvider() as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
18
18
  }
19
19
 
20
- /**
21
- * Check if ANTHROPIC_BASE_URL is a first-party Anthropic API URL.
22
- * Returns true if not set (default API) or points to api.anthropic.com
23
- * (or api-staging.anthropic.com for ant users).
24
- */
20
+ /** Check if ANTHROPIC_BASE_URL points to an operator-approved first-party API. */
25
21
  export function isFirstPartyAnthropicBaseUrl(): boolean {
26
22
  const baseUrl = process.env.ANTHROPIC_BASE_URL
27
23
  if (!baseUrl) {
28
- return true
24
+ return false
29
25
  }
30
26
  try {
31
27
  const host = new URL(baseUrl).host
32
- const allowedHosts = ['api.anthropic.com']
33
- if (process.env.USER_TYPE === 'ant') {
34
- allowedHosts.push('api-staging.anthropic.com')
35
- }
28
+ const allowedHosts = (process.env.UMMAYA_FIRST_PARTY_API_HOSTS ?? '')
29
+ .split(',')
30
+ .map(value => value.trim())
31
+ .filter(Boolean)
36
32
  return allowedHosts.includes(host)
37
33
  } catch {
38
34
  return false
@@ -23,7 +23,6 @@ import {
23
23
  type ModelShortName,
24
24
  } from './model/model.js'
25
25
 
26
- // @see https://platform.claude.com/docs/en/about-claude/pricing
27
26
  export type ModelCosts = {
28
27
  inputTokens: number
29
28
  outputTokens: number
@@ -99,7 +98,6 @@ export function getOpus46CostTier(fastMode: boolean): ModelCosts {
99
98
  }
100
99
 
101
100
  // @[MODEL LAUNCH]: Add a pricing entry for the new model below.
102
- // Costs from https://platform.claude.com/docs/en/about-claude/pricing
103
101
  // Web search cost: $10 per 1000 requests = $0.01 per request
104
102
  export const MODEL_COSTS: Record<ModelShortName, ModelCosts> = {
105
103
  [firstPartyNameToCanonical(CLAUDE_3_5_HAIKU_CONFIG.firstParty)]:
@@ -1,11 +1,3 @@
1
- /**
2
- * Download functionality for native installer
3
- *
4
- * Handles downloading Claude binaries from various sources:
5
- * - Artifactory NPM packages
6
- * - GCS bucket
7
- */
8
-
9
1
  import { feature } from 'bun:bundle'
10
2
  import axios from 'axios'
11
3
  import { createHash } from 'crypto'
@@ -23,9 +15,10 @@ import { jsonStringify, writeFileSync_DEPRECATED } from '../slowOperations.js'
23
15
  import { getBinaryName, getPlatform } from './installer.js'
24
16
 
25
17
  const GCS_BUCKET_URL =
26
- 'https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases'
18
+ process.env.UMMAYA_NATIVE_DOWNLOAD_BASE_URL?.trim()
27
19
  export const ARTIFACTORY_REGISTRY_URL =
28
- 'https://artifactory.infra.ant.dev/artifactory/api/npm/npm-all/'
20
+ process.env.UMMAYA_NATIVE_NPM_REGISTRY_URL?.trim() ??
21
+ 'https://registry.npmjs.org/'
29
22
 
30
23
  export async function getLatestVersionFromArtifactory(
31
24
  tag: string = 'latest',
@@ -144,7 +137,9 @@ export async function getLatestVersion(
144
137
  return getLatestVersionFromArtifactory(npmTag)
145
138
  }
146
139
 
147
- // Use GCS for external users
140
+ if (!GCS_BUCKET_URL) {
141
+ throw new Error('UMMAYA_NATIVE_DOWNLOAD_BASE_URL is not configured')
142
+ }
148
143
  return getLatestVersionFromBinaryRepo(channel, GCS_BUCKET_URL)
149
144
  }
150
145
 
@@ -488,11 +483,12 @@ export async function downloadVersion(
488
483
  version: string,
489
484
  stagingPath: string,
490
485
  ): Promise<'npm' | 'binary'> {
491
- // Test-fixture versions route to the private sentinel bucket. DCE'd in all
492
- // shipped builds — the string 'claude-code-ci-sentinel' and the gcloud call
493
- // never exist in compiled binaries. Same gcloud-token pattern as
494
- // remoteSkillLoader.ts:175-195.
495
486
  if (feature('ALLOW_TEST_VERSIONS') && /^99\.99\./.test(version)) {
487
+ const testDownloadBaseUrl =
488
+ process.env.UMMAYA_NATIVE_TEST_DOWNLOAD_BASE_URL?.trim()
489
+ if (!testDownloadBaseUrl) {
490
+ throw new Error('UMMAYA_NATIVE_TEST_DOWNLOAD_BASE_URL is not configured')
491
+ }
496
492
  const { stdout } = await execFileNoThrowWithCwd('gcloud', [
497
493
  'auth',
498
494
  'print-access-token',
@@ -500,7 +496,7 @@ export async function downloadVersion(
500
496
  await downloadVersionFromBinaryRepo(
501
497
  version,
502
498
  stagingPath,
503
- 'https://storage.googleapis.com/claude-code-ci-sentinel',
499
+ testDownloadBaseUrl,
504
500
  { headers: { Authorization: `Bearer ${stdout.trim()}` } },
505
501
  )
506
502
  return 'binary'
@@ -512,7 +508,9 @@ export async function downloadVersion(
512
508
  return 'npm'
513
509
  }
514
510
 
515
- // Use GCS for external users
511
+ if (!GCS_BUCKET_URL) {
512
+ throw new Error('UMMAYA_NATIVE_DOWNLOAD_BASE_URL is not configured')
513
+ }
516
514
  await downloadVersionFromBinaryRepo(version, stagingPath, GCS_BUCKET_URL)
517
515
  return 'binary'
518
516
  }
@@ -1,13 +1,3 @@
1
- /**
2
- * Plugin install counts data layer
3
- *
4
- * This module fetches and caches plugin install counts from the official
5
- * Claude plugins statistics repository. The cache is refreshed if older
6
- * than 24 hours.
7
- *
8
- * Cache location: ~/.claude/plugins/install-counts-cache.json
9
- */
10
-
11
1
  import axios from 'axios'
12
2
  import { randomBytes } from 'crypto'
13
3
  import { readFile, rename, unlink, writeFile } from 'fs/promises'
@@ -23,7 +13,7 @@ import { getPluginsDirectory } from './pluginDirectories.js'
23
13
  const INSTALL_COUNTS_CACHE_VERSION = 1
24
14
  const INSTALL_COUNTS_CACHE_FILENAME = 'install-counts-cache.json'
25
15
  const INSTALL_COUNTS_URL =
26
- 'https://raw.githubusercontent.com/anthropics/claude-plugins-official/refs/heads/stats/stats/plugin-installs.json'
16
+ process.env.UMMAYA_PLUGIN_INSTALL_COUNTS_URL?.trim()
27
17
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
28
18
 
29
19
  /**
@@ -184,6 +174,9 @@ async function saveInstallCountsCache(
184
174
  async function fetchInstallCountsFromGitHub(): Promise<
185
175
  Array<{ plugin: string; unique_installs: number }>
186
176
  > {
177
+ if (!INSTALL_COUNTS_URL) {
178
+ return []
179
+ }
187
180
  logForDebugging(`Fetching install counts from ${INSTALL_COUNTS_URL}`)
188
181
 
189
182
  const started = performance.now()
@@ -1,13 +1,3 @@
1
- /**
2
- * inc-5046: fetch the official marketplace from a GCS mirror instead of
3
- * git-cloning GitHub on every startup.
4
- *
5
- * Backend (anthropic#317037) publishes a marketplace-only zip alongside the
6
- * titanium squashfs, keyed by base repo SHA. This module fetches the `latest`
7
- * pointer, compares against a local sentinel, and downloads+extracts the zip
8
- * when there's a new SHA. Callers decide fallback behavior on failure.
9
- */
10
-
11
1
  import axios from 'axios'
12
2
  import { chmod, mkdir, readFile, rename, rm, writeFile } from 'fs/promises'
13
3
  import { dirname, join, resolve, sep } from 'path'
@@ -20,13 +10,7 @@ import { errorMessage, getErrnoCode } from '../errors.js'
20
10
 
21
11
  type SafeString = AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
22
12
 
23
- // CDN-fronted domain for the public GCS bucket (same bucket the native
24
- // binary ships from — nativeInstaller/download.ts:24 uses the raw GCS URL).
25
- // `{sha}.zip` is content-addressed so CDN can cache it indefinitely;
26
- // `latest` has Cache-Control: max-age=300 so CDN staleness is bounded.
27
- // Backend (anthropic#317037) populates this prefix.
28
- const GCS_BASE =
29
- 'https://downloads.claude.ai/claude-code-releases/plugins/claude-plugins-official'
13
+ const GCS_BASE = process.env.UMMAYA_OFFICIAL_MARKETPLACE_BASE_URL?.trim()
30
14
 
31
15
  // Zip arc paths are seed-dir-relative (marketplaces/claude-plugins-official/…)
32
16
  // so the titanium seed machinery can use the same zip. Strip this prefix when
@@ -48,6 +32,9 @@ export async function fetchOfficialMarketplaceFromGcs(
48
32
  installLocation: string,
49
33
  marketplacesCacheDir: string,
50
34
  ): Promise<string | null> {
35
+ if (!GCS_BASE) {
36
+ return null
37
+ }
51
38
  // Defense in depth: this function does `rm(installLocation, {recursive})`
52
39
  // during the atomic swap. A corrupted known_marketplaces.json (gh-32793 —
53
40
  // Windows path read on WSL, literal tilde, manual edit) could point at the
@@ -158,7 +145,7 @@ export async function fetchOfficialMarketplaceFromGcs(
158
145
  // values below are static enums or a git SHA — not code/filepaths/PII.
159
146
  logEvent('tengu_plugin_remote_fetch', {
160
147
  source: 'marketplace_gcs' as SafeString,
161
- host: 'downloads.claude.ai' as SafeString,
148
+ host: new URL(GCS_BASE).host as SafeString,
162
149
  is_official: true,
163
150
  outcome: outcome as SafeString,
164
151
  duration_ms: Math.round(performance.now() - start),
@@ -26,9 +26,9 @@ const MAX_RELEASE_NOTES_SHOWN = 5
26
26
  * 3. Next time the user starts Claude, the cached changelog is available immediately
27
27
  */
28
28
  export const CHANGELOG_URL =
29
- 'https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md'
29
+ 'https://github.com/umyunsang/UMMAYA/blob/main/CHANGELOG.md'
30
30
  const RAW_CHANGELOG_URL =
31
- 'https://raw.githubusercontent.com/anthropics/claude-code/refs/heads/main/CHANGELOG.md'
31
+ 'https://raw.githubusercontent.com/umyunsang/UMMAYA/refs/heads/main/CHANGELOG.md'
32
32
 
33
33
  /**
34
34
  * Get the path for the cached changelog file.
@@ -887,7 +887,7 @@ export const SettingsSchema = lazySchema(() =>
887
887
  .string()
888
888
  .optional()
889
889
  .describe(
890
- 'Display name for the assistant, shown in the claude.ai session list',
890
+ 'Display name for the assistant, shown in the UMMAYA remote session list',
891
891
  ),
892
892
  }
893
893
  : {}),
@@ -125,13 +125,13 @@ const bothAuthMethodsNotice: StatusNoticeDefinition = {
125
125
  <Box flexDirection="column" marginLeft={3}>
126
126
  <Text color="warning">
127
127
  · Trying to use{' '}
128
- {authTokenInfo.source === 'claude.ai' ? 'claude.ai' : authTokenInfo.source}
128
+ {authTokenInfo.source === 'claude.ai' ? 'UMMAYA remote auth' : authTokenInfo.source}
129
129
  ?{' '}
130
- {apiKeySource === 'ANTHROPIC_API_KEY' ? 'Unset the ANTHROPIC_API_KEY environment variable, or claude /logout then say "No" to the API key approval before login.' : apiKeySource === 'apiKeyHelper' ? 'Unset the apiKeyHelper setting.' : 'claude /logout'}
130
+ {apiKeySource === 'ANTHROPIC_API_KEY' ? 'Unset the ANTHROPIC_API_KEY environment variable, or run ummaya /logout then say "No" to the API key approval before login.' : apiKeySource === 'apiKeyHelper' ? 'Unset the apiKeyHelper setting.' : 'ummaya /logout'}
131
131
  </Text>
132
132
  <Text color="warning">
133
133
  · Trying to use {apiKeySource}?{' '}
134
- {authTokenInfo.source === 'claude.ai' ? 'claude /logout to sign out of claude.ai.' : `Unset the ${authTokenInfo.source} environment variable.`}
134
+ {authTokenInfo.source === 'claude.ai' ? 'ummaya /logout to sign out of UMMAYA remote auth.' : `Unset the ${authTokenInfo.source} environment variable.`}
135
135
  </Text>
136
136
  </Box>
137
137
  </Box>;
@@ -37,25 +37,26 @@ type InternalMetricsPayload = {
37
37
  metrics: Metric[]
38
38
  }
39
39
 
40
+ function getMetricsExportEndpoint(): string | undefined {
41
+ const baseUrl =
42
+ process.env.UMMAYA_METRICS_BASE_URL ??
43
+ (process.env.USER_TYPE === 'ant'
44
+ ? process.env.ANT_CLAUDE_CODE_METRICS_ENDPOINT
45
+ : undefined)
46
+ const trimmed = baseUrl?.trim()
47
+ return trimmed
48
+ ? `${trimmed.replace(/\/$/, '')}/api/claude_code/metrics`
49
+ : undefined
50
+ }
51
+
40
52
  export class BigQueryMetricsExporter implements PushMetricExporter {
41
- private readonly endpoint: string
53
+ private readonly endpoint: string | undefined
42
54
  private readonly timeout: number
43
55
  private pendingExports: Promise<void>[] = []
44
56
  private isShutdown = false
45
57
 
46
58
  constructor(options: { timeout?: number } = {}) {
47
- const defaultEndpoint = 'https://api.anthropic.com/api/claude_code/metrics'
48
-
49
- if (
50
- process.env.USER_TYPE === 'ant' &&
51
- process.env.ANT_CLAUDE_CODE_METRICS_ENDPOINT
52
- ) {
53
- this.endpoint =
54
- process.env.ANT_CLAUDE_CODE_METRICS_ENDPOINT +
55
- '/api/claude_code/metrics'
56
- } else {
57
- this.endpoint = defaultEndpoint
58
- }
59
+ this.endpoint = getMetricsExportEndpoint()
59
60
 
60
61
  this.timeout = options.timeout || 5000
61
62
  }
@@ -101,6 +102,12 @@ export class BigQueryMetricsExporter implements PushMetricExporter {
101
102
  return
102
103
  }
103
104
 
105
+ if (!this.endpoint) {
106
+ logForDebugging('BigQuery metrics export: endpoint not configured')
107
+ resultCallback({ code: ExportResultCode.SUCCESS })
108
+ return
109
+ }
110
+
104
111
  // Check organization-level metrics opt-out
105
112
  const metricsStatus = await checkMetricsEnabled()
106
113
  if (!metricsStatus.enabled) {
package/uv.lock CHANGED
@@ -3052,7 +3052,7 @@ wheels = [
3052
3052
 
3053
3053
  [[package]]
3054
3054
  name = "ummaya"
3055
- version = "0.2.9"
3055
+ version = "0.2.11"
3056
3056
  source = { editable = "." }
3057
3057
  dependencies = [
3058
3058
  { name = "defusedxml" },