neondeck 1.0.0-beta.7 → 1.0.0-beta.9
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.
- package/CHANGELOG.md +18 -0
- package/config/dashboard.json +9 -2
- package/config/dashboard.schema.json +8 -3
- package/dist/assets/{app-BBIuPG77.js → app-ChpCY1hX.js} +335 -19
- package/dist/assets/app-ChpCY1hX.js.map +1 -0
- package/dist/assets/{autopilot-CnHJWMaF.js → autopilot-CMaU1iZd.js} +142 -30
- package/dist/assets/autopilot-CMaU1iZd.js.map +1 -0
- package/dist/assets/briefing-Bxg1ctBW.js +2 -0
- package/dist/assets/{briefing-hpGB8E6A.js → briefing-Cf4ZpqPr.js} +4 -4
- package/dist/assets/{briefing-hpGB8E6A.js.map → briefing-Cf4ZpqPr.js.map} +1 -1
- package/dist/assets/{briefings-DpDKxWsT.js → briefings-DtOcw7y6.js} +30 -16
- package/dist/assets/briefings-DtOcw7y6.js.map +1 -0
- package/dist/assets/{command-run-Dwt42N9e.js → command-run-B9uZYF9u.js} +4 -4
- package/dist/assets/{command-run-Dwt42N9e.js.map → command-run-B9uZYF9u.js.map} +1 -1
- package/dist/assets/command-run-CNnU2WOV.js +2 -0
- package/dist/assets/{display-assistant-Dwqj18Ka.js → display-assistant-DEh-qGUl.js} +6 -6
- package/dist/assets/{display-assistant-Dwqj18Ka.js.map → display-assistant-DEh-qGUl.js.map} +1 -1
- package/dist/assets/fix-pr-ci-DFdWMhjV.js +2 -0
- package/dist/assets/{fix-pr-ci-C7c6tPL_.js → fix-pr-ci-DolohowP.js} +2 -2
- package/dist/assets/{fix-pr-ci-C7c6tPL_.js.map → fix-pr-ci-DolohowP.js.map} +1 -1
- package/dist/assets/migrations/20260714213018_pr_reviews/migration.sql +34 -0
- package/dist/assets/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
- package/dist/assets/pr-reviews-CbYcf9Mj.js +522 -0
- package/dist/assets/pr-reviews-CbYcf9Mj.js.map +1 -0
- package/dist/assets/{prepare-pr-worktree-GIZ8cMUj.js → prepare-pr-worktree-CwalJPIV.js} +1 -1
- package/dist/assets/{prepare-pr-worktree-CckbyTsB.js → prepare-pr-worktree-D3gy9Uof.js} +3 -3
- package/dist/assets/{prepare-pr-worktree-CckbyTsB.js.map → prepare-pr-worktree-D3gy9Uof.js.map} +1 -1
- package/dist/assets/{push-pr-autofix-w85pTU9W.js → push-pr-autofix-DUXYeBds.js} +1 -1
- package/dist/assets/{push-pr-autofix-CQTtK2HC.js → push-pr-autofix-OOoR6FIp.js} +3 -3
- package/dist/assets/{push-pr-autofix-CQTtK2HC.js.map → push-pr-autofix-OOoR6FIp.js.map} +1 -1
- package/dist/assets/{review-pr-for-human-C_OT_LFW.js → review-pr-for-human-5oA8Lnwm.js} +100 -27
- package/dist/assets/review-pr-for-human-5oA8Lnwm.js.map +1 -0
- package/dist/assets/{review-pr-for-human-BQjIMKW2.js → review-pr-for-human-CTIL0RRy.js} +1 -1
- package/dist/assets/{safety-EnvDg7cY.js → safety-S_Ek3ETH.js} +20 -4
- package/dist/assets/safety-S_Ek3ETH.js.map +1 -0
- package/dist/assets/{scheduled-agent-instruction-B_K6qYBk.js → scheduled-agent-instruction-C7Xz50tm.js} +1 -1
- package/dist/assets/{scheduled-agent-instruction-BdSpSyHS.js → scheduled-agent-instruction-CEpmfBNA.js} +3 -3
- package/dist/assets/{scheduled-agent-instruction-BdSpSyHS.js.map → scheduled-agent-instruction-CEpmfBNA.js.map} +1 -1
- package/dist/assets/{scheduler-tick-DdiWIWU2.js → scheduler-tick-DO_6nnY9.js} +4 -4
- package/dist/assets/{scheduler-tick-DdiWIWU2.js.map → scheduler-tick-DO_6nnY9.js.map} +1 -1
- package/dist/assets/{scheduler-workflow-DoAFm2Pl.js → scheduler-workflow-CwK7no2d.js} +2 -2
- package/dist/assets/{scheduler-workflow-DoAFm2Pl.js.map → scheduler-workflow-CwK7no2d.js.map} +1 -1
- package/dist/assets/skills/neon-pr-review/SKILL.md +1 -1
- package/dist/assets/skills/neondeck/SKILL.md +1 -1
- package/dist/assets/{triage-pr-event-BIDtSjo4.js → triage-pr-event-C2g4s1dt.js} +1 -1
- package/dist/assets/{triage-pr-event-Dnetiswf.js → triage-pr-event-CCNMZZPE.js} +3 -3
- package/dist/assets/{triage-pr-event-Dnetiswf.js.map → triage-pr-event-CCNMZZPE.js.map} +1 -1
- package/dist/assets/{verify-then-push-pr-autofix-CBrpMv6H.js → verify-then-push-pr-autofix-9Dzuwky_.js} +1 -1
- package/dist/assets/{verify-then-push-pr-autofix-DaM3R_IS.js → verify-then-push-pr-autofix-CHEU7V9v.js} +3 -3
- package/dist/assets/{verify-then-push-pr-autofix-DaM3R_IS.js.map → verify-then-push-pr-autofix-CHEU7V9v.js.map} +1 -1
- package/dist/config/dashboard.json +9 -2
- package/dist/config/dashboard.schema.json +8 -3
- package/dist/server.mjs +14 -14
- package/dist/skills/neon-pr-review/SKILL.md +1 -1
- package/dist/skills/neondeck/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/modules/commands/handlers/queue.ts +30 -14
- package/src/modules/commands/schemas.ts +4 -2
- package/src/modules/commands/summaries.ts +16 -0
- package/src/modules/config/mutations/dashboard.ts +16 -2
- package/src/modules/github/index.ts +1 -0
- package/src/modules/github/pull-requests.ts +30 -3
- package/src/modules/github/queue.ts +8 -0
- package/src/modules/github/reviews.ts +25 -0
- package/src/modules/pr-events/index.ts +1 -0
- package/src/modules/pr-review-assist/actions.ts +53 -13
- package/src/modules/pr-review-assist/schemas.ts +18 -6
- package/src/modules/pr-review-assist/service.ts +45 -9
- package/src/modules/pr-reviews/events.ts +40 -0
- package/src/modules/pr-reviews/index.ts +4 -0
- package/src/modules/pr-reviews/service.ts +655 -0
- package/src/modules/pr-reviews/store.ts +186 -0
- package/src/modules/pr-reviews/types.ts +48 -0
- package/src/modules/reports/service.ts +21 -6
- package/src/modules/safety/policy-entries.ts +46 -1
- package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/migration.sql +34 -0
- package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
- package/src/runtime-home/app-db/schema.ts +44 -0
- package/src/runtime-home/bootstrap.ts +6 -0
- package/src/runtime-home/dashboard-migrations.ts +101 -0
- package/src/runtime-home/files.ts +5 -5
- package/src/runtime-home/index.ts +1 -0
- package/src/runtime-home/schemas.ts +7 -4
- package/src/server/create-app.ts +4 -0
- package/src/server/events/review-stream.ts +45 -0
- package/src/server/learning-hooks.ts +42 -0
- package/src/server/routes/github.ts +191 -4
- package/src/server/routes/reports.ts +2 -1
- package/src/server/routes/reviews.ts +257 -0
- package/src/skills/neon-pr-review/SKILL.md +1 -1
- package/src/skills/neondeck/SKILL.md +1 -1
- package/web/dist/assets/GitHubPrReview-CybXdsHd.js +3 -0
- package/web/dist/assets/{MultiFileView-CJTrTPMb.js → MultiFileView-BRXAY80r.js} +7 -7
- package/web/dist/assets/PrReviewPopoutPage-BAlIvAZL.js +1 -0
- package/web/dist/assets/index-D1VwAK0m.css +2 -0
- package/web/dist/assets/index-DLt_8zyR.js +44 -0
- package/web/dist/assets/{surfaces-CZfR7WsZ.js → surfaces-i0d1kpFn.js} +1 -1
- package/web/dist/index.html +2 -2
- package/dist/assets/app-BBIuPG77.js.map +0 -1
- package/dist/assets/autopilot-CnHJWMaF.js.map +0 -1
- package/dist/assets/briefing-CjRucNjn.js +0 -2
- package/dist/assets/briefings-DpDKxWsT.js.map +0 -1
- package/dist/assets/command-run-ujx2nwT9.js +0 -2
- package/dist/assets/fix-pr-ci-CXG_U_NI.js +0 -2
- package/dist/assets/review-pr-for-human-C_OT_LFW.js.map +0 -1
- package/dist/assets/safety-EnvDg7cY.js.map +0 -1
- package/web/dist/assets/GitHubPrReview-BFLAbu4J.js +0 -2
- package/web/dist/assets/index-2gqnSuHv.css +0 -2
- package/web/dist/assets/index-BNCOb0p_.js +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#118](https://github.com/pandemicsyn/neondeck/pull/118) [`df66b2c`](https://github.com/pandemicsyn/neondeck/commit/df66b2c3b4e1dc75a97534cdc0db99396245062f) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Keep ready dashboard notifications visible for one hour by default and allow configuring them to remain until dismissed.
|
|
8
|
+
|
|
9
|
+
- [#115](https://github.com/pandemicsyn/neondeck/pull/115) [`1e692f4`](https://github.com/pandemicsyn/neondeck/commit/1e692f44819715e102135ef2bd896c208786d310) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Correct PR branch freshness findings, replace stale Neon-generated review artifacts on re-review while preserving human edits, and speed up the focused review pop-out loading path.
|
|
10
|
+
|
|
11
|
+
- [#116](https://github.com/pandemicsyn/neondeck/pull/116) [`8c972c0`](https://github.com/pandemicsyn/neondeck/commit/8c972c0e1898b5e0462d59d69badfc4e08f87dba) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Complete the PR review workbench with in-dashboard artifacts, explicit finding anchors, manual report-only anchoring, workbench-started Neon reviews, reliable behind detection, and reserved whole-review submission.
|
|
12
|
+
|
|
13
|
+
- [#117](https://github.com/pandemicsyn/neondeck/pull/117) [`fc0618d`](https://github.com/pandemicsyn/neondeck/commit/fc0618dc456c67aa5362baf772ef2499a95d55ad) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Add the Reviews tab once to existing dashboard work regions while preserving the configured default tab and respecting later user removal.
|
|
14
|
+
|
|
15
|
+
## 1.0.0-beta.8
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- [#113](https://github.com/pandemicsyn/neondeck/pull/113) [`8eaa12d`](https://github.com/pandemicsyn/neondeck/commit/8eaa12df1c4b0344f1f7a11f0fbf491d76678be0) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Add a durable PR review inbox with live chat and dashboard updates, queue-independent review workbenches, linked local reports, and explicit whole-review GitHub submission.
|
|
20
|
+
|
|
3
21
|
## 1.0.0-beta.7
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/config/dashboard.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./dashboard.schema.json",
|
|
3
|
+
"schemaVersion": 1,
|
|
3
4
|
"display": {
|
|
4
5
|
"preset": "xeneon-edge",
|
|
5
6
|
"width": 2560,
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
"toasts": {
|
|
14
15
|
"enabled": true,
|
|
15
16
|
"minimumLevel": "ready",
|
|
16
|
-
"readyDurationMs":
|
|
17
|
+
"readyDurationMs": 3600000,
|
|
17
18
|
"maxVisible": 3
|
|
18
19
|
}
|
|
19
20
|
},
|
|
@@ -47,8 +48,14 @@
|
|
|
47
48
|
"row": 1,
|
|
48
49
|
"columnSpan": 4,
|
|
49
50
|
"rowSpan": 5,
|
|
50
|
-
"defaultTab": "
|
|
51
|
+
"defaultTab": "reviews",
|
|
51
52
|
"tabs": [
|
|
53
|
+
{
|
|
54
|
+
"id": "reviews",
|
|
55
|
+
"title": "REVIEWS",
|
|
56
|
+
"pluginId": "reviews-panel",
|
|
57
|
+
"config": {}
|
|
58
|
+
},
|
|
52
59
|
{
|
|
53
60
|
"id": "github",
|
|
54
61
|
"title": "GITHUB",
|
|
@@ -4,11 +4,16 @@
|
|
|
4
4
|
"title": "Neondeck dashboard config",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"additionalProperties": true,
|
|
7
|
-
"required": ["display", "theme", "layout"],
|
|
7
|
+
"required": ["schemaVersion", "display", "theme", "layout"],
|
|
8
8
|
"properties": {
|
|
9
9
|
"$schema": {
|
|
10
10
|
"type": "string"
|
|
11
11
|
},
|
|
12
|
+
"schemaVersion": {
|
|
13
|
+
"type": "integer",
|
|
14
|
+
"minimum": 1,
|
|
15
|
+
"description": "Version marker for one-time dashboard layout migrations."
|
|
16
|
+
},
|
|
12
17
|
"display": {
|
|
13
18
|
"type": "object",
|
|
14
19
|
"additionalProperties": false,
|
|
@@ -66,8 +71,8 @@
|
|
|
66
71
|
},
|
|
67
72
|
"readyDurationMs": {
|
|
68
73
|
"type": "integer",
|
|
69
|
-
"default":
|
|
70
|
-
"description": "Automatically dismiss ready toasts after this many milliseconds.
|
|
74
|
+
"default": 3600000,
|
|
75
|
+
"description": "Automatically dismiss ready toasts after this many milliseconds. Use 0 to keep them until dismissed. Nonzero values are clamped from 1000 through 86400000."
|
|
71
76
|
},
|
|
72
77
|
"maxVisible": {
|
|
73
78
|
"type": "integer",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { $ as readLearningOperatorState, $n as
|
|
2
|
-
import { a as readBriefingState, c as settleBriefingObservation, i as readBriefingRunDetails, l as updateBriefingProfile, o as rotateBriefingSession, r as linkBriefingWorkflowObservation, s as runBriefingNow } from "./briefings-
|
|
3
|
-
import { a as
|
|
4
|
-
import { a as
|
|
1
|
+
import { $ as readLearningOperatorState, $a as okAction, $i as readRepoHealthSnapshot, $n as runApprovedExecution, $r as listMcpAudit, $t as getGitHubPrFiles, A as readReport, Aa as subscribeNotificationEvents, Ai as listChatSessionCommandEvents, An as createBriefingTask, At as reviewKiloResult, Bt as readRepoFile, Ca as listWorkflowSummaries, Ci as readChatSession, Cn as setPrWatchPolling, Cr as bearerToken, D as fixPrReviewFeedback, Da as markNotificationRead, Di as createChatSession, Dr as readLocalApiToken, E as commentPrAutofixResult, Ea as listNotifications, Ei as archiveChatSession, Er as localApiTokenQueryParam, Fa as isRegisteredProvider, Fi as updateChatSessionCommandEvent, Fr as reloadRuntimeSkills, Ga as ConfigValidationError, Gi as listMemoryEvents, Gn as settleScheduledTaskWorkflowRun, Gr as logoutMcpOAuthServer, Gt as pushPrAutofix, Ha as ensureRuntimeHomeSync, Hi as listMemoryCandidates, Hr as getMcpRegistry, Ht as searchRepoFiles, I as recordConversationTurnAndMaybeQueueLearning, Ia as providerRuntimeRegistrations, Ii as formatChatSessionServerSentEvent, J as rejectSkillPatchCandidate, Ja as runtimePaths, Ji as formatConfigServerSentEvent, Jn as preparePrWorktree, Jr as addMcpServer, Jt as deleteGitHubPrReviewDraft, K as applySkillPatchCandidate, Ka as parseAppConfig, Ki as upsertMemory, Kr as readPublicMcpOAuthLogin, L as recordHandledPrFromWorkflowResult, La as readProviderConfigSync, Lt as patchRepoFiles, Ma as parseInput, Mi as renameChatSession, Mn as readTaskRecord, Mr as readRuntimeStatus, Mt as recordDocsDriftFixTaskBoundary, Ni as restoreChatSession, Nn as removeTask, Nr as listRuntimeSkills, Oa as resolveNotification, Oi as createChatSessionCommandEvent, Ot as listKiloResultStates, Pa as installFlueExecutionContextTracker, Pi as switchChatSession, Pn as setTaskEnabled, Pr as loadRuntimeSkill, Pt as fixPrCiFailure, Qa as invalidInputAction, Qr as listMcpApprovals, Qt as getGitHubPrFileDiff, Ra as loadNeondeckEnv, Ri as subscribeChatSessionEvents, Rt as readRepoCheckoutStatus, Sa as addWorkflowSummary, Si as listChatSessions, Sn as removePrWatch, Sr as readHostMetrics, St as searchKiloSessions, T as approvePreparedDiffPushWithPolicy, Ta as addNotification, Ti as searchChatSessions, Tr as localApiTokenMatches, Ua as readRuntimeJson, Ui as archiveMemory, Ut as writeRepoFile, Va as ensureRuntimeHome, Vi as decideMemoryCandidate, Vt as replaceRepoFile, Wi as listMemories, Wr as completeMcpOAuthCallback, Wt as listRepoEditEvents, Xa as asJsonValue, Xi as subscribeConfigEvents, Xr as setMcpServerEnabled, Xt as getGitHubPrBranchPermissions, Y as restoreSkillPatchCandidate, Yi as replayConfigEventsAfter, Yn as verifyPrWorktree, Yr as removeMcpServer, Yt as deleteGitHubPrReviewDraftComment, Za as failedAction, Zn as syncExeDevCheckout, Zr as updateMcpServer, Zt as getGitHubPrEventState, _a as readPreparedDiffFileDiff, _n as addPrWatch, _r as triagePrEvent, _t as readKiloSession, aa as cleanupWorktrees, ai as listGitHubPrQueue, an as postGitHubPrComment, ba as runPreparedDiffVerification, bi as referenceChatSession, bn as listPrWatches, bt as readKiloSessionMessages, c as abandonPreparedDiffWithRevisionAbort, ca as readWorktreeStatus, cn as postGitHubPrThreadReply, cr as updateRepoAutopilotPolicy, d as failAutopilotAdmission, dn as refreshPrWatchEventState, dr as updateAgentModels, dt as readKiloTaskDiff, ea as readRepoRegistrySnapshot, ei as resolveMcpApprovalWithPaths, en as getGitHubPrRequestedChanges, eo as __commonJSMin, er as listExecutionApprovals, et as readWorkflowObservability, f as recordAutopilotAdmissionRun, fr as updateWorktreePolicy, ft as readKiloTaskEvents, ga as readPreparedDiffChangedFiles, gr as reloadConfig, h as settleAutopilotAdmissionTriage, hr as updateDashboardLayout, ht as startKiloTask, i as runAutopilotRecoveryAction, ia as listWorktrees, in as patchGitHubPrReviewDraftComment, it as listLearningReviews, j as readReportHtml, ja as nonEmptyStringSchema, ji as pinChatSession, jn as listTaskRecords, jt as verifyKiloResult, k as listReports, ka as formatNotificationServerSentEvent, ki as linkChatSessionContext, kn as createAgentInstructionTask, kt as promoteKiloResult, l as runPreparedDiffRevision, la as releaseWorktreeLock, ln as postGitHubPrThreadResolution, lr as readProviderConfig, lt as abortKiloTask, m as settleAutopilotAdmissionPrepare, ma as openPreparedDiffWorktree, mr as applyDashboardPreset, mt as readKiloTaskStatus, nn as getGitHubPrReviewThreads, no as __require, nr as resolveExecutionApproval, nt as loadAutomationLearningMemoryContext, o as readAutopilotState, oa as createWorktree, on as postGitHubPrReview, or as readExecutionPolicy, p as recordAutopilotAdmissionTerminalFact, pa as listPreparedDiffs, pr as updateExecutionPolicy, pt as readKiloTaskSessions, q as listSkillPatchCandidates, qa as parseDashboardConfig, qi as readNeonSessionState, qr as startMcpOAuthLogin, r as readAutopilotRecoveryOptions, ri as getGitHubPullRequest, rn as listPrWatchEventWatermarks, rr as checkExecutionPolicy, rt as attachLearningReviewRunId, s as autopilotStateSchema, sa as lockWorktree, sn as postGitHubPrReviewDraftComment, ta as repoFullName, tn as getGitHubPrReviewDraft, tr as requestExecutionApproval, tt as recordFlueObservation, u as beginAutopilotAdmissionPrepare, ua as syncWorktree, un as putGitHubPrReviewDraft, ur as updateProviderConfig, ut as listKiloTasks, va as readPreparedDiffSummary, vi as listChatSessionActivity, vn as addRefWatch, vt as readKiloSessionChildren, wa as setWorkflowSummaryRunId, wi as readChatSessionMessages, wn as resolvePrReference, wr as localApiAuthHeader, xa as readApprovalRecord, xi as refreshChatSessionSummary, xn as listRefWatches, xt as readUnavailableSessionAdapter, ya as requestPreparedDiffRevision, yt as readKiloSessionDiff, zt as readRepoDiff } from "./autopilot-CMaU1iZd.js";
|
|
2
|
+
import { a as readBriefingState, c as settleBriefingObservation, i as readBriefingRunDetails, l as updateBriefingProfile, o as rotateBriefingSession, r as linkBriefingWorkflowObservation, s as runBriefingNow } from "./briefings-DtOcw7y6.js";
|
|
3
|
+
import { a as recentPrReviews, c as reservePrReviewSubmission, d as readPrReview, f as readPrReviewForTarget, i as failPrReview, l as startPrReview, m as subscribePrReviewEvents, n as beginPrReviewSubmissionAttempt, o as reconcilePrReviewSubmission, p as formatPrReviewServerSentEvent, s as releasePrReviewSubmission, t as attachPrReviewAttemptRun, u as submitPrReview } from "./pr-reviews-CbYcf9Mj.js";
|
|
4
|
+
import { a as runSchedulerTick, c as rollbackQuietly, d as supportedCommands, n as readSafetyPolicy, o as isSqliteBusy, s as readMetadataValue } from "./safety-S_Ek3ETH.js";
|
|
5
|
+
import { a as review_conversation_for_learning_default, r as review_pr_batch_for_learning_default, s as curate_learning_store_default, t as scheduler_tick_default } from "./scheduler-tick-DO_6nnY9.js";
|
|
5
6
|
import { getRun, invoke, listRuns, observe, registerProvider } from "@flue/runtime";
|
|
6
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
8
|
import * as v from "valibot";
|
|
@@ -379,6 +380,41 @@ function createNotificationEventRoutes() {
|
|
|
379
380
|
return routes;
|
|
380
381
|
}
|
|
381
382
|
//#endregion
|
|
383
|
+
//#region src/server/events/review-stream.ts
|
|
384
|
+
function createReviewEventRoutes() {
|
|
385
|
+
const routes = new Hono();
|
|
386
|
+
routes.get("/reviews", () => {
|
|
387
|
+
const encoder = new TextEncoder();
|
|
388
|
+
let cleanup = () => {};
|
|
389
|
+
const stream = new ReadableStream({
|
|
390
|
+
start(controller) {
|
|
391
|
+
const send = (value) => controller.enqueue(encoder.encode(value));
|
|
392
|
+
send(": connected\n\n");
|
|
393
|
+
const unsubscribe = subscribePrReviewEvents((event) => {
|
|
394
|
+
send(formatPrReviewServerSentEvent(event));
|
|
395
|
+
});
|
|
396
|
+
const heartbeat = setInterval(() => {
|
|
397
|
+
send(`: heartbeat ${Date.now()}\n\n`);
|
|
398
|
+
}, 25e3);
|
|
399
|
+
cleanup = () => {
|
|
400
|
+
clearInterval(heartbeat);
|
|
401
|
+
unsubscribe();
|
|
402
|
+
};
|
|
403
|
+
},
|
|
404
|
+
cancel() {
|
|
405
|
+
cleanup();
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
return new Response(stream, { headers: {
|
|
409
|
+
"cache-control": "no-cache, no-transform",
|
|
410
|
+
connection: "keep-alive",
|
|
411
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
412
|
+
"x-accel-buffering": "no"
|
|
413
|
+
} });
|
|
414
|
+
});
|
|
415
|
+
return routes;
|
|
416
|
+
}
|
|
417
|
+
//#endregion
|
|
382
418
|
//#region src/server/events/session-stream.ts
|
|
383
419
|
function createSessionEventRoutes() {
|
|
384
420
|
const routes = new Hono();
|
|
@@ -423,6 +459,11 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
|
|
|
423
459
|
const unsubscribe = (dependencies.observe ?? observe)((event, context) => {
|
|
424
460
|
const contextHome = flueContextRuntimeHome(context);
|
|
425
461
|
if (contextHome && contextHome !== paths.home) return;
|
|
462
|
+
if (event.type === "run_start") try {
|
|
463
|
+
linkPrReviewRunObservation(event, paths);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
console.error("[neondeck] failed to link PR review run", error);
|
|
466
|
+
}
|
|
426
467
|
if (event.type === "run_end") {
|
|
427
468
|
recordFlueObservation(event, paths).then(async () => {
|
|
428
469
|
const terminalFact = autopilotTerminalFact(event);
|
|
@@ -454,6 +495,9 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
|
|
|
454
495
|
linkBriefingWorkflowObservation(event, paths).catch((error) => {
|
|
455
496
|
console.error("[neondeck] failed to link briefing workflow run", error);
|
|
456
497
|
});
|
|
498
|
+
Promise.resolve().then(() => settlePrReviewObservation(event, paths)).catch((error) => {
|
|
499
|
+
console.error("[neondeck] failed to settle PR review run", error);
|
|
500
|
+
});
|
|
457
501
|
const learningReviewId = learningReviewResultId(event);
|
|
458
502
|
if (learningReviewId) Promise.resolve().then(() => attachLearningReviewRunId({
|
|
459
503
|
reviewId: learningReviewId,
|
|
@@ -509,6 +553,22 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
|
|
|
509
553
|
});
|
|
510
554
|
observationHandlerUnsubscribers.set(paths.home, unsubscribe);
|
|
511
555
|
}
|
|
556
|
+
function settlePrReviewObservation(event, paths) {
|
|
557
|
+
if (!event.isError) return null;
|
|
558
|
+
return failPrReview({
|
|
559
|
+
runId: event.runId,
|
|
560
|
+
allowReady: true,
|
|
561
|
+
message: "The Flue review workflow failed. Inspect the guarded run for details."
|
|
562
|
+
}, paths);
|
|
563
|
+
}
|
|
564
|
+
function linkPrReviewRunObservation(event, paths) {
|
|
565
|
+
if (event.workflowName !== "review-pr-for-human") return null;
|
|
566
|
+
if (!event.input || typeof event.input !== "object") return null;
|
|
567
|
+
const reviewId = stringField(event.input, "reviewId");
|
|
568
|
+
const attemptId = stringField(event.input, "attemptId");
|
|
569
|
+
if (!reviewId || !attemptId) return null;
|
|
570
|
+
return attachPrReviewAttemptRun(reviewId, attemptId, event.runId, paths);
|
|
571
|
+
}
|
|
512
572
|
function flueContextRuntimeHome(context) {
|
|
513
573
|
const value = context?.env?.NEONDECK_HOME;
|
|
514
574
|
return typeof value === "string" && value ? value : void 0;
|
|
@@ -518,7 +578,7 @@ async function startPrepareAfterTriage(event, paths) {
|
|
|
518
578
|
const admission = await beginAutopilotAdmissionPrepare({ triageRunId: event.runId }, paths);
|
|
519
579
|
if (!admission) return;
|
|
520
580
|
try {
|
|
521
|
-
const { runId } = await invoke((await import("./prepare-pr-worktree-
|
|
581
|
+
const { runId } = await invoke((await import("./prepare-pr-worktree-CwalJPIV.js")).default, { input: {
|
|
522
582
|
repoId: admission.repoId,
|
|
523
583
|
prNumber: admission.prNumber,
|
|
524
584
|
eventId: admission.eventFingerprint,
|
|
@@ -721,7 +781,7 @@ async function dispatchApprovedPreparedDiffPush(approval, paths, dependencies) {
|
|
|
721
781
|
try {
|
|
722
782
|
receipt = await invokeWorkflowForRuntimeHome(paths, dispatch, invokeWorkflow);
|
|
723
783
|
} catch (error) {
|
|
724
|
-
const message = errorMessage$
|
|
784
|
+
const message = errorMessage$4(error);
|
|
725
785
|
await recordDispatchFailure(preparedDiff, mode, dispatch, approvalId, message, paths);
|
|
726
786
|
return {
|
|
727
787
|
...withDispatchData(approval, {
|
|
@@ -752,7 +812,7 @@ async function dispatchApprovedPreparedDiffPush(approval, paths, dependencies) {
|
|
|
752
812
|
dispatchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
753
813
|
}
|
|
754
814
|
}, paths).catch(async (error) => {
|
|
755
|
-
const message = errorMessage$
|
|
815
|
+
const message = errorMessage$4(error);
|
|
756
816
|
await recordDispatchSummaryFailure(preparedDiff, mode, dispatch, approvalId, receipt.runId, message, paths);
|
|
757
817
|
return null;
|
|
758
818
|
});
|
|
@@ -801,8 +861,8 @@ async function invokeWorkflowForRuntimeHome(paths, dispatch, invokeWorkflow) {
|
|
|
801
861
|
return invokeWorkflow(dispatch.workflow, dispatch.input);
|
|
802
862
|
}
|
|
803
863
|
async function invokeAutopilotWorkflow(workflow, input) {
|
|
804
|
-
if (workflow === "push-pr-autofix") return invokeWorkflow((await import("./push-pr-autofix-
|
|
805
|
-
return invokeWorkflow((await import("./verify-then-push-pr-autofix-
|
|
864
|
+
if (workflow === "push-pr-autofix") return invokeWorkflow((await import("./push-pr-autofix-DUXYeBds.js")).default, { input });
|
|
865
|
+
return invokeWorkflow((await import("./verify-then-push-pr-autofix-9Dzuwky_.js")).default, { input });
|
|
806
866
|
}
|
|
807
867
|
async function recordDispatchFailure(preparedDiff, mode, dispatch, approvalId, error, paths) {
|
|
808
868
|
await addWorkflowSummary({
|
|
@@ -859,7 +919,7 @@ async function recordDispatchSummaryFailure(preparedDiff, mode, dispatch, approv
|
|
|
859
919
|
async function invokeWorkflow(workflow, request) {
|
|
860
920
|
return invoke(workflow, request);
|
|
861
921
|
}
|
|
862
|
-
function errorMessage$
|
|
922
|
+
function errorMessage$4(error) {
|
|
863
923
|
return error instanceof Error ? error.message : String(error);
|
|
864
924
|
}
|
|
865
925
|
function withDispatchData(approval, dispatch, message) {
|
|
@@ -1359,8 +1419,98 @@ function createGitHubRoutes(paths) {
|
|
|
1359
1419
|
routes.post("/prs/:owner/:repo/:number/reviews", async (c) => {
|
|
1360
1420
|
const target = prTargetFromParams(c.req.param("owner"), c.req.param("repo"), c.req.param("number"));
|
|
1361
1421
|
if (!target.ok) return c.json(target.result, 400);
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1422
|
+
const reviewInputObject = objectField$1(await safeJsonBody(c));
|
|
1423
|
+
const requestedHeadSha = typeof reviewInputObject.headSha === "string" ? reviewInputObject.headSha : null;
|
|
1424
|
+
const durableReview = readPrReviewForTarget(target.input.repo, target.input.prNumber, paths);
|
|
1425
|
+
if (durableReview && (durableReview.status !== "ready" || !requestedHeadSha || durableReview.headSha !== requestedHeadSha)) return c.json({
|
|
1426
|
+
ok: false,
|
|
1427
|
+
action: "github_pr_review_post",
|
|
1428
|
+
changed: false,
|
|
1429
|
+
message: durableReview.status !== "ready" ? "The durable review must be ready before it can be submitted." : "The durable review does not match the pull request head being submitted.",
|
|
1430
|
+
data: { reviewId: durableReview.id }
|
|
1431
|
+
}, 409);
|
|
1432
|
+
const verdict = reviewInputObject.verdict;
|
|
1433
|
+
if (verdict !== "comment" && verdict !== "approve" && verdict !== "request-changes") return c.json({
|
|
1434
|
+
ok: false,
|
|
1435
|
+
action: "github_pr_review_post",
|
|
1436
|
+
changed: false,
|
|
1437
|
+
message: "A review verdict is required."
|
|
1438
|
+
}, 400);
|
|
1439
|
+
const reserved = durableReview ? reservePrReviewSubmission({
|
|
1440
|
+
repoFullName: target.input.repo,
|
|
1441
|
+
prNumber: target.input.prNumber,
|
|
1442
|
+
headSha: requestedHeadSha ?? "",
|
|
1443
|
+
verdict
|
|
1444
|
+
}, paths) : null;
|
|
1445
|
+
if (durableReview && !reserved) return c.json({
|
|
1446
|
+
ok: false,
|
|
1447
|
+
action: "github_pr_review_post",
|
|
1448
|
+
changed: false,
|
|
1449
|
+
message: "The durable review changed before submission could be reserved. Refresh and try again.",
|
|
1450
|
+
data: { reviewId: durableReview.id }
|
|
1451
|
+
}, 409);
|
|
1452
|
+
const releaseReservation = () => {
|
|
1453
|
+
if (reserved) releasePrReviewSubmission({
|
|
1454
|
+
reviewId: reserved.id,
|
|
1455
|
+
headSha: reserved.headSha
|
|
1456
|
+
}, paths);
|
|
1457
|
+
};
|
|
1458
|
+
const endSubmissionAttempt = reserved ? beginPrReviewSubmissionAttempt(reserved.id) : () => {};
|
|
1459
|
+
let githubAccepted = false;
|
|
1460
|
+
try {
|
|
1461
|
+
const savedDraftResult = await putGitHubPrReviewDraft(target.input, {
|
|
1462
|
+
headSha: requestedHeadSha ?? "",
|
|
1463
|
+
body: typeof reviewInputObject.body === "string" ? reviewInputObject.body : null,
|
|
1464
|
+
verdict,
|
|
1465
|
+
reanchorHeadSha: true
|
|
1466
|
+
}, paths);
|
|
1467
|
+
if (!savedDraftResult.ok) {
|
|
1468
|
+
releaseReservation();
|
|
1469
|
+
return c.json(savedDraftResult, 400);
|
|
1470
|
+
}
|
|
1471
|
+
const savedDraft = objectField$1(objectField$1(savedDraftResult.data).draft);
|
|
1472
|
+
if (typeof savedDraft.id !== "string") {
|
|
1473
|
+
releaseReservation();
|
|
1474
|
+
return c.json({
|
|
1475
|
+
ok: false,
|
|
1476
|
+
action: "github_pr_review_post",
|
|
1477
|
+
changed: false,
|
|
1478
|
+
message: "Review draft could not be saved before submission."
|
|
1479
|
+
}, 409);
|
|
1480
|
+
}
|
|
1481
|
+
const result = await postGitHubPrReview(target.input, {
|
|
1482
|
+
draftId: savedDraft.id,
|
|
1483
|
+
headSha: requestedHeadSha ?? "",
|
|
1484
|
+
commentIds: Array.isArray(reviewInputObject.commentIds) ? reviewInputObject.commentIds.filter((id) => typeof id === "string") : void 0
|
|
1485
|
+
}, paths);
|
|
1486
|
+
if (!result.ok) {
|
|
1487
|
+
releaseReservation();
|
|
1488
|
+
return c.json(result, 400);
|
|
1489
|
+
}
|
|
1490
|
+
githubAccepted = true;
|
|
1491
|
+
const data = objectField$1(result.data);
|
|
1492
|
+
const draft = objectField$1(data.draft);
|
|
1493
|
+
const review = objectField$1(data.review);
|
|
1494
|
+
const submittedVerdict = prReviewVerdict(draft.verdict) ?? verdict;
|
|
1495
|
+
const submitted = reserved ? submitPrReview({
|
|
1496
|
+
reviewId: reserved.id,
|
|
1497
|
+
verdict: submittedVerdict,
|
|
1498
|
+
githubReviewUrl: typeof review.url === "string" ? review.url : null
|
|
1499
|
+
}, paths) : null;
|
|
1500
|
+
if (reserved && !submitted) return c.json({
|
|
1501
|
+
ok: false,
|
|
1502
|
+
action: "github_pr_review_post",
|
|
1503
|
+
changed: true,
|
|
1504
|
+
message: "GitHub accepted the review, but Neondeck could not settle its reserved durable review record.",
|
|
1505
|
+
data: result.data
|
|
1506
|
+
}, 409);
|
|
1507
|
+
return c.json(result, 200);
|
|
1508
|
+
} catch (error) {
|
|
1509
|
+
if (!githubAccepted) releaseReservation();
|
|
1510
|
+
throw error;
|
|
1511
|
+
} finally {
|
|
1512
|
+
endSubmissionAttempt();
|
|
1513
|
+
}
|
|
1364
1514
|
});
|
|
1365
1515
|
routes.post("/prs/:owner/:repo/:number/review-threads/:threadId/reply", async (c) => {
|
|
1366
1516
|
const target = prTargetFromParams(c.req.param("owner"), c.req.param("repo"), c.req.param("number"));
|
|
@@ -1402,6 +1552,12 @@ function createGitHubRoutes(paths) {
|
|
|
1402
1552
|
});
|
|
1403
1553
|
return routes;
|
|
1404
1554
|
}
|
|
1555
|
+
function objectField$1(value) {
|
|
1556
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1557
|
+
}
|
|
1558
|
+
function prReviewVerdict(value) {
|
|
1559
|
+
return value === "comment" || value === "approve" || value === "request-changes" ? value : null;
|
|
1560
|
+
}
|
|
1405
1561
|
function prTargetFromParams(owner, repo, numberText) {
|
|
1406
1562
|
const number = Number(numberText);
|
|
1407
1563
|
if (!Number.isInteger(number) || number <= 0) return {
|
|
@@ -1604,7 +1760,7 @@ async function registerHandoffPr(rawInput, paths = runtimePaths(), dependencies
|
|
|
1604
1760
|
queued: true
|
|
1605
1761
|
});
|
|
1606
1762
|
} catch (error) {
|
|
1607
|
-
const message = errorMessage$
|
|
1763
|
+
const message = errorMessage$3(error);
|
|
1608
1764
|
const audit = await addHandoffAudit({
|
|
1609
1765
|
event: "register-pr",
|
|
1610
1766
|
source,
|
|
@@ -1698,7 +1854,7 @@ async function externalReviewQueueAllowed(paths) {
|
|
|
1698
1854
|
}
|
|
1699
1855
|
async function invokeReviewPrWorkflow(input) {
|
|
1700
1856
|
const { invoke } = await import("@flue/runtime");
|
|
1701
|
-
return invoke((await import("./review-pr-for-human-
|
|
1857
|
+
return invoke((await import("./review-pr-for-human-CTIL0RRy.js")).default, { input });
|
|
1702
1858
|
}
|
|
1703
1859
|
async function addHandoffAudit(summary, paths, options = {}) {
|
|
1704
1860
|
return addWorkflowSummary({
|
|
@@ -1743,7 +1899,7 @@ function failResult(action, message, data = {}) {
|
|
|
1743
1899
|
function displaySource(source) {
|
|
1744
1900
|
return source.replace(/^(?:external|ci):/, "");
|
|
1745
1901
|
}
|
|
1746
|
-
function errorMessage$
|
|
1902
|
+
function errorMessage$3(error) {
|
|
1747
1903
|
if (error instanceof Error) return error.message;
|
|
1748
1904
|
return String(error);
|
|
1749
1905
|
}
|
|
@@ -2599,9 +2755,9 @@ async function stageDocsDriftFix(rawInput, paths = runtimePaths(), dependencies
|
|
|
2599
2755
|
allowedDocsPaths: docsFixAllowedDocsPaths(summary)
|
|
2600
2756
|
}, paths);
|
|
2601
2757
|
} catch (error) {
|
|
2602
|
-
return failedAction("docs_drift_stage_fix", `Could not record docs drift fix boundary: ${errorMessage$
|
|
2758
|
+
return failedAction("docs_drift_stage_fix", `Could not record docs drift fix boundary: ${errorMessage$2(error)}.`, {
|
|
2603
2759
|
requires: ["docsDriftBoundary"],
|
|
2604
|
-
errors: [errorMessage$
|
|
2760
|
+
errors: [errorMessage$2(error)]
|
|
2605
2761
|
});
|
|
2606
2762
|
}
|
|
2607
2763
|
const learningMemoryContext = await loadAutomationLearningMemoryContext(paths, {
|
|
@@ -2745,7 +2901,7 @@ function stringArrayConfig(value) {
|
|
|
2745
2901
|
function objectConfig(value) {
|
|
2746
2902
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2747
2903
|
}
|
|
2748
|
-
function errorMessage$
|
|
2904
|
+
function errorMessage$2(error) {
|
|
2749
2905
|
return error instanceof Error ? error.message : String(error);
|
|
2750
2906
|
}
|
|
2751
2907
|
//#endregion
|
|
@@ -2754,6 +2910,7 @@ function createReportApiRoutes(paths) {
|
|
|
2754
2910
|
const routes = new Hono();
|
|
2755
2911
|
routes.get("/reports", async (c) => {
|
|
2756
2912
|
const kind = c.req.query("kind")?.trim() || void 0;
|
|
2913
|
+
const excludeKind = c.req.query("excludeKind")?.trim() || void 0;
|
|
2757
2914
|
const limitText = c.req.query("limit");
|
|
2758
2915
|
const limit = limitText ? Number(limitText) : void 0;
|
|
2759
2916
|
if (limitText && (limit === void 0 || !Number.isFinite(limit) || limit <= 0)) return c.json({
|
|
@@ -2768,6 +2925,7 @@ function createReportApiRoutes(paths) {
|
|
|
2768
2925
|
action: "reports_list",
|
|
2769
2926
|
items: await listReports(paths, {
|
|
2770
2927
|
kind,
|
|
2928
|
+
excludeKind,
|
|
2771
2929
|
limit
|
|
2772
2930
|
}),
|
|
2773
2931
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2840,6 +2998,162 @@ function createReportFileRoutes(paths) {
|
|
|
2840
2998
|
return routes;
|
|
2841
2999
|
}
|
|
2842
3000
|
//#endregion
|
|
3001
|
+
//#region src/server/routes/reviews.ts
|
|
3002
|
+
function createReviewRoutes(paths) {
|
|
3003
|
+
const routes = new Hono();
|
|
3004
|
+
routes.get("/reviews", async (c) => {
|
|
3005
|
+
const repo = c.req.query("repo")?.trim();
|
|
3006
|
+
const prNumber = Number(c.req.query("prNumber"));
|
|
3007
|
+
if (repo && Number.isInteger(prNumber) && prNumber > 0) {
|
|
3008
|
+
const review = readPrReviewForTarget(repo, prNumber, paths);
|
|
3009
|
+
const items = review ? [review] : [];
|
|
3010
|
+
return c.json({
|
|
3011
|
+
ok: true,
|
|
3012
|
+
action: "pr_reviews_list",
|
|
3013
|
+
changed: false,
|
|
3014
|
+
items,
|
|
3015
|
+
groups: groupReviews(items, [])
|
|
3016
|
+
});
|
|
3017
|
+
}
|
|
3018
|
+
const reviews = recentPrReviews(paths);
|
|
3019
|
+
const queueResult = await listGitHubPrQueue(paths);
|
|
3020
|
+
const awaiting = (queueResult.ok ? queueFromResult(queueResult.data) : { items: [] }).items.filter((item) => item.relations.includes("review-requested")).map((pullRequest) => ({
|
|
3021
|
+
pullRequest,
|
|
3022
|
+
review: reviews.find((review) => review.repoFullName.toLowerCase() === pullRequest.repo.toLowerCase() && review.prNumber === pullRequest.number) ?? null
|
|
3023
|
+
}));
|
|
3024
|
+
return c.json({
|
|
3025
|
+
ok: true,
|
|
3026
|
+
action: "pr_reviews_list",
|
|
3027
|
+
changed: false,
|
|
3028
|
+
items: reviews,
|
|
3029
|
+
groups: groupReviews(reviews, awaiting),
|
|
3030
|
+
queueIssues: queueResult.ok ? [] : queueResult.errors ?? []
|
|
3031
|
+
});
|
|
3032
|
+
});
|
|
3033
|
+
routes.get("/reviews/:id", (c) => {
|
|
3034
|
+
const review = readPrReview(c.req.param("id"), paths);
|
|
3035
|
+
return review ? c.json({
|
|
3036
|
+
ok: true,
|
|
3037
|
+
action: "pr_review_read",
|
|
3038
|
+
changed: false,
|
|
3039
|
+
review
|
|
3040
|
+
}) : c.json({
|
|
3041
|
+
ok: false,
|
|
3042
|
+
action: "pr_review_read",
|
|
3043
|
+
changed: false,
|
|
3044
|
+
message: "PR review not found."
|
|
3045
|
+
}, 404);
|
|
3046
|
+
});
|
|
3047
|
+
routes.post("/reviews", async (c) => {
|
|
3048
|
+
const body = objectBody(await safeJsonBody(c));
|
|
3049
|
+
const ref = typeof body.ref === "string" ? body.ref.trim() : "";
|
|
3050
|
+
if (!ref) return c.json({
|
|
3051
|
+
ok: false,
|
|
3052
|
+
action: "pr_review_start",
|
|
3053
|
+
changed: false,
|
|
3054
|
+
message: "A pull request reference is required.",
|
|
3055
|
+
requires: ["ref"]
|
|
3056
|
+
}, 400);
|
|
3057
|
+
try {
|
|
3058
|
+
const result = await startPrReview({
|
|
3059
|
+
ref,
|
|
3060
|
+
origin: reviewOrigin(body.origin)
|
|
3061
|
+
}, paths);
|
|
3062
|
+
return c.json({
|
|
3063
|
+
ok: true,
|
|
3064
|
+
action: "pr_review_start",
|
|
3065
|
+
changed: true,
|
|
3066
|
+
message: `Started review for ${result.review.repoFullName}#${result.review.prNumber}.`,
|
|
3067
|
+
...result
|
|
3068
|
+
}, 202);
|
|
3069
|
+
} catch (error) {
|
|
3070
|
+
return c.json({
|
|
3071
|
+
ok: false,
|
|
3072
|
+
action: "pr_review_start",
|
|
3073
|
+
changed: false,
|
|
3074
|
+
message: errorMessage$1(error)
|
|
3075
|
+
}, 400);
|
|
3076
|
+
}
|
|
3077
|
+
});
|
|
3078
|
+
routes.post("/reviews/:id/review", async (c) => {
|
|
3079
|
+
const existing = readPrReview(c.req.param("id"), paths);
|
|
3080
|
+
if (!existing) return c.json({
|
|
3081
|
+
ok: false,
|
|
3082
|
+
action: "pr_review_restart",
|
|
3083
|
+
changed: false,
|
|
3084
|
+
message: "PR review not found."
|
|
3085
|
+
}, 404);
|
|
3086
|
+
try {
|
|
3087
|
+
const result = await startPrReview({
|
|
3088
|
+
ref: existing.ref,
|
|
3089
|
+
origin: "panel"
|
|
3090
|
+
}, paths);
|
|
3091
|
+
return c.json({
|
|
3092
|
+
ok: true,
|
|
3093
|
+
action: "pr_review_restart",
|
|
3094
|
+
changed: true,
|
|
3095
|
+
message: `Re-reviewing ${existing.repoFullName}#${existing.prNumber}.`,
|
|
3096
|
+
...result
|
|
3097
|
+
}, 202);
|
|
3098
|
+
} catch (error) {
|
|
3099
|
+
return c.json({
|
|
3100
|
+
ok: false,
|
|
3101
|
+
action: "pr_review_restart",
|
|
3102
|
+
changed: false,
|
|
3103
|
+
message: errorMessage$1(error)
|
|
3104
|
+
}, 400);
|
|
3105
|
+
}
|
|
3106
|
+
});
|
|
3107
|
+
routes.post("/reviews/:id/reconcile", async (c) => {
|
|
3108
|
+
try {
|
|
3109
|
+
const result = await reconcilePrReviewSubmission({ reviewId: c.req.param("id") }, paths);
|
|
3110
|
+
const message = result.outcome === "submitted" ? "Recovered the submitted review from GitHub." : result.outcome === "ready" ? "GitHub has no matching review; the local draft is ready to submit again." : result.outcome === "pending" ? "GitHub has not reported the review yet. Wait a moment, then check again." : `The review is already ${result.review.status}.`;
|
|
3111
|
+
return c.json({
|
|
3112
|
+
ok: true,
|
|
3113
|
+
action: "pr_review_submission_reconcile",
|
|
3114
|
+
changed: result.outcome === "submitted" || result.outcome === "ready",
|
|
3115
|
+
message,
|
|
3116
|
+
review: result.review,
|
|
3117
|
+
reviewId: result.review.id,
|
|
3118
|
+
runId: result.review.runId ?? ""
|
|
3119
|
+
}, result.outcome === "pending" ? 202 : 200);
|
|
3120
|
+
} catch (error) {
|
|
3121
|
+
const message = errorMessage$1(error);
|
|
3122
|
+
return c.json({
|
|
3123
|
+
ok: false,
|
|
3124
|
+
action: "pr_review_submission_reconcile",
|
|
3125
|
+
changed: false,
|
|
3126
|
+
message
|
|
3127
|
+
}, message === "GITHUB_TOKEN is not configured." ? 503 : 502);
|
|
3128
|
+
}
|
|
3129
|
+
});
|
|
3130
|
+
return routes;
|
|
3131
|
+
}
|
|
3132
|
+
function groupReviews(reviews, awaiting) {
|
|
3133
|
+
return {
|
|
3134
|
+
awaiting,
|
|
3135
|
+
inProgress: reviews.filter((review) => review.status === "reviewing" || review.status === "submitting"),
|
|
3136
|
+
needsAction: reviews.filter((review) => review.status === "ready" || review.status === "failed"),
|
|
3137
|
+
submitted: reviews.filter((review) => review.status === "submitted")
|
|
3138
|
+
};
|
|
3139
|
+
}
|
|
3140
|
+
function queueFromResult(value) {
|
|
3141
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { items: [] };
|
|
3142
|
+
const queue = value.queue;
|
|
3143
|
+
if (!queue || typeof queue !== "object" || Array.isArray(queue)) return { items: [] };
|
|
3144
|
+
const items = queue.items;
|
|
3145
|
+
return { items: Array.isArray(items) ? items : [] };
|
|
3146
|
+
}
|
|
3147
|
+
function objectBody(value) {
|
|
3148
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3149
|
+
}
|
|
3150
|
+
function reviewOrigin(value) {
|
|
3151
|
+
return value === "chat" || value === "panel" || value === "api" ? value : "api";
|
|
3152
|
+
}
|
|
3153
|
+
function errorMessage$1(error) {
|
|
3154
|
+
return error instanceof Error ? error.message : String(error);
|
|
3155
|
+
}
|
|
3156
|
+
//#endregion
|
|
2843
3157
|
//#region src/server/routes/repos.ts
|
|
2844
3158
|
function createReposRoutes(paths) {
|
|
2845
3159
|
const routes = new Hono();
|
|
@@ -3594,6 +3908,7 @@ async function createApp(options = {}) {
|
|
|
3594
3908
|
app.route("/api", createRuntimeRoutes(paths));
|
|
3595
3909
|
app.route("/api/events", createConfigEventRoutes());
|
|
3596
3910
|
app.route("/api/events", createNotificationEventRoutes());
|
|
3911
|
+
app.route("/api/events", createReviewEventRoutes());
|
|
3597
3912
|
app.route("/api/events", createSessionEventRoutes());
|
|
3598
3913
|
app.route("/api/safety", createSafetyRoutes(paths));
|
|
3599
3914
|
app.route("/api/execution", createExecutionRoutes(paths));
|
|
@@ -3617,6 +3932,7 @@ async function createApp(options = {}) {
|
|
|
3617
3932
|
app.route("/api/skills", createSkillRoutes(paths));
|
|
3618
3933
|
app.route("/api/commands", createCommandRoutes());
|
|
3619
3934
|
app.route("/api", createReportApiRoutes(paths));
|
|
3935
|
+
app.route("/api", createReviewRoutes(paths));
|
|
3620
3936
|
app.route("/api/workflows", createWorkflowRoutes(paths));
|
|
3621
3937
|
app.route("/api/github", createGitHubRoutes(paths));
|
|
3622
3938
|
app.use("/api/flue/agents/display-assistant/*", displayAssistantLearningMiddleware(paths));
|
|
@@ -3656,4 +3972,4 @@ var app_default = await createApp();
|
|
|
3656
3972
|
//#endregion
|
|
3657
3973
|
export { app_default as default };
|
|
3658
3974
|
|
|
3659
|
-
//# sourceMappingURL=app-
|
|
3975
|
+
//# sourceMappingURL=app-ChpCY1hX.js.map
|