@vibedeckx/darwin-arm64 0.2.18 → 0.2.19
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 +242 -15
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -186274,7 +186274,7 @@ var createSearchCacheRepos = (kdb, _h) => ({
|
|
|
186274
186274
|
});
|
|
186275
186275
|
|
|
186276
186276
|
// src/storage/repositories/workflow-runs.ts
|
|
186277
|
-
var ACTIVE = ["waiting_reviewer", "waiting_feedback", "sending_feedback"];
|
|
186277
|
+
var ACTIVE = ["waiting_reviewer", "waiting_feedback", "discussing", "sending_feedback"];
|
|
186278
186278
|
var asRun = (row) => row;
|
|
186279
186279
|
var createWorkflowRunRepos = (kdb) => ({
|
|
186280
186280
|
workflowRuns: {
|
|
@@ -202331,7 +202331,7 @@ import { existsSync as existsSync3 } from "fs";
|
|
|
202331
202331
|
// src/notification-milestones.ts
|
|
202332
202332
|
var sessionResultReadyId = (sessionId, turnEndEntryIndex) => `session:${sessionId}:turn:${turnEndEntryIndex}:result-ready`;
|
|
202333
202333
|
var sessionFailedId = (sessionId, turnEndEntryIndex) => `session:${sessionId}:turn:${turnEndEntryIndex}:failed`;
|
|
202334
|
-
var reviewReadyId = (workflowRunId) => `workflow:${workflowRunId}:review-ready`;
|
|
202334
|
+
var reviewReadyId = (workflowRunId, turnEndEntryIndex) => `workflow:${workflowRunId}:turn:${turnEndEntryIndex}:review-ready`;
|
|
202335
202335
|
var workflowFailedId = (workflowRunId, stateVersion) => `workflow:${workflowRunId}:failed:${stateVersion}`;
|
|
202336
202336
|
function findTurnOpeningUserEntry(entries, beforeIndex) {
|
|
202337
202337
|
let opening;
|
|
@@ -225173,6 +225173,19 @@ var AgentSessionManager = class {
|
|
|
225173
225173
|
console.error(`[AgentSession] Error in ${label} handler for ${session.id}:`, err);
|
|
225174
225174
|
});
|
|
225175
225175
|
}
|
|
225176
|
+
/**
|
|
225177
|
+
* Same serial chain as `enqueueSessionWork`, for a caller that needs the
|
|
225178
|
+
* result back. The chain itself absorbs the outcome (success or failure) so
|
|
225179
|
+
* one queued step can never break the next; the caller gets the real promise.
|
|
225180
|
+
*/
|
|
225181
|
+
runSerialForResult(session, work) {
|
|
225182
|
+
const result = session.eventChain.then(work);
|
|
225183
|
+
session.eventChain = result.then(
|
|
225184
|
+
() => void 0,
|
|
225185
|
+
() => void 0
|
|
225186
|
+
);
|
|
225187
|
+
return result;
|
|
225188
|
+
}
|
|
225176
225189
|
clearGraceTimer(session) {
|
|
225177
225190
|
if (session.graceTimer) {
|
|
225178
225191
|
clearTimeout(session.graceTimer);
|
|
@@ -226051,6 +226064,86 @@ var AgentSessionManager = class {
|
|
|
226051
226064
|
}
|
|
226052
226065
|
return "ok";
|
|
226053
226066
|
}
|
|
226067
|
+
/**
|
|
226068
|
+
* Set (or clear, with null) a session's model. The model is a spawn
|
|
226069
|
+
* argument, so it takes effect on the next process the session spawns —
|
|
226070
|
+
* immediately for a dormant session (a branch, or one that was stopped),
|
|
226071
|
+
* and after retiring the idle process for a session that has one.
|
|
226072
|
+
*
|
|
226073
|
+
* Refused ("busy") under exactly the rule switchAgentType uses: a turn in
|
|
226074
|
+
* flight on a session that has history. Both are respawn-shaped changes, so
|
|
226075
|
+
* a divergent rule here would only mean the model chip and the agent chip
|
|
226076
|
+
* lock at different moments in the same header row.
|
|
226077
|
+
*
|
|
226078
|
+
* The name is never validated — an unknown one is passed to the CLI and
|
|
226079
|
+
* fails there, same as at creation.
|
|
226080
|
+
*
|
|
226081
|
+
* The whole transition runs on the session's serial event chain and writes
|
|
226082
|
+
* the row BEFORE touching memory, so the three places a model lives — the
|
|
226083
|
+
* row, `session.model`, and the process spawned from it — can never disagree:
|
|
226084
|
+
* a failed write ("error") leaves all three exactly as they were.
|
|
226085
|
+
*/
|
|
226086
|
+
async setModel(sessionId, model) {
|
|
226087
|
+
const session = this.sessions.get(sessionId);
|
|
226088
|
+
if (!session) return "not_found";
|
|
226089
|
+
const normalized = model?.trim() ? model.trim() : null;
|
|
226090
|
+
return this.runSerialForResult(session, async () => {
|
|
226091
|
+
if (session.model === normalized) return "ok";
|
|
226092
|
+
if (this.isModelChangeTooLate(session)) return "busy";
|
|
226093
|
+
console.log(`[AgentSession] Setting session ${sessionId} model ${session.model ?? "default"} \u2192 ${normalized ?? "default"}`);
|
|
226094
|
+
const previous = session.model;
|
|
226095
|
+
if (!session.skipDb) {
|
|
226096
|
+
try {
|
|
226097
|
+
await this.storage.agentSessions.updateModel(sessionId, normalized);
|
|
226098
|
+
} catch (err) {
|
|
226099
|
+
console.error(`[AgentSession] Failed to persist model for ${sessionId}:`, err);
|
|
226100
|
+
return "error";
|
|
226101
|
+
}
|
|
226102
|
+
if (this.isModelChangeTooLate(session)) {
|
|
226103
|
+
try {
|
|
226104
|
+
await this.storage.agentSessions.updateModel(sessionId, previous);
|
|
226105
|
+
} catch (err) {
|
|
226106
|
+
console.error(`[AgentSession] Failed to roll back model for ${sessionId}:`, err);
|
|
226107
|
+
}
|
|
226108
|
+
return "busy";
|
|
226109
|
+
}
|
|
226110
|
+
}
|
|
226111
|
+
session.model = normalized;
|
|
226112
|
+
if (session.process) {
|
|
226113
|
+
const proc = session.process;
|
|
226114
|
+
session.process = null;
|
|
226115
|
+
this.killProcess(proc);
|
|
226116
|
+
this.emitProcessAlive(session, false);
|
|
226117
|
+
await this.finalizeStreamingEntry(session);
|
|
226118
|
+
session.store.currentAssistantIndex = null;
|
|
226119
|
+
session.buffer = "";
|
|
226120
|
+
this.resetCompletion(session);
|
|
226121
|
+
session.dormant = true;
|
|
226122
|
+
if (session.status !== "stopped") {
|
|
226123
|
+
session.status = "stopped";
|
|
226124
|
+
if (!session.skipDb) {
|
|
226125
|
+
try {
|
|
226126
|
+
await this.storage.agentSessions.updateStatus(sessionId, "stopped");
|
|
226127
|
+
} catch (err) {
|
|
226128
|
+
console.error(`[AgentSession] Failed to persist stopped status for ${sessionId}:`, err);
|
|
226129
|
+
}
|
|
226130
|
+
}
|
|
226131
|
+
this.broadcastPatch(sessionId, ConversationPatch.updateStatus("stopped"));
|
|
226132
|
+
this.eventBus?.emit({ type: "session:status", projectId: session.projectId, branch: session.branch, sessionId: session.id, status: "stopped" });
|
|
226133
|
+
}
|
|
226134
|
+
}
|
|
226135
|
+
return "ok";
|
|
226136
|
+
});
|
|
226137
|
+
}
|
|
226138
|
+
/**
|
|
226139
|
+
* True once the model can no longer reach the CLI: a turn is in flight on a
|
|
226140
|
+
* session that has history. Same rule switchAgentType refuses on — both are
|
|
226141
|
+
* respawn-shaped changes, and a divergent rule would only mean the model
|
|
226142
|
+
* chip and the agent chip lock at different moments in the same header row.
|
|
226143
|
+
*/
|
|
226144
|
+
isModelChangeTooLate(session) {
|
|
226145
|
+
return session.status === "running" && session.store.entries.some(Boolean);
|
|
226146
|
+
}
|
|
226054
226147
|
/**
|
|
226055
226148
|
* Switch permission mode for a session (preserves conversation history)
|
|
226056
226149
|
*/
|
|
@@ -226811,6 +226904,9 @@ function runUpdatedEventFromRemoteFrame(parsed, sessionId, remoteInfo) {
|
|
|
226811
226904
|
const run2 = mapRemoteRun(bare, remoteInfo.remoteServerId, projectId);
|
|
226812
226905
|
return { type: "workflow:run-updated", projectId, branch: run2.branch, run: run2 };
|
|
226813
226906
|
}
|
|
226907
|
+
function runUpdatedFrameForSubscribers(evt) {
|
|
226908
|
+
return JSON.stringify({ workflowRunUpdated: evt.run });
|
|
226909
|
+
}
|
|
226814
226910
|
|
|
226815
226911
|
// src/routes/notification-outbox-routes.ts
|
|
226816
226912
|
var import_fastify_plugin = __toESM(require_plugin2(), 1);
|
|
@@ -226871,7 +226967,8 @@ var routes = async (fastify2) => {
|
|
|
226871
226967
|
events: [],
|
|
226872
226968
|
headCursor,
|
|
226873
226969
|
nextCursor: headCursor,
|
|
226874
|
-
hasMore: false
|
|
226970
|
+
hasMore: false,
|
|
226971
|
+
sessionTitle: null
|
|
226875
226972
|
});
|
|
226876
226973
|
continue;
|
|
226877
226974
|
}
|
|
@@ -226881,12 +226978,14 @@ var routes = async (fastify2) => {
|
|
|
226881
226978
|
validated.limit
|
|
226882
226979
|
);
|
|
226883
226980
|
const nextCursor = events.length > 0 ? events[events.length - 1].seq : request.after;
|
|
226981
|
+
const session = events.length > 0 ? await fastify2.storage.agentSessions.getById(request.sessionId) : void 0;
|
|
226884
226982
|
sessions.push({
|
|
226885
226983
|
sessionId: request.sessionId,
|
|
226886
226984
|
events,
|
|
226887
226985
|
headCursor,
|
|
226888
226986
|
nextCursor,
|
|
226889
|
-
hasMore: nextCursor < headCursor
|
|
226987
|
+
hasMore: nextCursor < headCursor,
|
|
226988
|
+
sessionTitle: session?.title ?? null
|
|
226890
226989
|
});
|
|
226891
226990
|
}
|
|
226892
226991
|
return reply.code(200).send({ sessions });
|
|
@@ -226904,6 +227003,7 @@ var SYNC_INTERVAL_MS = 6e4;
|
|
|
226904
227003
|
var COMPLETION_NUDGE_DEBOUNCE_MS = 250;
|
|
226905
227004
|
var MAX_CONCURRENT_SERVERS = 4;
|
|
226906
227005
|
var MAX_PAGES_PER_SYNC = 50;
|
|
227006
|
+
var MAX_SESSION_TITLE_LENGTH = 200;
|
|
226907
227007
|
function localWorkflowRunId(remoteServerId, projectId, remoteRunId) {
|
|
226908
227008
|
return `remote-${remoteServerId}-${projectId}-${remoteRunId}`;
|
|
226909
227009
|
}
|
|
@@ -227225,6 +227325,7 @@ var RemoteNotificationSync = class {
|
|
|
227225
227325
|
console.warn(`[RemoteNotifications] project ${mapping.project_id} not found; skipping ${mapping.local_session_id}`);
|
|
227226
227326
|
return false;
|
|
227227
227327
|
}
|
|
227328
|
+
const sessionTitle = typeof session.sessionTitle === "string" ? session.sessionTitle.slice(0, MAX_SESSION_TITLE_LENGTH) : null;
|
|
227228
227329
|
for (const event of session.events) {
|
|
227229
227330
|
const notification = await this.notificationService.buildNotification(event, {
|
|
227230
227331
|
id: localNotificationId(remoteServerId, event.id),
|
|
@@ -227232,7 +227333,7 @@ var RemoteNotificationSync = class {
|
|
|
227232
227333
|
projectId: mapping.project_id,
|
|
227233
227334
|
sessionId: mapping.local_session_id,
|
|
227234
227335
|
workflowRunId: event.workflow_run_id ? localWorkflowRunId(remoteServerId, mapping.project_id, event.workflow_run_id) : null
|
|
227235
|
-
});
|
|
227336
|
+
}, { sessionTitle });
|
|
227236
227337
|
const { inserted } = await this.storage.notifications.importRemote({
|
|
227237
227338
|
notification,
|
|
227238
227339
|
remoteServerId,
|
|
@@ -227450,9 +227551,10 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, wsOptions, rev
|
|
|
227450
227551
|
}
|
|
227451
227552
|
}
|
|
227452
227553
|
} else if ("workflowRunUpdated" in parsed) {
|
|
227453
|
-
|
|
227454
|
-
|
|
227455
|
-
|
|
227554
|
+
const evt = runUpdatedEventFromRemoteFrame(parsed, sessionId, remoteInfo);
|
|
227555
|
+
if (evt) {
|
|
227556
|
+
eventBus?.emit(evt);
|
|
227557
|
+
cache2.broadcast(sessionId, runUpdatedFrameForSubscribers(evt));
|
|
227456
227558
|
}
|
|
227457
227559
|
} else if ("processAlive" in parsed) {
|
|
227458
227560
|
cache2.broadcast(sessionId, raw);
|
|
@@ -230126,11 +230228,24 @@ ${opts.reviewFocus}` : null,
|
|
|
230126
230228
|
function buildFeedbackMessage(feedback) {
|
|
230127
230229
|
return [
|
|
230128
230230
|
"[Review Feedback]",
|
|
230129
|
-
"A reviewer agent examined your last completed work.
|
|
230231
|
+
"A reviewer agent examined your last completed work. It was in read-only mode and saw only this turn's diff plus a distilled brief of the conversation, so it may be working from wrong premises. Treat its findings as input to verify, not as conclusions.",
|
|
230232
|
+
"",
|
|
230233
|
+
"- Verify each item against the code before changing anything.",
|
|
230234
|
+
"- Push back when you have grounds: say what the item gets wrong and leave the code as it is. Do not change code to be agreeable.",
|
|
230235
|
+
"- Address blocking findings first; non-blocking notes need not be done this turn.",
|
|
230236
|
+
"- Do not widen the scope: no fixes the reviewer did not raise, no abstractions for hypothetical cases.",
|
|
230237
|
+
"- Close with a per-item account: fixed, or not fixed and why.",
|
|
230130
230238
|
"",
|
|
230131
230239
|
feedback
|
|
230132
230240
|
].join("\n");
|
|
230133
230241
|
}
|
|
230242
|
+
var FINAL_VERDICT_PROMPT = [
|
|
230243
|
+
"[Final verdict request]",
|
|
230244
|
+
"\u8BF7\u628A\u8BA8\u8BBA\u540E\u7684\u6700\u7EC8 review \u610F\u89C1\u5B8C\u6574\u8F93\u51FA\u4E3A\u9762\u5411\u4F5C\u8005\u7684\u5B9A\u7A3F\u3002\u8FD9\u6BB5\u8F93\u51FA\u5C06\u539F\u6837\u53D1\u9001\u7ED9\u4F5C\u8005\u2014\u2014\u4E0D\u8981\u5305\u542B\u5BF9\u8BDD\u6027\u5185\u5BB9\uFF1A\u4E0D\u8981\u5F15\u7528\u8BA8\u8BBA\u8FC7\u7A0B\u672C\u8EAB\uFF0C\u4E0D\u8981\u5411\u6211\u63D0\u95EE\u3002",
|
|
230245
|
+
"- \u5438\u6536\u8BA8\u8BBA\u4E2D\u8FBE\u6210\u4E00\u81F4\u7684\u4FEE\u6B63\uFF1A\u64A4\u56DE\u7684\u6761\u76EE\u4E0D\u518D\u51FA\u73B0\uFF0C\u4FEE\u8BA2\u8FC7\u7684\u6761\u76EE\u4EE5\u4FEE\u8BA2\u540E\u7684\u5F62\u5F0F\u7ED9\u51FA\u3002",
|
|
230246
|
+
"- \u4FDD\u6301\u5177\u4F53\uFF1A\u6BCF\u6761\u6307\u660E\u6587\u4EF6/\u4F4D\u7F6E\u4E0E\u95EE\u9898\uFF0C\u4EE5\u53CA\u671F\u671B\u7684\u4FEE\u590D\u65B9\u5411\u3002",
|
|
230247
|
+
...VERDICT_INSTRUCTIONS
|
|
230248
|
+
].join("\n");
|
|
230134
230249
|
var REVIEWER_AGENT_TYPES = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
230135
230250
|
var WorkflowEngine = class {
|
|
230136
230251
|
constructor(storage, agentOps) {
|
|
@@ -230452,7 +230567,7 @@ var WorkflowEngine = class {
|
|
|
230452
230567
|
...driftNote ? { error: driftNote } : {}
|
|
230453
230568
|
},
|
|
230454
230569
|
{
|
|
230455
|
-
id: reviewReadyId(run2.id),
|
|
230570
|
+
id: reviewReadyId(run2.id, boundary),
|
|
230456
230571
|
kind: "review_ready",
|
|
230457
230572
|
project_id: run2.project_id,
|
|
230458
230573
|
branch: run2.branch,
|
|
@@ -230499,12 +230614,49 @@ var WorkflowEngine = class {
|
|
|
230499
230614
|
this.emitRunUpdated(done);
|
|
230500
230615
|
return done;
|
|
230501
230616
|
}
|
|
230617
|
+
/**
|
|
230618
|
+
* Discussion → verdict: CAS the run back onto the reviewer track and inject
|
|
230619
|
+
* the final-verdict prompt. From waiting_reviewer the existing
|
|
230620
|
+
* handleTaskCompleted path reopens the gate with the new turn's output.
|
|
230621
|
+
* Send failure rolls the claim back so the finalize button stays actionable —
|
|
230622
|
+
* mirror of approveFeedback's no-auto-retry contract.
|
|
230623
|
+
*/
|
|
230624
|
+
async requestFinalVerdict(runId) {
|
|
230625
|
+
const run2 = await this.storage.workflowRuns.getById(runId);
|
|
230626
|
+
if (!run2 || run2.status !== "discussing" || !run2.reviewer_session_id) {
|
|
230627
|
+
throw new WorkflowError("bad-state", "run \u4E0D\u5728\u8BA8\u8BBA\u72B6\u6001");
|
|
230628
|
+
}
|
|
230629
|
+
const reviewerSession = await this.storage.agentSessions.getById(run2.reviewer_session_id);
|
|
230630
|
+
if (reviewerSession && reviewerSession.status === "running") {
|
|
230631
|
+
throw new WorkflowError("session-busy", "reviewer \u6B63\u5728\u56DE\u590D\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5176\u5B8C\u6210\u540E\u518D\u751F\u6210\u7EC8\u7A3F");
|
|
230632
|
+
}
|
|
230633
|
+
const claimed = await this.storage.workflowRuns.transition(runId, "discussing", "waiting_reviewer", { error: null });
|
|
230634
|
+
if (!claimed) throw new WorkflowError("bad-state", "run \u72B6\u6001\u5DF2\u53D8\u5316\uFF08\u53EF\u80FD\u5DF2\u88AB\u5904\u7406\uFF09");
|
|
230635
|
+
const project = await this.storage.projects.getById(run2.project_id);
|
|
230636
|
+
const sent = await this.agentOps.sendUserMessage(run2.reviewer_session_id, FINAL_VERDICT_PROMPT, project?.path ?? void 0, void 0, REVIEWER_TURN).catch(() => false);
|
|
230637
|
+
if (!sent) {
|
|
230638
|
+
const rolledBack = await this.storage.workflowRuns.transition(runId, "waiting_reviewer", "discussing", {
|
|
230639
|
+
error: "\u53D1\u9001\u5931\u8D25\uFF1Areviewer session \u53EF\u80FD\u672A\u8FD0\u884C\u3002\u8BF7\u5728\u5176\u7A97\u53E3\u4E2D\u5524\u9192\u540E\u91CD\u8BD5\uFF0C\u6216\u7ED3\u675F\u672C\u6B21 review\u3002"
|
|
230640
|
+
});
|
|
230641
|
+
if (!rolledBack) {
|
|
230642
|
+
console.warn(
|
|
230643
|
+
`requestFinalVerdict: rollback CAS lost for run ${runId} \u2014 run moved concurrently (e.g. cancelled) while the send was in flight; rollback skipped`
|
|
230644
|
+
);
|
|
230645
|
+
}
|
|
230646
|
+
const rolled = await this.storage.workflowRuns.getById(runId);
|
|
230647
|
+
if (rolled) this.emitRunUpdated(rolled);
|
|
230648
|
+
throw new WorkflowError("send-failed", "\u5411 reviewer \u53D1\u9001\u7EC8\u7A3F\u8BF7\u6C42\u5931\u8D25");
|
|
230649
|
+
}
|
|
230650
|
+
const updated = await this.storage.workflowRuns.getById(runId);
|
|
230651
|
+
this.emitRunUpdated(updated);
|
|
230652
|
+
return updated;
|
|
230653
|
+
}
|
|
230502
230654
|
async cancelRun(runId, reason) {
|
|
230503
230655
|
const run2 = await this.storage.workflowRuns.getById(runId);
|
|
230504
230656
|
if (!run2) return void 0;
|
|
230505
230657
|
if (TERMINAL_STATUSES.has(run2.status)) return run2;
|
|
230506
230658
|
const patch = reason ? { error: reason } : void 0;
|
|
230507
|
-
const cancelled = await this.storage.workflowRuns.transition(runId, "waiting_reviewer", "cancelled", patch) || await this.storage.workflowRuns.transition(runId, "waiting_feedback", "cancelled", patch);
|
|
230659
|
+
const cancelled = await this.storage.workflowRuns.transition(runId, "waiting_reviewer", "cancelled", patch) || await this.storage.workflowRuns.transition(runId, "waiting_feedback", "cancelled", patch) || await this.storage.workflowRuns.transition(runId, "discussing", "cancelled", patch);
|
|
230508
230660
|
if (!cancelled) {
|
|
230509
230661
|
const current = await this.storage.workflowRuns.getById(runId);
|
|
230510
230662
|
if (current?.status === "sending_feedback") {
|
|
@@ -230522,6 +230674,10 @@ var WorkflowEngine = class {
|
|
|
230522
230674
|
/**
|
|
230523
230675
|
* Human takeover (spec §3.4): user sent a message directly to a run session.
|
|
230524
230676
|
*
|
|
230677
|
+
* Reviewer 分流:向 reviewer 发消息不再是接管——它开启一轮讨论,把 run
|
|
230678
|
+
* 移入 `discussing`(gate 收起),等待显式的 requestFinalVerdict 重新出稿。
|
|
230679
|
+
* 只有向 source session 发消息才算接管,结束 run。
|
|
230680
|
+
*
|
|
230525
230681
|
* Never-throws contract: this is called inline from the agent-session
|
|
230526
230682
|
* `/message` route BEFORE the user's message is delivered
|
|
230527
230683
|
* (agentOps.sendUserMessage). A throw here would abort delivery of that
|
|
@@ -230536,8 +230692,23 @@ var WorkflowEngine = class {
|
|
|
230536
230692
|
async handleExternalUserMessage(sessionId) {
|
|
230537
230693
|
const p2 = this.participants.get(sessionId);
|
|
230538
230694
|
if (!p2) return;
|
|
230695
|
+
if (p2.role === "reviewer") {
|
|
230696
|
+
try {
|
|
230697
|
+
const moved = await this.storage.workflowRuns.transition(p2.runId, "waiting_feedback", "discussing", { error: null }) || await this.storage.workflowRuns.transition(p2.runId, "waiting_reviewer", "discussing", { error: null });
|
|
230698
|
+
if (moved) {
|
|
230699
|
+
const updated = await this.storage.workflowRuns.getById(p2.runId);
|
|
230700
|
+
if (updated) this.emitRunUpdated(updated);
|
|
230701
|
+
}
|
|
230702
|
+
} catch (err) {
|
|
230703
|
+
console.error(
|
|
230704
|
+
`[WorkflowEngine] handleExternalUserMessage: failed moving run ${p2.runId} to discussing; swallowed to honor never-throws contract`,
|
|
230705
|
+
err
|
|
230706
|
+
);
|
|
230707
|
+
}
|
|
230708
|
+
return;
|
|
230709
|
+
}
|
|
230539
230710
|
try {
|
|
230540
|
-
await this.cancelRun(p2.runId, "\u7528\u6237\u63A5\u7BA1\uFF1A\u76F4\u63A5\u5411
|
|
230711
|
+
await this.cancelRun(p2.runId, "\u7528\u6237\u63A5\u7BA1\uFF1A\u76F4\u63A5\u5411 source session \u53D1\u9001\u4E86\u6D88\u606F\uFF0Creview \u5DF2\u7ED3\u675F\u3002");
|
|
230541
230712
|
} catch (err) {
|
|
230542
230713
|
if (err instanceof WorkflowError && err.code === "bad-state") {
|
|
230543
230714
|
console.warn(
|
|
@@ -232422,8 +232593,12 @@ var NotificationService = class {
|
|
|
232422
232593
|
* Assemble the persisted row. `ids` is separate from the event because remote
|
|
232423
232594
|
* imports substitute front-local identities (see RemoteNotificationSync) while
|
|
232424
232595
|
* reusing this exact copy generation.
|
|
232596
|
+
*
|
|
232597
|
+
* `opts.sessionTitle` covers the remote-import case: the front has a mapping
|
|
232598
|
+
* but no local session row, so the worker's query-time title is the only way
|
|
232599
|
+
* to label the notification with the session's name.
|
|
232425
232600
|
*/
|
|
232426
|
-
async buildNotification(event, ids) {
|
|
232601
|
+
async buildNotification(event, ids, opts) {
|
|
232427
232602
|
const session = ids.sessionId ? await this.storage.agentSessions.getById(ids.sessionId) : void 0;
|
|
232428
232603
|
const project = await this.storage.projects.getById(ids.projectId);
|
|
232429
232604
|
return {
|
|
@@ -232436,7 +232611,7 @@ var NotificationService = class {
|
|
|
232436
232611
|
workflow_run_id: ids.workflowRunId,
|
|
232437
232612
|
title: notificationTitle(event.kind),
|
|
232438
232613
|
body: notificationBody({
|
|
232439
|
-
sessionTitle: session?.title,
|
|
232614
|
+
sessionTitle: session?.title ?? opts?.sessionTitle,
|
|
232440
232615
|
branch: event.branch,
|
|
232441
232616
|
projectName: project?.name
|
|
232442
232617
|
}),
|
|
@@ -236551,6 +236726,54 @@ var routes12 = async (fastify2) => {
|
|
|
236551
236726
|
return reply.code(200).send({ success: true, agentType });
|
|
236552
236727
|
}
|
|
236553
236728
|
);
|
|
236729
|
+
fastify2.post(
|
|
236730
|
+
"/api/agent-sessions/:sessionId/model",
|
|
236731
|
+
async (req, reply) => {
|
|
236732
|
+
const body = req.body || {};
|
|
236733
|
+
if (body.model === void 0) {
|
|
236734
|
+
return reply.code(400).send({ error: "model is required (null for the CLI default)" });
|
|
236735
|
+
}
|
|
236736
|
+
const { model } = body;
|
|
236737
|
+
if (model !== null && typeof model !== "string") {
|
|
236738
|
+
return reply.code(400).send({ error: "model must be a string or null" });
|
|
236739
|
+
}
|
|
236740
|
+
const userId = requireAuth(req, reply);
|
|
236741
|
+
if (userId === null) return;
|
|
236742
|
+
if (req.params.sessionId.startsWith("remote-")) {
|
|
236743
|
+
const remoteInfo = await getAuthorizedRemoteSessionInfo(req.params.sessionId, userId);
|
|
236744
|
+
if (!remoteInfo) {
|
|
236745
|
+
return reply.code(404).send({ error: "Remote session not found" });
|
|
236746
|
+
}
|
|
236747
|
+
const result = await proxyAuto(
|
|
236748
|
+
remoteInfo.remoteServerId,
|
|
236749
|
+
remoteInfo.remoteUrl,
|
|
236750
|
+
remoteInfo.remoteApiKey,
|
|
236751
|
+
"POST",
|
|
236752
|
+
`/api/agent-sessions/${remoteInfo.remoteSessionId}/model`,
|
|
236753
|
+
{ model }
|
|
236754
|
+
);
|
|
236755
|
+
return reply.code(proxyStatus(result)).send(result.data);
|
|
236756
|
+
}
|
|
236757
|
+
const row = await fastify2.storage.agentSessions.getById(req.params.sessionId);
|
|
236758
|
+
if (!row || !await fastify2.storage.projects.getById(row.project_id, userId)) {
|
|
236759
|
+
return reply.code(404).send({ error: "Session not found" });
|
|
236760
|
+
}
|
|
236761
|
+
const outcome = await fastify2.agentSessionManager.setModel(req.params.sessionId, model);
|
|
236762
|
+
if (outcome === "not_found") {
|
|
236763
|
+
return reply.code(404).send({ error: "Session not found" });
|
|
236764
|
+
}
|
|
236765
|
+
if (outcome === "busy") {
|
|
236766
|
+
return reply.code(409).send({ error: "Agent is currently running \u2014 stop it before changing the model" });
|
|
236767
|
+
}
|
|
236768
|
+
if (outcome === "error") {
|
|
236769
|
+
return reply.code(500).send({ error: "Couldn't save the model \u2014 the session kept its current one" });
|
|
236770
|
+
}
|
|
236771
|
+
return reply.code(200).send({
|
|
236772
|
+
success: true,
|
|
236773
|
+
model: fastify2.agentSessionManager.getSession(req.params.sessionId)?.model ?? null
|
|
236774
|
+
});
|
|
236775
|
+
}
|
|
236776
|
+
);
|
|
236554
236777
|
fastify2.post(
|
|
236555
236778
|
"/api/agent-sessions/:sessionId/branch",
|
|
236556
236779
|
async (req, reply) => {
|
|
@@ -238358,7 +238581,11 @@ async function routes19(fastify2) {
|
|
|
238358
238581
|
const run2 = await fastify2.workflowEngine.cancelRun(req.params.id);
|
|
238359
238582
|
return reply.send({ run: run2 });
|
|
238360
238583
|
}
|
|
238361
|
-
|
|
238584
|
+
if (action === "finalize") {
|
|
238585
|
+
const run2 = await fastify2.workflowEngine.requestFinalVerdict(req.params.id);
|
|
238586
|
+
return reply.send({ run: run2 });
|
|
238587
|
+
}
|
|
238588
|
+
return reply.code(400).send({ error: "action must be approve, cancel or finalize" });
|
|
238362
238589
|
} catch (err) {
|
|
238363
238590
|
const status = errStatus(err);
|
|
238364
238591
|
if (status) return reply.code(status).send({ error: err.message });
|