@oss-autopilot/core 0.43.1 → 0.44.0

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.
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * Startup command
3
3
  * Combines all pre-flight checks into a single CLI invocation:
4
- * auth check, setup check, daily fetch, dashboard generation, version detection, issue list detection.
4
+ * auth check, setup check, daily fetch, dashboard launch, version detection, issue list detection.
5
5
  *
6
6
  * Replaces the ~100-line inline bash script in commands/oss.md with a single
7
7
  * `node cli.bundle.cjs startup --json` call, reducing UI noise in Claude Code.
8
8
  */
9
9
  import * as fs from 'fs';
10
10
  import { execFile } from 'child_process';
11
- import { getStateManager, getGitHubToken, getCLIVersion, getStatePath, getDashboardPath } from '../core/index.js';
11
+ import { getStateManager, getGitHubToken, getCLIVersion } from '../core/index.js';
12
12
  import { errorMessage } from '../core/errors.js';
13
- import { warn } from '../core/logger.js';
14
13
  import { executeDailyCheck } from './daily.js';
15
- import { writeDashboardFromState } from './dashboard.js';
16
14
  import { launchDashboardServer } from './dashboard-lifecycle.js';
15
+ import { writeDashboardFromState } from './dashboard.js';
17
16
  /**
18
17
  * Parse issueListPath from a config file's YAML frontmatter.
19
18
  * Returns the path string or undefined if not found.
@@ -94,21 +93,21 @@ export function detectIssueList() {
94
93
  return { path: issueListPath, source, availableCount: 0, completedCount: 0 };
95
94
  }
96
95
  }
97
- function openInBrowser(filePath) {
96
+ export function openInBrowser(url) {
98
97
  let openCmd;
99
98
  let args;
100
99
  switch (process.platform) {
101
100
  case 'darwin':
102
101
  openCmd = 'open';
103
- args = [filePath];
102
+ args = [url];
104
103
  break;
105
104
  case 'win32':
106
105
  openCmd = 'cmd';
107
- args = ['/c', 'start', '', filePath];
106
+ args = ['/c', 'start', '', url];
108
107
  break;
109
108
  default:
110
109
  openCmd = 'xdg-open';
111
- args = [filePath];
110
+ args = [url];
112
111
  break;
113
112
  }
114
113
  execFile(openCmd, args, (error) => {
@@ -117,31 +116,12 @@ function openInBrowser(filePath) {
117
116
  }
118
117
  });
119
118
  }
120
- /**
121
- * Check whether the dashboard HTML file is at least as recent as state.json.
122
- * Returns true when the dashboard exists and its mtime >= state mtime,
123
- * meaning there is no need to regenerate it.
124
- */
125
- function isDashboardFresh() {
126
- try {
127
- const dashPath = getDashboardPath();
128
- if (!fs.existsSync(dashPath))
129
- return false;
130
- const dashMtime = fs.statSync(dashPath).mtimeMs;
131
- const stateMtime = fs.statSync(getStatePath()).mtimeMs;
132
- return dashMtime >= stateMtime;
133
- }
134
- catch (error) {
135
- warn('startup', `Failed to check dashboard freshness, will regenerate: ${errorMessage(error)}`);
136
- return false;
137
- }
138
- }
139
119
  /**
140
120
  * Run startup checks and return structured output.
141
121
  * Returns StartupOutput with one of three shapes:
142
122
  * 1. Setup incomplete: { version, setupComplete: false }
143
123
  * 2. Auth failure: { version, setupComplete: true, authError: "..." }
144
- * 3. Success: { version, setupComplete: true, daily, dashboardPath?, dashboardUrl?, issueList? }
124
+ * 3. Success: { version, setupComplete: true, daily, dashboardUrl?, dashboardPath?, issueList? }
145
125
  *
146
126
  * Errors from the daily check propagate to the caller.
147
127
  */
@@ -163,56 +143,52 @@ export async function runStartup() {
163
143
  }
164
144
  // 3. Run daily check
165
145
  const daily = await executeDailyCheck(token);
166
- // 4. Generate static HTML dashboard (serves as fallback + snapshot).
167
- // Skip regeneration if the dashboard HTML is already newer than state.json.
146
+ // 4. Launch interactive SPA dashboard (with static HTML fallback)
147
+ // Skip opening on first run (0 PRs) the welcome flow handles onboarding
148
+ let dashboardUrl;
168
149
  let dashboardPath;
169
- try {
170
- if (isDashboardFresh()) {
171
- dashboardPath = getDashboardPath();
172
- console.error('[STARTUP] Dashboard HTML is fresh, skipping regeneration');
173
- }
174
- else {
150
+ let dashboardOpened = false;
151
+ function tryStaticHtmlFallback() {
152
+ try {
175
153
  dashboardPath = writeDashboardFromState();
154
+ openInBrowser(dashboardPath);
155
+ return true;
156
+ }
157
+ catch (htmlError) {
158
+ console.error('[STARTUP] Static HTML dashboard fallback also failed:', errorMessage(htmlError));
159
+ return false;
176
160
  }
177
161
  }
178
- catch (error) {
179
- console.error('[STARTUP] Dashboard generation failed:', errorMessage(error));
180
- }
181
- // 5. Launch interactive SPA dashboard (preferred) with static HTML fallback
182
- // Skip opening on first run (0 PRs) — the welcome flow handles onboarding
183
- let dashboardUrl;
184
- let dashboardOpened = false;
185
162
  if (daily.digest.summary.totalActivePRs > 0) {
186
- let spaResult = null;
187
163
  try {
188
- spaResult = await launchDashboardServer();
164
+ const spaResult = await launchDashboardServer();
165
+ if (spaResult) {
166
+ dashboardUrl = spaResult.url;
167
+ openInBrowser(spaResult.url);
168
+ dashboardOpened = true;
169
+ }
170
+ else {
171
+ console.error('[STARTUP] Dashboard SPA assets not found, falling back to static HTML dashboard');
172
+ dashboardOpened = tryStaticHtmlFallback();
173
+ }
189
174
  }
190
175
  catch (error) {
191
176
  console.error('[STARTUP] SPA dashboard launch failed:', errorMessage(error));
192
- }
193
- if (spaResult) {
194
- dashboardUrl = spaResult.url;
195
- openInBrowser(spaResult.url);
196
- dashboardOpened = true;
197
- }
198
- else if (dashboardPath) {
199
- // SPA unavailable (assets not built) — fall back to static HTML
200
- openInBrowser(dashboardPath);
201
- dashboardOpened = true;
177
+ dashboardOpened = tryStaticHtmlFallback();
202
178
  }
203
179
  }
204
180
  // Append dashboard status to brief summary (only startup opens the browser, not daily)
205
181
  if (dashboardOpened) {
206
182
  daily.briefSummary += ' | Dashboard opened in browser';
207
183
  }
208
- // 6. Detect issue list
184
+ // 5. Detect issue list
209
185
  const issueList = detectIssueList();
210
186
  return {
211
187
  version,
212
188
  setupComplete: true,
213
189
  daily,
214
- dashboardPath,
215
190
  dashboardUrl,
191
+ dashboardPath,
216
192
  issueList,
217
193
  };
218
194
  }
@@ -509,5 +509,5 @@ export function printDigest(digest, capacity, commentedIssues = []) {
509
509
  console.log('');
510
510
  }
511
511
  console.log('Run with --json for structured output');
512
- console.log('Run "dashboard --open" for browser view');
512
+ console.log('Run "dashboard serve" for browser view');
513
513
  }
@@ -5,7 +5,7 @@
5
5
  * Returns the oss-autopilot data directory path, creating it if it does not exist.
6
6
  *
7
7
  * The directory is located at `~/.oss-autopilot/` and serves as the root for
8
- * all persisted user data (state, backups, dashboard).
8
+ * all persisted user data (state, backups, cache).
9
9
  *
10
10
  * @returns Absolute path to the data directory (e.g., `/Users/you/.oss-autopilot`)
11
11
  *
@@ -53,11 +53,8 @@ export declare function getBackupDir(): string;
53
53
  */
54
54
  export declare function getCacheDir(): string;
55
55
  /**
56
- * Returns the path to the generated HTML dashboard file (`~/.oss-autopilot/dashboard.html`).
57
- *
58
- * Implicitly creates the data directory via {@link getDataDir} if it does not exist.
59
- *
60
- * @returns Absolute path to `dashboard.html`
56
+ * Returns the path to the static HTML dashboard file (~/.oss-autopilot/dashboard.html).
57
+ * Used as a fallback when the interactive SPA dashboard cannot be launched.
61
58
  *
62
59
  * @example
63
60
  * const dashPath = getDashboardPath();
@@ -15,7 +15,7 @@ let tokenFetchAttempted = false;
15
15
  * Returns the oss-autopilot data directory path, creating it if it does not exist.
16
16
  *
17
17
  * The directory is located at `~/.oss-autopilot/` and serves as the root for
18
- * all persisted user data (state, backups, dashboard).
18
+ * all persisted user data (state, backups, cache).
19
19
  *
20
20
  * @returns Absolute path to the data directory (e.g., `/Users/you/.oss-autopilot`)
21
21
  *
@@ -83,11 +83,8 @@ export function getCacheDir() {
83
83
  return dir;
84
84
  }
85
85
  /**
86
- * Returns the path to the generated HTML dashboard file (`~/.oss-autopilot/dashboard.html`).
87
- *
88
- * Implicitly creates the data directory via {@link getDataDir} if it does not exist.
89
- *
90
- * @returns Absolute path to `dashboard.html`
86
+ * Returns the path to the static HTML dashboard file (~/.oss-autopilot/dashboard.html).
87
+ * Used as a fallback when the interactive SPA dashboard cannot be launched.
91
88
  *
92
89
  * @example
93
90
  * const dashPath = getDashboardPath();
@@ -200,16 +200,17 @@ export interface IssueListInfo {
200
200
  * Three valid shapes:
201
201
  * 1. Setup incomplete: { version, setupComplete: false }
202
202
  * 2. Auth failure: { version, setupComplete: true, authError: "..." }
203
- * 3. Success: { version, setupComplete: true, daily, dashboardPath?, dashboardUrl?, issueList? }
203
+ * 3. Success: { version, setupComplete: true, daily, dashboardUrl?, issueList? }
204
204
  */
205
205
  export interface StartupOutput {
206
206
  version: string;
207
207
  setupComplete: boolean;
208
208
  authError?: string;
209
209
  daily?: DailyOutput;
210
- dashboardPath?: string;
211
210
  /** URL of the interactive SPA dashboard server, when running (e.g., "http://localhost:3000") */
212
211
  dashboardUrl?: string;
212
+ /** Path to the static HTML dashboard file (fallback when SPA cannot launch) */
213
+ dashboardPath?: string;
213
214
  issueList?: IssueListInfo;
214
215
  }
215
216
  /** A single parsed issue from a markdown list (#82) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-autopilot/core",
3
- "version": "0.43.1",
3
+ "version": "0.44.0",
4
4
  "description": "CLI and core library for managing open source contributions",
5
5
  "type": "module",
6
6
  "bin": {