@bivy/bivy 0.6.0-staging.86 → 0.6.0-staging.87
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/server.js +53 -2
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -5225,6 +5225,47 @@ async function resolveTokenForRepo(owner, repo) {
|
|
|
5225
5225
|
}
|
|
5226
5226
|
return (await resolveGitHubToken()) ?? (await hostedMintToken());
|
|
5227
5227
|
}
|
|
5228
|
+
/** The session source a Linear-issue pickup advertises, keyed by the issue's
|
|
5229
|
+
* provider-native id so the control plane can correlate a re-dispatch to it
|
|
5230
|
+
* (findSessionByExternalId → "linear:<externalId>"). The Linear analogue of the
|
|
5231
|
+
* GitHub `issue:owner/repo#N` source. */
|
|
5232
|
+
function linearSessionSource(externalId) {
|
|
5233
|
+
return `linear:${externalId}`;
|
|
5234
|
+
}
|
|
5235
|
+
/**
|
|
5236
|
+
* Case B for a queued follow-up the control plane correlated to an existing
|
|
5237
|
+
* session (`targetKind === "existing_session"`): if that session is still live on
|
|
5238
|
+
* this node, continue it as a normal chat — run `prompt` as a follow-up turn and
|
|
5239
|
+
* re-publish its branch/PR — so a channel reply lands in the same thread. The
|
|
5240
|
+
* provider-agnostic analogue of the GitHub issue follow-up (`runIssueFollowUp`);
|
|
5241
|
+
* used by both the Linear and the generic (Slack) pickup paths. When the session
|
|
5242
|
+
* isn't live here (its machine was torn down), best-effort restore its snapshot so
|
|
5243
|
+
* the caller's fresh pickup continues its branch/transcript instead of cold-
|
|
5244
|
+
* starting, and return false so the caller falls through. Returns true only when
|
|
5245
|
+
* it fully handled the item.
|
|
5246
|
+
*/
|
|
5247
|
+
async function continueCorrelatedSession(item, prompt, report) {
|
|
5248
|
+
if (item.targetKind !== "existing_session" || !item.targetSessionId)
|
|
5249
|
+
return false;
|
|
5250
|
+
const record = openSessions.get(item.targetSessionId);
|
|
5251
|
+
if (!record) {
|
|
5252
|
+
await restoreSessionFromSnapshot(item.targetSessionId).catch((e) => console.warn(`[case-b] snapshot restore for ${item.targetSessionId} failed:`, e.message));
|
|
5253
|
+
return false;
|
|
5254
|
+
}
|
|
5255
|
+
const branch = record.worktree?.branch;
|
|
5256
|
+
await runSessionTurn(record, prompt);
|
|
5257
|
+
if (record.worktree) {
|
|
5258
|
+
await maybePushWorktreeBranch(record);
|
|
5259
|
+
await maybeDetectPullRequest(record);
|
|
5260
|
+
}
|
|
5261
|
+
await report({
|
|
5262
|
+
output: { sessionId: record.id, branch, prUrl: record.prUrl },
|
|
5263
|
+
events: record.prUrl
|
|
5264
|
+
? [{ at: new Date().toISOString(), kind: "pull_request", summary: "Pull request updated.", ref: branch, url: record.prUrl }]
|
|
5265
|
+
: undefined,
|
|
5266
|
+
});
|
|
5267
|
+
return true;
|
|
5268
|
+
}
|
|
5228
5269
|
async function runWorkItem(item, report) {
|
|
5229
5270
|
if ((item.source === "schedule" || item.source === "manual") && item.body?.startsWith("bivy-room-v1:")) {
|
|
5230
5271
|
const [, nodeId, ...payload] = item.body.split(":");
|
|
@@ -5303,6 +5344,10 @@ async function runWorkItem(item, report) {
|
|
|
5303
5344
|
const parsed = parseRepo(repoSlug);
|
|
5304
5345
|
if (!parsed)
|
|
5305
5346
|
throw new Error(`Linear work item has an invalid repo "${repoSlug}"`);
|
|
5347
|
+
// Case B: a re-dispatch the control plane correlated to an existing session
|
|
5348
|
+
// continues it as a normal chat instead of starting cold (mirrors GitHub).
|
|
5349
|
+
if (await continueCorrelatedSession(item, buildLinearTaskPrompt(issue), report))
|
|
5350
|
+
return;
|
|
5306
5351
|
const githubToken = await resolveGitHubToken();
|
|
5307
5352
|
if (!githubToken)
|
|
5308
5353
|
throw new Error("no GitHub token available to clone the Linear issue repository");
|
|
@@ -5313,7 +5358,7 @@ async function runWorkItem(item, report) {
|
|
|
5313
5358
|
const record = await createSession(repoDir, undefined, {
|
|
5314
5359
|
worktree: { branch, base },
|
|
5315
5360
|
makeActive: false,
|
|
5316
|
-
source:
|
|
5361
|
+
source: linearSessionSource(item.externalId),
|
|
5317
5362
|
runtimeId: item.runtimeId || nodeConfiguredDefaultAgent(),
|
|
5318
5363
|
sandbox: normalizeSandboxTier(item.sandbox),
|
|
5319
5364
|
approvalMode: approvalModeFrom(item.approvalMode),
|
|
@@ -5339,6 +5384,13 @@ async function runWorkItem(item, report) {
|
|
|
5339
5384
|
const parsedRepo = item.repo ? parseRepo(item.repo) : undefined;
|
|
5340
5385
|
if (item.repo && !parsedRepo)
|
|
5341
5386
|
throw new Error(`work item ${item.id} has an invalid repo "${item.repo}"`);
|
|
5387
|
+
const request = item.body ? `${item.title}\n\n${item.body}` : item.title;
|
|
5388
|
+
// Case B (provider-agnostic): a follow-up the control plane correlated to an
|
|
5389
|
+
// existing session continues it as a normal chat. Reached by Slack the moment a
|
|
5390
|
+
// reply carries a thread identity the control plane can correlate; a one-shot
|
|
5391
|
+
// slash command has none, so it simply falls through to a fresh session.
|
|
5392
|
+
if (await continueCorrelatedSession(item, request, report))
|
|
5393
|
+
return;
|
|
5342
5394
|
const sessionOpts = {
|
|
5343
5395
|
makeActive: false,
|
|
5344
5396
|
title: item.title,
|
|
@@ -5359,7 +5411,6 @@ async function runWorkItem(item, report) {
|
|
|
5359
5411
|
}
|
|
5360
5412
|
catch { }
|
|
5361
5413
|
}
|
|
5362
|
-
const request = item.body ? `${item.title}\n\n${item.body}` : item.title;
|
|
5363
5414
|
const prompt = parsedRepo || record.worktree
|
|
5364
5415
|
? [
|
|
5365
5416
|
request,
|
package/package.json
CHANGED