@vibedeckx/linux-x64 0.2.6 → 0.2.7
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/dist/bin.js +248 -17
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -186146,7 +186146,11 @@ var asRun = (row) => row;
|
|
|
186146
186146
|
var createWorkflowRunRepos = (kdb) => ({
|
|
186147
186147
|
workflowRuns: {
|
|
186148
186148
|
create: async (opts) => {
|
|
186149
|
-
await kdb.insertInto("workflow_runs").values({
|
|
186149
|
+
await kdb.insertInto("workflow_runs").values({
|
|
186150
|
+
...opts,
|
|
186151
|
+
reviewer_session_id: opts.reviewer_session_id ?? null,
|
|
186152
|
+
status: "waiting_reviewer"
|
|
186153
|
+
}).execute();
|
|
186150
186154
|
const row = await kdb.selectFrom("workflow_runs").selectAll().where("id", "=", opts.id).executeTakeFirstOrThrow();
|
|
186151
186155
|
return asRun(row);
|
|
186152
186156
|
},
|
|
@@ -186169,6 +186173,10 @@ var createWorkflowRunRepos = (kdb) => ({
|
|
|
186169
186173
|
])).executeTakeFirst();
|
|
186170
186174
|
return row ? asRun(row) : void 0;
|
|
186171
186175
|
},
|
|
186176
|
+
getLatestCompletedBySource: async (sourceSessionId) => {
|
|
186177
|
+
const row = await kdb.selectFrom("workflow_runs").selectAll().where("source_session_id", "=", sourceSessionId).where("status", "=", "completed").where("reviewer_session_id", "is not", null).orderBy("created_at", "desc").orderBy(sql`rowid`, "desc").executeTakeFirst();
|
|
186178
|
+
return row ? asRun(row) : void 0;
|
|
186179
|
+
},
|
|
186172
186180
|
update: async (id, patch) => {
|
|
186173
186181
|
if (Object.keys(patch).length > 0) {
|
|
186174
186182
|
await kdb.updateTable("workflow_runs").set({ ...patch, updated_at: sql`datetime('now')` }).where("id", "=", id).execute();
|
|
@@ -226027,6 +226035,13 @@ function mapRemoteRun(run2, remoteServerId, projectId) {
|
|
|
226027
226035
|
reviewer_session_id: run2.reviewer_session_id ? `${prefix}${run2.reviewer_session_id}` : null
|
|
226028
226036
|
};
|
|
226029
226037
|
}
|
|
226038
|
+
function mapRemoteReviewerCandidate(candidate, remoteServerId, projectId) {
|
|
226039
|
+
if (!candidate?.sessionId) return candidate;
|
|
226040
|
+
return {
|
|
226041
|
+
...candidate,
|
|
226042
|
+
sessionId: `remote-${remoteServerId}-${projectId}-${candidate.sessionId}`
|
|
226043
|
+
};
|
|
226044
|
+
}
|
|
226030
226045
|
function runUpdatedEventFromRemoteFrame(parsed, sessionId, remoteInfo) {
|
|
226031
226046
|
if (!("workflowRunUpdated" in parsed)) return null;
|
|
226032
226047
|
const bare = parsed.workflowRunUpdated;
|
|
@@ -228713,9 +228728,10 @@ function extractLatestTurnEndIndex(entries) {
|
|
|
228713
228728
|
}
|
|
228714
228729
|
return null;
|
|
228715
228730
|
}
|
|
228716
|
-
function
|
|
228731
|
+
function extractLastAssistantInTurn(entries, beforeIndex) {
|
|
228717
228732
|
for (let i = beforeIndex - 1; i >= 0; i--) {
|
|
228718
228733
|
const e = entries[i];
|
|
228734
|
+
if (e?.type === "user") return null;
|
|
228719
228735
|
if (e?.type === "assistant" && typeof e.content === "string" && e.content.trim()) return e.content;
|
|
228720
228736
|
}
|
|
228721
228737
|
return null;
|
|
@@ -228746,6 +228762,27 @@ ${opts.reviewFocus}` : null,
|
|
|
228746
228762
|
"\nEnd your final message with a clear, actionable list of feedback items \u2014 or state explicitly that the work looks good."
|
|
228747
228763
|
].filter((l) => l !== null).join("\n");
|
|
228748
228764
|
}
|
|
228765
|
+
function reviewTargetPromptLine(target) {
|
|
228766
|
+
return target.baseHead ? `- The work was captured at commit ${target.baseHead}${target.diffStat ? ` with uncommitted changes (${target.diffStat})` : " with no uncommitted changes"}.` : null;
|
|
228767
|
+
}
|
|
228768
|
+
function buildRereviewerPrompt(opts) {
|
|
228769
|
+
return [
|
|
228770
|
+
"The source agent has addressed feedback from your previous review.",
|
|
228771
|
+
"Review the latest workspace state again.",
|
|
228772
|
+
opts.taskContext ? `
|
|
228773
|
+
## Latest source turn
|
|
228774
|
+
${opts.taskContext}` : null,
|
|
228775
|
+
opts.reviewFocus ? `
|
|
228776
|
+
## Review focus
|
|
228777
|
+
${opts.reviewFocus}` : null,
|
|
228778
|
+
"\n## How to review",
|
|
228779
|
+
"- Verify whether your previous feedback was addressed correctly.",
|
|
228780
|
+
"- Check for regressions and remaining correctness or test gaps.",
|
|
228781
|
+
"- Do NOT modify files \u2014 remain in read-only review mode.",
|
|
228782
|
+
reviewTargetPromptLine(opts.target),
|
|
228783
|
+
"- End with actionable feedback, or explicitly state that it looks good."
|
|
228784
|
+
].filter((line) => line !== null).join("\n");
|
|
228785
|
+
}
|
|
228749
228786
|
function buildFeedbackMessage(feedback) {
|
|
228750
228787
|
return [
|
|
228751
228788
|
"[Review Feedback]",
|
|
@@ -228754,6 +228791,7 @@ function buildFeedbackMessage(feedback) {
|
|
|
228754
228791
|
feedback
|
|
228755
228792
|
].join("\n");
|
|
228756
228793
|
}
|
|
228794
|
+
var REVIEWER_AGENT_TYPES = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
228757
228795
|
var WorkflowEngine = class {
|
|
228758
228796
|
constructor(storage, agentOps) {
|
|
228759
228797
|
this.storage = storage;
|
|
@@ -228803,6 +228841,15 @@ var WorkflowEngine = class {
|
|
|
228803
228841
|
if (p2.runId === run2.id) this.participants.delete(sid);
|
|
228804
228842
|
}
|
|
228805
228843
|
}
|
|
228844
|
+
releaseReservations(runId) {
|
|
228845
|
+
for (const [sid, participant] of this.participants) {
|
|
228846
|
+
if (participant.runId === runId) this.participants.delete(sid);
|
|
228847
|
+
}
|
|
228848
|
+
}
|
|
228849
|
+
async failRun(run2, error48) {
|
|
228850
|
+
const failed = await this.storage.workflowRuns.update(run2.id, { status: "failed", error: error48 });
|
|
228851
|
+
if (failed) this.untrackRun(failed);
|
|
228852
|
+
}
|
|
228806
228853
|
/** Sync check used by ChatSessionManager before waking the commander model. */
|
|
228807
228854
|
shouldSuppressAgentEvent(sessionId) {
|
|
228808
228855
|
return this.participants.get(sessionId)?.role === "reviewer";
|
|
@@ -228810,14 +228857,62 @@ var WorkflowEngine = class {
|
|
|
228810
228857
|
isSessionInActiveRun(sessionId) {
|
|
228811
228858
|
return this.participants.has(sessionId);
|
|
228812
228859
|
}
|
|
228860
|
+
async getReviewerCandidate(sourceSessionId) {
|
|
228861
|
+
const previous = await this.storage.workflowRuns.getLatestCompletedBySource(sourceSessionId);
|
|
228862
|
+
if (!previous?.reviewer_session_id) return null;
|
|
228863
|
+
const unavailable = (reason) => ({
|
|
228864
|
+
available: false,
|
|
228865
|
+
sessionId: null,
|
|
228866
|
+
title: null,
|
|
228867
|
+
agentType: null,
|
|
228868
|
+
reason
|
|
228869
|
+
});
|
|
228870
|
+
const source = await this.storage.agentSessions.getById(sourceSessionId);
|
|
228871
|
+
const reviewer = await this.storage.agentSessions.getById(previous.reviewer_session_id);
|
|
228872
|
+
if (!reviewer) return unavailable("deleted");
|
|
228873
|
+
if (!source || reviewer.project_id !== source.project_id || reviewer.project_id !== previous.project_id) {
|
|
228874
|
+
return unavailable("project-mismatch");
|
|
228875
|
+
}
|
|
228876
|
+
if ((reviewer.branch || null) !== (source.branch || null) || (reviewer.branch || null) !== previous.branch) {
|
|
228877
|
+
return unavailable("branch-mismatch");
|
|
228878
|
+
}
|
|
228879
|
+
if (!REVIEWER_AGENT_TYPES.has(reviewer.agent_type)) {
|
|
228880
|
+
return unavailable("unsupported-agent");
|
|
228881
|
+
}
|
|
228882
|
+
if (reviewer.status === "running") return unavailable("running");
|
|
228883
|
+
if (reviewer.status !== "stopped") return unavailable("unavailable");
|
|
228884
|
+
if (this.participants.has(reviewer.id) || await this.storage.workflowRuns.getActiveBySession(reviewer.id)) {
|
|
228885
|
+
return unavailable("busy");
|
|
228886
|
+
}
|
|
228887
|
+
return {
|
|
228888
|
+
available: true,
|
|
228889
|
+
sessionId: reviewer.id,
|
|
228890
|
+
title: reviewer.title ?? null,
|
|
228891
|
+
agentType: reviewer.agent_type,
|
|
228892
|
+
reason: null
|
|
228893
|
+
};
|
|
228894
|
+
}
|
|
228813
228895
|
async startAdhocReview(opts) {
|
|
228814
|
-
if (
|
|
228815
|
-
throw new WorkflowError("
|
|
228896
|
+
if (opts.reviewerSessionId === opts.sourceSessionId) {
|
|
228897
|
+
throw new WorkflowError("reviewer-unavailable", "reviewer session \u4E0D\u80FD\u4E0E source session \u76F8\u540C");
|
|
228898
|
+
}
|
|
228899
|
+
const runId = randomUUID5();
|
|
228900
|
+
const participantIds = [opts.sourceSessionId, opts.reviewerSessionId].filter((id) => Boolean(id));
|
|
228901
|
+
for (const sessionId of participantIds) {
|
|
228902
|
+
if (this.participants.has(sessionId)) {
|
|
228903
|
+
throw new WorkflowError("session-busy", "\u8BE5 session \u5DF2\u5728\u4E00\u4E2A\u8FDB\u884C\u4E2D\u7684 review \u91CC");
|
|
228904
|
+
}
|
|
228905
|
+
}
|
|
228906
|
+
this.participants.set(opts.sourceSessionId, { runId, role: "source" });
|
|
228907
|
+
if (opts.reviewerSessionId) {
|
|
228908
|
+
this.participants.set(opts.reviewerSessionId, { runId, role: "reviewer" });
|
|
228816
228909
|
}
|
|
228817
|
-
this.participants.set(opts.sourceSessionId, { runId: "pending", role: "source" });
|
|
228818
228910
|
try {
|
|
228819
|
-
const
|
|
228820
|
-
|
|
228911
|
+
for (const sessionId of participantIds) {
|
|
228912
|
+
if (await this.storage.workflowRuns.getActiveBySession(sessionId)) {
|
|
228913
|
+
throw new WorkflowError("session-busy", "\u8BE5 session \u5DF2\u5728\u4E00\u4E2A\u8FDB\u884C\u4E2D\u7684 review \u91CC");
|
|
228914
|
+
}
|
|
228915
|
+
}
|
|
228821
228916
|
const sourceSession = await this.storage.agentSessions.getById(opts.sourceSessionId);
|
|
228822
228917
|
if (sourceSession?.status === "running") {
|
|
228823
228918
|
throw new WorkflowError("source-running", "source session \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D turn \u5B8C\u6210\u540E\u518D\u53D1\u8D77 review");
|
|
@@ -228829,16 +228924,61 @@ var WorkflowEngine = class {
|
|
|
228829
228924
|
}
|
|
228830
228925
|
const worktreePath = resolveWorktreePath(opts.project.path, opts.branch);
|
|
228831
228926
|
const target = captureReviewTarget(worktreePath);
|
|
228927
|
+
let reviewerSession = null;
|
|
228928
|
+
if (opts.reviewerSessionId) {
|
|
228929
|
+
reviewerSession = await this.storage.agentSessions.getById(opts.reviewerSessionId);
|
|
228930
|
+
if (!reviewerSession) {
|
|
228931
|
+
throw new WorkflowError("reviewer-unavailable", "\u4E0A\u6B21 reviewer session \u5DF2\u4E0D\u5B58\u5728");
|
|
228932
|
+
}
|
|
228933
|
+
if (reviewerSession.project_id !== opts.project.id) {
|
|
228934
|
+
throw new WorkflowError("reviewer-unavailable", "reviewer session \u4E0D\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE");
|
|
228935
|
+
}
|
|
228936
|
+
if ((reviewerSession.branch || null) !== opts.branch) {
|
|
228937
|
+
throw new WorkflowError("reviewer-unavailable", "reviewer session \u4E0D\u5C5E\u4E8E\u5F53\u524D branch");
|
|
228938
|
+
}
|
|
228939
|
+
if (!REVIEWER_AGENT_TYPES.has(reviewerSession.agent_type)) {
|
|
228940
|
+
throw new WorkflowError("reviewer-unavailable", "reviewer agent \u7C7B\u578B\u4E0D\u53EF\u7528");
|
|
228941
|
+
}
|
|
228942
|
+
if (reviewerSession.status !== "stopped") {
|
|
228943
|
+
throw new WorkflowError("reviewer-unavailable", "reviewer session \u6B63\u5728\u8FD0\u884C\u6216\u4E0D\u53EF\u7528");
|
|
228944
|
+
}
|
|
228945
|
+
}
|
|
228832
228946
|
const run2 = await this.storage.workflowRuns.create({
|
|
228833
|
-
id:
|
|
228947
|
+
id: runId,
|
|
228834
228948
|
project_id: opts.project.id,
|
|
228835
228949
|
branch: opts.branch,
|
|
228836
228950
|
source_session_id: opts.sourceSessionId,
|
|
228837
228951
|
source_turn_end_index: turnEndIndex,
|
|
228838
228952
|
review_focus: opts.reviewFocus ?? null,
|
|
228839
|
-
review_target: JSON.stringify(target)
|
|
228953
|
+
review_target: JSON.stringify(target),
|
|
228954
|
+
reviewer_session_id: opts.reviewerSessionId ?? null
|
|
228840
228955
|
});
|
|
228841
228956
|
this.trackParticipants(run2);
|
|
228957
|
+
if (opts.reviewerSessionId && reviewerSession) {
|
|
228958
|
+
if (reviewerSession.permission_mode !== "plan") {
|
|
228959
|
+
let switched = false;
|
|
228960
|
+
try {
|
|
228961
|
+
switched = await this.agentOps.switchMode(opts.reviewerSessionId, opts.project.path, "plan");
|
|
228962
|
+
} catch {
|
|
228963
|
+
}
|
|
228964
|
+
if (!switched) {
|
|
228965
|
+
await this.failRun(run2, "\u65E0\u6CD5\u5C06 reviewer \u6062\u590D\u4E3A\u53EA\u8BFB plan \u6A21\u5F0F");
|
|
228966
|
+
throw new WorkflowError("reviewer-unavailable", "\u65E0\u6CD5\u5C06 reviewer \u6062\u590D\u4E3A\u53EA\u8BFB plan \u6A21\u5F0F");
|
|
228967
|
+
}
|
|
228968
|
+
}
|
|
228969
|
+
const prompt = buildRereviewerPrompt({
|
|
228970
|
+
taskContext: extractTaskContextBefore(entries, turnEndIndex),
|
|
228971
|
+
reviewFocus: opts.reviewFocus ?? null,
|
|
228972
|
+
target
|
|
228973
|
+
});
|
|
228974
|
+
const sent = await this.agentOps.sendUserMessage(opts.reviewerSessionId, prompt, opts.project.path).catch(() => false);
|
|
228975
|
+
if (!sent) {
|
|
228976
|
+
await this.failRun(run2, "\u5411\u4E0A\u6B21 reviewer \u6295\u9012\u590D\u5BA1\u4EFB\u52A1\u5931\u8D25");
|
|
228977
|
+
throw new WorkflowError("send-failed", "\u5411\u4E0A\u6B21 reviewer \u6295\u9012\u590D\u5BA1\u4EFB\u52A1\u5931\u8D25");
|
|
228978
|
+
}
|
|
228979
|
+
this.emitRunUpdated(run2);
|
|
228980
|
+
return run2;
|
|
228981
|
+
}
|
|
228842
228982
|
try {
|
|
228843
228983
|
const reviewerId = await this.agentOps.createNewSession(
|
|
228844
228984
|
opts.project.id,
|
|
@@ -228882,9 +229022,7 @@ var WorkflowEngine = class {
|
|
|
228882
229022
|
throw new WorkflowError("spawn-failed", "\u521B\u5EFA reviewer session \u5931\u8D25");
|
|
228883
229023
|
}
|
|
228884
229024
|
} catch (err) {
|
|
228885
|
-
|
|
228886
|
-
this.participants.delete(opts.sourceSessionId);
|
|
228887
|
-
}
|
|
229025
|
+
this.releaseReservations(runId);
|
|
228888
229026
|
throw err;
|
|
228889
229027
|
}
|
|
228890
229028
|
}
|
|
@@ -228895,7 +229033,7 @@ var WorkflowEngine = class {
|
|
|
228895
229033
|
if (!run2 || run2.status !== "waiting_reviewer") return;
|
|
228896
229034
|
const entries = this.agentOps.getRawMessages(event.sessionId);
|
|
228897
229035
|
const boundary = event.turnEndEntryIndex ?? extractLatestTurnEndIndex(entries) ?? entries.length;
|
|
228898
|
-
const feedback =
|
|
229036
|
+
const feedback = extractLastAssistantInTurn(entries, boundary) ?? "(reviewer \u6CA1\u6709\u8F93\u51FA\u53EF\u7528\u7684\u53CD\u9988\u6587\u672C)";
|
|
228899
229037
|
let driftNote = null;
|
|
228900
229038
|
try {
|
|
228901
229039
|
const target = run2.review_target ? JSON.parse(run2.review_target) : null;
|
|
@@ -234932,6 +235070,9 @@ var routes11 = async (fastify2) => {
|
|
|
234932
235070
|
);
|
|
234933
235071
|
return reply.code(proxyStatus(result)).send(result.data);
|
|
234934
235072
|
}
|
|
235073
|
+
if (fastify2.workflowEngine.isSessionInActiveRun(req.params.sessionId)) {
|
|
235074
|
+
return reply.code(409).send({ error: "Session is participating in an active review" });
|
|
235075
|
+
}
|
|
234935
235076
|
const session = fastify2.agentSessionManager.getSession(req.params.sessionId);
|
|
234936
235077
|
if (!session) {
|
|
234937
235078
|
return reply.code(404).send({ error: "Session not found" });
|
|
@@ -234971,6 +235112,9 @@ var routes11 = async (fastify2) => {
|
|
|
234971
235112
|
);
|
|
234972
235113
|
return reply.code(proxyStatus(result)).send(result.data);
|
|
234973
235114
|
}
|
|
235115
|
+
if (fastify2.workflowEngine.isSessionInActiveRun(req.params.sessionId)) {
|
|
235116
|
+
return reply.code(409).send({ error: "Session is participating in an active review" });
|
|
235117
|
+
}
|
|
234974
235118
|
const session = fastify2.agentSessionManager.getSession(req.params.sessionId);
|
|
234975
235119
|
if (!session) {
|
|
234976
235120
|
return reply.code(404).send({ error: "Session not found" });
|
|
@@ -235909,7 +236053,6 @@ var command_routes_default = (0, import_fastify_plugin18.default)(routes17, { na
|
|
|
235909
236053
|
|
|
235910
236054
|
// src/routes/workflow-run-routes.ts
|
|
235911
236055
|
var import_fastify_plugin19 = __toESM(require_plugin2(), 1);
|
|
235912
|
-
var REVIEWER_AGENT_TYPES = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
235913
236056
|
function parseReviewerAgentType(raw) {
|
|
235914
236057
|
if (raw === void 0) return void 0;
|
|
235915
236058
|
return typeof raw === "string" && REVIEWER_AGENT_TYPES.has(raw) ? raw : null;
|
|
@@ -235921,6 +236064,8 @@ function errStatus(err) {
|
|
|
235921
236064
|
return 409;
|
|
235922
236065
|
case "source-running":
|
|
235923
236066
|
return 409;
|
|
236067
|
+
case "reviewer-unavailable":
|
|
236068
|
+
return 409;
|
|
235924
236069
|
case "bad-state":
|
|
235925
236070
|
return 409;
|
|
235926
236071
|
case "no-completed-turn":
|
|
@@ -235960,6 +236105,14 @@ async function routes18(fastify2) {
|
|
|
235960
236105
|
if (!projectId || !sourceSessionId) return reply.code(400).send({ error: "projectId and sourceSessionId are required" });
|
|
235961
236106
|
const reviewerAgentType = parseReviewerAgentType(req.body?.reviewerAgentType);
|
|
235962
236107
|
if (reviewerAgentType === null) return reply.code(400).send({ error: "reviewerAgentType must be one of: claude-code, codex" });
|
|
236108
|
+
const reviewerSessionIdRaw = req.body?.reviewerSessionId;
|
|
236109
|
+
if (reviewerSessionIdRaw !== void 0 && (typeof reviewerSessionIdRaw !== "string" || reviewerSessionIdRaw.trim() === "")) {
|
|
236110
|
+
return reply.code(400).send({ error: "reviewerSessionId must be a non-empty string" });
|
|
236111
|
+
}
|
|
236112
|
+
if (reviewerSessionIdRaw !== void 0 && reviewerAgentType !== void 0) {
|
|
236113
|
+
return reply.code(400).send({ error: "reviewerSessionId and reviewerAgentType are mutually exclusive" });
|
|
236114
|
+
}
|
|
236115
|
+
const reviewerSessionId = reviewerSessionIdRaw?.trim();
|
|
235963
236116
|
if (sourceSessionId.startsWith("remote-")) {
|
|
235964
236117
|
const remoteInfo = fastify2.remoteSessionMap.get(sourceSessionId);
|
|
235965
236118
|
if (!remoteInfo) return reply.code(404).send({ error: "Session not found" });
|
|
@@ -235967,11 +236120,20 @@ async function routes18(fastify2) {
|
|
|
235967
236120
|
if (derivedProjectId !== projectId) return reply.code(404).send({ error: "Session not found" });
|
|
235968
236121
|
const remoteProject = await fastify2.storage.projects.getById(projectId, userId);
|
|
235969
236122
|
if (!remoteProject) return reply.code(404).send({ error: "Project not found" });
|
|
236123
|
+
let bareReviewerSessionId;
|
|
236124
|
+
if (reviewerSessionId) {
|
|
236125
|
+
const reviewerInfo = fastify2.remoteSessionMap.get(reviewerSessionId);
|
|
236126
|
+
if (!reviewerInfo || reviewerInfo.remoteServerId !== remoteInfo.remoteServerId || projectIdFromRemoteSessionId(reviewerSessionId, reviewerInfo) !== projectId) {
|
|
236127
|
+
return reply.code(404).send({ error: "Reviewer session not found" });
|
|
236128
|
+
}
|
|
236129
|
+
bareReviewerSessionId = reviewerInfo.remoteSessionId;
|
|
236130
|
+
}
|
|
235970
236131
|
const result = await proxyAuto(remoteInfo, "POST", "/api/path/workflow-runs", {
|
|
235971
236132
|
sourceSessionId: remoteInfo.remoteSessionId,
|
|
235972
236133
|
reviewFocus,
|
|
235973
236134
|
sourceTurnEndIndex,
|
|
235974
|
-
reviewerAgentType
|
|
236135
|
+
reviewerAgentType,
|
|
236136
|
+
reviewerSessionId: bareReviewerSessionId
|
|
235975
236137
|
});
|
|
235976
236138
|
if (!result.ok) return sendProxyFailure(reply, result);
|
|
235977
236139
|
const bareRun = result.data.run;
|
|
@@ -236044,7 +236206,8 @@ async function routes18(fastify2) {
|
|
|
236044
236206
|
sourceSessionId,
|
|
236045
236207
|
reviewFocus,
|
|
236046
236208
|
sourceTurnEndIndex,
|
|
236047
|
-
reviewerAgentType
|
|
236209
|
+
reviewerAgentType,
|
|
236210
|
+
reviewerSessionId
|
|
236048
236211
|
});
|
|
236049
236212
|
return reply.code(201).send({ run: run2 });
|
|
236050
236213
|
} catch (err) {
|
|
@@ -236053,6 +236216,55 @@ async function routes18(fastify2) {
|
|
|
236053
236216
|
throw err;
|
|
236054
236217
|
}
|
|
236055
236218
|
});
|
|
236219
|
+
fastify2.get("/api/workflow-runs/reviewer-candidate", async (req, reply) => {
|
|
236220
|
+
const userId = requireAuth(req, reply);
|
|
236221
|
+
if (userId === null) return;
|
|
236222
|
+
const { projectId, sourceSessionId } = req.query;
|
|
236223
|
+
if (!projectId || !sourceSessionId) {
|
|
236224
|
+
return reply.code(400).send({ error: "projectId and sourceSessionId are required" });
|
|
236225
|
+
}
|
|
236226
|
+
const project = await fastify2.storage.projects.getById(projectId, userId);
|
|
236227
|
+
if (!project) return reply.code(404).send({ error: "Project not found" });
|
|
236228
|
+
if (sourceSessionId.startsWith("remote-")) {
|
|
236229
|
+
const remoteInfo = fastify2.remoteSessionMap.get(sourceSessionId);
|
|
236230
|
+
if (!remoteInfo || projectIdFromRemoteSessionId(sourceSessionId, remoteInfo) !== projectId) {
|
|
236231
|
+
return reply.code(404).send({ error: "Session not found" });
|
|
236232
|
+
}
|
|
236233
|
+
const params = new URLSearchParams({ sourceSessionId: remoteInfo.remoteSessionId });
|
|
236234
|
+
const result = await proxyAuto(
|
|
236235
|
+
remoteInfo,
|
|
236236
|
+
"GET",
|
|
236237
|
+
`/api/path/workflow-runs/reviewer-candidate?${params}`
|
|
236238
|
+
);
|
|
236239
|
+
if (!result.ok) return sendProxyFailure(reply, result);
|
|
236240
|
+
const bareCandidate = result.data.candidate;
|
|
236241
|
+
const candidate2 = mapRemoteReviewerCandidate(bareCandidate, remoteInfo.remoteServerId, projectId);
|
|
236242
|
+
if (bareCandidate?.sessionId && candidate2?.sessionId) {
|
|
236243
|
+
const reviewerInfo = {
|
|
236244
|
+
remoteServerId: remoteInfo.remoteServerId,
|
|
236245
|
+
remoteUrl: remoteInfo.remoteUrl,
|
|
236246
|
+
remoteApiKey: remoteInfo.remoteApiKey,
|
|
236247
|
+
remoteSessionId: bareCandidate.sessionId,
|
|
236248
|
+
branch: remoteInfo.branch
|
|
236249
|
+
};
|
|
236250
|
+
fastify2.remoteSessionMap.set(candidate2.sessionId, reviewerInfo);
|
|
236251
|
+
await fastify2.storage.remoteSessionMappings.upsert(
|
|
236252
|
+
candidate2.sessionId,
|
|
236253
|
+
projectId,
|
|
236254
|
+
remoteInfo.remoteServerId,
|
|
236255
|
+
bareCandidate.sessionId,
|
|
236256
|
+
remoteInfo.branch
|
|
236257
|
+
);
|
|
236258
|
+
}
|
|
236259
|
+
return reply.send({ candidate: candidate2 });
|
|
236260
|
+
}
|
|
236261
|
+
const sourceSession = await fastify2.storage.agentSessions.getById(sourceSessionId);
|
|
236262
|
+
if (!sourceSession || sourceSession.project_id !== projectId) {
|
|
236263
|
+
return reply.code(404).send({ error: "Session not found" });
|
|
236264
|
+
}
|
|
236265
|
+
const candidate = await fastify2.workflowEngine.getReviewerCandidate(sourceSessionId);
|
|
236266
|
+
return reply.send({ candidate });
|
|
236267
|
+
});
|
|
236056
236268
|
fastify2.get(
|
|
236057
236269
|
"/api/workflow-runs",
|
|
236058
236270
|
async (req, reply) => {
|
|
@@ -236175,6 +236387,14 @@ async function routes18(fastify2) {
|
|
|
236175
236387
|
if (!sourceSessionId) return reply.code(400).send({ error: "sourceSessionId is required" });
|
|
236176
236388
|
const reviewerAgentType = parseReviewerAgentType(req.body?.reviewerAgentType);
|
|
236177
236389
|
if (reviewerAgentType === null) return reply.code(400).send({ error: "reviewerAgentType must be one of: claude-code, codex" });
|
|
236390
|
+
const reviewerSessionIdRaw = req.body?.reviewerSessionId;
|
|
236391
|
+
if (reviewerSessionIdRaw !== void 0 && (typeof reviewerSessionIdRaw !== "string" || reviewerSessionIdRaw.trim() === "")) {
|
|
236392
|
+
return reply.code(400).send({ error: "reviewerSessionId must be a non-empty string" });
|
|
236393
|
+
}
|
|
236394
|
+
if (reviewerSessionIdRaw !== void 0 && reviewerAgentType !== void 0) {
|
|
236395
|
+
return reply.code(400).send({ error: "reviewerSessionId and reviewerAgentType are mutually exclusive" });
|
|
236396
|
+
}
|
|
236397
|
+
const reviewerSessionId = reviewerSessionIdRaw?.trim();
|
|
236178
236398
|
const sourceSession = await fastify2.storage.agentSessions.getById(sourceSessionId);
|
|
236179
236399
|
if (!sourceSession) return reply.code(404).send({ error: "Session not found" });
|
|
236180
236400
|
const project = await fastify2.storage.projects.getById(sourceSession.project_id);
|
|
@@ -236187,7 +236407,8 @@ async function routes18(fastify2) {
|
|
|
236187
236407
|
sourceSessionId,
|
|
236188
236408
|
reviewFocus,
|
|
236189
236409
|
sourceTurnEndIndex,
|
|
236190
|
-
reviewerAgentType
|
|
236410
|
+
reviewerAgentType,
|
|
236411
|
+
reviewerSessionId
|
|
236191
236412
|
});
|
|
236192
236413
|
return reply.code(201).send({ run: run2 });
|
|
236193
236414
|
} catch (err) {
|
|
@@ -236196,6 +236417,16 @@ async function routes18(fastify2) {
|
|
|
236196
236417
|
throw err;
|
|
236197
236418
|
}
|
|
236198
236419
|
});
|
|
236420
|
+
fastify2.get("/api/path/workflow-runs/reviewer-candidate", async (req, reply) => {
|
|
236421
|
+
const userId = requireAuth(req, reply);
|
|
236422
|
+
if (userId === null) return;
|
|
236423
|
+
const { sourceSessionId } = req.query;
|
|
236424
|
+
if (!sourceSessionId) return reply.code(400).send({ error: "sourceSessionId is required" });
|
|
236425
|
+
const sourceSession = await fastify2.storage.agentSessions.getById(sourceSessionId);
|
|
236426
|
+
if (!sourceSession) return reply.code(404).send({ error: "Session not found" });
|
|
236427
|
+
const candidate = await fastify2.workflowEngine.getReviewerCandidate(sourceSessionId);
|
|
236428
|
+
return reply.send({ candidate });
|
|
236429
|
+
});
|
|
236199
236430
|
fastify2.get("/api/path/workflow-runs", async (req, reply) => {
|
|
236200
236431
|
const userId = requireAuth(req, reply);
|
|
236201
236432
|
if (userId === null) return;
|