@oss-autopilot/core 1.8.0 → 1.9.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.
@@ -63,6 +63,7 @@ export { runCheckIntegration } from './check-integration.js';
63
63
  export { runDetectFormatters } from './detect-formatters.js';
64
64
  /** Scan for locally cloned repos. */
65
65
  export { runLocalRepos } from './local-repos.js';
66
+ export type { ErrorCode } from '../formatters/json.js';
66
67
  export type { DailyOutput, SearchOutput, StartupOutput, StatusOutput, TrackOutput } from '../formatters/json.js';
67
68
  export type { VetOutput, CommentsOutput, PostOutput, ClaimOutput } from '../formatters/json.js';
68
69
  export type { ConfigOutput, DetectFormattersOutput, ParseIssueListOutput, ParsedIssueItem, CheckIntegrationOutput, LocalReposOutput, } from '../formatters/json.js';
@@ -7,6 +7,7 @@
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
+ import * as path from 'path';
10
11
  import { execFile } from 'child_process';
11
12
  import { getStateManager, getGitHubToken, getCLIVersion, detectGitHubUsername } from '../core/index.js';
12
13
  import { errorMessage } from '../core/errors.js';
@@ -102,15 +103,36 @@ export function detectIssueList() {
102
103
  if (!issueListPath)
103
104
  return undefined;
104
105
  // 4. Count available/completed items
106
+ let availableCount = 0;
107
+ let completedCount = 0;
105
108
  try {
106
109
  const content = fs.readFileSync(issueListPath, 'utf-8');
107
- const { availableCount, completedCount } = countIssueListItems(content);
108
- return { path: issueListPath, source, availableCount, completedCount };
110
+ ({ availableCount, completedCount } = countIssueListItems(content));
109
111
  }
110
112
  catch (error) {
111
113
  console.error(`[STARTUP] Failed to read issue list at ${issueListPath}:`, errorMessage(error));
112
- return { path: issueListPath, source, availableCount: 0, completedCount: 0 };
113
114
  }
115
+ // 5. Detect skipped issues file
116
+ let skippedIssuesPath;
117
+ // Check config first
118
+ try {
119
+ const stateManager = getStateManager();
120
+ const configuredSkipPath = stateManager.getState().config.skippedIssuesPath;
121
+ if (configuredSkipPath && fs.existsSync(configuredSkipPath)) {
122
+ skippedIssuesPath = configuredSkipPath;
123
+ }
124
+ }
125
+ catch {
126
+ /* fall through */
127
+ }
128
+ // Probe default path: same directory as issue list, named skipped-issues.md
129
+ if (!skippedIssuesPath && issueListPath) {
130
+ const defaultSkipPath = path.join(path.dirname(issueListPath), 'skipped-issues.md');
131
+ if (fs.existsSync(defaultSkipPath)) {
132
+ skippedIssuesPath = defaultSkipPath;
133
+ }
134
+ }
135
+ return { path: issueListPath, source, availableCount, completedCount, skippedIssuesPath };
114
136
  }
115
137
  /**
116
138
  * Open a URL in the default system browser.
@@ -39,3 +39,9 @@ export declare function getHttpStatusCode(error: unknown): number | undefined;
39
39
  export declare function isRateLimitError(error: unknown): boolean;
40
40
  /** Return true for errors that should propagate (not degrade gracefully): rate limits, auth failures, abuse detection. */
41
41
  export declare function isRateLimitOrAuthError(err: unknown): boolean;
42
+ /**
43
+ * Map an unknown error to a structured ErrorCode for JSON output.
44
+ * Checks custom error classes, HTTP status codes (Octokit errors),
45
+ * and error message patterns in priority order.
46
+ */
47
+ export declare function resolveErrorCode(err: unknown): import('../formatters/json.js').ErrorCode;
@@ -75,3 +75,40 @@ export function isRateLimitOrAuthError(err) {
75
75
  }
76
76
  return false;
77
77
  }
78
+ /**
79
+ * Map an unknown error to a structured ErrorCode for JSON output.
80
+ * Checks custom error classes, HTTP status codes (Octokit errors),
81
+ * and error message patterns in priority order.
82
+ */
83
+ export function resolveErrorCode(err) {
84
+ // Check our custom error classes first
85
+ if (err instanceof ConfigurationError)
86
+ return 'CONFIGURATION';
87
+ if (err instanceof ValidationError)
88
+ return 'VALIDATION';
89
+ // Check HTTP status codes (Octokit errors)
90
+ const status = getHttpStatusCode(err);
91
+ if (status === 401)
92
+ return 'AUTH_REQUIRED';
93
+ if (status === 403) {
94
+ const msg = errorMessage(err).toLowerCase();
95
+ if (msg.includes('rate limit') || msg.includes('abuse detection'))
96
+ return 'RATE_LIMITED';
97
+ return 'AUTH_REQUIRED';
98
+ }
99
+ if (status === 404)
100
+ return 'NOT_FOUND';
101
+ if (status === 429)
102
+ return 'RATE_LIMITED';
103
+ // Check error message patterns
104
+ const msg = errorMessage(err).toLowerCase();
105
+ if (msg.includes('enotfound') ||
106
+ msg.includes('econnrefused') ||
107
+ msg.includes('econnreset') ||
108
+ msg.includes('etimedout') ||
109
+ msg.includes('fetch failed'))
110
+ return 'NETWORK';
111
+ if (msg.includes('state') && (msg.includes('corrupt') || msg.includes('invalid')))
112
+ return 'STATE_CORRUPTED';
113
+ return 'UNKNOWN';
114
+ }
@@ -10,7 +10,7 @@ export { IssueConversationMonitor } from './issue-conversation.js';
10
10
  export { isBotAuthor, isAcknowledgmentComment } from './comment-utils.js';
11
11
  export { getOctokit, checkRateLimit, type RateLimitInfo } from './github.js';
12
12
  export { parseGitHubUrl, daysBetween, splitRepo, isOwnRepo, getCLIVersion, getDataDir, getStatePath, getBackupDir, getCacheDir, formatRelativeTime, byDateDescending, getGitHubToken, getGitHubTokenAsync, requireGitHubToken, resetGitHubTokenCache, detectGitHubUsername, stateFileExists, DEFAULT_CONCURRENCY, } from './utils.js';
13
- export { OssAutopilotError, ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isRateLimitError, isRateLimitOrAuthError, } from './errors.js';
13
+ export { OssAutopilotError, ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isRateLimitError, isRateLimitOrAuthError, resolveErrorCode, } from './errors.js';
14
14
  export { enableDebug, isDebugEnabled, debug, info, warn, timed } from './logger.js';
15
15
  export { HttpCache, getHttpCache, cachedRequest, type CacheEntry } from './http-cache.js';
16
16
  export { CRITICAL_STATUSES, applyStatusOverrides, computeRepoSignals, groupPRsByRepo, assessCapacity, collectActionableIssues, computeActionMenu, toShelvedPRRef, formatActionHint, formatBriefSummary, formatSummary, printDigest, } from './daily-logic.js';
@@ -10,7 +10,7 @@ export { IssueConversationMonitor } from './issue-conversation.js';
10
10
  export { isBotAuthor, isAcknowledgmentComment } from './comment-utils.js';
11
11
  export { getOctokit, checkRateLimit } from './github.js';
12
12
  export { parseGitHubUrl, daysBetween, splitRepo, isOwnRepo, getCLIVersion, getDataDir, getStatePath, getBackupDir, getCacheDir, formatRelativeTime, byDateDescending, getGitHubToken, getGitHubTokenAsync, requireGitHubToken, resetGitHubTokenCache, detectGitHubUsername, stateFileExists, DEFAULT_CONCURRENCY, } from './utils.js';
13
- export { OssAutopilotError, ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isRateLimitError, isRateLimitOrAuthError, } from './errors.js';
13
+ export { OssAutopilotError, ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isRateLimitError, isRateLimitOrAuthError, resolveErrorCode, } from './errors.js';
14
14
  export { enableDebug, isDebugEnabled, debug, info, warn, timed } from './logger.js';
15
15
  export { HttpCache, getHttpCache, cachedRequest } from './http-cache.js';
16
16
  export { CRITICAL_STATUSES, applyStatusOverrides, computeRepoSignals, groupPRsByRepo, assessCapacity, collectActionableIssues, computeActionMenu, toShelvedPRRef, formatActionHint, formatBriefSummary, formatSummary, printDigest, } from './daily-logic.js';
@@ -229,6 +229,7 @@ export declare const AgentConfigSchema: z.ZodObject<{
229
229
  lastActivityAt: z.ZodString;
230
230
  }, z.core.$strip>>>;
231
231
  issueListPath: z.ZodOptional<z.ZodString>;
232
+ skippedIssuesPath: z.ZodOptional<z.ZodString>;
232
233
  projectCategories: z.ZodDefault<z.ZodArray<z.ZodEnum<{
233
234
  nonprofit: "nonprofit";
234
235
  devtools: "devtools";
@@ -375,6 +376,7 @@ export declare const AgentStateSchema: z.ZodObject<{
375
376
  lastActivityAt: z.ZodString;
376
377
  }, z.core.$strip>>>;
377
378
  issueListPath: z.ZodOptional<z.ZodString>;
379
+ skippedIssuesPath: z.ZodOptional<z.ZodString>;
378
380
  projectCategories: z.ZodDefault<z.ZodArray<z.ZodEnum<{
379
381
  nonprofit: "nonprofit";
380
382
  devtools: "devtools";
@@ -148,6 +148,7 @@ export const AgentConfigSchema = z.object({
148
148
  dismissedIssues: z.record(z.string(), z.string()).default({}),
149
149
  statusOverrides: z.record(z.string(), StatusOverrideSchema).optional(),
150
150
  issueListPath: z.string().optional(),
151
+ skippedIssuesPath: z.string().optional(),
151
152
  projectCategories: z.array(ProjectCategorySchema).default([]),
152
153
  preferredOrgs: z.array(z.string()).default([]),
153
154
  });
@@ -7,10 +7,12 @@ import type { ContributionStats } from '../core/stats.js';
7
7
  import type { PRCheckFailure } from '../core/pr-monitor.js';
8
8
  import type { SearchPriority } from '../core/types.js';
9
9
  import type { CIFormatterDiagnosis, FormatterDetectionResult } from '../core/formatter-detection.js';
10
+ export type ErrorCode = 'AUTH_REQUIRED' | 'RATE_LIMITED' | 'VALIDATION' | 'CONFIGURATION' | 'NETWORK' | 'NOT_FOUND' | 'STATE_CORRUPTED' | 'UNKNOWN';
10
11
  export interface JsonOutput<T = unknown> {
11
12
  success: boolean;
12
13
  data?: T;
13
14
  error?: string;
15
+ errorCode?: ErrorCode;
14
16
  timestamp: string;
15
17
  }
16
18
  export interface CapacityAssessment {
@@ -215,6 +217,7 @@ export interface IssueListInfo {
215
217
  source: 'configured' | 'auto-detected';
216
218
  availableCount: number;
217
219
  completedCount: number;
220
+ skippedIssuesPath?: string;
218
221
  }
219
222
  /**
220
223
  * Output of the startup command (combines auth, setup, daily, dashboard, issue list).
@@ -383,7 +386,7 @@ export declare function jsonSuccess<T>(data: T): JsonOutput<T>;
383
386
  /**
384
387
  * Create an error JSON output
385
388
  */
386
- export declare function jsonError(message: string): JsonOutput<never>;
389
+ export declare function jsonError(message: string, errorCode?: ErrorCode): JsonOutput<never>;
387
390
  /**
388
391
  * Output JSON to stdout
389
392
  */
@@ -391,4 +394,4 @@ export declare function outputJson<T>(data: T): void;
391
394
  /**
392
395
  * Output error JSON to stdout (sets success: false)
393
396
  */
394
- export declare function outputJsonError(message: string): void;
397
+ export declare function outputJsonError(message: string, errorCode?: ErrorCode): void;
@@ -85,10 +85,11 @@ export function jsonSuccess(data) {
85
85
  /**
86
86
  * Create an error JSON output
87
87
  */
88
- export function jsonError(message) {
88
+ export function jsonError(message, errorCode) {
89
89
  return {
90
90
  success: false,
91
91
  error: message,
92
+ errorCode,
92
93
  timestamp: new Date().toISOString(),
93
94
  };
94
95
  }
@@ -101,6 +102,6 @@ export function outputJson(data) {
101
102
  /**
102
103
  * Output error JSON to stdout (sets success: false)
103
104
  */
104
- export function outputJsonError(message) {
105
- console.log(JSON.stringify(jsonError(message), null, 2));
105
+ export function outputJsonError(message, errorCode) {
106
+ console.log(JSON.stringify(jsonError(message, errorCode), null, 2));
106
107
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-autopilot/core",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "CLI and core library for managing open source contributions",
5
5
  "type": "module",
6
6
  "bin": {