sidekick-shared 0.27.6 → 0.28.1

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 (269) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +59 -18
  3. package/dist/browser.d.ts +13 -2
  4. package/dist/browser.js +30 -2
  5. package/dist/claudePaths.d.ts +11 -0
  6. package/dist/claudePaths.js +61 -0
  7. package/dist/claudeProfiles.d.ts +2 -9
  8. package/dist/claudeProfiles.js +10 -25
  9. package/dist/codexPaths.d.ts +22 -0
  10. package/dist/codexPaths.js +67 -0
  11. package/dist/codexProfiles.d.ts +1 -4
  12. package/dist/codexProfiles.js +5 -43
  13. package/dist/doctor.js +2 -2
  14. package/dist/esm/accountChangeSignal.js +15 -0
  15. package/dist/esm/accountChanges.js +152 -0
  16. package/dist/esm/accountHealth.js +288 -0
  17. package/dist/esm/accountLaunch.js +145 -0
  18. package/dist/esm/accountLease.js +60 -0
  19. package/dist/esm/accountManager.js +606 -0
  20. package/dist/esm/accountRegistry.js +214 -0
  21. package/dist/esm/accountStatus.js +51 -0
  22. package/dist/esm/accountSwitch.js +74 -0
  23. package/dist/esm/accountSync.js +156 -0
  24. package/dist/esm/accountSyncTypes.js +4 -0
  25. package/dist/esm/accounts.js +1291 -0
  26. package/dist/esm/aggregation/EventAggregator.js +2034 -0
  27. package/dist/esm/aggregation/FrequencyTracker.js +69 -0
  28. package/dist/esm/aggregation/HeatmapTracker.js +89 -0
  29. package/dist/esm/aggregation/PatternExtractor.js +168 -0
  30. package/dist/esm/aggregation/costProvenance.js +31 -0
  31. package/dist/esm/aggregation/snapshot.js +161 -0
  32. package/dist/esm/aggregation/types.js +5 -0
  33. package/dist/esm/analytics/codeImpact.js +18 -0
  34. package/dist/esm/analytics/compactionLedger.js +37 -0
  35. package/dist/esm/analytics/qualityScore.js +112 -0
  36. package/dist/esm/autoSwitch.js +185 -0
  37. package/dist/esm/browser.js +34 -0
  38. package/dist/esm/claudeCredentialDoctor.js +239 -0
  39. package/dist/esm/claudeCredentialLedger.js +91 -0
  40. package/dist/esm/claudeCredentials.js +111 -0
  41. package/dist/esm/claudeLiveGuard.js +43 -0
  42. package/dist/esm/claudePaths.js +22 -0
  43. package/dist/esm/claudeProfiles.js +142 -0
  44. package/dist/esm/claudeRefreshLock.js +106 -0
  45. package/dist/esm/codexAuth.js +101 -0
  46. package/dist/esm/codexCredentialDoctor.js +265 -0
  47. package/dist/esm/codexCredentialStore.js +164 -0
  48. package/dist/esm/codexKeepAlive.js +112 -0
  49. package/dist/esm/codexPaths.js +172 -0
  50. package/dist/esm/codexProfiles.js +1251 -0
  51. package/dist/esm/codexQuota.js +564 -0
  52. package/dist/esm/codexQuotaWatcher.js +363 -0
  53. package/dist/esm/context/composer.js +71 -0
  54. package/dist/esm/context/sessionContext.js +546 -0
  55. package/dist/esm/credentialIO.js +283 -0
  56. package/dist/esm/credentials.js +49 -0
  57. package/dist/esm/doctor.js +305 -0
  58. package/dist/esm/ensureDefaultAccounts.js +62 -0
  59. package/dist/esm/errorHistory.js +56 -0
  60. package/dist/esm/extractors/errorTaxonomy.js +43 -0
  61. package/dist/esm/extractors/gatherAssets.js +32 -0
  62. package/dist/esm/extractors/sessionAssets.js +176 -0
  63. package/dist/esm/extractors/sources/claudeAssets.js +158 -0
  64. package/dist/esm/extractors/sources/codexAssets.js +234 -0
  65. package/dist/esm/extractors/tokenUsage.js +41 -0
  66. package/dist/esm/extractors/toolCall.js +142 -0
  67. package/dist/esm/failingTools.js +65 -0
  68. package/dist/esm/fileHead.js +27 -0
  69. package/dist/esm/formatters/eventHighlighter.js +332 -0
  70. package/dist/esm/formatters/noiseClassifier.js +209 -0
  71. package/dist/esm/formatters/sessionDump.js +328 -0
  72. package/dist/esm/formatters/toolSummary.js +226 -0
  73. package/dist/esm/formatting.js +82 -0
  74. package/dist/esm/handoffUrl.js +23 -0
  75. package/dist/esm/historicalStore.js +305 -0
  76. package/dist/esm/humanPrompt.js +88 -0
  77. package/dist/esm/index.js +213 -0
  78. package/dist/esm/keepAlive.js +189 -0
  79. package/dist/esm/liveCredentialGuard.js +33 -0
  80. package/dist/esm/modelAliases.js +51 -0
  81. package/dist/esm/modelCatalog.js +139 -0
  82. package/dist/esm/modelContext.js +280 -0
  83. package/dist/esm/modelInfo.js +832 -0
  84. package/dist/esm/multiProviderQuotaService.js +450 -0
  85. package/dist/esm/node.js +46 -0
  86. package/dist/esm/observedContextWindows.js +165 -0
  87. package/dist/esm/observedSessionCollector.js +939 -0
  88. package/dist/esm/parsers/changelogParser.js +71 -0
  89. package/dist/esm/parsers/codexHistory.js +89 -0
  90. package/dist/esm/parsers/codexParser.js +906 -0
  91. package/dist/esm/parsers/debugLogParser.js +126 -0
  92. package/dist/esm/parsers/jsonl.js +66 -0
  93. package/dist/esm/parsers/mcpToolName.js +28 -0
  94. package/dist/esm/parsers/openCodeParser.js +625 -0
  95. package/dist/esm/parsers/planExtractor.js +335 -0
  96. package/dist/esm/parsers/sessionActivityDetector.js +246 -0
  97. package/dist/esm/parsers/sessionPathResolver.js +713 -0
  98. package/dist/esm/parsers/subagentScanner.js +360 -0
  99. package/dist/esm/parsers/subagentStatsCache.js +45 -0
  100. package/dist/esm/parsers/subagentTraceParser.js +325 -0
  101. package/dist/esm/paths.js +134 -0
  102. package/dist/esm/peakHours.js +194 -0
  103. package/dist/esm/phrases.js +1330 -0
  104. package/dist/esm/pricingCatalog.js +247 -0
  105. package/dist/esm/processDetection.js +200 -0
  106. package/dist/esm/projectMigration.js +59 -0
  107. package/dist/esm/promptHistory.js +1221 -0
  108. package/dist/esm/providerFailure.js +362 -0
  109. package/dist/esm/providerIds.js +6 -0
  110. package/dist/esm/providerQuota.js +1 -0
  111. package/dist/esm/providerServiceStatus.js +145 -0
  112. package/dist/esm/providerServiceStatusTypes.js +1 -0
  113. package/dist/esm/providerStatus.js +117 -0
  114. package/dist/esm/providers/claudeCode.js +575 -0
  115. package/dist/esm/providers/claudeListing.js +121 -0
  116. package/dist/esm/providers/codex.js +1034 -0
  117. package/dist/esm/providers/codexDatabase.js +297 -0
  118. package/dist/esm/providers/codexRollouts.js +215 -0
  119. package/dist/esm/providers/detect.js +185 -0
  120. package/dist/esm/providers/diagnostics.js +83 -0
  121. package/dist/esm/providers/directoryListingCache.js +206 -0
  122. package/dist/esm/providers/factory.js +54 -0
  123. package/dist/esm/providers/openCode.js +2008 -0
  124. package/dist/esm/providers/openCodeDatabase.js +419 -0
  125. package/dist/esm/providers/rolloutWalker.js +252 -0
  126. package/dist/esm/providers/types.js +12 -0
  127. package/dist/esm/quota.js +182 -0
  128. package/dist/esm/quotaHistory.js +364 -0
  129. package/dist/esm/quotaPoller.js +230 -0
  130. package/dist/esm/quotaPresentation.js +97 -0
  131. package/dist/esm/quotaResolver.js +231 -0
  132. package/dist/esm/quotaSnapshots.js +130 -0
  133. package/dist/esm/quotaThresholds.js +85 -0
  134. package/dist/esm/readers/decisions.js +24 -0
  135. package/dist/esm/readers/handoff.js +20 -0
  136. package/dist/esm/readers/helpers.js +27 -0
  137. package/dist/esm/readers/history.js +9 -0
  138. package/dist/esm/readers/notes.js +48 -0
  139. package/dist/esm/readers/plans.js +225 -0
  140. package/dist/esm/readers/tasks.js +19 -0
  141. package/dist/esm/report/htmlHelpers.js +280 -0
  142. package/dist/esm/report/htmlReportGenerator.js +704 -0
  143. package/dist/esm/report/index.js +7 -0
  144. package/dist/esm/report/logo.js +2 -0
  145. package/dist/esm/report/openBrowser.js +19 -0
  146. package/dist/esm/report/sessionReportInputs.js +33 -0
  147. package/dist/esm/report/transcriptParser.js +83 -0
  148. package/dist/esm/report/types.js +4 -0
  149. package/dist/esm/schemas/accountManager.js +204 -0
  150. package/dist/esm/schemas/accountStatus.js +25 -0
  151. package/dist/esm/schemas/assistantTurn.js +74 -0
  152. package/dist/esm/schemas/index.js +25 -0
  153. package/dist/esm/schemas/observedSessionV1.js +77 -0
  154. package/dist/esm/schemas/providerFailure.js +37 -0
  155. package/dist/esm/schemas/quota.js +132 -0
  156. package/dist/esm/schemas/quotaHistory.js +40 -0
  157. package/dist/esm/schemas/sessionEvent.js +216 -0
  158. package/dist/esm/schemas/stateFile.js +75 -0
  159. package/dist/esm/schemas/tokenEstimation.js +7 -0
  160. package/dist/esm/schemas/transcript.js +86 -0
  161. package/dist/esm/schemas/usageNormalization.js +38 -0
  162. package/dist/esm/search/advancedFilter.js +197 -0
  163. package/dist/esm/search/sessionSearch.js +66 -0
  164. package/dist/esm/sessionFingerprint.js +40 -0
  165. package/dist/esm/sessionMonitor.js +198 -0
  166. package/dist/esm/sessionPreviews.js +522 -0
  167. package/dist/esm/sessionPromptHistory.js +254 -0
  168. package/dist/esm/sessionPromptSignals.js +364 -0
  169. package/dist/esm/sessionStats.js +160 -0
  170. package/dist/esm/sessionTokenTotals.js +98 -0
  171. package/dist/esm/sessionTranscripts.js +49 -0
  172. package/dist/esm/stateFile.js +119 -0
  173. package/dist/esm/statusline/BurnRateCalculator.js +40 -0
  174. package/dist/esm/statusline/claudeStatuslinePayload.js +148 -0
  175. package/dist/esm/statusline/formatter.js +122 -0
  176. package/dist/esm/statusline/index.js +8 -0
  177. package/dist/esm/terminalSync.js +95 -0
  178. package/dist/esm/testing/credentialGuard.js +222 -0
  179. package/dist/esm/testing/index.js +12 -0
  180. package/dist/esm/testing/sessionLogFixtures.js +128 -0
  181. package/dist/esm/tokenEstimation.js +67 -0
  182. package/dist/esm/tokenSummary.js +113 -0
  183. package/dist/esm/toolCategory.js +82 -0
  184. package/dist/esm/transcript.js +257 -0
  185. package/dist/esm/turns/assistantTurn.js +373 -0
  186. package/dist/esm/types/codex.js +23 -0
  187. package/dist/esm/types/decisionLog.js +5 -0
  188. package/dist/esm/types/historicalData.js +47 -0
  189. package/dist/esm/types/knowledgeNote.js +15 -0
  190. package/dist/esm/types/observedSessionV1.js +257 -0
  191. package/dist/esm/types/opencode.js +12 -0
  192. package/dist/esm/types/plan.js +7 -0
  193. package/dist/esm/types/sessionEvent.js +10 -0
  194. package/dist/esm/types/taskPersistence.js +12 -0
  195. package/dist/esm/usage/billingBlocks.js +148 -0
  196. package/dist/esm/usage/claudeUsageDedupe.js +189 -0
  197. package/dist/esm/usage/importSessionHistory.js +84 -0
  198. package/dist/esm/usage/subagentUsage.js +18 -0
  199. package/dist/esm/usage/usageEvents.js +402 -0
  200. package/dist/esm/usage/usageReports.js +202 -0
  201. package/dist/esm/usageNormalization.js +95 -0
  202. package/dist/esm/watchers/eventBridge.js +219 -0
  203. package/dist/esm/watchers/factory.js +63 -0
  204. package/dist/esm/watchers/jsonlTail.js +289 -0
  205. package/dist/esm/watchers/jsonlWatcher.js +435 -0
  206. package/dist/esm/watchers/providerReaderWatcher.js +118 -0
  207. package/dist/esm/watchers/sqliteWatcher.js +285 -0
  208. package/dist/esm/watchers/types.js +4 -0
  209. package/dist/esm/workspaceRoots.js +56 -0
  210. package/dist/esm/writers/atomic.js +375 -0
  211. package/dist/esm/writers/decisions.js +51 -0
  212. package/dist/esm/writers/notes.js +46 -0
  213. package/dist/esm/writers/tasks.js +63 -0
  214. package/dist/esm/zaiQuota.js +323 -0
  215. package/dist/esm/zaiQuotaApi.js +271 -0
  216. package/dist/esm/zaiQuotaWatcher.js +265 -0
  217. package/dist/fileHead.d.ts +22 -0
  218. package/dist/fileHead.js +33 -0
  219. package/dist/index.d.ts +16 -7
  220. package/dist/index.js +49 -15
  221. package/dist/node.d.ts +13 -1
  222. package/dist/node.js +43 -2
  223. package/dist/parsers/codexHistory.js +2 -2
  224. package/dist/parsers/codexParser.d.ts +12 -0
  225. package/dist/parsers/codexParser.js +34 -12
  226. package/dist/parsers/debugLogParser.js +2 -2
  227. package/dist/parsers/sessionPathResolver.js +5 -4
  228. package/dist/promptHistory.d.ts +32 -0
  229. package/dist/promptHistory.js +115 -59
  230. package/dist/providerFailure.d.ts +12 -6
  231. package/dist/providerFailure.js +45 -0
  232. package/dist/providers/claudeCode.js +7 -99
  233. package/dist/providers/claudeListing.d.ts +22 -0
  234. package/dist/providers/claudeListing.js +158 -0
  235. package/dist/providers/codex.d.ts +3 -1
  236. package/dist/providers/codex.js +26 -227
  237. package/dist/providers/codexRollouts.d.ts +44 -0
  238. package/dist/providers/codexRollouts.js +261 -0
  239. package/dist/providers/detect.js +4 -4
  240. package/dist/readers/plans.js +3 -3
  241. package/dist/schemas/index.d.ts +2 -0
  242. package/dist/schemas/index.js +7 -2
  243. package/dist/schemas/providerFailure.d.ts +154 -0
  244. package/dist/schemas/providerFailure.js +40 -0
  245. package/dist/sessionPromptHistory.d.ts +12 -7
  246. package/dist/sessionPromptHistory.js +15 -3
  247. package/dist/sessionPromptSignals.d.ts +9 -0
  248. package/dist/sessionPromptSignals.js +13 -0
  249. package/dist/testing/credentialGuard.d.ts +23 -0
  250. package/dist/testing/credentialGuard.js +258 -0
  251. package/dist/testing/index.d.ts +14 -0
  252. package/dist/testing/index.js +22 -0
  253. package/dist/testing/sessionLogFixtures.d.ts +28 -0
  254. package/dist/testing/sessionLogFixtures.js +169 -0
  255. package/dist/tokenEstimation.d.ts +2 -0
  256. package/dist/tokenEstimation.js +21 -11
  257. package/dist/toolCategory.d.ts +18 -0
  258. package/dist/toolCategory.js +86 -0
  259. package/dist/types/codex.d.ts +4 -0
  260. package/dist/usage/usageEvents.d.ts +16 -0
  261. package/dist/usage/usageEvents.js +53 -9
  262. package/dist/watchers/jsonlTail.d.ts +26 -1
  263. package/dist/watchers/jsonlTail.js +136 -28
  264. package/dist/watchers/jsonlWatcher.js +7 -0
  265. package/dist/watchers/providerReaderWatcher.js +1 -0
  266. package/dist/watchers/types.d.ts +6 -0
  267. package/dist/workspaceRoots.d.ts +23 -0
  268. package/dist/workspaceRoots.js +93 -0
  269. package/package.json +22 -2
@@ -33,9 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CODEX_ARCHIVED_SESSIONS_SUBDIR = exports.CODEX_SESSIONS_SUBDIR = void 0;
36
37
  exports.getDefaultSystemCodexHome = getDefaultSystemCodexHome;
37
38
  exports.getExplicitCodexHome = getExplicitCodexHome;
38
39
  exports.getSystemCodexHome = getSystemCodexHome;
40
+ exports.resolveSidekickCodexHome = resolveSidekickCodexHome;
41
+ exports.getCodexExecutionEnv = getCodexExecutionEnv;
39
42
  exports.getCodexProfilesDir = getCodexProfilesDir;
40
43
  exports.getCodexProfileDir = getCodexProfileDir;
41
44
  exports.getCodexProfileHome = getCodexProfileHome;
@@ -49,6 +52,8 @@ exports.getCodexLoginsDir = getCodexLoginsDir;
49
52
  exports.getCodexLoginDir = getCodexLoginDir;
50
53
  exports.getCodexLoginHome = getCodexLoginHome;
51
54
  exports.getCodexLoginStatePath = getCodexLoginStatePath;
55
+ exports.getCodexMonitoringHomes = getCodexMonitoringHomes;
56
+ exports.getCodexSessionsDirs = getCodexSessionsDirs;
52
57
  const fs = __importStar(require("fs"));
53
58
  const os = __importStar(require("os"));
54
59
  const path = __importStar(require("path"));
@@ -64,6 +69,23 @@ function getExplicitCodexHome() {
64
69
  function getSystemCodexHome() {
65
70
  return getExplicitCodexHome() ?? getDefaultSystemCodexHome();
66
71
  }
72
+ function resolveSidekickCodexHome() {
73
+ // Account switching swaps auth.json inside the system home, so the system
74
+ // home (or an explicit CODEX_HOME) is always the single live home.
75
+ return getSystemCodexHome();
76
+ }
77
+ /**
78
+ * The environment for spawning `codex`: `baseEnv` with `CODEX_HOME` set to the
79
+ * live home. A non-blank `CODEX_HOME` already in `baseEnv` is kept, so a caller
80
+ * that points one child at its own home does not have it overwritten.
81
+ */
82
+ function getCodexExecutionEnv(baseEnv = process.env) {
83
+ const requested = baseEnv.CODEX_HOME?.trim();
84
+ return {
85
+ ...baseEnv,
86
+ CODEX_HOME: requested ? requested : resolveSidekickCodexHome(),
87
+ };
88
+ }
67
89
  function getCodexProfilesDir() {
68
90
  return path.join((0, accountRegistry_1.getAccountsDir)(), 'codex', 'profiles');
69
91
  }
@@ -159,3 +181,48 @@ function getCodexLoginStatePath(id) {
159
181
  const dir = getCodexLoginDir(id);
160
182
  return fs.existsSync(dir) ? path.join(dir, 'profile.json') : getCodexProfileStatePath(id);
161
183
  }
184
+ function dedupePaths(paths) {
185
+ const seen = new Set();
186
+ const unique = [];
187
+ for (const candidate of paths) {
188
+ const normalized = path.resolve(candidate);
189
+ if (seen.has(normalized))
190
+ continue;
191
+ seen.add(normalized);
192
+ unique.push(candidate);
193
+ }
194
+ return unique;
195
+ }
196
+ function getCodexMonitoringHomes() {
197
+ const explicitHome = getExplicitCodexHome();
198
+ if (explicitHome)
199
+ return [explicitHome];
200
+ // The system home is the single live home; profile homes only matter for
201
+ // sessions recorded back when they doubled as live CODEX_HOMEs.
202
+ const homes = [getDefaultSystemCodexHome()];
203
+ for (const profile of (0, accountRegistry_1.listSavedAccountProfiles)('codex')) {
204
+ const profileHome = getCodexProfileHome(profile.id);
205
+ if (fs.existsSync(path.join(profileHome, 'sessions'))) {
206
+ homes.push(profileHome);
207
+ }
208
+ }
209
+ return dedupePaths(homes);
210
+ }
211
+ /** Where Codex writes live rollouts, below each home. */
212
+ exports.CODEX_SESSIONS_SUBDIR = 'sessions';
213
+ /** Where Codex moves a rollout when its thread is archived, below each home. */
214
+ exports.CODEX_ARCHIVED_SESSIONS_SUBDIR = 'archived_sessions';
215
+ /**
216
+ * Every directory that may hold Codex rollouts: each home's `sessions`, then
217
+ * each home's `archived_sessions` that exists. Live directories come first so
218
+ * callers that pick one directory pick a live one.
219
+ */
220
+ function getCodexSessionsDirs(homes = getCodexMonitoringHomes(), options = {}) {
221
+ const live = homes.map((home) => path.join(home, exports.CODEX_SESSIONS_SUBDIR));
222
+ if (options.includeArchived === false)
223
+ return live;
224
+ const archived = homes
225
+ .map((home) => path.join(home, exports.CODEX_ARCHIVED_SESSIONS_SUBDIR))
226
+ .filter((dir) => fs.existsSync(dir));
227
+ return [...live, ...archived];
228
+ }
@@ -5,7 +5,7 @@ import { type SwitchAccountOptions, type SwitchAccountResult } from './accountSw
5
5
  import { type ProviderSyncReport } from './accountSyncTypes';
6
6
  import { type AccountConsumerScan } from './processDetection';
7
7
  import { type CodexAuthSnapshot } from './codexCredentialStore';
8
- export { getCodexProfilesDir, getCodexProfileHome, getSystemCodexHome, getCodexCredentialStoreMode, } from './codexPaths';
8
+ export { getCodexProfilesDir, getCodexProfileHome, getSystemCodexHome, getCodexCredentialStoreMode, getCodexMonitoringHomes, resolveSidekickCodexHome, getCodexExecutionEnv, } from './codexPaths';
9
9
  export type { CodexCredentialStoreMode } from './codexPaths';
10
10
  export interface CodexAccountManagerResult extends AccountManagerResult {
11
11
  needsLogin?: boolean;
@@ -13,7 +13,6 @@ export interface CodexAccountManagerResult extends AccountManagerResult {
13
13
  codexHome?: string;
14
14
  }
15
15
  export declare const CODEX_KEYRING_FIX_HINT = "Set `cli_auth_credentials_store = \"file\"` in ~/.codex/config.toml and run `codex login` again.";
16
- export declare function getCodexMonitoringHomes(): string[];
17
16
  /** Read the freshest saved login without creating a CLI-usable copy. */
18
17
  export declare function readStoredCodexAccount(profileId: string): CodexAuthSnapshot | null;
19
18
  export declare function isLiveCodexProfile(profile: SavedAccountProfile): boolean;
@@ -39,7 +38,6 @@ export declare function isCodexProfileAuthenticated(codexHome: string): boolean;
39
38
  export declare function isCodexProfileAuthenticatedAsync(codexHome: string): Promise<boolean>;
40
39
  export declare function listCodexAccounts(): SavedAccountProfile[];
41
40
  export declare function getActiveCodexAccount(): SavedAccountProfile | null;
42
- export declare function resolveSidekickCodexHome(): string;
43
41
  /**
44
42
  * Resolves the *currently logged-in* Codex account for display, preferring the
45
43
  * live `auth.json` identity over the saved registry pointer (which only sidekick's
@@ -56,7 +54,6 @@ export declare function resolveSidekickCodexHome(): string;
56
54
  export declare function resolveActiveCodexAccount(options?: {
57
55
  selfHeal?: boolean;
58
56
  }): ResolvedActiveAccount;
59
- export declare function getCodexExecutionEnv(baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
60
57
  /** Legacy callers can import current; explicit sign-in passes importCurrent: false. */
61
58
  export declare function prepareCodexAccount(label: string, options?: {
62
59
  importCurrent?: boolean;
@@ -33,8 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.CODEX_KEYRING_FIX_HINT = exports.getCodexCredentialStoreMode = exports.getSystemCodexHome = exports.getCodexProfileHome = exports.getCodexProfilesDir = void 0;
37
- exports.getCodexMonitoringHomes = getCodexMonitoringHomes;
36
+ exports.CODEX_KEYRING_FIX_HINT = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.getCodexMonitoringHomes = exports.getCodexCredentialStoreMode = exports.getSystemCodexHome = exports.getCodexProfileHome = exports.getCodexProfilesDir = void 0;
38
37
  exports.readStoredCodexAccount = readStoredCodexAccount;
39
38
  exports.isLiveCodexProfile = isLiveCodexProfile;
40
39
  exports.storeCodexProfileAuthUnlocked = storeCodexProfileAuthUnlocked;
@@ -48,9 +47,7 @@ exports.isCodexProfileAuthenticated = isCodexProfileAuthenticated;
48
47
  exports.isCodexProfileAuthenticatedAsync = isCodexProfileAuthenticatedAsync;
49
48
  exports.listCodexAccounts = listCodexAccounts;
50
49
  exports.getActiveCodexAccount = getActiveCodexAccount;
51
- exports.resolveSidekickCodexHome = resolveSidekickCodexHome;
52
50
  exports.resolveActiveCodexAccount = resolveActiveCodexAccount;
53
- exports.getCodexExecutionEnv = getCodexExecutionEnv;
54
51
  exports.prepareCodexAccount = prepareCodexAccount;
55
52
  exports.prepareCodexAccountAsync = prepareCodexAccountAsync;
56
53
  exports.discardCodexLogin = discardCodexLogin;
@@ -97,34 +94,10 @@ Object.defineProperty(exports, "getCodexProfilesDir", { enumerable: true, get: f
97
94
  Object.defineProperty(exports, "getCodexProfileHome", { enumerable: true, get: function () { return codexPaths_2.getCodexProfileHome; } });
98
95
  Object.defineProperty(exports, "getSystemCodexHome", { enumerable: true, get: function () { return codexPaths_2.getSystemCodexHome; } });
99
96
  Object.defineProperty(exports, "getCodexCredentialStoreMode", { enumerable: true, get: function () { return codexPaths_2.getCodexCredentialStoreMode; } });
97
+ Object.defineProperty(exports, "getCodexMonitoringHomes", { enumerable: true, get: function () { return codexPaths_2.getCodexMonitoringHomes; } });
98
+ Object.defineProperty(exports, "resolveSidekickCodexHome", { enumerable: true, get: function () { return codexPaths_2.resolveSidekickCodexHome; } });
99
+ Object.defineProperty(exports, "getCodexExecutionEnv", { enumerable: true, get: function () { return codexPaths_2.getCodexExecutionEnv; } });
100
100
  exports.CODEX_KEYRING_FIX_HINT = 'Set `cli_auth_credentials_store = "file"` in ~/.codex/config.toml and run `codex login` again.';
101
- function dedupePaths(paths) {
102
- const seen = new Set();
103
- const unique = [];
104
- for (const candidate of paths) {
105
- const normalized = path.resolve(candidate);
106
- if (seen.has(normalized))
107
- continue;
108
- seen.add(normalized);
109
- unique.push(candidate);
110
- }
111
- return unique;
112
- }
113
- function getCodexMonitoringHomes() {
114
- const explicitHome = (0, codexPaths_1.getExplicitCodexHome)();
115
- if (explicitHome)
116
- return [explicitHome];
117
- // The system home is the single live home; profile homes only matter for
118
- // sessions recorded back when they doubled as live CODEX_HOMEs.
119
- const homes = [(0, codexPaths_1.getDefaultSystemCodexHome)()];
120
- for (const profile of listCodexAccounts()) {
121
- const profileHome = (0, codexPaths_1.getCodexProfileHome)(profile.id);
122
- if (fs.existsSync(path.join(profileHome, 'sessions'))) {
123
- homes.push(profileHome);
124
- }
125
- }
126
- return dedupePaths(homes);
127
- }
128
101
  function readPendingProfile(profileId) {
129
102
  try {
130
103
  return JSON.parse(fs.readFileSync((0, codexPaths_1.getCodexLoginStatePath)(profileId), 'utf8'));
@@ -406,11 +379,6 @@ function listCodexAccounts() {
406
379
  function getActiveCodexAccount() {
407
380
  return (0, accountRegistry_1.getActiveSavedAccount)('codex');
408
381
  }
409
- function resolveSidekickCodexHome() {
410
- // Account switching swaps auth.json inside the system home, so the system
411
- // home (or an explicit CODEX_HOME) is always the single live home.
412
- return (0, codexPaths_1.getSystemCodexHome)();
413
- }
414
382
  function profileIdentity(profile) {
415
383
  return {
416
384
  email: profile.email ?? profile.metadata?.email,
@@ -432,7 +400,7 @@ function profileIdentity(profile) {
432
400
  */
433
401
  function resolveActiveCodexAccount(options = {}) {
434
402
  const selfHeal = options.selfHeal ?? true;
435
- const identity = (0, codexAuth_1.readAuthIdentityFromRaw)((0, codexPaths_1.readFileOrNull)(path.join(resolveSidekickCodexHome(), 'auth.json')));
403
+ const identity = (0, codexAuth_1.readAuthIdentityFromRaw)((0, codexPaths_1.readFileOrNull)(path.join((0, codexPaths_1.resolveSidekickCodexHome)(), 'auth.json')));
436
404
  if (identity && (identity.email || identity.workspaceId)) {
437
405
  const match = findProfileForIdentity(identity);
438
406
  if (match) {
@@ -471,12 +439,6 @@ function resolveActiveCodexAccount(options = {}) {
471
439
  }
472
440
  return { source: 'none' };
473
441
  }
474
- function getCodexExecutionEnv(baseEnv = process.env) {
475
- return {
476
- ...baseEnv,
477
- CODEX_HOME: resolveSidekickCodexHome(),
478
- };
479
- }
480
442
  // ── Prepare / finalize (add account) ─────────────────────────────────────
481
443
  function keyringRefusal(mode) {
482
444
  return {
package/dist/doctor.js CHANGED
@@ -37,7 +37,6 @@ exports.getSessionDiagnostics = getSessionDiagnostics;
37
37
  exports.runDoctor = runDoctor;
38
38
  exports.formatHealthReport = formatHealthReport;
39
39
  const fs = __importStar(require("fs"));
40
- const os = __importStar(require("os"));
41
40
  const path = __importStar(require("path"));
42
41
  const accountStatus_1 = require("./accountStatus");
43
42
  const paths_1 = require("./paths");
@@ -48,11 +47,12 @@ const openCode_1 = require("./providers/openCode");
48
47
  const factory_1 = require("./providers/factory");
49
48
  const detect_1 = require("./providers/detect");
50
49
  const openCodeDatabase_1 = require("./providers/openCodeDatabase");
50
+ const claudePaths_1 = require("./claudePaths");
51
51
  /** Collects the Claude Code path-resolution detail used by both host surfaces. */
52
52
  function getSessionDiagnostics(workspacePath) {
53
53
  const encodedPath = (0, sessionPathResolver_1.encodeWorkspacePath)(workspacePath);
54
54
  const expectedSessionDir = (0, sessionPathResolver_1.getSessionDirectory)(workspacePath);
55
- const projectsDir = path.join(os.homedir(), '.claude', 'projects');
55
+ const projectsDir = (0, claudePaths_1.getClaudeProjectsDir)();
56
56
  let existingProjectDirs = [];
57
57
  let expectedDirExists = false;
58
58
  try {
@@ -0,0 +1,15 @@
1
+ const listeners = new Set();
2
+ export function _onRawAccountsChanged(listener) {
3
+ listeners.add(listener);
4
+ return () => listeners.delete(listener);
5
+ }
6
+ export function _emitAccountsChanged(reason) {
7
+ for (const listener of listeners) {
8
+ try {
9
+ listener(reason);
10
+ }
11
+ catch {
12
+ // Account notifications are observational and cannot break mutations.
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,152 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { _emitAccountsChanged, _onRawAccountsChanged, } from './accountChangeSignal';
5
+ import { getActiveAccountStatus } from './accountStatus';
6
+ import { getAccountsDir } from './accountRegistry';
7
+ import { syncLiveAccountStateSync } from './accountSync';
8
+ import { getLiveClaudeHome } from './claudeProfiles';
9
+ import { getSystemCodexHome } from './codexPaths';
10
+ const listeners = new Set();
11
+ let watchers = [];
12
+ let pollTimer;
13
+ let stopRawListener;
14
+ let lastFingerprint;
15
+ let debounceTimer;
16
+ const DEFAULT_POLL_INTERVAL_MS = 30_000;
17
+ let activePollIntervalMs = DEFAULT_POLL_INTERVAL_MS;
18
+ /**
19
+ * Observe login, logout, and active-account switches. Local Sidekick mutations
20
+ * signal immediately; filesystem watchers cover external CLIs; a low-frequency
21
+ * catch-up poll protects network mounts and watcher-hostile filesystems.
22
+ */
23
+ export function onAccountsChanged(listener, options = {}) {
24
+ listeners.add(listener);
25
+ // The fastest interval any live subscriber asked for wins; a later, faster
26
+ // subscriber restarts the timer rather than being silently ignored.
27
+ const requestedPollMs = Math.max(1_000, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
28
+ if (!stopRawListener) {
29
+ activePollIntervalMs = requestedPollMs;
30
+ ensureMonitoring();
31
+ }
32
+ else if (requestedPollMs < activePollIntervalMs) {
33
+ activePollIntervalMs = requestedPollMs;
34
+ restartPollTimer();
35
+ }
36
+ if (options.emitCurrent)
37
+ emitIfChanged('poll', true, listener);
38
+ return {
39
+ dispose: () => {
40
+ listeners.delete(listener);
41
+ if (listeners.size === 0)
42
+ stopMonitoring();
43
+ },
44
+ };
45
+ }
46
+ function ensureMonitoring() {
47
+ if (stopRawListener)
48
+ return;
49
+ lastFingerprint = fingerprint(getActiveAccountStatus());
50
+ stopRawListener = _onRawAccountsChanged((reason) => scheduleCheck(reason));
51
+ for (const target of watchTargets()) {
52
+ try {
53
+ const watcher = fs.watch(target, { persistent: false }, () => {
54
+ scheduleCheck('filesystem');
55
+ });
56
+ watcher.on('error', () => {
57
+ watchers = watchers.filter((candidate) => candidate !== watcher);
58
+ try {
59
+ watcher.close();
60
+ }
61
+ catch {
62
+ // The catch-up poll remains active.
63
+ }
64
+ });
65
+ watchers.push(watcher);
66
+ }
67
+ catch {
68
+ // Missing/unwatchable directories are covered by the catch-up poll.
69
+ }
70
+ }
71
+ startPollTimer();
72
+ }
73
+ function startPollTimer() {
74
+ pollTimer = setInterval(() => emitIfChanged('poll'), activePollIntervalMs);
75
+ pollTimer.unref?.();
76
+ }
77
+ function restartPollTimer() {
78
+ if (pollTimer)
79
+ clearInterval(pollTimer);
80
+ startPollTimer();
81
+ }
82
+ function stopMonitoring() {
83
+ stopRawListener?.();
84
+ stopRawListener = undefined;
85
+ for (const watcher of watchers)
86
+ watcher.close();
87
+ watchers = [];
88
+ if (pollTimer)
89
+ clearInterval(pollTimer);
90
+ pollTimer = undefined;
91
+ if (debounceTimer)
92
+ clearTimeout(debounceTimer);
93
+ debounceTimer = undefined;
94
+ lastFingerprint = undefined;
95
+ activePollIntervalMs = DEFAULT_POLL_INTERVAL_MS;
96
+ }
97
+ function watchTargets() {
98
+ return Array.from(new Set([
99
+ getAccountsDir(),
100
+ getLiveClaudeHome(),
101
+ path.join(os.homedir(), '.claude'),
102
+ getSystemCodexHome(),
103
+ ]));
104
+ }
105
+ function scheduleCheck(reason) {
106
+ if (debounceTimer)
107
+ clearTimeout(debounceTimer);
108
+ debounceTimer = setTimeout(() => {
109
+ debounceTimer = undefined;
110
+ // Never force: watch targets include ~/.claude and the Codex home, whose
111
+ // history files churn on every prompt. Only a real status change may wake
112
+ // subscribers, or dormant quota pollers would poll on unrelated writes.
113
+ emitIfChanged(reason);
114
+ }, 25);
115
+ debounceTimer.unref?.();
116
+ }
117
+ function emitIfChanged(reason, force = false, singleListener) {
118
+ // External CLIs write the live homes directly: fold their logins into the
119
+ // saved profiles before reporting status, so a native `claude /login` is
120
+ // registered and its rotated tokens are backed up without a host round-trip.
121
+ // `local` signals come from our own registry writes and need no sync.
122
+ if (reason === 'filesystem' || reason === 'poll') {
123
+ try {
124
+ syncLiveAccountStateSync({ reason: reason === 'poll' ? 'poll' : 'watch' });
125
+ }
126
+ catch {
127
+ // Sync problems surface through the health model, never through the watcher.
128
+ }
129
+ }
130
+ const status = getActiveAccountStatus();
131
+ const nextFingerprint = fingerprint(status);
132
+ if (!force && nextFingerprint === lastFingerprint)
133
+ return;
134
+ lastFingerprint = nextFingerprint;
135
+ const event = { reason, status };
136
+ const targets = singleListener ? [singleListener] : [...listeners];
137
+ for (const listener of targets) {
138
+ try {
139
+ listener(event);
140
+ }
141
+ catch {
142
+ // A host callback cannot stop monitoring.
143
+ }
144
+ }
145
+ }
146
+ function fingerprint(status) {
147
+ return JSON.stringify(status);
148
+ }
149
+ /** Internal bridge for account mutations outside the registry module. */
150
+ export function _notifyAccountsChanged() {
151
+ _emitAccountsChanged('local');
152
+ }