@oss-autopilot/core 0.41.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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -0
  3. package/dist/cli.bundle.cjs +17657 -0
  4. package/dist/cli.d.ts +12 -0
  5. package/dist/cli.js +325 -0
  6. package/dist/commands/check-integration.d.ts +10 -0
  7. package/dist/commands/check-integration.js +192 -0
  8. package/dist/commands/comments.d.ts +24 -0
  9. package/dist/commands/comments.js +311 -0
  10. package/dist/commands/config.d.ts +11 -0
  11. package/dist/commands/config.js +82 -0
  12. package/dist/commands/daily.d.ts +29 -0
  13. package/dist/commands/daily.js +433 -0
  14. package/dist/commands/dashboard-data.d.ts +45 -0
  15. package/dist/commands/dashboard-data.js +132 -0
  16. package/dist/commands/dashboard-templates.d.ts +23 -0
  17. package/dist/commands/dashboard-templates.js +1627 -0
  18. package/dist/commands/dashboard.d.ts +18 -0
  19. package/dist/commands/dashboard.js +134 -0
  20. package/dist/commands/dismiss.d.ts +13 -0
  21. package/dist/commands/dismiss.js +49 -0
  22. package/dist/commands/init.d.ts +10 -0
  23. package/dist/commands/init.js +27 -0
  24. package/dist/commands/local-repos.d.ts +14 -0
  25. package/dist/commands/local-repos.js +155 -0
  26. package/dist/commands/parse-list.d.ts +13 -0
  27. package/dist/commands/parse-list.js +139 -0
  28. package/dist/commands/read.d.ts +12 -0
  29. package/dist/commands/read.js +33 -0
  30. package/dist/commands/search.d.ts +10 -0
  31. package/dist/commands/search.js +74 -0
  32. package/dist/commands/setup.d.ts +15 -0
  33. package/dist/commands/setup.js +276 -0
  34. package/dist/commands/shelve.d.ts +13 -0
  35. package/dist/commands/shelve.js +49 -0
  36. package/dist/commands/snooze.d.ts +18 -0
  37. package/dist/commands/snooze.js +83 -0
  38. package/dist/commands/startup.d.ts +33 -0
  39. package/dist/commands/startup.js +197 -0
  40. package/dist/commands/status.d.ts +10 -0
  41. package/dist/commands/status.js +43 -0
  42. package/dist/commands/track.d.ts +16 -0
  43. package/dist/commands/track.js +59 -0
  44. package/dist/commands/validation.d.ts +43 -0
  45. package/dist/commands/validation.js +112 -0
  46. package/dist/commands/vet.d.ts +10 -0
  47. package/dist/commands/vet.js +36 -0
  48. package/dist/core/checklist-analysis.d.ts +17 -0
  49. package/dist/core/checklist-analysis.js +39 -0
  50. package/dist/core/ci-analysis.d.ts +78 -0
  51. package/dist/core/ci-analysis.js +163 -0
  52. package/dist/core/comment-utils.d.ts +15 -0
  53. package/dist/core/comment-utils.js +52 -0
  54. package/dist/core/concurrency.d.ts +5 -0
  55. package/dist/core/concurrency.js +15 -0
  56. package/dist/core/daily-logic.d.ts +77 -0
  57. package/dist/core/daily-logic.js +512 -0
  58. package/dist/core/display-utils.d.ts +10 -0
  59. package/dist/core/display-utils.js +100 -0
  60. package/dist/core/errors.d.ts +24 -0
  61. package/dist/core/errors.js +34 -0
  62. package/dist/core/github-stats.d.ts +73 -0
  63. package/dist/core/github-stats.js +272 -0
  64. package/dist/core/github.d.ts +19 -0
  65. package/dist/core/github.js +60 -0
  66. package/dist/core/http-cache.d.ts +97 -0
  67. package/dist/core/http-cache.js +269 -0
  68. package/dist/core/index.d.ts +15 -0
  69. package/dist/core/index.js +15 -0
  70. package/dist/core/issue-conversation.d.ts +29 -0
  71. package/dist/core/issue-conversation.js +231 -0
  72. package/dist/core/issue-discovery.d.ts +85 -0
  73. package/dist/core/issue-discovery.js +589 -0
  74. package/dist/core/issue-filtering.d.ts +51 -0
  75. package/dist/core/issue-filtering.js +103 -0
  76. package/dist/core/issue-scoring.d.ts +40 -0
  77. package/dist/core/issue-scoring.js +92 -0
  78. package/dist/core/issue-vetting.d.ts +49 -0
  79. package/dist/core/issue-vetting.js +536 -0
  80. package/dist/core/logger.d.ts +21 -0
  81. package/dist/core/logger.js +49 -0
  82. package/dist/core/maintainer-analysis.d.ts +10 -0
  83. package/dist/core/maintainer-analysis.js +59 -0
  84. package/dist/core/pagination.d.ts +11 -0
  85. package/dist/core/pagination.js +20 -0
  86. package/dist/core/pr-monitor.d.ts +109 -0
  87. package/dist/core/pr-monitor.js +594 -0
  88. package/dist/core/review-analysis.d.ts +72 -0
  89. package/dist/core/review-analysis.js +163 -0
  90. package/dist/core/state.d.ts +371 -0
  91. package/dist/core/state.js +1089 -0
  92. package/dist/core/types.d.ts +507 -0
  93. package/dist/core/types.js +34 -0
  94. package/dist/core/utils.d.ts +249 -0
  95. package/dist/core/utils.js +422 -0
  96. package/dist/formatters/json.d.ts +269 -0
  97. package/dist/formatters/json.js +88 -0
  98. package/package.json +67 -0
@@ -0,0 +1,269 @@
1
+ /**
2
+ * JSON output formatter for CLI --json mode
3
+ * Provides structured output that can be consumed by scripts and plugins
4
+ */
5
+ import type { FetchedPR, DailyDigest, AgentState, RepoGroup, CommentedIssue, ShelvedPRRef } from '../core/types.js';
6
+ import type { PRCheckFailure } from '../core/pr-monitor.js';
7
+ import type { SearchPriority } from '../core/issue-discovery.js';
8
+ export interface JsonOutput<T = unknown> {
9
+ success: boolean;
10
+ data?: T;
11
+ error?: string;
12
+ timestamp: string;
13
+ }
14
+ export interface CapacityAssessment {
15
+ hasCapacity: boolean;
16
+ activePRCount: number;
17
+ maxActivePRs: number;
18
+ shelvedPRCount: number;
19
+ criticalIssueCount: number;
20
+ reason: string;
21
+ }
22
+ export type ActionableIssueType = 'ci_failing' | 'merge_conflict' | 'needs_response' | 'needs_changes' | 'incomplete_checklist';
23
+ export interface ActionableIssue {
24
+ type: ActionableIssueType;
25
+ pr: FetchedPR;
26
+ label: string;
27
+ }
28
+ /**
29
+ * Compact version of ActionableIssue for JSON output.
30
+ * References the PR by URL instead of embedding the full object,
31
+ * since the full PR is already available in digest.openPRs.
32
+ * Uses URL (globally unique) instead of number to avoid cross-repo collisions.
33
+ */
34
+ export interface CompactActionableIssue {
35
+ type: ActionableIssueType;
36
+ prUrl: string;
37
+ label: string;
38
+ }
39
+ /**
40
+ * A single action menu item pre-computed by the CLI.
41
+ * The orchestration layer can use these directly in AskUserQuestion prompts.
42
+ */
43
+ export interface ActionMenuItem {
44
+ /** Stable identifier for routing (e.g., "address_all", "search", "done"). */
45
+ key: string;
46
+ /** Display text for the option (e.g., "Work through all 3 issues (Recommended)"). */
47
+ label: string;
48
+ /** Explanation shown below the label. */
49
+ description: string;
50
+ }
51
+ /**
52
+ * Pre-computed action menu for the orchestration layer.
53
+ * Contains the menu items the CLI can determine from PR data and capacity,
54
+ * plus context flags so the orchestration can insert issue-list options.
55
+ */
56
+ export interface ActionMenu {
57
+ /** Ordered list of menu items. The orchestration may insert issue-list items after the CLI-generated items (address_all, issue_replies) or at the start when none exist. */
58
+ items: ActionMenuItem[];
59
+ /** Context flags for the orchestration layer to decide on issue-list options. */
60
+ context: {
61
+ hasActionableIssues: boolean;
62
+ actionableCount: number;
63
+ hasCapacity: boolean;
64
+ hasIssueResponses: boolean;
65
+ issueResponseCount: number;
66
+ };
67
+ }
68
+ /**
69
+ * Deduplicated daily digest for JSON output (#287).
70
+ *
71
+ * Full PR objects live only in `openPRs`. Category arrays contain PR URLs
72
+ * that reference into `openPRs`, reducing JSON payload size by ~60-70%.
73
+ * Uses URLs (globally unique) instead of numbers to avoid cross-repo collisions.
74
+ * Consumers look up full PR details via: openPRs.find(pr => pr.url === url)
75
+ */
76
+ export interface DailyDigestCompact {
77
+ generatedAt: string;
78
+ /** All open PRs authored by the user — the single source of truth for full PR objects. */
79
+ openPRs: FetchedPR[];
80
+ prsNeedingResponse: string[];
81
+ ciFailingPRs: string[];
82
+ ciBlockedPRs: string[];
83
+ ciNotRunningPRs: string[];
84
+ mergeConflictPRs: string[];
85
+ needsRebasePRs: string[];
86
+ missingRequiredFilesPRs: string[];
87
+ incompleteChecklistPRs: string[];
88
+ needsChangesPRs: string[];
89
+ changesAddressedPRs: string[];
90
+ waitingOnMaintainerPRs: string[];
91
+ approachingDormant: string[];
92
+ dormantPRs: string[];
93
+ healthyPRs: string[];
94
+ recentlyClosedPRs: DailyDigest['recentlyClosedPRs'];
95
+ recentlyMergedPRs: DailyDigest['recentlyMergedPRs'];
96
+ shelvedPRs: ShelvedPRRef[];
97
+ autoUnshelvedPRs: ShelvedPRRef[];
98
+ summary: DailyDigest['summary'];
99
+ }
100
+ /**
101
+ * Compact repo group for JSON output (#287).
102
+ * Uses PR URLs instead of full objects; look up in digest.openPRs.
103
+ * Uses URLs (globally unique) instead of numbers to avoid cross-repo collisions.
104
+ */
105
+ export interface CompactRepoGroup {
106
+ repo: string;
107
+ prUrls: string[];
108
+ }
109
+ export interface DailyOutput {
110
+ digest: DailyDigestCompact;
111
+ updates: unknown[];
112
+ capacity: CapacityAssessment;
113
+ summary: string;
114
+ briefSummary: string;
115
+ actionableIssues: CompactActionableIssue[];
116
+ actionMenu: ActionMenu;
117
+ commentedIssues: CommentedIssue[];
118
+ repoGroups: CompactRepoGroup[];
119
+ failures: PRCheckFailure[];
120
+ }
121
+ /**
122
+ * Convert a full DailyDigest to the compact format for JSON output (#287).
123
+ * Category arrays become PR URL arrays; full objects stay only in openPRs.
124
+ * Uses URLs (globally unique) instead of numbers to avoid cross-repo collisions.
125
+ */
126
+ export declare function deduplicateDigest(digest: DailyDigest): DailyDigestCompact;
127
+ /**
128
+ * Convert ActionableIssue[] to CompactActionableIssue[] for JSON output (#287).
129
+ * Replaces the full PR object with just the PR URL (globally unique).
130
+ */
131
+ export declare function compactActionableIssues(issues: ActionableIssue[]): CompactActionableIssue[];
132
+ /**
133
+ * Convert RepoGroup[] to CompactRepoGroup[] for JSON output (#287).
134
+ * Replaces full PR arrays with PR URL arrays.
135
+ */
136
+ export declare function compactRepoGroups(groups: RepoGroup[]): CompactRepoGroup[];
137
+ export interface StatusOutput {
138
+ stats: {
139
+ mergedPRs: number;
140
+ closedPRs: number;
141
+ activeIssues: number;
142
+ trustedProjects: number;
143
+ mergeRate: string;
144
+ needsResponse: number;
145
+ };
146
+ lastRunAt: string;
147
+ offline?: boolean;
148
+ lastUpdated?: string;
149
+ }
150
+ export interface SearchOutput {
151
+ candidates: Array<{
152
+ issue: {
153
+ repo: string;
154
+ number: number;
155
+ title: string;
156
+ url: string;
157
+ labels: string[];
158
+ };
159
+ recommendation: 'approve' | 'skip' | 'needs_review';
160
+ reasonsToApprove: string[];
161
+ reasonsToSkip: string[];
162
+ searchPriority: SearchPriority;
163
+ /** 0-100 scale composite viability score */
164
+ viabilityScore: number;
165
+ repoScore?: {
166
+ /** 1-10 scale repository quality score */
167
+ score: number;
168
+ mergedPRCount: number;
169
+ closedWithoutMergeCount: number;
170
+ isResponsive: boolean;
171
+ lastMergedAt?: string;
172
+ };
173
+ }>;
174
+ excludedRepos: string[];
175
+ /** Repos with known anti-AI contribution policies, filtered from search results (#108). */
176
+ aiPolicyBlocklist: string[];
177
+ /** Present when rate limits affected the search — either low pre-flight quota or mid-search rate limit hits (#100). */
178
+ rateLimitWarning?: string;
179
+ }
180
+ export interface TrackOutput {
181
+ pr: {
182
+ repo: string;
183
+ number: number;
184
+ title: string;
185
+ url: string;
186
+ };
187
+ }
188
+ export interface ConfigOutput {
189
+ config: AgentState['config'];
190
+ }
191
+ /** Info about a detected issue list file */
192
+ export interface IssueListInfo {
193
+ path: string;
194
+ source: 'configured' | 'auto-detected';
195
+ availableCount: number;
196
+ completedCount: number;
197
+ }
198
+ /**
199
+ * Output of the startup command (combines auth, setup, daily, dashboard, issue list).
200
+ *
201
+ * Three valid shapes:
202
+ * 1. Setup incomplete: { version, setupComplete: false }
203
+ * 2. Auth failure: { version, setupComplete: true, authError: "..." }
204
+ * 3. Success: { version, setupComplete: true, daily, dashboardPath?, issueList? }
205
+ */
206
+ export interface StartupOutput {
207
+ version: string;
208
+ setupComplete: boolean;
209
+ authError?: string;
210
+ daily?: DailyOutput;
211
+ dashboardPath?: string;
212
+ issueList?: IssueListInfo;
213
+ }
214
+ /** A single parsed issue from a markdown list (#82) */
215
+ export interface ParsedIssueItem {
216
+ repo: string;
217
+ number: number;
218
+ title: string;
219
+ tier: string;
220
+ url: string;
221
+ }
222
+ /** Output of the parse-issue-list command (#82) */
223
+ export interface ParseIssueListOutput {
224
+ available: ParsedIssueItem[];
225
+ completed: ParsedIssueItem[];
226
+ availableCount: number;
227
+ completedCount: number;
228
+ }
229
+ /** Info about a new file's integration status (#83) */
230
+ export interface NewFileInfo {
231
+ path: string;
232
+ referencedBy: string[];
233
+ isIntegrated: boolean;
234
+ suggestedEntryPoints?: string[];
235
+ }
236
+ /** Output of the check-integration command (#83) */
237
+ export interface CheckIntegrationOutput {
238
+ newFiles: NewFileInfo[];
239
+ unreferencedCount: number;
240
+ }
241
+ /** Info about a local git clone (#84) */
242
+ export interface LocalRepoInfo {
243
+ path: string;
244
+ exists: boolean;
245
+ currentBranch: string | null;
246
+ }
247
+ /** Output of the local-repos command (#84) */
248
+ export interface LocalReposOutput {
249
+ repos: Record<string, LocalRepoInfo>;
250
+ scanPaths: string[];
251
+ cachedAt: string;
252
+ fromCache: boolean;
253
+ }
254
+ /**
255
+ * Wrap data in a standard JSON output envelope
256
+ */
257
+ export declare function jsonSuccess<T>(data: T): JsonOutput<T>;
258
+ /**
259
+ * Create an error JSON output
260
+ */
261
+ export declare function jsonError(message: string): JsonOutput<never>;
262
+ /**
263
+ * Output JSON to stdout
264
+ */
265
+ export declare function outputJson<T>(data: T): void;
266
+ /**
267
+ * Output error JSON to stdout (sets success: false)
268
+ */
269
+ export declare function outputJsonError(message: string): void;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * JSON output formatter for CLI --json mode
3
+ * Provides structured output that can be consumed by scripts and plugins
4
+ */
5
+ /**
6
+ * Convert a full DailyDigest to the compact format for JSON output (#287).
7
+ * Category arrays become PR URL arrays; full objects stay only in openPRs.
8
+ * Uses URLs (globally unique) instead of numbers to avoid cross-repo collisions.
9
+ */
10
+ export function deduplicateDigest(digest) {
11
+ const toUrls = (prs) => prs.map((pr) => pr.url);
12
+ return {
13
+ generatedAt: digest.generatedAt,
14
+ openPRs: digest.openPRs,
15
+ prsNeedingResponse: toUrls(digest.prsNeedingResponse),
16
+ ciFailingPRs: toUrls(digest.ciFailingPRs),
17
+ ciBlockedPRs: toUrls(digest.ciBlockedPRs),
18
+ ciNotRunningPRs: toUrls(digest.ciNotRunningPRs),
19
+ mergeConflictPRs: toUrls(digest.mergeConflictPRs),
20
+ needsRebasePRs: toUrls(digest.needsRebasePRs),
21
+ missingRequiredFilesPRs: toUrls(digest.missingRequiredFilesPRs),
22
+ incompleteChecklistPRs: toUrls(digest.incompleteChecklistPRs),
23
+ needsChangesPRs: toUrls(digest.needsChangesPRs),
24
+ changesAddressedPRs: toUrls(digest.changesAddressedPRs),
25
+ waitingOnMaintainerPRs: toUrls(digest.waitingOnMaintainerPRs),
26
+ approachingDormant: toUrls(digest.approachingDormant),
27
+ dormantPRs: toUrls(digest.dormantPRs),
28
+ healthyPRs: toUrls(digest.healthyPRs),
29
+ recentlyClosedPRs: digest.recentlyClosedPRs,
30
+ recentlyMergedPRs: digest.recentlyMergedPRs,
31
+ shelvedPRs: digest.shelvedPRs,
32
+ autoUnshelvedPRs: digest.autoUnshelvedPRs,
33
+ summary: digest.summary,
34
+ };
35
+ }
36
+ /**
37
+ * Convert ActionableIssue[] to CompactActionableIssue[] for JSON output (#287).
38
+ * Replaces the full PR object with just the PR URL (globally unique).
39
+ */
40
+ export function compactActionableIssues(issues) {
41
+ return issues.map((issue) => ({
42
+ type: issue.type,
43
+ prUrl: issue.pr.url,
44
+ label: issue.label,
45
+ }));
46
+ }
47
+ /**
48
+ * Convert RepoGroup[] to CompactRepoGroup[] for JSON output (#287).
49
+ * Replaces full PR arrays with PR URL arrays.
50
+ */
51
+ export function compactRepoGroups(groups) {
52
+ return groups.map((group) => ({
53
+ repo: group.repo,
54
+ prUrls: group.prs.map((pr) => pr.url),
55
+ }));
56
+ }
57
+ /**
58
+ * Wrap data in a standard JSON output envelope
59
+ */
60
+ export function jsonSuccess(data) {
61
+ return {
62
+ success: true,
63
+ data,
64
+ timestamp: new Date().toISOString(),
65
+ };
66
+ }
67
+ /**
68
+ * Create an error JSON output
69
+ */
70
+ export function jsonError(message) {
71
+ return {
72
+ success: false,
73
+ error: message,
74
+ timestamp: new Date().toISOString(),
75
+ };
76
+ }
77
+ /**
78
+ * Output JSON to stdout
79
+ */
80
+ export function outputJson(data) {
81
+ console.log(JSON.stringify(jsonSuccess(data), null, 2));
82
+ }
83
+ /**
84
+ * Output error JSON to stdout (sets success: false)
85
+ */
86
+ export function outputJsonError(message) {
87
+ console.log(JSON.stringify(jsonError(message), null, 2));
88
+ }
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@oss-autopilot/core",
3
+ "version": "0.41.0",
4
+ "description": "CLI and core library for managing open source contributions",
5
+ "type": "module",
6
+ "bin": {
7
+ "oss-autopilot": "./dist/cli.bundle.cjs"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/core/index.js",
12
+ "types": "./dist/core/index.d.ts"
13
+ },
14
+ "./types": {
15
+ "import": "./dist/core/types.js",
16
+ "types": "./dist/core/types.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist/"
21
+ ],
22
+ "keywords": [
23
+ "open-source",
24
+ "github",
25
+ "contributions",
26
+ "cli",
27
+ "pr-monitoring",
28
+ "issue-discovery"
29
+ ],
30
+ "author": "John Costa",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/costajohnt/oss-autopilot.git",
35
+ "directory": "packages/core"
36
+ },
37
+ "homepage": "https://github.com/costajohnt/oss-autopilot#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/costajohnt/oss-autopilot/issues"
40
+ },
41
+ "engines": {
42
+ "node": ">=20.0.0"
43
+ },
44
+ "dependencies": {
45
+ "@octokit/plugin-throttling": "^11.0.3",
46
+ "@octokit/rest": "^22.0.1",
47
+ "commander": "^14.0.3"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^25.3.0",
51
+ "@vitest/coverage-v8": "^4.0.18",
52
+ "esbuild": "^0.27.3",
53
+ "tsx": "^4.21.0",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^4.0.16"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc",
59
+ "bundle": "esbuild src/cli.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/cli.bundle.cjs",
60
+ "start": "tsx src/cli.ts",
61
+ "dev": "tsx watch src/cli.ts",
62
+ "typecheck": "tsc --noEmit",
63
+ "test": "vitest run",
64
+ "test:coverage": "vitest run --coverage",
65
+ "test:watch": "vitest"
66
+ }
67
+ }