better-codex 0.2.2 → 0.2.4

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.
@@ -74,7 +74,7 @@ export function Sidebar({ onNavigate }: SidebarProps) {
74
74
  }
75
75
 
76
76
  const handleAccountAuth = async (accountId: string, method: AuthMethod, apiKey?: string): Promise<boolean> => {
77
- if (connectionStatus !== 'connected') {
77
+ if (connectionStatus !== 'connected' || !hubClient.isConnected()) {
78
78
  setAlertDialog({
79
79
  open: true,
80
80
  title: 'Not Connected',
@@ -123,6 +123,9 @@ export const useHubConnection = () => {
123
123
  method: string,
124
124
  params?: unknown
125
125
  ): Promise<T | null> => {
126
+ if (disposed || !hubClient.isConnected()) {
127
+ return null
128
+ }
126
129
  try {
127
130
  return (await hubClient.request(profileId, method, params)) as T
128
131
  } catch (error) {
@@ -361,8 +361,12 @@ class HubClient {
361
361
  return data.sessions ?? []
362
362
  }
363
363
 
364
+ isConnected(): boolean {
365
+ return this.ws !== null && this.ws.readyState === WebSocket.OPEN
366
+ }
367
+
364
368
  private async sendRequest(profileId: string, method: string, params?: unknown): Promise<unknown> {
365
- if (!this.ws) {
369
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
366
370
  console.error('[HubClient] WebSocket not connected')
367
371
  throw new Error('WebSocket not connected')
368
372
  }
@@ -96,9 +96,15 @@ export const accountStatusFromRead = (result: AccountReadResult): AccountStatus
96
96
  }
97
97
 
98
98
  export const fetchAllModels = async (profileId: string): Promise<ModelInfo[]> => {
99
+ if (!hubClient.isConnected()) {
100
+ return []
101
+ }
99
102
  const models: ModelInfo[] = []
100
103
  let cursor: string | null = null
101
104
  for (let page = 0; page < 10; page += 1) {
105
+ if (!hubClient.isConnected()) {
106
+ return models
107
+ }
102
108
  let result: ModelListResult | null = null
103
109
  try {
104
110
  result = (await hubClient.request(profileId, 'model/list', {
@@ -125,6 +131,9 @@ export const refreshAccountSnapshot = async (
125
131
  updateAccount: (id: string, updater: (account: Account) => Account) => void,
126
132
  setModelsForAccount: (id: string, models: ModelInfo[]) => void
127
133
  ): Promise<void> => {
134
+ if (!hubClient.isConnected()) {
135
+ return
136
+ }
128
137
  let accountResult: AccountReadResult | null = null
129
138
  try {
130
139
  accountResult = (await hubClient.request(profileId, 'account/read', {
@@ -153,6 +153,7 @@ const isRoot = (dir) =>
153
153
  existsSync(join(dir, 'apps', 'web', 'package.json'));
154
154
 
155
155
  const findRoot = (explicit) => {
156
+ // If --root is provided, honor it as-is (after validation).
156
157
  if (explicit) {
157
158
  const resolved = resolve(explicit);
158
159
  if (isRoot(resolved)) {
@@ -161,6 +162,14 @@ const findRoot = (explicit) => {
161
162
  throw new Error(`Specified root does not contain apps/: ${explicit}`);
162
163
  }
163
164
 
165
+ // First, check if apps/ exists relative to this script (npm global install).
166
+ const scriptDir = __dirname;
167
+ const packageRoot = dirname(scriptDir);
168
+ if (isRoot(packageRoot)) {
169
+ return packageRoot;
170
+ }
171
+
172
+ // Fall back to searching from cwd (for development).
164
173
  let current = resolve(process.cwd());
165
174
  for (let depth = 0; depth < 8; depth += 1) {
166
175
  if (isRoot(current)) {
@@ -171,21 +180,9 @@ const findRoot = (explicit) => {
171
180
  current = parent;
172
181
  }
173
182
 
174
- const bundledRoot = resolve(dirname(__filename), '..');
175
- if (isRoot(bundledRoot)) {
176
- return bundledRoot;
177
- }
178
-
179
- const npmGlobalRoot = resolve(dirname(__filename), '..', '..');
180
- const npmPackageRoot = join(npmGlobalRoot, 'better-codex');
181
- if (isRoot(npmPackageRoot)) {
182
- return npmPackageRoot;
183
- }
184
-
185
183
  throw new Error(
186
- `Could not locate Better Codex apps.\n` +
187
- `The bundled apps may be missing. Try reinstalling:\n` +
188
- ` ${c.cyan}npm install -g better-codex${c.reset}`
184
+ `Could not locate Better Codex apps starting from ${process.cwd()}.\n` +
185
+ `Run the CLI from your project root or pass ${c.cyan}--root <path>${c.reset}.`
189
186
  );
190
187
  };
191
188
 
@@ -239,7 +236,8 @@ const runWeb = (options) => {
239
236
  log.success(`Bun ${c.dim}v${bunVersion}${c.reset}`);
240
237
 
241
238
  const root = findRoot(options.root);
242
- log.success(`Project root: ${c.dim}${root}${c.reset}`);
239
+ const workspaceDir = resolve(process.cwd());
240
+ log.success(`Workspace: ${c.dim}${workspaceDir}${c.reset}`);
243
241
 
244
242
  const backendDir = join(root, 'apps', 'backend');
245
243
  const webDir = join(root, 'apps', 'web');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-codex",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Web launcher for Codex Hub",
5
5
  "bin": {
6
6
  "better-codex": "bin/better-codex.cjs"